All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
@ 2016-02-11 17:19 Harry Wentland
  2016-02-11 17:19 ` [PATCH 01/29] drm/amd/dal: Add dal headers Harry Wentland
                   ` (32 more replies)
  0 siblings, 33 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

This set of patches enables the new DAL display driver for amdgpu on Carrizo
Tonga, and Fiji ASICs. This driver will allow us going forward to bring
display features on the open amdgpu driver (mostly) on par with the Catalyst
driver.

This driver adds support for 
- Atomic KMS API
- MST
- HDMI 2.0
- Better powerplay integration
- Support of HW bandwidth formula on Carrizo
- Better multi-display support and handling of co-functionality
- Broader support of display dongles
- Timing synchronization between DP and HDMI

This patch series is based on Alex Deucher's drm-next-4.6-wip tree.



Andrey Grodzovsky (1):
  drm/amd/dal: Force bw programming for DCE 10 until we start calculate
    BW.

Harry Wentland (27):
  drm/amd/dal: Add dal headers
  drm/amd/dal: Add DAL Basic Types and Logger
  drm/amd/dal: Fixed point arithmetic
  drm/amd/dal: Asic Capabilities
  drm/amd/dal: GPIO (General Purpose IO)
  drm/amd/dal: Adapter Service
  drm/amd/dal: BIOS Parser
  drm/amd/dal: I2C Aux Manager
  drm/amd/dal: IRQ Service
  drm/amd/dal: GPU
  drm/amd/dal: Audio
  drm/amd/dal: Bandwidth calculations
  drm/amd/dal: Add encoder HW programming
  drm/amd/dal: Add clock source HW programming
  drm/amd/dal: Add timing generator HW programming
  drm/amd/dal: Add surface HW programming
  drm/amd/dal: Add framebuffer compression HW programming
  drm/amd/dal: Add input pixel processing HW programming
  drm/amd/dal: Add output pixel processing HW programming
  drm/amd/dal: Add transform & scaler HW programming
  drm/amd/dal: Add Carrizo HW sequencer and resource
  drm/amd/dal: Add Tonga/Fiji HW sequencer and resource
  drm/amd/dal: Add empty encoder programming for virtual HW
  drm/amd/dal: Add display core
  drm/amd/dal: Adding amdgpu_dm for dal
  drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji
  drm/amd/dal: Correctly interpret rotation as bit set

Mykola Lysenko (1):
  drm/amd/dal: fix flip clean-up state

 drivers/gpu/drm/amd/amdgpu/Kconfig                 |    3 +
 drivers/gpu/drm/amd/amdgpu/Makefile                |   17 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h                |   10 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         |   69 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c            |    4 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c             |    5 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c            |   20 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h           |   54 +-
 drivers/gpu/drm/amd/amdgpu/vi.c                    |  250 +
 drivers/gpu/drm/amd/dal/Kconfig                    |   48 +
 drivers/gpu/drm/amd/dal/Makefile                   |   21 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile         |   17 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c      | 1468 ++++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h      |  168 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c  |  474 ++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c  |  820 ++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h  |  122 +
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c    |  480 ++
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h    |   36 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c |  457 ++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c    | 2577 ++++++++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h    |  100 +
 drivers/gpu/drm/amd/dal/dal_services.h             |  266 ++
 drivers/gpu/drm/amd/dal/dal_services_types.h       |   62 +
 drivers/gpu/drm/amd/dal/dc/Makefile                |   28 +
 drivers/gpu/drm/amd/dal/dc/adapter/Makefile        |   24 +
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.c   | 2089 ++++++++
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.h   |   71 +
 .../adapter/dce110/hw_ctx_adapter_service_dce110.c |  304 ++
 .../adapter/dce110/hw_ctx_adapter_service_dce110.h |   40 +
 .../diagnostics/hw_ctx_adapter_service_diag.c      |  133 +
 .../diagnostics/hw_ctx_adapter_service_diag.h      |   33 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.c    |  164 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.h    |   86 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.c  |  208 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.h  |   80 +
 .../gpu/drm/amd/dal/dc/asic_capability/Makefile    |   35 +
 .../amd/dal/dc/asic_capability/asic_capability.c   |  190 +
 .../dc/asic_capability/carrizo_asic_capability.c   |  147 +
 .../dc/asic_capability/carrizo_asic_capability.h   |   36 +
 .../dal/dc/asic_capability/tonga_asic_capability.c |  146 +
 .../dal/dc/asic_capability/tonga_asic_capability.h |   36 +
 drivers/gpu/drm/amd/dal/dc/audio/Makefile          |   22 +
 drivers/gpu/drm/amd/dal/dc/audio/audio.h           |  195 +
 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c      |  470 ++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c |  453 ++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h |   42 +
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c  | 1930 ++++++++
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h  |   47 +
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c    |  771 +++
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h    |  285 ++
 drivers/gpu/drm/amd/dal/dc/basics/Makefile         |   10 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.c     |  224 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.h     |   49 +
 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c     |  692 +++
 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c     |  223 +
 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c |  134 +
 drivers/gpu/drm/amd/dal/dc/basics/logger.c         |  954 ++++
 drivers/gpu/drm/amd/dal/dc/basics/logger.h         |   64 +
 .../gpu/drm/amd/dal/dc/basics/register_logger.c    |  197 +
 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c   |  116 +
 drivers/gpu/drm/amd/dal/dc/basics/vector.c         |  309 ++
 drivers/gpu/drm/amd/dal/dc/bios/Makefile           |   26 +
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c      | 5029 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h      |   84 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c   |  198 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h   |  108 +
 drivers/gpu/drm/amd/dal/dc/bios/command_table.c    | 2730 +++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/command_table.h    |  117 +
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.c |  285 ++
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.h |   90 +
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.c |  484 ++
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.h |   34 +
 .../dc/bios/dce110/command_table_helper_dce110.c   |  366 ++
 .../dc/bios/dce110/command_table_helper_dce110.h   |   34 +
 drivers/gpu/drm/amd/dal/dc/calcs/Makefile          |   10 +
 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 3941 +++++++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c        |  300 ++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c   | 1992 ++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h   |   74 +
 drivers/gpu/drm/amd/dal/dc/core/dc.c               |  932 ++++
 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c  |   56 +
 drivers/gpu/drm/amd/dal/dc/core/dc_link.c          | 1644 +++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c      | 1151 +++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c       | 1728 +++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c     |  201 +
 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c      | 1243 +++++
 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c          |  116 +
 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c        |  188 +
 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c       |  123 +
 drivers/gpu/drm/amd/dal/dc/core/dc_target.c        |  548 +++
 drivers/gpu/drm/amd/dal/dc/dc.h                    |  462 ++
 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h         |  277 ++
 drivers/gpu/drm/amd/dal/dc/dc_types.h              |  936 ++++
 drivers/gpu/drm/amd/dal/dc/dce100/Makefile         |   23 +
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.c    |  360 ++
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.h    |   36 +
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c    | 1135 +++++
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.h    |   43 +
 drivers/gpu/drm/amd/dal/dc/dce110/Makefile         |   15 +
 .../drm/amd/dal/dc/dce110/dce110_clock_source.c    | 1162 +++++
 .../drm/amd/dal/dc/dce110/dce110_clock_source.h    |   64 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.c  |  886 ++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.h  |   84 +
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 1658 +++++++
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h    |   36 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c     |   65 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h     |  100 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c  |  256 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c   |  872 ++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.c    | 1927 ++++++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.h    |  156 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c   |  965 ++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h   |  117 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c     |  272 ++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h     |  143 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c |  904 ++++
 .../drm/amd/dal/dc/dce110/dce110_opp_formatter.c   |  610 +++
 .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2474 ++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c    | 1238 +++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.h    |   46 +
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.c  | 1123 +++++
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.h  |  122 +
 .../amd/dal/dc/dce110/dce110_timing_generator.c    | 1864 ++++++++
 .../amd/dal/dc/dce110/dce110_timing_generator.h    |  234 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c   |   91 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.h   |   87 +
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.c |  851 ++++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.h |   51 +
 .../drm/amd/dal/dc/dce110/dce110_transform_gamut.c |  296 ++
 .../drm/amd/dal/dc/dce110/dce110_transform_scl.c   |  818 ++++
 .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c  |  531 +++
 drivers/gpu/drm/amd/dal/dc/dm_helpers.h            |   98 +
 drivers/gpu/drm/amd/dal/dc/dm_services.h           |  468 ++
 drivers/gpu/drm/amd/dal/dc/dm_services_types.h     |  167 +
 drivers/gpu/drm/amd/dal/dc/gpio/Makefile           |   32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c |  882 ++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h |   46 +
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c |   81 +
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h |   32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c |  366 ++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h |   47 +
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.c   |  400 ++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.h   |   34 +
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c              |  290 ++
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h              |   45 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c  |   97 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h  |   34 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.c  |   65 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.h  |   32 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c  |  101 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h  |   35 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.c    |   41 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.h    |   34 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h             |   48 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c        |  279 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c     |  386 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h     |   57 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c           |  104 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h           |   60 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c       |   93 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h       |   71 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c          |  407 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h          |  129 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c      |   92 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h      |   47 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c      |   85 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h      |   79 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c           |   87 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h           |   45 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c     |   77 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h     |   50 +
 drivers/gpu/drm/amd/dal/dc/gpio/irq.c              |  180 +
 drivers/gpu/drm/amd/dal/dc/gpio/irq.h              |   42 +
 drivers/gpu/drm/amd/dal/dc/gpu/Makefile            |   22 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c    |   92 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h    |   63 +
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c |   90 +
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h |   33 +
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.c   |  968 ++++
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.h   |   53 +
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c     |  205 +
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h     |   82 +
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c     |  127 +
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h     |   63 +
 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |   33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     |  567 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     |  119 +
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   |  788 +++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |   56 +
 .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |   25 +
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    |  954 ++++
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |   58 +
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    |  172 +
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |   43 +
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   |  266 ++
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |   39 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    |  112 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |   33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         |  129 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |   67 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     |  121 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     |  113 +
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  |  286 ++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |   77 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  |  246 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |   80 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  |  614 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |   81 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         |  529 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         |  123 +
 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h   |  510 ++
 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h          |   64 +
 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h      |  176 +
 drivers/gpu/drm/amd/dal/dc/inc/compressor.h        |  140 +
 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h           |   54 +
 drivers/gpu/drm/amd/dal/dc/inc/core_status.h       |   46 +
 drivers/gpu/drm/amd/dal/dc/inc/core_types.h        |  357 ++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h       |  151 +
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h        |   56 +
 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h       |  118 +
 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h      |  126 +
 drivers/gpu/drm/amd/dal/dc/inc/ipp.h               |  106 +
 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h      |  138 +
 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h         |   68 +
 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h         |   83 +
 drivers/gpu/drm/amd/dal/dc/inc/opp.h               |  308 ++
 drivers/gpu/drm/amd/dal/dc/inc/resource.h          |   80 +
 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h    |   88 +
 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h  |  155 +
 drivers/gpu/drm/amd/dal/dc/inc/transform.h         |  217 +
 drivers/gpu/drm/amd/dal/dc/irq/Makefile            |   21 +
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.c |  389 ++
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.h |   34 +
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c       |  177 +
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h       |   85 +
 drivers/gpu/drm/amd/dal/dc/irq_types.h             |  199 +
 drivers/gpu/drm/amd/dal/dc/virtual/Makefile        |    9 +
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.c  |  133 +
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.h  |   35 +
 .../amd/dal/dc/virtual/virtual_stream_encoder.c    |  124 +
 .../amd/dal/dc/virtual/virtual_stream_encoder.h    |   39 +
 .../amd/dal/include/adapter_service_interface.h    |  632 +++
 .../drm/amd/dal/include/adapter_service_types.h    |   71 +
 .../amd/dal/include/asic_capability_interface.h    |   58 +
 .../drm/amd/dal/include/asic_capability_types.h    |  134 +
 drivers/gpu/drm/amd/dal/include/audio_interface.h  |  184 +
 drivers/gpu/drm/amd/dal/include/audio_types.h      |  277 ++
 .../drm/amd/dal/include/bios_parser_interface.h    |   98 +
 .../gpu/drm/amd/dal/include/bios_parser_types.h    |  327 ++
 drivers/gpu/drm/amd/dal/include/dal_asic_id.h      |  117 +
 .../gpu/drm/amd/dal/include/dal_register_logger.h  |   43 +
 drivers/gpu/drm/amd/dal/include/dal_types.h        |  305 ++
 .../amd/dal/include/dc_clock_generator_interface.h |   77 +
 drivers/gpu/drm/amd/dal/include/dcs_types.h        |  742 +++
 drivers/gpu/drm/amd/dal/include/ddc_interface.h    |   74 +
 .../gpu/drm/amd/dal/include/ddc_service_types.h    |  221 +
 .../drm/amd/dal/include/display_clock_interface.h  |  186 +
 .../drm/amd/dal/include/display_path_interface.h   |  436 ++
 drivers/gpu/drm/amd/dal/include/dmcu_interface.h   |   87 +
 drivers/gpu/drm/amd/dal/include/dmcu_types.h       |  199 +
 drivers/gpu/drm/amd/dal/include/dpcd_defs.h        |  873 ++++
 .../gpu/drm/amd/dal/include/encoder_interface.h    |  278 ++
 drivers/gpu/drm/amd/dal/include/fixed31_32.h       |  389 ++
 drivers/gpu/drm/amd/dal/include/fixed32_32.h       |   82 +
 drivers/gpu/drm/amd/dal/include/gpio_interface.h   |   93 +
 .../drm/amd/dal/include/gpio_service_interface.h   |   81 +
 drivers/gpu/drm/amd/dal/include/gpio_types.h       |  341 ++
 drivers/gpu/drm/amd/dal/include/grph_csc_types.h   |   98 +
 .../drm/amd/dal/include/grph_object_ctrl_defs.h    |  593 +++
 drivers/gpu/drm/amd/dal/include/grph_object_defs.h |  328 ++
 drivers/gpu/drm/amd/dal/include/grph_object_id.h   |  277 ++
 .../drm/amd/dal/include/hw_sequencer_interface.h   |  388 ++
 .../gpu/drm/amd/dal/include/hw_sequencer_types.h   |  304 ++
 drivers/gpu/drm/amd/dal/include/i2caux_interface.h |  127 +
 drivers/gpu/drm/amd/dal/include/irq_interface.h    |   53 +
 .../drm/amd/dal/include/irq_service_interface.h    |   55 +
 .../drm/amd/dal/include/link_service_interface.h   |  202 +
 .../gpu/drm/amd/dal/include/link_service_types.h   |  427 ++
 drivers/gpu/drm/amd/dal/include/logger_interface.h |  153 +
 drivers/gpu/drm/amd/dal/include/logger_types.h     |  356 ++
 drivers/gpu/drm/amd/dal/include/scaler_types.h     |  196 +
 drivers/gpu/drm/amd/dal/include/set_mode_types.h   |  142 +
 drivers/gpu/drm/amd/dal/include/signal_types.h     |   59 +
 drivers/gpu/drm/amd/dal/include/vector.h           |  150 +
 drivers/gpu/drm/amd/dal/include/video_csc_types.h  |  135 +
 .../gpu/drm/amd/dal/include/video_gamma_types.h    |   57 +
 287 files changed, 93942 insertions(+), 30 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/dal/Kconfig
 create mode 100644 drivers/gpu/drm/amd/dal/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_target.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_helpers.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_status.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_asic_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_register_logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_clock_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_path_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed31_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed32_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/i2caux_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/scaler_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/signal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/vector.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_gamma_types.h

-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH 01/29] drm/amd/dal: Add dal headers
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 02/29] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
                   ` (31 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dal_services.h             | 266 ++++++
 drivers/gpu/drm/amd/dal/dal_services_types.h       |  62 ++
 drivers/gpu/drm/amd/dal/dc/dc.h                    | 462 ++++++++++
 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h         | 277 ++++++
 drivers/gpu/drm/amd/dal/dc/dc_types.h              | 936 +++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/dm_helpers.h            |  98 +++
 drivers/gpu/drm/amd/dal/dc/dm_services.h           | 485 +++++++++++
 drivers/gpu/drm/amd/dal/dc/dm_services_types.h     | 167 ++++
 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h   | 510 +++++++++++
 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h          |  64 ++
 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h      | 176 ++++
 drivers/gpu/drm/amd/dal/dc/inc/compressor.h        | 140 +++
 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h           |  54 ++
 drivers/gpu/drm/amd/dal/dc/inc/core_status.h       |  46 +
 drivers/gpu/drm/amd/dal/dc/inc/core_types.h        | 357 ++++++++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h       | 151 ++++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h        |  56 ++
 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h       | 118 +++
 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h      | 126 +++
 drivers/gpu/drm/amd/dal/dc/inc/ipp.h               | 106 +++
 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h      | 138 +++
 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h         |  68 ++
 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h         |  83 ++
 drivers/gpu/drm/amd/dal/dc/inc/opp.h               | 308 +++++++
 drivers/gpu/drm/amd/dal/dc/inc/resource.h          |  80 ++
 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h    |  88 ++
 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h  | 155 ++++
 drivers/gpu/drm/amd/dal/dc/inc/transform.h         | 217 +++++
 drivers/gpu/drm/amd/dal/dc/irq_types.h             | 199 +++++
 .../amd/dal/include/adapter_service_interface.h    | 632 ++++++++++++++
 .../drm/amd/dal/include/adapter_service_types.h    |  71 ++
 .../amd/dal/include/asic_capability_interface.h    |  58 ++
 .../drm/amd/dal/include/asic_capability_types.h    | 134 +++
 drivers/gpu/drm/amd/dal/include/audio_interface.h  | 184 ++++
 drivers/gpu/drm/amd/dal/include/audio_types.h      | 277 ++++++
 .../drm/amd/dal/include/bios_parser_interface.h    |  98 +++
 .../gpu/drm/amd/dal/include/bios_parser_types.h    | 327 +++++++
 drivers/gpu/drm/amd/dal/include/dal_asic_id.h      | 117 +++
 .../gpu/drm/amd/dal/include/dal_register_logger.h  |  43 +
 drivers/gpu/drm/amd/dal/include/dal_types.h        | 305 +++++++
 .../amd/dal/include/dc_clock_generator_interface.h |  77 ++
 drivers/gpu/drm/amd/dal/include/dcs_types.h        | 742 ++++++++++++++++
 drivers/gpu/drm/amd/dal/include/ddc_interface.h    |  74 ++
 .../gpu/drm/amd/dal/include/ddc_service_types.h    | 221 +++++
 .../drm/amd/dal/include/display_clock_interface.h  | 186 ++++
 .../drm/amd/dal/include/display_path_interface.h   | 436 ++++++++++
 drivers/gpu/drm/amd/dal/include/dmcu_interface.h   |  87 ++
 drivers/gpu/drm/amd/dal/include/dmcu_types.h       | 199 +++++
 drivers/gpu/drm/amd/dal/include/dpcd_defs.h        | 873 +++++++++++++++++++
 .../gpu/drm/amd/dal/include/encoder_interface.h    | 278 ++++++
 drivers/gpu/drm/amd/dal/include/fixed31_32.h       | 389 +++++++++
 drivers/gpu/drm/amd/dal/include/fixed32_32.h       |  82 ++
 drivers/gpu/drm/amd/dal/include/gpio_interface.h   |  93 ++
 .../drm/amd/dal/include/gpio_service_interface.h   |  81 ++
 drivers/gpu/drm/amd/dal/include/gpio_types.h       | 341 ++++++++
 drivers/gpu/drm/amd/dal/include/grph_csc_types.h   |  98 +++
 .../drm/amd/dal/include/grph_object_ctrl_defs.h    | 593 +++++++++++++
 drivers/gpu/drm/amd/dal/include/grph_object_defs.h | 328 ++++++++
 drivers/gpu/drm/amd/dal/include/grph_object_id.h   | 277 ++++++
 .../drm/amd/dal/include/hw_sequencer_interface.h   | 388 +++++++++
 .../gpu/drm/amd/dal/include/hw_sequencer_types.h   | 304 +++++++
 drivers/gpu/drm/amd/dal/include/i2caux_interface.h | 127 +++
 drivers/gpu/drm/amd/dal/include/irq_interface.h    |  53 ++
 .../drm/amd/dal/include/irq_service_interface.h    |  55 ++
 .../drm/amd/dal/include/link_service_interface.h   | 202 +++++
 .../gpu/drm/amd/dal/include/link_service_types.h   | 427 ++++++++++
 drivers/gpu/drm/amd/dal/include/logger_interface.h | 153 ++++
 drivers/gpu/drm/amd/dal/include/logger_types.h     | 356 ++++++++
 drivers/gpu/drm/amd/dal/include/scaler_types.h     | 196 +++++
 drivers/gpu/drm/amd/dal/include/set_mode_types.h   | 142 ++++
 drivers/gpu/drm/amd/dal/include/signal_types.h     |  59 ++
 drivers/gpu/drm/amd/dal/include/vector.h           | 150 ++++
 drivers/gpu/drm/amd/dal/include/video_csc_types.h  | 135 +++
 .../gpu/drm/amd/dal/include/video_gamma_types.h    |  57 ++
 74 files changed, 16498 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_helpers.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_status.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_asic_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_register_logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_clock_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_path_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed31_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed32_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/i2caux_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/scaler_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/signal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/vector.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_gamma_types.h

diff --git a/drivers/gpu/drm/amd/dal/dal_services.h b/drivers/gpu/drm/amd/dal/dal_services.h
new file mode 100644
index 000000000000..398e4e559455
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dal_services.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SERVICES_H__
+#define __DAL_SERVICES_H__
+
+/* DC headers*/
+#include "dc/dc_services.h"
+
+#include "dal_power_interface_types.h"
+
+#include "irq_types.h"
+#include "include/dal_types.h"
+
+/* TODO: investigate if it can be removed. */
+/* Undefine DEPRECATED because it conflicts with printk.h */
+#undef DEPRECATED
+
+/*
+ *
+ * interrupt services to register and unregister handlers
+ *
+ */
+
+/* the timer "interrupt" current implementation supports only
+'one-shot' type, and LOW level (asynchronous) context */
+void dal_register_timer_interrupt(
+	struct dc_context *ctx,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *handler_args);
+
+/*
+ *
+ * kernel memory manipulation
+ *
+ */
+
+/* Reallocate memory. The contents will remain unchanged.*/
+void *dc_service_realloc(struct dc_context *ctx, const void *ptr, uint32_t size);
+
+void dc_service_memmove(void *dst, const void *src, uint32_t size);
+
+void dc_service_memset(void *p, int32_t c, uint32_t count);
+
+int32_t dal_memcmp(const void *p1, const void *p2, uint32_t count);
+
+int32_t dal_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count);
+
+/*
+ *
+ * GPU registers access
+ *
+ */
+static inline uint32_t dal_read_reg(
+	const struct dc_context *ctx,
+	uint32_t address)
+{
+	uint32_t value = cgs_read_register(ctx->cgs_device, address);
+
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s 0x%x 0x%x\n", __func__, address, value);
+	}
+#endif
+	return value;
+}
+
+static inline uint32_t get_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (mask & reg_value) >> shift;
+}
+
+#define get_reg_field_value(reg_value, reg_name, reg_field)\
+	get_reg_field_value_ex(\
+		(reg_value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+static inline uint32_t set_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (reg_value & ~mask) | (mask & (value << shift));
+}
+
+#define set_reg_field_value(reg_value, value, reg_name, reg_field)\
+	(reg_value) = set_reg_field_value_ex(\
+		(reg_value),\
+		(value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+static inline void dal_write_reg(
+	const struct dc_context *ctx,
+	uint32_t address,
+	uint32_t value)
+{
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s 0x%x 0x%x\n", __func__, address, value);
+	}
+#endif
+	cgs_write_register(ctx->cgs_device, address, value);
+}
+
+static inline uint32_t dal_read_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index)
+{
+	return cgs_read_ind_register(ctx->cgs_device,addr_space,index);
+}
+
+static inline void dal_write_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index,
+	uint32_t value)
+{
+	cgs_write_ind_register(ctx->cgs_device,addr_space,index,value);
+}
+
+enum platform_method {
+	PM_GET_AVAILABLE_METHODS = 1 << 0,
+	PM_GET_LID_STATE = 1 << 1,
+	PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2
+};
+
+struct platform_info_params {
+	enum platform_method method;
+	void *data;
+};
+
+struct platform_info_brightness_caps {
+	uint8_t ac_level_percentage;
+	uint8_t dc_level_percentage;
+};
+
+struct platform_info_ext_brightness_caps {
+	struct platform_info_brightness_caps basic_caps;
+	struct data_point {
+		uint8_t luminance;
+		uint8_t	signal_level;
+	} data_points[99];
+
+	uint8_t	data_points_num;
+	uint8_t	min_input_signal;
+	uint8_t	max_input_signal;
+};
+
+bool dal_get_platform_info(
+	struct dc_context *ctx,
+	struct platform_info_params *params);
+
+
+static inline uint32_t dal_bios_cmd_table_para_revision(
+	struct dc_context *ctx,
+	uint32_t index)
+{
+	uint8_t frev;
+	uint8_t crev;
+
+	if (cgs_atom_get_cmd_table_revs(
+			ctx->cgs_device,
+			index,
+			&frev,
+			&crev) != 0)
+		return 0;
+
+	return crev;
+}
+
+/* Calls to notification */
+
+/* Notify display manager for hotplug event */
+void dal_notify_hotplug(
+	struct dc_context *ctx,
+	uint32_t display_index,
+	bool is_connected);
+
+
+void dal_notify_setmode_complete(
+	struct dc_context *ctx,
+	uint32_t h_total,
+	uint32_t v_total,
+	uint32_t h_active,
+	uint32_t v_active,
+	uint32_t pix_clk_in_khz);
+
+/* End of notification calls */
+
+/*
+ *
+ * Delay functions.
+ *
+ *
+ */
+
+/* Following the guidance:
+ * https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
+ *
+ * This is a busy wait for nano seconds and should be used only for
+ * extremely short ranges
+ */
+void dal_delay_in_nanoseconds(uint32_t nanoseconds);
+
+
+/*
+ *
+ * atombios services
+ *
+ */
+
+bool dal_exec_bios_cmd_table(
+	struct dc_context *ctx,
+	uint32_t index,
+	void *params);
+
+/*
+ *
+ * print-out services
+ *
+ */
+#define dal_log_to_buffer(buffer, size, fmt, args)\
+	vsnprintf(buffer, size, fmt, args)
+
+long dal_get_pid(void);
+long dal_get_tgid(void);
+
+/*
+ *
+ * general debug capabilities
+ *
+ */
+
+#endif /* __DAL_SERVICES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dal_services_types.h b/drivers/gpu/drm/amd/dal/dal_services_types.h
new file mode 100644
index 000000000000..89c73c651d09
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dal_services_types.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SERVICES_TYPES_H__
+#define __DAL_SERVICES_TYPES_H__
+
+#define INVALID_DISPLAY_INDEX 0xffffffff
+
+#if defined __KERNEL__
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <drm/drmP.h>
+
+#include "cgs_linux.h"
+
+#if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU)
+#define BIGENDIAN_CPU
+#elif defined(__LITTLE_ENDIAN) && !defined(LITTLEENDIAN_CPU)
+#define LITTLEENDIAN_CPU
+#endif
+
+#undef READ
+#undef WRITE
+#undef FRAME_SIZE
+
+#define dal_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__)
+
+#define dal_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__)
+
+#define dal_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__)
+
+#define dal_vlog(fmt, args) vprintk(fmt, args)
+
+#define dal_min(x, y) min(x, y)
+#define dal_max(x, y) max(x, y)
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dc.h b/drivers/gpu/drm/amd/dal/dc/dc.h
new file mode 100644
index 000000000000..61f13bd0af49
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc.h
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2012-14 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DC_INTERFACE_H_
+#define DC_INTERFACE_H_
+
+#include "dc_types.h"
+#include "dal_types.h"
+#include "audio_types.h"
+#include "logger_types.h"
+
+#define MAX_SINKS_PER_LINK 4
+
+/*******************************************************************************
+ * Display Core Interfaces
+ ******************************************************************************/
+struct dc_init_data {
+	struct dc_context *ctx;
+	struct adapter_service *adapter_srv;
+	uint8_t num_virtual_links;
+};
+
+struct dc_caps {
+    uint32_t max_targets;
+    uint32_t max_links;
+    uint32_t max_audios;
+};
+
+void dc_get_caps(const struct dc *dc, struct dc_caps *caps);
+
+struct dc *dc_create(const struct dal_init_data *init_params);
+void dc_destroy(struct dc **dc);
+
+/*******************************************************************************
+ * Surface Interfaces
+ ******************************************************************************/
+
+struct dc_surface {
+	bool visible;
+	bool flip_immediate;
+	struct dc_plane_address address;
+
+	struct scaling_taps scaling_quality;
+	struct rect src_rect;
+	struct rect dst_rect;
+	struct rect clip_rect;
+
+	union plane_size plane_size;
+	struct dc_tiling_info tiling_info;
+	struct plane_colorimetry colorimetry;
+
+	enum surface_pixel_format format;
+	enum dc_rotation_angle rotation;
+	enum plane_stereo_format stereo_format;
+
+	struct gamma_ramp gamma_correction; /* deprecated */
+	struct dc_gamma_ramp gamma;
+};
+
+/*
+ * This structure is filled in by dc_surface_get_status and contains
+ * the last requested address and the currently active address so the called
+ * can determine if there are any outstanding flips
+ */
+struct dc_surface_status {
+	struct dc_plane_address requested_address;
+	struct dc_plane_address current_address;
+	const struct dc_target *dc_target;
+};
+
+/*
+ * Create a new surface with default parameters;
+ */
+struct dc_surface *dc_create_surface(const struct dc *dc);
+const struct dc_surface_status* dc_surface_get_status(
+						struct dc_surface *dc_surface);
+
+void dc_surface_retain(const struct dc_surface *dc_surface);
+void dc_surface_release(const struct dc_surface *dc_surface);
+
+/*
+ * This structure holds a surface address.  There could be multiple addresses
+ * in cases such as Stereo 3D, Planar YUV, etc.  Other per-flip attributes such
+ * as frame durations and DCC format can also be set.
+ */
+struct dc_flip_addrs {
+	struct dc_plane_address address;
+	bool flip_immediate;
+	/* TODO: DCC format info */
+	/* TODO: add flip duration for FreeSync */
+};
+
+/*
+ * Optimized flip address update function.
+ *
+ * After this call:
+ *   Surface addresses and flip attributes are programmed.
+ *   Surface flip occur at next configured time (h_sync or v_sync flip)
+ */
+void dc_flip_surface_addrs(struct dc* dc,
+		const struct dc_surface *const surfaces[],
+		struct dc_flip_addrs flip_addrs[],
+		uint32_t count);
+
+/*
+ * Set up surface attributes and associate to a target
+ * The surfaces parameter is an absolute set of all surface active for the target.
+ * If no surfaces are provided, the target will be blanked; no memory read.
+ * Any flip related attribute changes must be done through this interface.
+ *
+ * After this call:
+ *   Surfaces attributes are programmed and configured to be composed into target.
+ *   This does not trigger a flip.  No surface address is programmed.
+ */
+bool dc_commit_surfaces_to_target(
+		struct dc *dc,
+		struct dc_surface *dc_surfaces[],
+		uint8_t surface_count,
+		struct dc_target *dc_target);
+
+/*******************************************************************************
+ * Target Interfaces
+ ******************************************************************************/
+#define MAX_STREAM_NUM 1
+
+struct dc_target {
+	uint8_t stream_count;
+	const struct dc_stream *streams[MAX_STREAM_NUM];
+};
+
+/*
+ * Target status is returned from dc_target_get_status in order to get the
+ * the IRQ source, current frame counter and currently attached surfaces.
+ */
+struct dc_target_status {
+	enum dc_irq_source page_flip_src;
+	enum dc_irq_source v_update_src;
+	uint32_t cur_frame_count;
+	const struct dc_surface *surfaces[MAX_SURFACE_NUM];
+	uint8_t surface_count;
+};
+
+struct dc_target *dc_create_target_for_streams(
+		struct dc_stream *dc_streams[],
+		uint8_t stream_count);
+
+/*
+ * Get the current target status.
+ */
+const struct dc_target_status *dc_target_get_status(
+					const struct dc_target* dc_target);
+
+void dc_target_retain(struct dc_target *dc_target);
+void dc_target_release(struct dc_target *dc_target);
+void dc_target_log(
+	const struct dc_target *dc_target,
+	struct dal_logger *dal_logger,
+	enum log_major log_major,
+	enum log_minor log_minor);
+
+uint8_t dc_get_current_target_count(const struct dc *dc);
+struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i);
+
+bool dc_target_is_connected_to_sink(
+		const struct dc_target *dc_target,
+		const struct dc_sink *dc_sink);
+
+uint8_t dc_target_get_link_index(const struct dc_target *dc_target);
+uint8_t dc_target_get_controller_id(const struct dc_target *dc_target);
+
+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target);
+enum dc_irq_source dc_target_get_irq_src(
+	const struct dc_target *dc_target, const enum irq_type irq_type);
+
+void dc_target_enable_memory_requests(struct dc_target *target);
+void dc_target_disable_memory_requests(struct dc_target *target);
+
+/*
+ * Structure to store surface/target associations for validation
+ */
+struct dc_validation_set {
+	const struct dc_target *target;
+	const struct dc_surface *surfaces[4];
+	uint8_t surface_count;
+};
+
+/*
+ * This function takes a set of resources and checks that they are cofunctional.
+ *
+ * After this call:
+ *   No hardware is programmed for call.  Only validation is done.
+ */
+bool dc_validate_resources(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count);
+
+/*
+ * Set up streams and links associated to targets to drive sinks
+ * The targets parameter is an absolute set of all active targets.
+ *
+ * After this call:
+ *   Phy, Encoder, Timing Generator are programmed and enabled.
+ *   New targets are enabled with blank stream; no memory read.
+ */
+bool dc_commit_targets(
+		struct dc *dc,
+		struct dc_target *targets[],
+		uint8_t target_count);
+
+/*******************************************************************************
+ * Stream Interfaces
+ ******************************************************************************/
+struct dc_stream {
+	const struct dc_sink *sink;
+	struct dc_crtc_timing timing;
+
+	struct rect src; /* viewport in target space*/
+	struct rect dst; /* stream addressable area */
+
+	struct audio_info audio_info;
+
+	/* TODO: dithering */
+	/* TODO: transfer function (CSC/regamma/gamut remap) */
+	/* TODO: custom INFO packets */
+	/* TODO: DRR/Freesync parameters */
+	/* TODO: ABM info (DMCU) */
+	/* TODO: PSR info */
+	/* TODO: CEA VIC */
+};
+
+/**
+ * Create a new default stream for the requested sink
+ */
+struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink);
+
+void dc_stream_retain(struct dc_stream *dc_stream);
+void dc_stream_release(struct dc_stream *dc_stream);
+
+void dc_update_stream(const struct dc_stream *dc_stream,
+		struct rect *src, struct rect *dst);
+
+/*******************************************************************************
+ * Link Interfaces
+ ******************************************************************************/
+
+/*
+ * A link contains one or more sinks and their connected status.
+ * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported.
+ */
+struct dc_link {
+	const struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK];
+	unsigned int sink_count;
+	const struct dc_sink *local_sink;
+	unsigned int link_index;
+	enum dc_connection_type type;
+	enum signal_type connector_signal;
+	enum dc_irq_source irq_source_hpd;
+	enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse  */
+};
+
+/*
+ * Return an enumerated dc_link.  dc_link order is constant and determined at
+ * boot time.  They cannot be created or destroyed.
+ * Use dc_get_caps() to get number of links.
+ */
+const struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index);
+
+/* Return id of physical connector represented by a dc_link at link_index.*/
+const struct graphics_object_id dc_get_link_id_at_index(
+		struct dc *dc, uint32_t link_index);
+
+/* Set backlight level of an embedded panel (eDP, LVDS). */
+bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level);
+
+/* Request DC to detect if there is a Panel connected.
+ * boot - If this call is during initial boot.
+ * Return false for any type of detection failure or MST detection
+ * true otherwise. True meaning further action is required (status update
+ * and OS notification).
+ */
+bool dc_link_detect(const struct dc_link *dc_link, bool boot);
+
+/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt).
+ * Return:
+ * true - Downstream port status changed. DM should call DC to do the
+ * detection.
+ * false - no change in Downstream port status. No further action required
+ * from DM. */
+bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link);
+
+bool dc_link_add_remote_sink(const struct dc_link *link, struct dc_sink *sink);
+
+void dc_link_remove_remote_sink(
+	const struct dc_link *link,
+	const struct dc_sink *sink);
+
+/* Used by diagnostics for virtual link at the moment */
+void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink);
+
+/*******************************************************************************
+ * Sink Interfaces - A sink corresponds to a display output device
+ ******************************************************************************/
+
+/*
+ * The sink structure contains EDID and other display device properties
+ */
+struct dc_sink {
+	enum signal_type sink_signal;
+	struct dc_edid dc_edid; /* raw edid */
+	struct dc_edid_caps edid_caps; /* parse display caps */
+};
+
+void dc_sink_retain(const struct dc_sink *sink);
+void dc_sink_release(const struct dc_sink *sink);
+
+const struct audio **dc_get_audios(struct dc *dc);
+
+struct dc_sink_init_data {
+	enum signal_type sink_signal;
+	const struct dc_link *link;
+	uint32_t dongle_max_pix_clk;
+	bool converter_disable_audio;
+};
+
+struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params);
+
+
+/*******************************************************************************
+ * Cursor interfaces - To manages the cursor within a target
+ ******************************************************************************/
+/* TODO: Deprecated once we switch to dc_set_cursor_position */
+bool dc_target_set_cursor_attributes(
+	struct dc_target *dc_target,
+	const struct dc_cursor_attributes *attributes);
+
+bool dc_target_set_cursor_position(
+	struct dc_target *dc_target,
+	const struct dc_cursor_position *position);
+
+/* Newer interfaces  */
+struct dc_cursor {
+	struct dc_plane_address address;
+	struct dc_cursor_attributes attributes;
+};
+
+/*
+ * Create a new cursor with default values for a given target.
+ */
+struct dc_cursor *dc_create_cursor_for_target(
+		const struct dc *dc,
+		struct dc_target *dc_target);
+
+/**
+ * Commit cursor attribute changes such as pixel format and dimensions and
+ * surface address.
+ *
+ * After this call:
+ *   Cursor address and format is programmed to the new values.
+ *   Cursor position is unmodified.
+ */
+bool dc_commit_cursor(
+		const struct dc *dc,
+		struct dc_cursor *cursor);
+
+/*
+ * Optimized cursor position update
+ *
+ * After this call:
+ *   Cursor position will be programmed as well as enable/disable bit.
+ */
+bool dc_set_cursor_position(
+		const struct dc *dc,
+		struct dc_cursor *cursor,
+		struct dc_cursor_position *pos);
+
+
+
+/*******************************************************************************
+ * Interrupt interfaces
+ ******************************************************************************/
+enum dc_irq_source dc_interrupt_to_irq_source(
+		struct dc *dc,
+		uint32_t src_id,
+		uint32_t ext_id);
+void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable);
+void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src);
+const enum dc_irq_source dc_get_hpd_irq_source_at_index(
+		struct dc *dc, uint32_t link_index);
+const struct dc_target *dc_get_target_on_irq_source(
+		const struct dc *dc,
+		enum dc_irq_source src);
+
+
+/*******************************************************************************
+ * Power Interfaces
+ ******************************************************************************/
+
+void dc_set_power_state(
+		struct dc *dc,
+		enum dc_acpi_cm_power_state power_state,
+		enum dc_video_power_state video_power_state);
+void dc_resume(const struct dc *dc);
+
+/*******************************************************************************
+ * DDC Interfaces
+ ******************************************************************************/
+
+const struct ddc_service *dc_get_ddc_at_index(
+		struct dc *dc, uint32_t link_index);
+
+/*
+ * DPCD access interfaces
+ */
+
+bool dc_read_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size);
+
+bool dc_write_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		const uint8_t *data,
+	uint32_t size);
+
+
+uint8_t dc_get_dig_index(const struct dc_stream *stream);
+
+enum signal_type  dc_get_display_signal(
+		const struct dc_stream *stream);
+
+enum gpio_ddc_line dc_get_ddc_line(
+		const struct dc_stream *stream);
+
+
+#endif /* DC_INTERFACE_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dc_bios_types.h b/drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
new file mode 100644
index 000000000000..53f047788b31
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DC_BIOS_TYPES_H
+#define DC_BIOS_TYPES_H
+
+/******************************************************************************
+ * Interface file for VBIOS implementations.
+ *
+ * The default implementation is inside DC.
+ * Display Manager (which instantiates DC) has the option to supply it's own
+ * (external to DC) implementation of VBIOS, which will be called by DC, using
+ * this interface.
+ * (The intended use is Diagnostics, but other uses may appear.)
+ *****************************************************************************/
+
+#include "include/bios_parser_types.h"
+
+
+struct dc_vbios_funcs {
+	uint8_t (*get_connectors_number)(struct dc_bios *bios);
+
+	void (*power_down)(struct dc_bios *bios);
+	void (*power_up)(struct dc_bios *bios);
+
+	uint8_t (*get_encoders_number)(struct dc_bios *bios);
+	uint32_t (*get_oem_ddc_lines_number)(struct dc_bios *bios);
+
+	struct graphics_object_id (*get_encoder_id)(
+		struct dc_bios *bios,
+		uint32_t i);
+	struct graphics_object_id (*get_connector_id)(
+		struct dc_bios *bios,
+		uint8_t connector_index);
+	uint32_t (*get_src_number)(
+		struct dc_bios *bios,
+		struct graphics_object_id id);
+	uint32_t (*get_dst_number)(
+		struct dc_bios *bios,
+		struct graphics_object_id id);
+
+	uint32_t (*get_gpio_record)(
+		struct dc_bios *dcb,
+		struct graphics_object_id id,
+		struct bp_gpio_cntl_info *gpio_record,
+		uint32_t record_size);
+
+	enum bp_result (*get_src_obj)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id, uint32_t index,
+		struct graphics_object_id *src_object_id);
+	enum bp_result (*get_dst_obj)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id, uint32_t index,
+		struct graphics_object_id *dest_object_id);
+	enum bp_result (*get_oem_ddc_info)(
+		struct dc_bios *bios,
+		uint32_t index,
+		struct graphics_object_i2c_info *info);
+
+	enum bp_result (*get_i2c_info)(
+		struct dc_bios *dcb,
+		struct graphics_object_id id,
+		struct graphics_object_i2c_info *info);
+
+	enum bp_result (*get_voltage_ddc_info)(
+		struct dc_bios *bios,
+		uint32_t index,
+		struct graphics_object_i2c_info *info);
+	enum bp_result (*get_thermal_ddc_info)(
+		struct dc_bios *bios,
+		uint32_t i2c_channel_id,
+		struct graphics_object_i2c_info *info);
+	enum bp_result (*get_hpd_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id id,
+		struct graphics_object_hpd_info *info);
+	enum bp_result (*get_device_tag)(
+		struct dc_bios *bios,
+		struct graphics_object_id connector_object_id,
+		uint32_t device_tag_index,
+		struct connector_device_tag_info *info);
+	enum bp_result (*get_firmware_info)(
+		struct dc_bios *bios,
+		struct firmware_info *info);
+	enum bp_result (*get_spread_spectrum_info)(
+		struct dc_bios *bios,
+		enum as_signal_type signal,
+		uint32_t index,
+		struct spread_spectrum_info *ss_info);
+	uint32_t (*get_ss_entry_number)(
+		struct dc_bios *bios,
+		enum as_signal_type signal);
+	enum bp_result (*get_embedded_panel_info)(
+		struct dc_bios *bios,
+		struct embedded_panel_info *info);
+	enum bp_result (*enum_embedded_panel_patch_mode)(
+		struct dc_bios *bios,
+		uint32_t index,
+		struct embedded_panel_patch_mode *mode);
+	enum bp_result (*get_gpio_pin_info)(
+		struct dc_bios *bios,
+		uint32_t gpio_id,
+		struct gpio_pin_info *info);
+	enum bp_result (*get_faked_edid_len)(
+		struct dc_bios *bios,
+		uint32_t *len);
+	enum bp_result (*get_faked_edid_buf)(
+		struct dc_bios *bios,
+		uint8_t *buff,
+		uint32_t len);
+	enum bp_result (*get_encoder_cap_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id,
+		struct bp_encoder_cap_info *info);
+	enum bp_result (*get_din_connector_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id id,
+		struct din_connector_info *info);
+
+	bool (*is_lid_open)(
+		struct dc_bios *bios);
+	bool (*is_lid_status_changed)(
+		struct dc_bios *bios);
+	bool (*is_display_config_changed)(
+		struct dc_bios *bios);
+	bool (*is_accelerated_mode)(
+		struct dc_bios *bios);
+	void (*set_scratch_lcd_scale)(
+		struct dc_bios *bios,
+		enum lcd_scale scale);
+	enum lcd_scale  (*get_scratch_lcd_scale)(
+		struct dc_bios *bios);
+	void (*get_bios_event_info)(
+		struct dc_bios *bios,
+		struct bios_event_info *info);
+	void (*update_requested_backlight_level)(
+		struct dc_bios *bios,
+		uint32_t backlight_8bit);
+	uint32_t (*get_requested_backlight_level)(
+		struct dc_bios *bios);
+	void (*take_backlight_control)(
+		struct dc_bios *bios,
+		bool cntl);
+	bool (*is_active_display)(
+		struct dc_bios *bios,
+		enum signal_type signal,
+		const struct connector_device_tag_info *device_tag);
+	enum controller_id (*get_embedded_display_controller_id)(
+		struct dc_bios *bios);
+	uint32_t (*get_embedded_display_refresh_rate)(
+		struct dc_bios *bios);
+	void (*set_scratch_connected)(
+		struct dc_bios *bios,
+		struct graphics_object_id connector_id,
+		bool connected,
+		const struct connector_device_tag_info *device_tag);
+	void (*prepare_scratch_active_and_requested)(
+		struct dc_bios *bios,
+		enum controller_id controller_id,
+		enum signal_type signal,
+		const struct connector_device_tag_info *device_tag);
+	void (*set_scratch_active_and_requested)(
+		struct dc_bios *bios);
+	void (*set_scratch_critical_state)(
+		struct dc_bios *bios,
+		bool state);
+	void (*set_scratch_acc_mode_change)(
+		struct dc_bios *bios);
+
+	bool (*is_device_id_supported)(
+		struct dc_bios *bios,
+		struct device_id id);
+
+	/* COMMANDS */
+
+	enum bp_result (*encoder_control)(
+		struct dc_bios *bios,
+		struct bp_encoder_control *cntl);
+	enum bp_result (*transmitter_control)(
+		struct dc_bios *bios,
+		struct bp_transmitter_control *cntl);
+	enum bp_result (*crt_control)(
+		struct dc_bios *bios,
+		enum engine_id engine_id,
+		bool enable,
+		uint32_t pixel_clock);
+	enum bp_result (*enable_crtc)(
+		struct dc_bios *bios,
+		enum controller_id id,
+		bool enable);
+	enum bp_result (*adjust_pixel_clock)(
+		struct dc_bios *bios,
+		struct bp_adjust_pixel_clock_parameters *bp_params);
+	enum bp_result (*set_pixel_clock)(
+		struct dc_bios *bios,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*set_dce_clock)(
+		struct dc_bios *bios,
+		struct bp_set_dce_clock_parameters *bp_params);
+	enum bp_result (*enable_spread_spectrum_on_ppll)(
+		struct dc_bios *bios,
+		struct bp_spread_spectrum_parameters *bp_params,
+		bool enable);
+	enum bp_result (*program_crtc_timing)(
+		struct dc_bios *bios,
+		struct bp_hw_crtc_timing_parameters *bp_params);
+	enum bp_result (*blank_crtc)(
+		struct dc_bios *bios,
+		struct bp_blank_crtc_parameters *bp_params,
+		bool blank);
+	enum bp_result (*set_overscan)(
+		struct dc_bios *bios,
+		struct bp_hw_crtc_overscan_parameters *bp_params);
+	enum bp_result (*crtc_source_select)(
+		struct dc_bios *bios,
+		struct bp_crtc_source_select *bp_params);
+	enum bp_result (*program_display_engine_pll)(
+		struct dc_bios *bios,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*get_divider_for_target_display_clock)(
+		struct dc_bios *bios,
+		struct bp_display_clock_parameters *bp_params);
+	enum signal_type (*dac_load_detect)(
+		struct dc_bios *bios,
+		struct graphics_object_id encoder,
+		struct graphics_object_id connector,
+		enum signal_type display_signal);
+	enum bp_result (*enable_memory_requests)(
+		struct dc_bios *bios,
+		enum controller_id controller_id,
+		bool enable);
+	enum bp_result (*external_encoder_control)(
+		struct dc_bios *bios,
+		struct bp_external_encoder_control *cntl);
+	enum bp_result (*enable_disp_power_gating)(
+		struct dc_bios *bios,
+		enum controller_id controller_id,
+		enum bp_pipe_control_action action);
+
+	void (*post_init)(struct dc_bios *bios);
+
+	struct integrated_info *(*create_integrated_info)(
+		struct dc_bios *bios);
+
+	void (*destroy_integrated_info)(
+		struct dc_bios *dcb,
+		struct integrated_info **info);
+};
+
+struct dc_bios {
+	const struct dc_vbios_funcs *funcs;
+};
+
+#endif /* DC_BIOS_TYPES_H */
diff --git a/drivers/gpu/drm/amd/dal/dc/dc_types.h b/drivers/gpu/drm/amd/dal/dc/dc_types.h
new file mode 100644
index 000000000000..c238531dc6c0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc_types.h
@@ -0,0 +1,936 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef DC_TYPES_H_
+#define DC_TYPES_H_
+
+#include "dm_services_types.h"
+#include "fixed32_32.h"
+#include "fixed31_32.h"
+#include "irq_types.h"
+
+/* forward declarations */
+struct dc;
+struct dc_surface;
+struct dc_target;
+struct dc_stream;
+struct dc_link;
+struct dc_sink;
+struct dal;
+
+/********************************
+ * Environment definitions
+ ********************************/
+enum dce_environment {
+	DCE_ENV_PRODUCTION_DRV = 0,
+	/* Emulation on FPGA, in "Maximus" System.
+	 * This environment enforces that *only* DC registers accessed.
+	 * (access to non-DC registers will hang FPGA) */
+	DCE_ENV_FPGA_MAXIMUS,
+	/* Emulation on real HW or on FPGA. Used by Diagnostics, enforces
+	 * requirements of Diagnostics team. */
+	DCE_ENV_DIAG
+};
+
+/* Note: use these macro definitions instead of direct comparison! */
+#define IS_FPGA_MAXIMUS_DC(dce_environment) \
+	(dce_environment == DCE_ENV_FPGA_MAXIMUS)
+
+#define IS_DIAG_DC(dce_environment) \
+	(IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG))
+
+/********************************/
+
+#define MAX_EDID_BUFFER_SIZE 512
+#define MAX_SURFACE_NUM 2
+#define NUM_PIXEL_FORMATS 10
+
+enum surface_color_space {
+	SURFACE_COLOR_SPACE_SRGB = 0x0000,
+	SURFACE_COLOR_SPACE_BT601 = 0x0001,
+	SURFACE_COLOR_SPACE_BT709 = 0x0002,
+	SURFACE_COLOR_SPACE_XVYCC_BT601 = 0x0004,
+	SURFACE_COLOR_SPACE_XVYCC_BT709 = 0x0008,
+	SURFACE_COLOR_SPACE_XRRGB = 0x0010
+};
+
+/*Displayable pixel format in fb*/
+enum surface_pixel_format {
+	SURFACE_PIXEL_FORMAT_GRPH_BEGIN = 0,
+	/*TOBE REMOVED paletta 256 colors*/
+	SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS =
+		SURFACE_PIXEL_FORMAT_GRPH_BEGIN,
+	/*16 bpp*/
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB1555,
+	/*16 bpp*/
+	SURFACE_PIXEL_FORMAT_GRPH_RGB565,
+	/*32 bpp*/
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB8888,
+	/*32 bpp swaped*/
+	SURFACE_PIXEL_FORMAT_GRPH_BGRA8888,
+
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010,
+	/*swaped*/
+	SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010,
+	/*TOBE REMOVED swaped, XR_BIAS has no differance
+	 * for pixel layout than previous and we can
+	 * delete this after discusion*/
+	SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS,
+	/*64 bpp */
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616,
+	/*swaped & float*/
+	SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F,
+	/*grow graphics here if necessary */
+
+	SURFACE_PIXEL_FORMAT_VIDEO_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr =
+		SURFACE_PIXEL_FORMAT_VIDEO_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCr,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbY,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrY,
+	/*grow 422/420 video here if necessary */
+	SURFACE_PIXEL_FORMAT_VIDEO_444_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb1555 =
+		SURFACE_PIXEL_FORMAT_VIDEO_444_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_CrYCb565,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb4444,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA5551,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb8888,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb2101010,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA1010102
+	/*grow 444 video here if necessary */
+};
+
+
+/* Pixel format */
+enum pixel_format {
+	/*graph*/
+	PIXEL_FORMAT_UNINITIALIZED,
+	PIXEL_FORMAT_INDEX8,
+	PIXEL_FORMAT_RGB565,
+	PIXEL_FORMAT_ARGB8888,
+	PIXEL_FORMAT_ARGB2101010,
+	PIXEL_FORMAT_ARGB2101010_XRBIAS,
+	PIXEL_FORMAT_FP16,
+	/*video*/
+	PIXEL_FORMAT_420BPP12,
+	PIXEL_FORMAT_422BPP16,
+	PIXEL_FORMAT_444BPP16,
+	PIXEL_FORMAT_444BPP32,
+	/*end of pixel format definition*/
+	PIXEL_FORMAT_INVALID,
+
+	PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8,
+	PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16,
+	PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12,
+	PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_444BPP32,
+	PIXEL_FORMAT_UNKNOWN
+};
+
+enum plane_stereo_format {
+	PLANE_STEREO_FORMAT_NONE = 0,
+	PLANE_STEREO_FORMAT_SIDE_BY_SIDE = 1,
+	PLANE_STEREO_FORMAT_TOP_AND_BOTTOM = 2,
+	PLANE_STEREO_FORMAT_FRAME_ALTERNATE = 3,
+	PLANE_STEREO_FORMAT_ROW_INTERLEAVED = 5,
+	PLANE_STEREO_FORMAT_COLUMN_INTERLEAVED = 6,
+	PLANE_STEREO_FORMAT_CHECKER_BOARD = 7
+};
+
+/* 3D format for view, typically define how L/R eye surface is arranged within
+ * frames
+ */
+enum view_3d_format {
+	VIEW_3D_FORMAT_NONE = 0,
+	VIEW_3D_FORMAT_FRAME_SEQUENTIAL,
+	VIEW_3D_FORMAT_SIDE_BY_SIDE,
+	VIEW_3D_FORMAT_TOP_AND_BOTTOM,
+	VIEW_3D_FORMAT_COUNT,
+	VIEW_3D_FORMAT_FIRST = VIEW_3D_FORMAT_FRAME_SEQUENTIAL
+};
+
+enum dc_pixel_encoding {
+	PIXEL_ENCODING_UNDEFINED,
+	PIXEL_ENCODING_RGB,
+	PIXEL_ENCODING_YCBCR422,
+	PIXEL_ENCODING_YCBCR444,
+	PIXEL_ENCODING_YCBCR420,
+	PIXEL_ENCODING_COUNT
+};
+
+/* TODO: Find way to calculate number of bits
+ *  Please increase if pixel_format enum increases
+ * num  from  PIXEL_FORMAT_INDEX8 to PIXEL_FORMAT_444BPP32
+ */
+
+union large_integer {
+	struct {
+		uint32_t low_part;
+		int32_t high_part;
+	};
+
+	struct {
+		uint32_t low_part;
+		int32_t high_part;
+	} u;
+
+	int64_t quad_part;
+};
+
+#define PHYSICAL_ADDRESS_LOC union large_integer
+
+enum dc_edid_connector_type {
+	EDID_CONNECTOR_UNKNOWN = 0,
+	EDID_CONNECTOR_ANALOG = 1,
+	EDID_CONNECTOR_DIGITAL = 10,
+	EDID_CONNECTOR_DVI = 11,
+	EDID_CONNECTOR_HDMIA = 12,
+	EDID_CONNECTOR_MDDI = 14,
+	EDID_CONNECTOR_DISPLAYPORT = 15
+};
+
+enum dc_edid_status {
+	EDID_OK,
+	EDID_BAD_INPUT,
+	EDID_NO_RESPONSE,
+	EDID_BAD_CHECKSUM,
+};
+
+struct plane_colorimetry {
+	enum surface_color_space color_space;
+	bool limited_range;
+};
+
+/* audio capability from EDID*/
+struct dc_cea_audio_mode {
+	uint8_t format_code; /* ucData[0] [6:3]*/
+	uint8_t channel_count; /* ucData[0] [2:0]*/
+	uint8_t sample_rate; /* ucData[1]*/
+	union {
+		uint8_t sample_size; /* for LPCM*/
+		/*  for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/
+		uint8_t max_bit_rate;
+		uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/
+	};
+};
+
+struct dc_edid {
+	uint32_t length;
+	uint8_t raw_edid[MAX_EDID_BUFFER_SIZE];
+};
+
+/* When speaker location data block is not available, DEFAULT_SPEAKER_LOCATION
+ * is used. In this case we assume speaker location are: front left, front
+ * right and front center. */
+#define DEFAULT_SPEAKER_LOCATION 5
+
+#define DC_MAX_AUDIO_DESC_COUNT 16
+
+#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20
+
+struct dc_edid_caps {
+	/* sink identification */
+	uint16_t manufacturer_id;
+	uint16_t product_id;
+	uint32_t serial_number;
+	uint8_t manufacture_week;
+	uint8_t manufacture_year;
+	uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS];
+
+	/* audio caps */
+	uint8_t speaker_flags;
+	uint32_t audio_mode_count;
+	struct dc_cea_audio_mode audio_modes[DC_MAX_AUDIO_DESC_COUNT];
+	uint32_t audio_latency;
+	uint32_t video_latency;
+
+	/*HDMI 2.0 caps*/
+	uint8_t lte_340mcsc_scramble;
+};
+
+struct scaling_taps {
+	uint32_t v_taps;
+	uint32_t h_taps;
+	uint32_t v_taps_c;
+	uint32_t h_taps_c;
+};
+
+struct scaling_ratios {
+	struct fixed31_32 horz;
+	struct fixed31_32 vert;
+	struct fixed31_32 horz_c;
+	struct fixed31_32 vert_c;
+};
+
+struct rect {
+	uint32_t x;
+	uint32_t y;
+	uint32_t width;
+	uint32_t height;
+};
+
+struct view {
+	uint32_t width;
+	uint32_t height;
+};
+
+struct dc_resolution {
+	uint32_t width;
+	uint32_t height;
+};
+
+
+struct dc_mode_flags {
+	/* note: part of refresh rate flag*/
+	uint32_t INTERLACE :1;
+	/* native display timing*/
+	uint32_t NATIVE :1;
+	/* preferred is the recommended mode, one per display */
+	uint32_t PREFERRED :1;
+	/* true if this mode should use reduced blanking timings
+	 *_not_ related to the Reduced Blanking adjustment*/
+	uint32_t REDUCED_BLANKING :1;
+	/* note: part of refreshrate flag*/
+	uint32_t VIDEO_OPTIMIZED_RATE :1;
+	/* should be reported to upper layers as mode_flags*/
+	uint32_t PACKED_PIXEL_FORMAT :1;
+	/*< preferred view*/
+	uint32_t PREFERRED_VIEW :1;
+	/* this timing should be used only in tiled mode*/
+	uint32_t TILED_MODE :1;
+	uint32_t DSE_MODE :1;
+	/* Refresh rate divider when Miracast sink is using a
+	 different rate than the output display device
+	 Must be zero for wired displays and non-zero for
+	 Miracast displays*/
+	uint32_t MIRACAST_REFRESH_DIVIDER;
+};
+
+struct dc_crtc_timing_flags {
+	uint32_t INTERLACE :1;
+	uint32_t HSYNC_POSITIVE_POLARITY :1; /* when set to 1,
+	 it is positive polarity --reversed with dal1 or video bios define*/
+	uint32_t VSYNC_POSITIVE_POLARITY :1; /* when set to 1,
+	 it is positive polarity --reversed with dal1 or video bios define*/
+
+	uint32_t HORZ_COUNT_BY_TWO:1;
+
+	uint32_t EXCLUSIVE_3D :1; /* if this bit set,
+	 timing can be driven in 3D format only
+	 and there is no corresponding 2D timing*/
+	uint32_t RIGHT_EYE_3D_POLARITY :1; /* 1 - means right eye polarity
+	 (right eye = '1', left eye = '0') */
+	uint32_t SUB_SAMPLE_3D :1; /* 1 - means left/right  images subsampled
+	 when mixed into 3D image. 0 - means summation (3D timing is doubled)*/
+	uint32_t USE_IN_3D_VIEW_ONLY :1; /* Do not use this timing in 2D View,
+	 because corresponding 2D timing also present in the list*/
+	uint32_t STEREO_3D_PREFERENCE :1; /* Means this is 2D timing
+	 and we want to match priority of corresponding 3D timing*/
+	uint32_t Y_ONLY :1;
+
+	uint32_t YCBCR420 :1; /* TODO: shouldn't need this flag, should be a separate pixel format */
+	uint32_t DTD_COUNTER :5; /* values 1 to 16 */
+
+	/* HDMI 2.0 - Support scrambling for TMDS character
+	 * rates less than or equal to 340Mcsc */
+	uint32_t LTE_340MCSC_SCRAMBLE:1;
+
+};
+
+enum dc_timing_standard {
+	TIMING_STANDARD_UNDEFINED,
+	TIMING_STANDARD_DMT,
+	TIMING_STANDARD_GTF,
+	TIMING_STANDARD_CVT,
+	TIMING_STANDARD_CVT_RB,
+	TIMING_STANDARD_CEA770,
+	TIMING_STANDARD_CEA861,
+	TIMING_STANDARD_HDMI,
+	TIMING_STANDARD_TV_NTSC,
+	TIMING_STANDARD_TV_NTSC_J,
+	TIMING_STANDARD_TV_PAL,
+	TIMING_STANDARD_TV_PAL_M,
+	TIMING_STANDARD_TV_PAL_CN,
+	TIMING_STANDARD_TV_SECAM,
+	TIMING_STANDARD_EXPLICIT,
+	/*!< For explicit timings from EDID, VBIOS, etc.*/
+	TIMING_STANDARD_USER_OVERRIDE,
+	/*!< For mode timing override by user*/
+	TIMING_STANDARD_MAX
+};
+
+enum dc_aspect_ratio {
+	ASPECT_RATIO_NO_DATA,
+	ASPECT_RATIO_4_3,
+	ASPECT_RATIO_16_9,
+	ASPECT_RATIO_64_27,
+	ASPECT_RATIO_256_135,
+	ASPECT_RATIO_FUTURE
+};
+
+enum dc_color_depth {
+	COLOR_DEPTH_UNDEFINED,
+	COLOR_DEPTH_666,
+	COLOR_DEPTH_888,
+	COLOR_DEPTH_101010,
+	COLOR_DEPTH_121212,
+	COLOR_DEPTH_141414,
+	COLOR_DEPTH_161616,
+	COLOR_DEPTH_COUNT
+};
+
+enum dc_timing_3d_format {
+	TIMING_3D_FORMAT_NONE,
+	TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/
+	TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/
+	TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/
+	/* for active DP-HDMI dongle*/
+	TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/
+	TIMING_3D_FORMAT_HW_FRAME_PACKING,
+	TIMING_3D_FORMAT_SW_FRAME_PACKING,
+	TIMING_3D_FORMAT_ROW_INTERLEAVE,
+	TIMING_3D_FORMAT_COLUMN_INTERLEAVE,
+	TIMING_3D_FORMAT_PIXEL_INTERLEAVE,
+	TIMING_3D_FORMAT_SIDE_BY_SIDE,
+	TIMING_3D_FORMAT_TOP_AND_BOTTOM,
+	TIMING_3D_FORMAT_SBS_SW_PACKED,
+	/* Side-by-side, packed by application/driver into 2D frame*/
+	TIMING_3D_FORMAT_TB_SW_PACKED,
+	/* Top-and-bottom, packed by application/driver into 2D frame*/
+
+	TIMING_3D_FORMAT_MAX,
+};
+
+enum dc_timing_source {
+	TIMING_SOURCE_UNDEFINED,
+
+	/* explicitly specifed by user, most important*/
+	TIMING_SOURCE_USER_FORCED,
+	TIMING_SOURCE_USER_OVERRIDE,
+	TIMING_SOURCE_CUSTOM,
+	TIMING_SOURCE_EXPLICIT,
+
+	/* explicitly specified by the display device, more important*/
+	TIMING_SOURCE_EDID_CEA_SVD_3D,
+	TIMING_SOURCE_EDID_CEA_SVD_PREFERRED,
+	TIMING_SOURCE_EDID_CEA_SVD_420,
+	TIMING_SOURCE_EDID_DETAILED,
+	TIMING_SOURCE_EDID_ESTABLISHED,
+	TIMING_SOURCE_EDID_STANDARD,
+	TIMING_SOURCE_EDID_CEA_SVD,
+	TIMING_SOURCE_EDID_CVT_3BYTE,
+	TIMING_SOURCE_EDID_4BYTE,
+	TIMING_SOURCE_VBIOS,
+	TIMING_SOURCE_CV,
+	TIMING_SOURCE_TV,
+	TIMING_SOURCE_HDMI_VIC,
+
+	/* implicitly specified by display device, still safe but less important*/
+	TIMING_SOURCE_DEFAULT,
+
+	/* only used for custom base modes */
+	TIMING_SOURCE_CUSTOM_BASE,
+
+	/* these timing might not work, least important*/
+	TIMING_SOURCE_RANGELIMIT,
+	TIMING_SOURCE_OS_FORCED,
+	TIMING_SOURCE_IMPLICIT,
+
+	/* only used by default mode list*/
+	TIMING_SOURCE_BASICMODE,
+
+	TIMING_SOURCE_COUNT
+};
+
+enum dc_timing_support_method {
+	TIMING_SUPPORT_METHOD_UNDEFINED,
+	TIMING_SUPPORT_METHOD_EXPLICIT,
+	TIMING_SUPPORT_METHOD_IMPLICIT,
+	TIMING_SUPPORT_METHOD_NATIVE
+};
+
+struct dc_mode_info {
+	uint32_t pixel_width;
+	uint32_t pixel_height;
+	uint32_t field_rate;
+	/* Vertical refresh rate for progressive modes.
+	* Field rate for interlaced modes.*/
+
+	enum dc_timing_standard timing_standard;
+	enum dc_timing_source timing_source;
+	struct dc_mode_flags flags;
+};
+
+/* TODO: assess necessity*/
+/*scanning type*/
+enum scanning_type {
+	SCANNING_TYPE_NODATA = 0,
+	SCANNING_TYPE_OVERSCAN,
+	SCANNING_TYPE_UNDERSCAN,
+	SCANNING_TYPE_FUTURE,
+	SCANNING_TYPE_UNDEFINED
+};
+
+struct dc_crtc_timing {
+	uint32_t h_total;
+	uint32_t h_border_left;
+	uint32_t h_addressable;
+	uint32_t h_border_right;
+	uint32_t h_front_porch;
+	uint32_t h_sync_width;
+
+	uint32_t v_total;
+	uint32_t v_border_top;
+	uint32_t v_addressable;
+	uint32_t v_border_bottom;
+	uint32_t v_front_porch;
+	uint32_t v_sync_width;
+
+	uint32_t pix_clk_khz;
+
+	uint32_t vic;
+	uint32_t hdmi_vic;
+	enum dc_timing_standard timing_standard;
+	enum dc_timing_3d_format timing_3d_format;
+	enum dc_color_depth display_color_depth;
+	enum dc_pixel_encoding pixel_encoding;
+	enum dc_aspect_ratio aspect_ratio;
+	enum scanning_type scan_type;
+
+	struct dc_crtc_timing_flags flags;
+};
+
+struct dc_mode_timing {
+	struct dc_mode_info mode_info;
+	struct dc_crtc_timing crtc_timing;
+};
+
+/* Rotation angle */
+enum dc_rotation_angle {
+	ROTATION_ANGLE_0 = 0,
+	ROTATION_ANGLE_90,
+	ROTATION_ANGLE_180,
+	ROTATION_ANGLE_270,
+	ROTATION_ANGLE_COUNT
+};
+
+struct dc_cursor_position {
+	uint32_t x;
+	uint32_t y;
+
+	uint32_t x_origin;
+	uint32_t y_origin;
+
+	/*
+	 * This parameter indicates whether HW cursor should be enabled
+	 */
+	bool enable;
+
+	/*
+	 * This parameter indicates whether cursor hot spot should be
+	 * programmed
+	 */
+	bool hot_spot_enable;
+};
+
+/* This enum is for programming CURSOR_MODE register field. */
+/* What this register should be programmed to depends on */
+/* OS requested cursor shape flags */
+/* and what we stored in the cursor surface. */
+enum dc_cursor_color_format {
+	CURSOR_MODE_MONO,
+	CURSOR_MODE_COLOR_1BIT_AND,
+	CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA,
+	CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA
+};
+
+union dc_cursor_attribute_flags {
+	struct {
+		uint32_t ENABLE_MAGNIFICATION:1;
+		uint32_t INVERSE_TRANSPARENT_CLAMPING:1;
+		uint32_t HORIZONTAL_MIRROR:1;
+		uint32_t VERTICAL_MIRROR:1;
+		uint32_t RESERVED:28;
+	} bits;
+	uint32_t value;
+};
+
+/* This is all the parameters required by DAL in order to */
+/* update the cursor attributes, */
+/* including the new cursor image surface address, size, */
+/* hotspot location, color format, etc. */
+struct dc_cursor_attributes {
+	PHYSICAL_ADDRESS_LOC address;
+
+	/* Width and height should correspond to cursor surface width x heigh */
+	uint32_t width;
+	uint32_t height;
+	uint32_t x_hot;
+	uint32_t y_hot;
+
+	enum dc_cursor_color_format color_format;
+
+	/* In case we support HW Cursor rotation in the future */
+	enum dc_rotation_angle rotation_angle;
+
+	union dc_cursor_attribute_flags attribute_flags;
+
+};
+
+
+enum dc_plane_addr_type {
+	PLN_ADDR_TYPE_GRAPHICS = 0,
+	PLN_ADDR_TYPE_GRPH_STEREO,
+	PLN_ADDR_TYPE_VIDEO_PROGRESSIVE,
+};
+
+struct dc_plane_address {
+	enum dc_plane_addr_type type;
+	union {
+		struct{
+			PHYSICAL_ADDRESS_LOC addr;
+		} grph;
+
+		/*stereo*/
+		struct {
+			PHYSICAL_ADDRESS_LOC left_addr;
+			PHYSICAL_ADDRESS_LOC right_addr;
+		} grph_stereo;
+
+		/*video  progressive*/
+		struct {
+			PHYSICAL_ADDRESS_LOC chroma_addr;
+			PHYSICAL_ADDRESS_LOC luma_addr;
+		} video_progressive;
+	};
+};
+
+enum dc_power_state {
+	DC_POWER_STATE_ON = 1,
+	DC_POWER_STATE_STANDBY,
+	DC_POWER_STATE_SUSPEND,
+	DC_POWER_STATE_OFF
+};
+
+/* DC PowerStates */
+enum dc_video_power_state {
+	DC_VIDEO_POWER_UNSPECIFIED = 0,
+	DC_VIDEO_POWER_ON = 1,
+	DC_VIDEO_POWER_STANDBY,
+	DC_VIDEO_POWER_SUSPEND,
+	DC_VIDEO_POWER_OFF,
+	DC_VIDEO_POWER_HIBERNATE,
+	DC_VIDEO_POWER_SHUTDOWN,
+	DC_VIDEO_POWER_ULPS,	/* BACO or Ultra-Light-Power-State */
+	DC_VIDEO_POWER_AFTER_RESET,
+	DC_VIDEO_POWER_MAXIMUM
+};
+
+enum dc_acpi_cm_power_state {
+	DC_ACPI_CM_POWER_STATE_D0 = 1,
+	DC_ACPI_CM_POWER_STATE_D1 = 2,
+	DC_ACPI_CM_POWER_STATE_D2 = 4,
+	DC_ACPI_CM_POWER_STATE_D3 = 8
+};
+
+struct view_port_alignment {
+	uint8_t x_width_size_alignment;
+	uint8_t y_height_size_alignment;
+	uint8_t x_start_alignment;
+	uint8_t y_start_alignment;
+};
+
+enum dc_connection_type {
+	dc_connection_none,
+	dc_connection_single,
+	dc_connection_mst_branch,
+	dc_connection_active_dongle
+};
+
+/*
+ * Gamma ramp representation in DC
+ *
+ * A gamma ramp is just a curve defined within the range of [min, max] with
+ * arbitrary precision.
+ *
+ * DM is responsible for providing DC with an interface to obtain any y value
+ * within that range with a selected precision.
+ *
+ * bit32 ------------------------------------------------- bit 0
+ *       [  padding  ][ exponent bits ][  fraction bits  ]
+ *
+ * DC specifies the input x value and precision to the callback function
+ * get_gamma_value as well as providing the context and DM returns the y
+ * value.
+ *
+ * If fraction_bits + exponent_bits exceed width of 32 bits, get_gamma_value
+ * returns 0.  If x is outside the bounds of [min, max], get_gamma_value
+ * returns 0.
+ *
+ */
+/* TODO: Deprecated */
+enum {
+	RGB_256X3X16 = 256,
+	DX_GAMMA_RAMP_MAX = 1025
+};
+
+enum gamma_ramp_type {
+	GAMMA_RAMP_UNINITIALIZED = 0,
+	GAMMA_RAMP_DEFAULT,
+	GAMMA_RAMP_RBG256X3X16,
+	GAMMA_RAMP_DXGI_1,
+};
+
+struct dxgi_rgb {
+	struct fixed32_32 red;
+	struct fixed32_32 green;
+	struct fixed32_32 blue;
+};
+
+struct gamma_ramp_dxgi_1 {
+	struct dxgi_rgb scale;
+	struct dxgi_rgb offset;
+	struct dxgi_rgb gamma_curve[DX_GAMMA_RAMP_MAX];
+};
+
+struct gamma_ramp_rgb256x3x16 {
+	uint16_t red[RGB_256X3X16];
+	uint16_t green[RGB_256X3X16];
+	uint16_t blue[RGB_256X3X16];
+};
+
+struct gamma_ramp {
+	enum gamma_ramp_type type;
+	union {
+		struct gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16;
+		struct gamma_ramp_dxgi_1 gamma_ramp_dxgi1;
+	};
+	uint32_t size;
+};
+
+
+struct dc_gamma_ramp {
+	uint32_t (*get_gamma_value) (
+			void *context,
+			uint8_t exponent_bits,
+			uint8_t fraction_bits,
+			uint32_t x);
+	void *context;
+	uint32_t min;
+	uint32_t max;
+};
+
+struct dc_csc_adjustments {
+	struct fixed31_32 contrast;
+	struct fixed31_32 saturation;
+	struct fixed31_32 brightness;
+	struct fixed31_32 hue;
+};
+
+
+enum {
+	MAX_LANES = 2,
+	MAX_COFUNC_PATH = 6,
+	LAYER_INDEX_PRIMARY = -1,
+};
+
+/* Scaling format */
+enum scaling_transformation {
+	SCALING_TRANSFORMATION_UNINITIALIZED,
+	SCALING_TRANSFORMATION_IDENTITY = 0x0001,
+	SCALING_TRANSFORMATION_CENTER_TIMING = 0x0002,
+	SCALING_TRANSFORMATION_FULL_SCREEN_SCALE = 0x0004,
+	SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE = 0x0008,
+	SCALING_TRANSFORMATION_DAL_DECIDE = 0x0010,
+	SCALING_TRANSFORMATION_INVALID = 0x80000000,
+
+	/* Flag the first and last */
+	SCALING_TRANSFORMATION_BEGING = SCALING_TRANSFORMATION_IDENTITY,
+	SCALING_TRANSFORMATION_END =
+		SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE
+};
+
+struct view_stereo_3d_support {
+	enum view_3d_format format;
+	struct {
+		uint32_t CLONE_MODE:1;
+		uint32_t SCALING:1;
+		uint32_t SINGLE_FRAME_SW_PACKED:1;
+	} features;
+};
+
+enum tiling_mode {
+	TILING_MODE_INVALID,
+	TILING_MODE_LINEAR,
+	TILING_MODE_TILED,
+	TILING_MODE_COUNT
+};
+
+struct view_position {
+	uint32_t x;
+	uint32_t y;
+};
+
+struct render_mode {
+	struct view view;
+	enum pixel_format pixel_format;
+};
+
+struct pixel_format_support {
+	bool INDEX8 :1;
+	bool RGB565 :1;
+	bool ARGB8888 :1;
+	bool ARGB2101010 :1;
+	bool ARGB2101010_XRBIAS :1;
+	bool FP16 :1;
+};
+
+struct stereo_3d_view {
+	enum view_3d_format view_3d_format;
+	union {
+		uint32_t raw;
+		struct /*stereo_3d_view_flags*/
+		{
+			bool SINGLE_FRAME_SW_PACKED :1;
+			bool EXCLUSIVE_3D :1;
+		} bits;
+	} flags;
+};
+
+/* TODO: These values come from hardware spec. We need to readdress this
+ * if they ever change.
+ */
+enum array_mode_values {
+	DC_ARRAY_UNDEFINED = 0,
+	DC_ARRAY_1D_TILED_THIN1 = 0x2,
+	DC_ARRAY_2D_TILED_THIN1 = 0x4,
+};
+
+
+enum tile_mode_values {
+	DC_ADDR_SURF_MICRO_TILING_DISPLAY = 0x0,
+	DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1,
+};
+
+enum tile_split_values {
+	DC_DISPLAY_MICRO_TILING = 0x0,
+	DC_THIN_MICRO_TILING = 0x1,
+	DC_DEPTH_MICRO_TILING = 0x2,
+	DC_ROTATED_MICRO_TILING = 0x3,
+};
+
+struct dc_tiling_info {
+
+	/* Specifies the number of memory banks for tiling
+	 *	purposes.
+	 * Only applies to 2D and 3D tiling modes.
+	 *	POSSIBLE VALUES: 2,4,8,16
+	 */
+	unsigned int num_banks;
+	/* Specifies the number of tiles in the x direction
+	 *	to be incorporated into the same bank.
+	 * Only applies to 2D and 3D tiling modes.
+	 *	POSSIBLE VALUES: 1,2,4,8
+	 */
+	unsigned int bank_width;
+	/* Specifies the number of tiles in the y direction to
+	 *	be incorporated into the same bank.
+	 * Only applies to 2D and 3D tiling modes.
+	 *	POSSIBLE VALUES: 1,2,4,8
+	 */
+	unsigned int bank_height;
+	/* Specifies the macro tile aspect ratio. Only applies
+	 * to 2D and 3D tiling modes.
+	 */
+	unsigned int tile_aspect;
+	/* Specifies the number of bytes that will be stored
+	 *	contiguously for each tile.
+	 * If the tile data requires more storage than this
+	 *	amount, it is split into multiple slices.
+	 * This field must not be larger than
+	 *	GB_ADDR_CONFIG.DRAM_ROW_SIZE.
+	 * Only applies to 2D and 3D tiling modes.
+	 * For color render targets, TILE_SPLIT >= 256B.
+	 */
+	enum tile_split_values tile_split;
+	/* Specifies the addressing within a tile.
+	 *	0x0 - DISPLAY_MICRO_TILING
+	 *	0x1 - THIN_MICRO_TILING
+	 *	0x2 - DEPTH_MICRO_TILING
+	 *	0x3 - ROTATED_MICRO_TILING
+	 */
+	enum tile_mode_values tile_mode;
+	/* Specifies the number of pipes and how they are
+	 *	interleaved in the surface.
+	 * Refer to memory addressing document for complete
+	 *	details and constraints.
+	 */
+	unsigned int pipe_config;
+	/* Specifies the tiling mode of the surface.
+	 * THIN tiles use an 8x8x1 tile size.
+	 * THICK tiles use an 8x8x4 tile size.
+	 * 2D tiling modes rotate banks for successive Z slices
+	 * 3D tiling modes rotate pipes and banks for Z slices
+	 * Refer to memory addressing document for complete
+	 *	details and constraints.
+	 */
+	enum array_mode_values array_mode;
+};
+
+union plane_size {
+	/* Grph or Video will be selected
+	 * based on format above:
+	 * Use Video structure if
+	 * format >= DalPixelFormat_VideoBegin
+	 * else use Grph structure
+	 */
+	struct {
+		struct rect surface_size;
+		/* Graphic surface pitch in pixels.
+		 * In LINEAR_GENERAL mode, pitch
+		 * is 32 pixel aligned.
+		 */
+		uint32_t surface_pitch;
+	} grph;
+
+	struct {
+		struct rect luma_size;
+		/* Graphic surface pitch in pixels.
+		 * In LINEAR_GENERAL mode, pitch is
+		 * 32 pixel aligned.
+		 */
+		uint32_t luma_pitch;
+
+		struct rect chroma_size;
+		/* Graphic surface pitch in pixels.
+		 * In LINEAR_GENERAL mode, pitch is
+		 * 32 pixel aligned.
+		 */
+		uint32_t chroma_pitch;
+	} video;
+};
+
+#endif /* DC_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_helpers.h b/drivers/gpu/drm/amd/dal/dc/dm_helpers.h
new file mode 100644
index 000000000000..b6ce51080b86
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dm_helpers.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/**
+ * This file defines helper functions provided by the Display Manager to
+ * Display Core.
+ */
+#ifndef __DM_HELPERS__
+#define __DM_HELPERS__
+
+#include "dc_types.h"
+#include "dc.h"
+
+struct dp_mst_stream_allocation_table;
+
+enum dc_edid_status dm_helpers_parse_edid_caps(
+	struct dc_context *ctx,
+	const struct dc_edid *edid,
+	struct dc_edid_caps *edid_caps);
+
+/*
+ * Writes payload allocation table in immediate downstream device.
+ */
+bool dm_helpers_dp_mst_write_payload_allocation_table(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		struct dp_mst_stream_allocation_table *proposed_table,
+		bool enable);
+
+/*
+ * Polls for ACT (allocation change trigger) handled and
+ */
+bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+		struct dc_context *ctx,
+		const struct dc_stream *stream);
+/*
+ * Sends ALLOCATE_PAYLOAD message.
+ */
+bool dm_helpers_dp_mst_send_payload_allocation(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		bool enable);
+
+void dm_helpers_dp_mst_handle_mst_hpd_rx_irq(
+		void *param);
+
+bool dm_helpers_dp_mst_start_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		bool boot);
+
+void dm_helpers_dp_mst_stop_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link);
+
+/**
+ * OS specific aux read callback.
+ */
+bool dm_helper_dp_read_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size);
+
+/**
+ * OS specific aux write callback.
+ */
+bool dm_helper_dp_write_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t size);
+
+#endif /* __DM_HELPERS__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services.h b/drivers/gpu/drm/amd/dal/dc/dm_services.h
new file mode 100644
index 000000000000..206c0b7df7c6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dm_services.h
@@ -0,0 +1,485 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/**
+ * This file defines external dependencies of Display Core.
+ */
+
+#ifndef __DM_SERVICES_H__
+
+#define __DM_SERVICES_H__
+
+/* TODO: remove when DC is complete. */
+#include "dm_services_types.h"
+#include "logger_interface.h"
+#include "include/dal_types.h"
+#include "irq_types.h"
+#include "link_service_types.h"
+
+#undef DEPRECATED
+
+/* if the pointer is not NULL, the allocated memory is zeroed */
+void *dm_alloc(struct dc_context *ctx, uint32_t size);
+
+/* reallocate memory. The contents will remain unchanged.*/
+void *dm_realloc(struct dc_context *ctx, const void *ptr, uint32_t size);
+
+void dm_free(struct dc_context *ctx, void *p);
+
+void dm_memset(void *p, int32_t c, uint32_t count);
+
+void dm_memmove(void *dst, const void *src, uint32_t size);
+
+int32_t dm_memcmp(const void *p1, const void *p2, uint32_t count);
+
+int32_t dm_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count);
+
+irq_handler_idx dm_register_interrupt(
+	struct dc_context *ctx,
+	struct dc_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *handler_args);
+
+void dm_unregister_interrupt(
+	struct dc_context *ctx,
+	enum dc_irq_source irq_source,
+	irq_handler_idx handler_idx);
+
+/*
+ *
+ * GPU registers access
+ *
+ */
+
+#define dm_read_reg(ctx, address)	\
+		dm_read_reg_func(ctx, address, __func__)
+
+static inline uint32_t dm_read_reg_func(
+	const struct dc_context *ctx,
+	uint32_t address,
+	const char *func_name)
+{
+	uint32_t value = cgs_read_register(ctx->cgs_device, address);
+
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s DC_READ_REG: 0x%x 0x%x\n", func_name, address, value);
+	}
+#endif
+	return value;
+}
+
+#define dm_write_reg(ctx, address, value)	\
+	dm_write_reg_func(ctx, address, value, __func__)
+
+static inline void dm_write_reg_func(
+	const struct dc_context *ctx,
+	uint32_t address,
+	uint32_t value,
+	const char *func_name)
+{
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s DC_WRITE_REG: 0x%x 0x%x\n", func_name, address, value);
+	}
+#endif
+	cgs_write_register(ctx->cgs_device, address, value);
+}
+
+static inline uint32_t dm_read_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index)
+{
+	return cgs_read_ind_register(ctx->cgs_device, addr_space, index);
+}
+
+static inline void dm_write_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index,
+	uint32_t value)
+{
+	cgs_write_ind_register(ctx->cgs_device, addr_space, index, value);
+}
+
+static inline uint32_t get_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (mask & reg_value) >> shift;
+}
+
+#define get_reg_field_value(reg_value, reg_name, reg_field)\
+	get_reg_field_value_ex(\
+		(reg_value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+static inline uint32_t set_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (reg_value & ~mask) | (mask & (value << shift));
+}
+
+#define set_reg_field_value(reg_value, value, reg_name, reg_field)\
+	(reg_value) = set_reg_field_value_ex(\
+		(reg_value),\
+		(value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+/*
+ * atombios services
+ */
+
+bool dm_exec_bios_cmd_table(
+	struct dc_context *ctx,
+	uint32_t index,
+	void *params);
+
+#ifdef BUILD_DAL_TEST
+uint32_t dm_bios_cmd_table_para_revision(
+struct dc_context *ctx,
+	uint32_t index);
+
+bool dm_bios_cmd_table_revision(
+	struct dc_context *ctx,
+	uint32_t index,
+	uint8_t *frev,
+	uint8_t *crev);
+#endif
+
+#ifndef BUILD_DAL_TEST
+static inline uint32_t dm_bios_cmd_table_para_revision(
+	struct dc_context *ctx,
+	uint32_t index)
+{
+	uint8_t frev;
+	uint8_t crev;
+
+	if (cgs_atom_get_cmd_table_revs(
+			ctx->cgs_device,
+			index,
+			&frev,
+			&crev) != 0)
+		return 0;
+
+	return crev;
+}
+#else
+uint32_t dm_bios_cmd_table_para_revision(
+		struct dc_context *ctx,
+		uint32_t index);
+#endif
+
+/**************************************
+ * Power Play (PP) interfaces
+ **************************************/
+
+enum dal_to_power_clocks_state {
+	PP_CLOCKS_STATE_INVALID,
+	PP_CLOCKS_STATE_ULTRA_LOW,
+	PP_CLOCKS_STATE_LOW,
+	PP_CLOCKS_STATE_NOMINAL,
+	PP_CLOCKS_STATE_PERFORMANCE
+};
+
+/* clocks in khz */
+struct dal_to_power_info {
+	enum dal_to_power_clocks_state required_clock;
+	uint32_t min_sclk;
+	uint32_t min_mclk;
+	uint32_t min_deep_sleep_sclk;
+};
+
+/* clocks in khz */
+struct power_to_dal_info {
+	uint32_t min_sclk;
+	uint32_t max_sclk;
+	uint32_t min_mclk;
+	uint32_t max_mclk;
+};
+
+/* clocks in khz */
+struct dal_system_clock_range {
+	uint32_t min_sclk;
+	uint32_t max_sclk;
+
+	uint32_t min_mclk;
+	uint32_t max_mclk;
+
+	uint32_t min_dclk;
+	uint32_t max_dclk;
+
+	/* Wireless Display */
+	uint32_t min_eclk;
+	uint32_t max_eclk;
+};
+
+/* clocks in khz */
+struct dal_to_power_dclk {
+	uint32_t optimal; /* input: best optimizes for stutter efficiency */
+	uint32_t minimal; /* input: the lowest clk that DAL can support */
+	uint32_t established; /* output: the actually set one */
+};
+
+/* DAL calls this function to notify PP about clocks it needs for the Mode Set.
+ * This is done *before* it changes DCE clock.
+ *
+ * If required clock is higher than current, then PP will increase the voltage.
+ *
+ * If required clock is lower than current, then PP will defer reduction of
+ * voltage until the call to dc_service_pp_post_dce_clock_change().
+ *
+ * \input - Contains clocks needed for Mode Set.
+ *
+ * \output - Contains clocks adjusted by PP which DAL should use for Mode Set.
+ *		Valid only if function returns zero.
+ *
+ * \returns	true - call is successful
+ *		false - call failed
+ */
+bool dm_pp_pre_dce_clock_change(
+	struct dc_context *ctx,
+	struct dal_to_power_info *input,
+	struct power_to_dal_info *output);
+
+struct dc_pp_single_disp_config {
+	enum signal_type signal;
+	uint8_t transmitter;
+	uint8_t ddi_channel_mapping;
+	uint8_t pipe_idx;
+	uint32_t src_height;
+	uint32_t src_width;
+	uint32_t v_refresh;
+	uint32_t sym_clock; /* HDMI only */
+	struct link_settings link_settings; /* DP only */
+};
+
+struct dc_pp_display_configuration {
+	bool nb_pstate_switch_disable;/* controls NB PState switch */
+	bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */
+	bool cpu_pstate_disable;
+	uint32_t cpu_pstate_separation_time;
+
+	uint32_t min_memory_clock_khz;
+	uint32_t min_engine_clock_khz;
+	uint32_t min_engine_clock_deep_sleep_khz;
+
+	uint32_t avail_mclk_switch_time_us;
+	uint32_t avail_mclk_switch_time_in_disp_active_us;
+
+	uint32_t disp_clk_khz;
+
+	bool all_displays_in_sync;
+
+	uint8_t display_count;
+	struct dc_pp_single_disp_config disp_configs[3];
+
+	/*Controller Index of primary display - used in MCLK SMC switching hang
+	 * SW Workaround*/
+	uint8_t crtc_index;
+	/*htotal*1000/pixelclk - used in MCLK SMC switching hang SW Workaround*/
+	uint32_t line_time_in_us;
+};
+
+enum dc_pp_clocks_state {
+	DC_PP_CLOCKS_STATE_INVALID = 0,
+	DC_PP_CLOCKS_STATE_ULTRA_LOW,
+	DC_PP_CLOCKS_STATE_LOW,
+	DC_PP_CLOCKS_STATE_NOMINAL,
+	DC_PP_CLOCKS_STATE_PERFORMANCE,
+
+	/* Starting from DCE11, Max 8 levels of DPM state supported. */
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_INVALID = DC_PP_CLOCKS_STATE_INVALID,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_0 = DC_PP_CLOCKS_STATE_ULTRA_LOW,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_1 = DC_PP_CLOCKS_STATE_LOW,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_2 = DC_PP_CLOCKS_STATE_NOMINAL,
+	/* to be backward compatible */
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_3 = DC_PP_CLOCKS_STATE_PERFORMANCE,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_4 = DC_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_5 = DC_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_6 = DC_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_7 = DC_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1,
+};
+
+struct dc_pp_static_clock_info {
+	uint32_t max_sclk_khz;
+	uint32_t max_mclk_khz;
+
+	 /* max possible display block clocks state */
+	enum dc_pp_clocks_state max_clocks_state;
+};
+
+/* The returned clocks range are 'static' system clocks which will be used for
+ * mode validation purposes.
+ *
+ * \returns	true - call is successful
+ *		false - call failed
+ */
+bool dc_service_get_system_clocks_range(
+	const struct dc_context *ctx,
+	struct dal_system_clock_range *sys_clks);
+
+enum dc_pp_clock_type {
+	DC_PP_CLOCK_TYPE_DISPLAY_CLK = 1,
+	DC_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */
+	DC_PP_CLOCK_TYPE_MEMORY_CLK
+};
+
+#define DC_DECODE_PP_CLOCK_TYPE(clk_type) \
+	(clk_type) == DC_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \
+	(clk_type) == DC_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \
+	(clk_type) == DC_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid"
+
+#define DC_PP_MAX_CLOCK_LEVELS 8
+
+struct dc_pp_clock_levels {
+	uint32_t num_levels;
+	uint32_t clocks_in_khz[DC_PP_MAX_CLOCK_LEVELS];
+};
+
+/* Gets valid clocks levels from pplib
+ *
+ * input: clk_type - display clk / sclk / mem clk
+ *
+ * output: array of valid clock levels for given type in ascending order,
+ * with invalid levels filtered out
+ *
+ */
+bool dm_pp_get_clock_levels_by_type(
+	const struct dc_context *ctx,
+	enum dc_pp_clock_type clk_type,
+	struct dc_pp_clock_levels *clk_level_info);
+
+
+bool dm_pp_apply_safe_state(
+		const struct dc_context *ctx);
+
+/* DAL calls this function to notify PP about completion of Mode Set.
+ * For PP it means that current DCE clocks are those which were returned
+ * by dc_service_pp_pre_dce_clock_change(), in the 'output' parameter.
+ *
+ * If the clocks are higher than before, then PP does nothing.
+ *
+ * If the clocks are lower than before, then PP reduces the voltage.
+ *
+ * \returns	true - call is successful
+ *		false - call failed
+ */
+bool dm_pp_apply_display_requirements(
+	const struct dc_context *ctx,
+	const struct dc_pp_display_configuration *pp_display_cfg);
+
+
+/****** end of PP interfaces ******/
+
+void dm_sleep_in_milliseconds(struct dc_context *ctx, uint32_t milliseconds);
+
+void dm_delay_in_microseconds(struct dc_context *ctx, uint32_t microseconds);
+
+enum platform_method {
+	PM_GET_AVAILABLE_METHODS = 1 << 0,
+	PM_GET_LID_STATE = 1 << 1,
+	PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2
+};
+
+struct platform_info_params {
+	enum platform_method method;
+	void *data;
+};
+
+struct platform_info_brightness_caps {
+	uint8_t ac_level_percentage;
+	uint8_t dc_level_percentage;
+};
+
+struct platform_info_ext_brightness_caps {
+	struct platform_info_brightness_caps basic_caps;
+	struct data_point {
+		uint8_t luminance;
+		uint8_t	signal_level;
+	} data_points[99];
+
+	uint8_t	data_points_num;
+	uint8_t	min_input_signal;
+	uint8_t	max_input_signal;
+};
+
+bool dm_get_platform_info(
+	struct dc_context *ctx,
+	struct platform_info_params *params);
+
+/*
+ *
+ * print-out services
+ *
+ */
+#define dm_log_to_buffer(buffer, size, fmt, args)\
+	vsnprintf(buffer, size, fmt, args)
+
+long dm_get_pid(void);
+long dm_get_tgid(void);
+
+/*
+ *
+ * general debug capabilities
+ *
+ */
+#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER)
+
+#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB)
+#define ASSERT_CRITICAL(expr) do {	\
+	if (WARN_ON(!(expr))) { \
+		kgdb_breakpoint(); \
+	} \
+} while (0)
+#else
+#define ASSERT_CRITICAL(expr) do {	\
+	if (WARN_ON(!(expr))) { \
+		; \
+	} \
+} while (0)
+#endif
+
+#if defined(CONFIG_DEBUG_KERNEL_DAL)
+#define ASSERT(expr) ASSERT_CRITICAL(expr)
+
+#else
+#define ASSERT(expr) WARN_ON(!(expr))
+#endif
+
+#define BREAK_TO_DEBUGGER() ASSERT(0)
+
+#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */
+
+#endif /* __DM_SERVICES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services_types.h b/drivers/gpu/drm/amd/dal/dc/dm_services_types.h
new file mode 100644
index 000000000000..bc458aa41a5d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dm_services_types.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DM_SERVICES_TYPES_H__
+#define __DM_SERVICES_TYPES_H__
+
+#define INVALID_DISPLAY_INDEX 0xffffffff
+
+#if defined __KERNEL__
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <drm/drmP.h>
+
+#include "cgs_linux.h"
+
+#if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU)
+#define BIGENDIAN_CPU
+#elif defined(__LITTLE_ENDIAN) && !defined(LITTLEENDIAN_CPU)
+#define LITTLEENDIAN_CPU
+#endif
+
+#undef READ
+#undef WRITE
+#undef FRAME_SIZE
+
+#define dm_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__)
+
+#define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__)
+
+#define dm_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__)
+
+#define dm_vlog(fmt, args) vprintk(fmt, args)
+
+#define dm_min(x, y) min(x, y)
+#define dm_max(x, y) max(x, y)
+
+#elif defined BUILD_DAL_TEST
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdio.h>
+
+#include <stdarg.h>
+
+#include "cgs_linux.h"
+
+#define LONG_MAX	((long)(~0UL>>1))
+#define LONG_MIN	(-LONG_MAX - 1)
+#define LLONG_MAX	((long long)(~0ULL>>1))
+#define LLONG_MIN	(-LLONG_MAX - 1)
+#define UINT_MAX	(~0U)
+
+typedef _Bool bool;
+enum { false, true };
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define LITTLEENDIAN_CPU 1
+
+#include <test_context.h>
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#define container_of(ptr, type, member) \
+	((type *)((char *)(ptr) - offsetof(type, member)))
+
+#define dal_test_not_implemented() \
+	printf("[DAL_TEST_NOT_IMPL]:%s\n", __func__)
+
+#define dm_output_to_console(fmt, ...) do { \
+	printf("[DAL_LOG]" fmt, ##__VA_ARGS__); } \
+	while (false)
+
+#define dm_error(fmt, ...) printf("[DAL_ERROR]" fmt, ##__VA_ARGS__)
+
+#define dm_output_to_console(fmt, ...) do { \
+			printf("[DAL_LOG]" fmt, ##__VA_ARGS__); } \
+				while (false)
+
+
+#define dm_debug(fmt, ...) printf("[DAL_DBG]" fmt, ##__VA_ARGS__)
+
+#define dm_vlog(fmt, args) vprintf(fmt, args)
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+#define dm_min(x, y) ({\
+	typeof(x) _min1 = (x);\
+	typeof(y) _min2 = (y);\
+	(void) (&_min1 == &_min2);\
+	_min1 < _min2 ? _min1 : _min2; })
+
+#define dm_max(x, y) ({\
+	typeof(x) _max1 = (x);\
+	typeof(y) _max2 = (y);\
+	(void) (&_max1 == &_max2);\
+	_max1 > _max2 ? _max1 : _max2; })
+
+/* division functions */
+
+static inline int64_t div64_s64(int64_t x, int64_t y)
+{
+	return x / y;
+}
+
+static inline uint64_t div64_u64(uint64_t x, uint64_t y)
+{
+	return x / y;
+}
+
+static inline uint64_t div_u64(uint64_t x, uint32_t y)
+{
+	return x / y;
+}
+
+static inline uint64_t div64_u64_rem(uint64_t x, uint64_t y, uint64_t *rem)
+{
+	if (rem)
+		*rem = x % y;
+	return x / y;
+}
+
+static inline uint64_t div_u64_rem(uint64_t x, uint32_t y, uint32_t *rem)
+{
+	if (rem)
+		*rem = x % y;
+	return x / y;
+}
+
+#define cpu_to_le16(do_nothing) do_nothing
+
+#define le16_to_cpu(do_nothing) do_nothing
+
+#define cpu_to_le32(do_nothing) do_nothing
+
+#define le32_to_cpu(do_nothing) do_nothing
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
new file mode 100644
index 000000000000..0d228ed0455c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/**
+ * Bandwidth and Watermark calculations interface.
+ * (Refer to "DCE11_mode_support.xlsm" from Perforce.)
+ */
+#ifndef __BANDWIDTH_CALCS_H__
+#define __BANDWIDTH_CALCS_H__
+
+#include "bw_fixed.h"
+/*******************************************************************************
+ * There are three types of input into Calculations:
+ * 1. per-DCE static values - these are "hardcoded" properties of the DCEIP
+ * 2. board-level values - these are generally coming from VBIOS parser
+ * 3. mode/configuration values - depending Mode, Scaling number of Displays etc.
+ ******************************************************************************/
+enum bw_defines {
+	/*Common*/
+	bw_def_no = 0,
+	bw_def_none = 0,
+	bw_def_yes = 1,
+	bw_def_ok = 1,
+	bw_def_high = 2,
+	bw_def_mid = 1,
+	bw_def_low = 0,
+
+	/*Internal*/
+	bw_defs_start = 255,
+	bw_def_underlay422,
+	bw_def_underlay420_luma,
+	bw_def_underlay420_chroma,
+	bw_def_underlay444,
+	bw_def_graphics,
+	bw_def_display_write_back420_luma,
+	bw_def_display_write_back420_chroma,
+	bw_def_portrait,
+	bw_def_hsr_mtn_4,
+	bw_def_hsr_mtn_h_taps,
+	bw_def_ceiling__h_taps_div_4___meq_hsr,
+	bw_def_invalid_linear_or_stereo_mode,
+	bw_def_invalid_rotation_or_bpp_or_stereo,
+	bw_def_vsr_mtn_v_taps,
+	bw_def_vsr_mtn_4,
+	bw_def_auto,
+	bw_def_manual,
+	bw_def_exceeded_allowed_maximum_sclk,
+	bw_def_exceeded_allowed_page_close_open,
+	bw_def_exceeded_allowed_outstanding_pte_req_queue_size,
+	bw_def_exceeded_allowed_maximum_bw,
+	bw_def_high_no_nbp_state_change,
+	bw_def_landscape,
+
+	/*Panning and bezel*/
+	bw_def_any_lines,
+
+	/*Underlay mode*/
+	bw_def_underlay_only,
+	bw_def_blended,
+	bw_def_blend,
+
+	/*Stereo mode*/
+	bw_def_mono,
+	bw_def_side_by_side,
+	bw_def_top_bottom,
+
+	/*Underlay surface type*/
+	bw_def_420,
+	bw_def_422,
+	bw_def_444,
+
+	/*Tiling mode*/
+	bw_def_linear,
+	bw_def_tiled,
+
+	bw_def_notok = -1,
+	bw_def_na = -1
+};
+
+struct bw_calcs_dceip {
+	struct bw_fixed dmif_request_buffer_size;
+	struct bw_fixed de_tiling_buffer;
+	bool dcfclk_request_generation;
+	uint32_t lines_interleaved_into_lb;
+	uint32_t chunk_width;
+	uint32_t number_of_graphics_pipes;
+	uint32_t number_of_underlay_pipes;
+	bool display_write_back_supported;
+	bool argb_compression_support;
+	struct bw_fixed underlay_vscaler_efficiency6_bit_per_component;
+	struct bw_fixed underlay_vscaler_efficiency8_bit_per_component;
+	struct bw_fixed underlay_vscaler_efficiency10_bit_per_component;
+	struct bw_fixed underlay_vscaler_efficiency12_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency6_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency8_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency10_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency12_bit_per_component;
+	struct bw_fixed alpha_vscaler_efficiency;
+	uint32_t max_dmif_buffer_allocated;
+	uint32_t graphics_dmif_size;
+	uint32_t underlay_luma_dmif_size;
+	uint32_t underlay_chroma_dmif_size;
+	bool pre_downscaler_enabled;
+	bool underlay_downscale_prefetch_enabled;
+	struct bw_fixed lb_write_pixels_per_dispclk;
+	struct bw_fixed lb_size_per_component444;
+	bool graphics_lb_nodownscaling_multi_line_prefetching;
+	struct bw_fixed stutter_and_dram_clock_state_change_gated_before_cursor;
+	struct bw_fixed underlay420_luma_lb_size_per_component;
+	struct bw_fixed underlay420_chroma_lb_size_per_component;
+	struct bw_fixed underlay422_lb_size_per_component;
+	struct bw_fixed cursor_chunk_width;
+	struct bw_fixed cursor_dcp_buffer_lines;
+	struct bw_fixed cursor_memory_interface_buffer_pixels;
+	struct bw_fixed underlay_maximum_width_efficient_for_tiling;
+	struct bw_fixed underlay_maximum_height_efficient_for_tiling;
+	struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display;
+	struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation;
+	struct bw_fixed minimum_outstanding_pte_request_limit;
+	struct bw_fixed maximum_total_outstanding_pte_requests_allowed_by_saw;
+	bool limit_excessive_outstanding_dmif_requests;
+	struct bw_fixed linear_mode_line_request_alternation_slice;
+	uint32_t scatter_gather_lines_of_pte_prefetching_in_linear_mode;
+	uint32_t display_write_back420_luma_mcifwr_buffer_size;
+	uint32_t display_write_back420_chroma_mcifwr_buffer_size;
+	struct bw_fixed request_efficiency;
+	struct bw_fixed dispclk_per_request;
+	struct bw_fixed dispclk_ramping_factor;
+	struct bw_fixed display_pipe_throughput_factor;
+	uint32_t scatter_gather_pte_request_rows_in_tiling_mode;
+	struct bw_fixed mcifwr_all_surfaces_burst_time; /* 0 todo: this is a bug*/
+};
+
+struct bw_calcs_vbios {
+	uint32_t dram_channel_width_in_bits;
+	uint32_t number_of_dram_channels;
+	uint32_t number_of_dram_banks;
+	struct bw_fixed high_yclk; /*MHz*/
+	struct bw_fixed mid_yclk; /*MHz*/
+	struct bw_fixed low_yclk; /*MHz*/
+	struct bw_fixed low_sclk; /*MHz*/
+	struct bw_fixed mid_sclk; /*MHz*/
+	struct bw_fixed high_sclk; /*MHz*/
+	struct bw_fixed low_voltage_max_dispclk; /*MHz*/
+	struct bw_fixed mid_voltage_max_dispclk; /*MHz*/
+	struct bw_fixed high_voltage_max_dispclk; /*MHz*/
+	struct bw_fixed data_return_bus_width;
+	struct bw_fixed trc;
+	struct bw_fixed dmifmc_urgent_latency;
+	struct bw_fixed stutter_self_refresh_exit_latency;
+	struct bw_fixed nbp_state_change_latency;
+	struct bw_fixed mcifwrmc_urgent_latency;
+	bool scatter_gather_enable;
+	struct bw_fixed down_spread_percentage;
+	uint32_t cursor_width;
+	uint32_t average_compression_rate;
+	uint32_t number_of_request_slots_gmc_reserves_for_dmif_per_channel;
+	struct bw_fixed blackout_duration;
+	struct bw_fixed maximum_blackout_recovery_time;
+};
+
+struct bw_calcs_mode_data_internal {
+	/* data for all displays */
+	uint32_t number_of_displays;
+	uint32_t graphics_rotation_angle;
+	uint32_t underlay_rotation_angle;
+	enum bw_defines display_synchronization_enabled;
+	enum bw_defines underlay_surface_type;
+	enum bw_defines panning_and_bezel_adjustment;
+	enum bw_defines graphics_tiling_mode;
+	bool graphics_interlace_mode;
+	uint32_t graphics_bytes_per_pixel;
+	uint32_t graphics_htaps;
+	uint32_t graphics_vtaps;
+	uint32_t graphics_lb_bpc;
+	uint32_t underlay_lb_bpc;
+	enum bw_defines underlay_tiling_mode;
+	uint32_t underlay_htaps;
+	uint32_t underlay_vtaps;
+	uint32_t underlay_src_width;
+	uint32_t underlay_src_height;
+	uint32_t underlay_pitch_in_pixels;
+	enum bw_defines underlay_stereo_mode;
+	bool d0_fbc_enable;
+	bool d0_lpt_enable;
+	uint32_t d0_htotal;
+	struct bw_fixed d0_pixel_rate;
+	uint32_t d0_graphics_src_width;
+	uint32_t d0_graphics_src_height;
+	struct bw_fixed d0_graphics_scale_ratio;
+	enum bw_defines d0_graphics_stereo_mode;
+	enum bw_defines d0_underlay_mode;
+	struct bw_fixed d0_underlay_scale_ratio;
+	uint32_t d1_htotal;
+	struct bw_fixed d1_pixel_rate;
+	uint32_t d1_graphics_src_width;
+	uint32_t d1_graphics_src_height;
+	struct bw_fixed d1_graphics_scale_ratio;
+	enum bw_defines d1_graphics_stereo_mode;
+	bool d1_display_write_back_dwb_enable;
+	enum bw_defines d1_underlay_mode;
+	struct bw_fixed d1_underlay_scale_ratio;
+	uint32_t d2_htotal;
+	struct bw_fixed d2_pixel_rate;
+	uint32_t d2_graphics_src_width;
+	uint32_t d2_graphics_src_height;
+	struct bw_fixed d2_graphics_scale_ratio;
+	enum bw_defines d2_graphics_stereo_mode;
+};
+
+
+struct bw_calcs_input_single_display {
+	uint32_t graphics_rotation_angle;
+	uint32_t underlay_rotation_angle;
+	enum bw_defines underlay_surface_type;
+	enum bw_defines panning_and_bezel_adjustment;
+	uint32_t graphics_bytes_per_pixel;
+	bool graphics_interlace_mode;
+	enum bw_defines graphics_tiling_mode;
+	uint32_t graphics_h_taps;
+	uint32_t graphics_v_taps;
+	uint32_t graphics_lb_bpc;
+	uint32_t underlay_lb_bpc;
+	enum bw_defines underlay_tiling_mode;
+	uint32_t underlay_h_taps;
+	uint32_t underlay_v_taps;
+	uint32_t underlay_src_width;
+	uint32_t underlay_src_height;
+	uint32_t underlay_pitch_in_pixels;
+	enum bw_defines underlay_stereo_mode;
+	bool fbc_enable;
+	bool lpt_enable;
+	uint32_t h_total;
+	struct bw_fixed pixel_rate;
+	uint32_t graphics_src_width;
+	uint32_t graphics_src_height;
+	struct bw_fixed graphics_scale_ratio;
+	enum bw_defines graphics_stereo_mode;
+	enum bw_defines underlay_mode;
+};
+
+#define BW_CALCS_MAX_NUM_DISPLAYS 3
+
+struct bw_calcs_mode_data {
+	/* data for all displays */
+	uint8_t number_of_displays;
+	bool display_synchronization_enabled;
+
+	struct bw_calcs_input_single_display
+				displays_data[BW_CALCS_MAX_NUM_DISPLAYS];
+};
+
+/*******************************************************************************
+ * Output data structure(s).
+ ******************************************************************************/
+#define maximum_number_of_surfaces 12
+/*Units : MHz, us */
+struct bw_calcs_results {
+	bool cpup_state_change_enable;
+	bool cpuc_state_change_enable;
+	bool nbp_state_change_enable;
+	bool stutter_mode_enable;
+	uint32_t y_clk_level;
+	uint32_t sclk_level;
+	uint32_t number_of_underlay_surfaces;
+	struct bw_fixed src_width_after_surface_type;
+	struct bw_fixed src_height_after_surface_type;
+	struct bw_fixed hsr_after_surface_type;
+	struct bw_fixed vsr_after_surface_type;
+	struct bw_fixed src_width_after_rotation;
+	struct bw_fixed src_height_after_rotation;
+	struct bw_fixed hsr_after_rotation;
+	struct bw_fixed vsr_after_rotation;
+	struct bw_fixed source_height_pixels;
+	struct bw_fixed hsr_after_stereo;
+	struct bw_fixed vsr_after_stereo;
+	struct bw_fixed source_width_in_lb;
+	struct bw_fixed lb_line_pitch;
+	struct bw_fixed underlay_maximum_source_efficient_for_tiling;
+	struct bw_fixed num_lines_at_frame_start;
+	struct bw_fixed min_dmif_size_in_time;
+	struct bw_fixed min_mcifwr_size_in_time;
+	struct bw_fixed total_requests_for_dmif_size;
+	struct bw_fixed peak_pte_request_to_eviction_ratio_limiting;
+	struct bw_fixed useful_pte_per_pte_request;
+	struct bw_fixed scatter_gather_pte_request_rows;
+	struct bw_fixed scatter_gather_row_height;
+	struct bw_fixed scatter_gather_pte_requests_in_vblank;
+	struct bw_fixed inefficient_linear_pitch_in_bytes;
+	struct bw_fixed inefficient_underlay_pitch_in_pixels;
+	struct bw_fixed minimum_underlay_pitch_padding_recommended_for_efficiency;
+	struct bw_fixed cursor_total_data;
+	struct bw_fixed cursor_total_request_groups;
+	struct bw_fixed scatter_gather_total_pte_requests;
+	struct bw_fixed scatter_gather_total_pte_request_groups;
+	struct bw_fixed tile_width_in_pixels;
+	struct bw_fixed dmif_total_number_of_data_request_page_close_open;
+	struct bw_fixed mcifwr_total_number_of_data_request_page_close_open;
+	struct bw_fixed bytes_per_page_close_open;
+	struct bw_fixed mcifwr_total_page_close_open_time;
+	struct bw_fixed total_requests_for_adjusted_dmif_size;
+	struct bw_fixed total_dmifmc_urgent_trips;
+	struct bw_fixed total_dmifmc_urgent_latency;
+	struct bw_fixed total_display_reads_required_data;
+	struct bw_fixed total_display_reads_required_dram_access_data;
+	struct bw_fixed total_display_writes_required_data;
+	struct bw_fixed total_display_writes_required_dram_access_data;
+	struct bw_fixed display_reads_required_data;
+	struct bw_fixed display_reads_required_dram_access_data;
+	struct bw_fixed dmif_total_page_close_open_time;
+	struct bw_fixed min_cursor_memory_interface_buffer_size_in_time;
+	struct bw_fixed min_read_buffer_size_in_time;
+	struct bw_fixed display_reads_time_for_data_transfer;
+	struct bw_fixed display_writes_time_for_data_transfer;
+	struct bw_fixed dmif_required_dram_bandwidth;
+	struct bw_fixed mcifwr_required_dram_bandwidth;
+	struct bw_fixed required_dmifmc_urgent_latency_for_page_close_open;
+	struct bw_fixed required_mcifmcwr_urgent_latency;
+	struct bw_fixed required_dram_bandwidth_gbyte_per_second;
+	struct bw_fixed dram_bandwidth;
+	struct bw_fixed dmif_required_sclk;
+	struct bw_fixed mcifwr_required_sclk;
+	struct bw_fixed required_sclk;
+	struct bw_fixed downspread_factor;
+	struct bw_fixed v_scaler_efficiency;
+	struct bw_fixed scaler_limits_factor;
+	struct bw_fixed display_pipe_pixel_throughput;
+	struct bw_fixed total_dispclk_required_with_ramping;
+	struct bw_fixed total_dispclk_required_without_ramping;
+	struct bw_fixed total_read_request_bandwidth;
+	struct bw_fixed total_write_request_bandwidth;
+	struct bw_fixed dispclk_required_for_total_read_request_bandwidth;
+	struct bw_fixed total_dispclk_required_with_ramping_with_request_bandwidth;
+	struct bw_fixed total_dispclk_required_without_ramping_with_request_bandwidth;
+	struct bw_fixed dispclk;
+	struct bw_fixed blackout_recovery_time;
+	struct bw_fixed min_pixels_per_data_fifo_entry;
+	struct bw_fixed sclk_deep_sleep;
+	struct bw_fixed chunk_request_time;
+	struct bw_fixed cursor_request_time;
+	struct bw_fixed line_source_pixels_transfer_time;
+	struct bw_fixed dmifdram_access_efficiency;
+	struct bw_fixed mcifwrdram_access_efficiency;
+	struct bw_fixed total_average_bandwidth_no_compression;
+	struct bw_fixed total_average_bandwidth;
+	struct bw_fixed total_stutter_cycle_duration;
+	struct bw_fixed stutter_burst_time;
+	struct bw_fixed time_in_self_refresh;
+	struct bw_fixed stutter_efficiency;
+	struct bw_fixed worst_number_of_trips_to_memory;
+	struct bw_fixed immediate_flip_time;
+	struct bw_fixed latency_for_non_dmif_clients;
+	struct bw_fixed latency_for_non_mcifwr_clients;
+	struct bw_fixed dmifmc_urgent_latency_supported_in_high_sclk_and_yclk;
+	struct bw_fixed nbp_state_dram_speed_change_margin;
+	struct bw_fixed display_reads_time_for_data_transfer_and_urgent_latency;
+	bool displays_match_flag[maximum_number_of_surfaces];
+	bool use_alpha[maximum_number_of_surfaces];
+	bool orthogonal_rotation[maximum_number_of_surfaces];
+	bool enable[maximum_number_of_surfaces];
+	bool access_one_channel_only[maximum_number_of_surfaces];
+	bool scatter_gather_enable_for_pipe[maximum_number_of_surfaces];
+	bool interlace_mode[maximum_number_of_surfaces];
+	bool display_pstate_change_enable[maximum_number_of_surfaces];
+	struct bw_fixed dmif_buffer_transfer_time[maximum_number_of_surfaces];
+	struct bw_fixed displays_with_same_mode[maximum_number_of_surfaces];
+	uint32_t bytes_per_pixel[maximum_number_of_surfaces];
+	struct bw_fixed h_total[maximum_number_of_surfaces];
+	struct bw_fixed pixel_rate[maximum_number_of_surfaces];
+	struct bw_fixed src_width[maximum_number_of_surfaces];
+	struct bw_fixed pitch_in_pixels[maximum_number_of_surfaces];
+	struct bw_fixed pitch_in_pixels_after_surface_type[maximum_number_of_surfaces];
+	struct bw_fixed src_height[maximum_number_of_surfaces];
+	struct bw_fixed scale_ratio[maximum_number_of_surfaces];
+	struct bw_fixed h_taps[maximum_number_of_surfaces];
+	struct bw_fixed v_taps[maximum_number_of_surfaces];
+	struct bw_fixed rotation_angle[maximum_number_of_surfaces];
+	uint32_t lb_bpc[maximum_number_of_surfaces];
+	struct bw_fixed compression_rate[maximum_number_of_surfaces];
+	struct bw_fixed hsr[maximum_number_of_surfaces];
+	struct bw_fixed vsr[maximum_number_of_surfaces];
+	struct bw_fixed source_width_rounded_up_to_chunks[maximum_number_of_surfaces];
+	struct bw_fixed source_width_pixels[maximum_number_of_surfaces];
+	struct bw_fixed source_height_rounded_up_to_chunks[maximum_number_of_surfaces];
+	struct bw_fixed display_bandwidth[maximum_number_of_surfaces];
+	struct bw_fixed request_bandwidth[maximum_number_of_surfaces];
+	struct bw_fixed bytes_per_request[maximum_number_of_surfaces];
+	struct bw_fixed useful_bytes_per_request[maximum_number_of_surfaces];
+	struct bw_fixed lines_interleaved_in_mem_access[maximum_number_of_surfaces];
+	struct bw_fixed latency_hiding_lines[maximum_number_of_surfaces];
+	struct bw_fixed lb_partitions[maximum_number_of_surfaces];
+	struct bw_fixed lb_partitions_max[maximum_number_of_surfaces];
+	struct bw_fixed dispclk_required_with_ramping[maximum_number_of_surfaces];
+	struct bw_fixed dispclk_required_without_ramping[maximum_number_of_surfaces];
+	struct bw_fixed data_buffer_size[maximum_number_of_surfaces];
+	struct bw_fixed outstanding_chunk_request_limit[maximum_number_of_surfaces];
+	struct bw_fixed urgent_watermark[maximum_number_of_surfaces];
+	struct bw_fixed stutter_exit_watermark[maximum_number_of_surfaces];
+	struct bw_fixed nbp_state_change_watermark[maximum_number_of_surfaces];
+	struct bw_fixed v_filter_init[maximum_number_of_surfaces];
+	struct bw_fixed stutter_cycle_duration[maximum_number_of_surfaces];
+	struct bw_fixed average_bandwidth[maximum_number_of_surfaces];
+	struct bw_fixed average_bandwidth_no_compression[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_pte_request_limit[maximum_number_of_surfaces];
+	struct bw_fixed lb_size_per_component[maximum_number_of_surfaces];
+	struct bw_fixed memory_chunk_size_in_bytes[maximum_number_of_surfaces];
+	struct bw_fixed pipe_chunk_size_in_bytes[maximum_number_of_surfaces];
+	struct bw_fixed number_of_trips_to_memory_for_getting_apte_row[maximum_number_of_surfaces];
+	struct bw_fixed adjusted_data_buffer_size[maximum_number_of_surfaces];
+	struct bw_fixed adjusted_data_buffer_size_in_memory[maximum_number_of_surfaces];
+	struct bw_fixed pixels_per_data_fifo_entry[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_pte_requests_in_row[maximum_number_of_surfaces];
+	struct bw_fixed pte_request_per_chunk[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_page_width[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_page_height[maximum_number_of_surfaces];
+	struct bw_fixed lb_lines_in_per_line_out_in_beginning_of_frame[maximum_number_of_surfaces];
+	struct bw_fixed lb_lines_in_per_line_out_in_middle_of_frame[maximum_number_of_surfaces];
+	struct bw_fixed cursor_width_pixels[maximum_number_of_surfaces];
+	bool line_buffer_prefetch[maximum_number_of_surfaces];
+	struct bw_fixed minimum_latency_hiding[maximum_number_of_surfaces];
+	struct bw_fixed maximum_latency_hiding[maximum_number_of_surfaces];
+	struct bw_fixed minimum_latency_hiding_with_cursor[maximum_number_of_surfaces];
+	struct bw_fixed maximum_latency_hiding_with_cursor[maximum_number_of_surfaces];
+	struct bw_fixed src_pixels_for_first_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed src_pixels_for_last_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed src_data_for_first_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed src_data_for_last_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed active_time[maximum_number_of_surfaces];
+	struct bw_fixed horizontal_blank_and_chunk_granularity_factor[maximum_number_of_surfaces];
+	struct bw_fixed cursor_latency_hiding[maximum_number_of_surfaces];
+	struct bw_fixed dmif_burst_time[3][3];
+	struct bw_fixed mcifwr_burst_time[3][3];
+	struct bw_fixed line_source_transfer_time[maximum_number_of_surfaces][3][3];
+	struct bw_fixed dram_speed_change_line_source_transfer_time[maximum_number_of_surfaces][3][3];
+	struct bw_fixed min_dram_speed_change_margin[3][3];
+	struct bw_fixed dram_speed_change_margin[3][3];
+	struct bw_fixed dispclk_required_for_dram_speed_change[3][3];
+	struct bw_fixed blackout_duration_margin[3][3];
+	struct bw_fixed dispclk_required_for_blackout_duration[3][3];
+	struct bw_fixed dispclk_required_for_blackout_recovery[3][3];
+	struct bw_fixed dmif_required_sclk_for_urgent_latency[6];
+};
+
+struct bw_watermarks {
+	uint32_t a_mark;
+	uint32_t b_mark;
+};
+
+struct bw_calcs_output {
+	bool cpuc_state_change_enable;
+	bool cpup_state_change_enable;
+	bool stutter_mode_enable;
+	bool nbp_state_change_enable;
+	bool all_displays_in_sync;
+	struct bw_watermarks urgent_wm_ns[4];
+	struct bw_watermarks stutter_exit_wm_ns[4];
+	struct bw_watermarks nbp_state_change_wm_ns[4];
+	uint32_t required_sclk;
+	uint32_t required_sclk_deep_sleep;
+	uint32_t required_yclk;
+	uint32_t dispclk_khz;
+	int32_t required_blackout_duration_us;
+};
+
+
+/**
+ * Initialize structures with data which will NOT change at runtime.
+ */
+void bw_calcs_init(
+	struct bw_calcs_dceip *bw_dceip,
+	struct bw_calcs_vbios *bw_vbios);
+
+/**
+ * Return:
+ *	true -	Display(s) configuration supported.
+ *		In this case 'calcs_output' contains data for HW programming
+ *	false - Display(s) configuration not supported (not enough bandwidth).
+ */
+bool bw_calcs(
+	struct dc_context *ctx,
+	const struct bw_calcs_dceip *dceip,
+	const struct bw_calcs_vbios *vbios,
+	const struct bw_calcs_mode_data *mode_data,
+	struct bw_calcs_output *calcs_output);
+
+
+#endif /* __BANDWIDTH_CALCS_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
new file mode 100644
index 000000000000..ff271cc0aea1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef BW_FIXED_H_
+#define BW_FIXED_H_
+
+struct bw_fixed {
+	int64_t value;
+};
+
+struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3);
+
+struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3);
+
+struct bw_fixed bw_int_to_fixed(int64_t value);
+
+int32_t bw_fixed_to_int(struct bw_fixed value);
+
+struct bw_fixed bw_frc_to_fixed(int64_t num, int64_t denum);
+
+struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw);
+
+struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2);
+
+struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_floor2(const struct bw_fixed arg, const struct bw_fixed significance);
+struct bw_fixed bw_ceil2(const struct bw_fixed arg, const struct bw_fixed significance);
+
+bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2);
+
+
+#endif //BW_FIXED_H_
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h b/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
new file mode 100644
index 000000000000..0120ee23e6be
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_CLOCK_SOURCE_H__
+#define __DC_CLOCK_SOURCE_H__
+
+#include "dc_types.h"
+#include "include/grph_object_id.h"
+#include "include/bios_parser_types.h"
+
+struct clock_source;
+
+struct spread_spectrum_data {
+	uint32_t percentage;		/*> In unit of 0.01% or 0.001%*/
+	uint32_t percentage_divider;	/*> 100 or 1000	*/
+	uint32_t freq_range_khz;
+	uint32_t modulation_freq_hz;
+
+	struct spread_spectrum_flags flags;
+};
+
+struct delta_sigma_data {
+	uint32_t feedback_amount;
+	uint32_t nfrac_amount;
+	uint32_t ds_frac_size;
+	uint32_t ds_frac_amount;
+};
+
+/**
+ *  Pixel Clock Parameters structure
+ *  These parameters are required as input
+ *  when calculating Pixel Clock Dividers for requested Pixel Clock
+ */
+struct pixel_clk_flags {
+	uint32_t ENABLE_SS:1;
+	uint32_t DISPLAY_BLANKED:1;
+	uint32_t PROGRAM_PIXEL_CLOCK:1;
+	uint32_t PROGRAM_ID_CLOCK:1;
+};
+
+/**
+ *  Display Port HW De spread of Reference Clock related Parameters structure
+ *  Store it once at boot for later usage
+  */
+struct csdp_ref_clk_ds_params {
+	bool hw_dso_n_dp_ref_clk;
+/* Flag for HW De Spread enabled (if enabled SS on DP Reference Clock)*/
+	uint32_t avg_dp_ref_clk_khz;
+/* Average DP Reference clock (in KHz)*/
+	uint32_t ss_percentage_on_dp_ref_clk;
+/* DP Reference clock SS percentage
+ * (not to be mixed with DP IDCLK SS from PLL Settings)*/
+	uint32_t ss_percentage_divider;
+/* DP Reference clock SS percentage divider */
+};
+
+struct pixel_clk_params {
+	uint32_t requested_pix_clk; /* in KHz */
+/*> Requested Pixel Clock
+ * (based on Video Timing standard used for requested mode)*/
+	uint32_t requested_sym_clk; /* in KHz */
+/*> Requested Sym Clock (relevant only for display port)*/
+	uint32_t dp_ref_clk; /* in KHz */
+/*> DP reference clock - calculated only for DP signal for specific cases*/
+	struct graphics_object_id encoder_object_id;
+/*> Encoder object Id - needed by VBIOS Exec table*/
+	enum signal_type signal_type;
+/*> signalType -> Encoder Mode - needed by VBIOS Exec table*/
+	enum controller_id controller_id;
+/*> ControllerId - which controller using this PLL*/
+	enum dc_color_depth color_depth;
+	struct csdp_ref_clk_ds_params de_spread_params;
+/*> de-spread info, relevant only for on-the-fly tune-up pixel rate*/
+
+	struct pixel_clk_flags flags;
+};
+
+/**
+ *  Pixel Clock Dividers structure with desired Pixel Clock
+ *  (adjusted after VBIOS exec table),
+ *  with actually calculated Clock and reference Crystal frequency
+ */
+struct pll_settings {
+	uint32_t actual_pix_clk;
+	uint32_t adjusted_pix_clk;
+	uint32_t calculated_pix_clk;
+	uint32_t vco_freq;
+	uint32_t reference_freq;
+	uint32_t reference_divider;
+	uint32_t feedback_divider;
+	uint32_t fract_feedback_divider;
+	uint32_t pix_clk_post_divider;
+	uint32_t ss_percentage;
+	bool use_external_clk;
+};
+
+struct calc_pll_clock_source_init_data {
+	struct dc_bios *bp;
+	uint32_t min_pix_clk_pll_post_divider;
+	uint32_t max_pix_clk_pll_post_divider;
+	uint32_t min_pll_ref_divider;
+	uint32_t max_pll_ref_divider;
+	uint32_t min_override_input_pxl_clk_pll_freq_khz;
+/* if not 0, override the firmware info */
+
+	uint32_t max_override_input_pxl_clk_pll_freq_khz;
+/* if not 0, override the firmware info */
+
+	uint32_t num_fract_fb_divider_decimal_point;
+/* number of decimal point for fractional feedback divider value */
+
+	uint32_t num_fract_fb_divider_decimal_point_precision;
+/* number of decimal point to round off for fractional feedback divider value*/
+	struct dc_context *ctx;
+
+};
+
+struct calc_pll_clock_source {
+	uint32_t ref_freq_khz;
+	uint32_t min_pix_clock_pll_post_divider;
+	uint32_t max_pix_clock_pll_post_divider;
+	uint32_t min_pll_ref_divider;
+	uint32_t max_pll_ref_divider;
+
+	uint32_t max_vco_khz;
+	uint32_t min_vco_khz;
+	uint32_t min_pll_input_freq_khz;
+	uint32_t max_pll_input_freq_khz;
+
+	uint32_t fract_fb_divider_decimal_points_num;
+	uint32_t fract_fb_divider_factor;
+	uint32_t fract_fb_divider_precision;
+	uint32_t fract_fb_divider_precision_factor;
+	struct dc_context *ctx;
+};
+
+struct clock_source_funcs {
+	bool (*cs_power_down)(
+			struct clock_source *);
+	bool (*program_pix_clk)(struct clock_source *,
+			struct pixel_clk_params *, struct pll_settings *);
+	uint32_t (*get_pix_clk_dividers)(
+			struct clock_source *,
+			struct pixel_clk_params *,
+			struct pll_settings *);
+};
+
+struct clock_source {
+	struct clock_source_funcs *funcs;
+	struct dc_context *ctx;
+	enum clock_source_id id;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/compressor.h b/drivers/gpu/drm/amd/dal/dc/inc/compressor.h
new file mode 100644
index 000000000000..4992ffde7c9a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/compressor.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMPRESSOR_H__
+#define __DAL_COMPRESSOR_H__
+
+#include "include/grph_object_id.h"
+
+enum fbc_compress_ratio {
+	FBC_COMPRESS_RATIO_INVALID = 0,
+	FBC_COMPRESS_RATIO_1TO1 = 1,
+	FBC_COMPRESS_RATIO_2TO1 = 2,
+	FBC_COMPRESS_RATIO_4TO1 = 4,
+	FBC_COMPRESS_RATIO_8TO1 = 8,
+};
+
+union fbc_physical_address {
+	struct {
+		uint32_t low_part;
+		int32_t high_part;
+	} addr;
+};
+
+struct compr_addr_and_pitch_params {
+	uint32_t inst;
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+};
+
+struct fbc_lpt_config {
+	uint32_t mem_channels_num;
+	uint32_t banks_num;
+	uint32_t chan_interleave_size;
+	uint32_t row_size;
+};
+
+struct fbc_input_info {
+	bool dynamic_fbc_buffer_alloc;
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+	uint32_t active_targets_num;
+	struct fbc_lpt_config lpt_config;
+};
+
+struct fbc_requested_compressed_size {
+	uint32_t preferred_size;
+	uint32_t preferred_size_alignment;
+	uint32_t min_size;
+	uint32_t min_size_alignment;
+	union {
+		struct {
+			/*Above preferred_size must be allocated in FB pool */
+			uint32_t PREFERRED_MUST_BE_FRAME_BUFFER_POOL:1;
+			/*Above min_size must be allocated in FB pool */
+			uint32_t MIN_MUST_BE_FRAME_BUFFER_POOL:1;
+		} flags;
+		uint32_t bits;
+	};
+};
+
+struct fbc_compressed_surface_info {
+	union fbc_physical_address compressed_surface_address;
+	uint32_t allocated_size;
+	union {
+		struct {
+			uint32_t FB_POOL:1; /*Allocated in FB Pool */
+			uint32_t DYNAMIC_ALLOC:1; /*Dynamic allocation */
+		} allocation_flags;
+		uint32_t bits;
+	};
+};
+
+enum fbc_hw_max_resolution_supported {
+	FBC_MAX_X = 3840,
+	FBC_MAX_Y = 2400
+};
+
+struct fbc_max_resolution_supported {
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+};
+
+struct compressor {
+	struct dc_context *ctx;
+	uint32_t attached_inst;
+	bool is_enabled;
+
+	union {
+		uint32_t raw;
+		struct {
+			uint32_t FBC_SUPPORT:1;
+			uint32_t FB_POOL:1;
+			uint32_t DYNAMIC_ALLOC:1;
+			uint32_t LPT_SUPPORT:1;
+			uint32_t LPT_MC_CONFIG:1;
+			uint32_t DUMMY_BACKEND:1;
+			uint32_t CLK_GATING_DISABLED:1;
+
+		} bits;
+	} options;
+
+	union fbc_physical_address compr_surface_address;
+
+	uint32_t embedded_panel_h_size;
+	uint32_t embedded_panel_v_size;
+	uint32_t memory_bus_width;
+	uint32_t banks_num;
+	uint32_t raw_size;
+	uint32_t channel_interleave_size;
+	uint32_t dram_channels_num;
+
+	uint32_t allocated_size;
+	uint32_t preferred_requested_size;
+	uint32_t lpt_channels_num;
+	enum fbc_compress_ratio min_compress_ratio;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h b/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
new file mode 100644
index 000000000000..3e66ad7ea72d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __CORE_DC_H__
+#define __CORE_DC_H__
+
+#include "core_types.h"
+#include "hw_sequencer.h"
+
+struct dc {
+	struct dc_context *ctx;
+
+	uint8_t link_count;
+	struct core_link *links[MAX_PIPES * 2];
+
+	/* TODO: determine max number of targets*/
+	struct validate_context current_context;
+	struct resource_pool res_pool;
+
+	/*Power State*/
+	enum dc_video_power_state previous_power_state;
+	enum dc_video_power_state current_power_state;
+
+	/* Inputs into BW and WM calculations. */
+	struct bw_calcs_dceip bw_dceip;
+	struct bw_calcs_vbios bw_vbios;
+
+	/* HW functions */
+	struct hw_sequencer_funcs hwss;
+};
+
+#endif /* __CORE_DC_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_status.h b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h
new file mode 100644
index 000000000000..9682cf866886
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _CORE_STATUS_H_
+#define _CORE_STATUS_H_
+
+enum dc_status {
+	DC_OK = 1,
+
+	DC_NO_CONTROLLER_RESOURCE,
+	DC_NO_STREAM_ENG_RESOURCE,
+	DC_NO_STREAM_AUDIO_RESOURCE,
+	DC_NO_CLOCK_SOURCE_RESOURCE,
+	DC_FAIL_CONTROLLER_VALIDATE,
+	DC_FAIL_ENC_VALIDATE,
+	DC_FAIL_ATTACH_SURFACES,
+	DC_NO_DP_LINK_BANDWIDTH,
+	DC_EXCEED_DONGLE_MAX_CLK,
+	DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */
+
+	DC_ERROR_UNEXPECTED = -1
+};
+
+#endif /* _CORE_STATUS_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
new file mode 100644
index 000000000000..7d63ebb8e789
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _CORE_TYPES_H_
+#define _CORE_TYPES_H_
+
+#include "dc.h"
+#include "bandwidth_calcs.h"
+#include "ddc_service_types.h"
+
+struct core_stream;
+/********* core_target *************/
+
+#define CONST_DC_TARGET_TO_CORE(dc_target) \
+	container_of(dc_target, const struct core_target, public)
+#define DC_TARGET_TO_CORE(dc_target) \
+	container_of(dc_target, struct core_target, public)
+
+#define MAX_PIPES 6
+#define MAX_STREAMS 6
+#define MAX_CLOCK_SOURCES 7
+
+struct core_target {
+	struct dc_target public;
+	struct dc_target_status status;
+
+	struct dc_context *ctx;
+};
+
+/********* core_surface **********/
+#define DC_SURFACE_TO_CORE(dc_surface) \
+	container_of(dc_surface, struct core_surface, public)
+
+struct core_surface {
+	struct dc_surface public;
+	struct dc_surface_status status;
+	struct dc_context *ctx;
+};
+
+void enable_surface_flip_reporting(struct dc_surface *dc_surface,
+		uint32_t controller_id);
+
+/********* core_stream ************/
+#include "grph_object_id.h"
+#include "link_encoder.h"
+#include "stream_encoder.h"
+#include "clock_source.h"
+#include "audio_interface.h"
+#include "scaler_types.h"
+#include "hw_sequencer_types.h"
+#include "opp.h"
+
+#define DC_STREAM_TO_CORE(dc_stream) container_of( \
+	dc_stream, struct core_stream, public)
+
+#define PIXEL_CLOCK	27030
+
+struct core_stream {
+	struct dc_stream public;
+
+	/* field internal to DC */
+	const struct core_sink *sink;
+
+	struct clock_source *clock_source;
+
+	struct mem_input *mi;
+	struct input_pixel_processor *ipp;
+	struct transform *xfm;
+	struct output_pixel_processor *opp;
+	struct timing_generator *tg;
+	struct stream_encoder *stream_enc;
+	struct display_clock *dis_clk;
+
+	struct overscan_info overscan;
+	struct scaling_ratios ratios;
+	struct rect viewport;
+	struct scaling_taps taps;
+	enum pixel_format format;
+
+	uint8_t controller_idx;
+
+	struct audio *audio;
+
+	enum signal_type signal;
+
+	/* TODO: move these members into appropriate places (work in progress)*/
+	/* timing validation (HDMI only) */
+	uint32_t max_tmds_clk_from_edid_in_mhz;
+	/* maximum supported deep color depth for HDMI */
+	enum dc_color_depth max_hdmi_deep_color;
+	/* maximum supported pixel clock for HDMI */
+	uint32_t max_hdmi_pixel_clock;
+	/* end of TODO */
+
+	/*TODO: AUTO merge if possible*/
+	struct pixel_clk_params pix_clk_params;
+	struct pll_settings pll_settings;
+
+	/*fmt*/
+	/*TODO: AUTO new codepath in apply_context to hw to
+	 * generate these bw unrelated/no fail params*/
+	struct bit_depth_reduction_params bit_depth_params;/* used by DCP and FMT */
+	struct clamping_and_pixel_encoding_params clamping;
+	struct hw_info_frame info_frame;
+	struct encoder_info_frame encoder_info_frame;
+
+	struct audio_output audio_output;
+	struct dc_context *ctx;
+};
+
+
+/************ core_sink *****************/
+
+#define DC_SINK_TO_CORE(dc_sink) \
+	container_of(dc_sink, struct core_sink, public)
+
+struct core_sink {
+	/** The public, read-only (for DM) area of sink. **/
+	struct dc_sink public;
+	/** End-of-public area. **/
+
+	/** The 'protected' area - read/write access, for use only inside DC **/
+	/* not used for now */
+	struct core_link *link;
+	struct dc_context *ctx;
+	uint32_t dongle_max_pix_clk;
+	bool converter_disable_audio;
+};
+
+/************ link *****************/
+#define DC_LINK_TO_CORE(dc_link) container_of(dc_link, struct core_link, public)
+
+struct link_init_data {
+	const struct dc *dc;
+	struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */
+	uint32_t connector_index; /* this will be mapped to the HPD pins */
+	uint32_t link_index; /* this is mapped to DAL display_index
+				TODO: remove it when DC is complete. */
+	struct adapter_service *adapter_srv;
+};
+
+struct link_caps {
+	/* support for Spread Spectrum(SS) */
+	bool ss_supported;
+	/* DP link settings (laneCount, linkRate, Spread) */
+	uint32_t lane_count;
+	uint32_t rate;
+	uint32_t spread;
+	enum dpcd_revision dpcd_revision;
+};
+
+struct dpcd_caps {
+	union dpcd_rev dpcd_rev;
+	union max_lane_count max_ln_count;
+
+	/* dongle type (DP converter, CV smart dongle) */
+	enum display_dongle_type dongle_type;
+	/* Dongle's downstream count. */
+	union sink_count sink_count;
+	/* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER,
+	indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/
+	bool is_dp_hdmi_s3d_converter;
+
+	bool allow_invalid_MSA_timing_param;
+	bool panel_mode_edp;
+	uint32_t sink_dev_id;
+	uint32_t branch_dev_id;
+	int8_t branch_dev_name[6];
+};
+
+union dp_wa {
+	struct {
+		/* keep DP receiver powered up on DisplayOutput */
+		uint32_t KEEP_RECEIVER_POWERED:1;
+
+		/* TODO: may add other member in.*/
+	} bits;
+	uint32_t raw;
+};
+
+/* DP MST stream allocation (payload bandwidth number) */
+struct link_mst_stream_allocation {
+	/* DIG front */
+	const struct stream_encoder *stream_enc;
+	/* associate DRM payload table with DC stream encoder */
+	uint8_t vcp_id;
+	/* number of slots required for the DP stream in transport packet */
+	uint8_t slot_count;
+};
+
+/* DP MST stream allocation table */
+struct link_mst_stream_allocation_table {
+	/* number of DP video streams */
+	int stream_count;
+	/* array of stream allocations */
+	struct link_mst_stream_allocation
+	stream_allocations[MAX_CONTROLLER_NUM];
+};
+
+struct core_link {
+	struct dc_link public;
+	const struct dc *dc;
+
+	struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/
+
+	struct adapter_service *adapter_srv;
+	struct link_encoder *link_enc;
+	struct ddc_service *ddc;
+	struct graphics_object_id link_id;
+	union ddi_channel_mapping ddi_channel_mapping;
+	struct connector_device_tag_info device_tag;
+	/* caps is the same as reported_link_cap. link_traing use
+	 * reported_link_cap. Will clean up.  TODO */
+	struct link_settings reported_link_cap;
+	struct link_settings verified_link_cap;
+	struct link_settings max_link_setting;
+	struct link_settings cur_link_settings;
+	struct lane_settings ln_setting;
+	struct dpcd_caps dpcd_caps;
+	unsigned int dpcd_sink_count;
+
+	enum edp_revision edp_revision;
+
+	/* MST record stream using this link */
+	struct link_flags {
+		bool dp_keep_receiver_powered;
+	} wa_flags;
+	struct link_mst_stream_allocation_table mst_stream_alloc_table;
+};
+
+#define DC_LINK_TO_LINK(dc_link) container_of(dc_link, struct core_link, public)
+
+struct core_link *link_create(const struct link_init_data *init_params);
+void link_destroy(struct core_link **link);
+
+enum dc_status dc_link_validate_mode_timing(
+		const struct core_sink *sink,
+		struct core_link *link,
+		const struct dc_crtc_timing *timing);
+
+void core_link_resume(struct core_link *link);
+
+void core_link_enable_stream(
+		struct core_link *link,
+		struct core_stream *stream);
+
+void core_link_disable_stream(
+		struct core_link *link,
+		struct core_stream *stream);
+
+/********** DAL Core*********************/
+#include "display_clock_interface.h"
+
+struct resource_pool;
+struct validate_context;
+
+struct resource_funcs {
+	void (*destruct)(struct resource_pool *pool);
+	struct link_encoder *(*link_enc_create)(
+			const struct encoder_init_data *init);
+	void (*link_enc_destroy)(struct link_encoder **enc);
+	enum dc_status (*validate_with_context)(
+					const struct dc *dc,
+					const struct dc_validation_set set[],
+					uint8_t set_count,
+					struct validate_context *context);
+
+	enum dc_status (*validate_bandwidth)(
+					const struct dc *dc,
+					struct validate_context *context);
+};
+
+struct resource_pool {
+	struct scaler_filter * scaler_filter;
+
+	struct mem_input *mis[MAX_PIPES];
+	struct input_pixel_processor *ipps[MAX_PIPES];
+	struct transform *transforms[MAX_PIPES];
+	struct output_pixel_processor *opps[MAX_PIPES];
+	struct timing_generator *timing_generators[MAX_STREAMS];
+	struct stream_encoder *stream_enc[MAX_PIPES * 2];
+
+	uint8_t controller_count;
+	uint8_t stream_enc_count;
+
+	union supported_stream_engines stream_engines;
+
+	struct clock_source *clock_sources[MAX_CLOCK_SOURCES];
+	uint8_t clk_src_count;
+
+	struct audio *audios[MAX_STREAMS];
+	uint8_t audio_count;
+
+	struct display_clock *display_clock;
+	struct adapter_service *adapter_srv;
+	struct irq_service *irqs;
+
+	struct resource_funcs *funcs;
+};
+
+struct controller_ctx {
+	struct core_surface *surface;
+	struct core_stream *stream;
+	struct flags {
+		bool unchanged;
+		bool timing_changed;
+	} flags;
+};
+
+struct resource_context {
+	struct resource_pool pool;
+	struct controller_ctx controller_ctx[MAX_PIPES];
+	union supported_stream_engines used_stream_engines;
+	bool is_stream_enc_acquired[MAX_PIPES * 2];
+	bool is_audio_acquired[MAX_STREAMS];
+	uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES];
+ };
+
+struct target_flags {
+	bool unchanged;
+};
+struct validate_context {
+	struct core_target *targets[MAX_PIPES];
+	struct target_flags target_flags[MAX_PIPES];
+	uint8_t target_count;
+
+	struct resource_context res_ctx;
+
+	struct bw_calcs_mode_data bw_mode_data;
+	/* The output from BW and WM calculations. */
+	struct bw_calcs_output bw_results;
+};
+
+
+#endif /* _CORE_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
new file mode 100644
index 000000000000..18104d6fa6d3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DDC_SERVICE_H__
+#define __DAL_DDC_SERVICE_H__
+
+#include "include/ddc_service_types.h"
+#include "include/i2caux_interface.h"
+
+#define EDID_SEGMENT_SIZE 256
+
+struct ddc_service;
+struct adapter_service;
+struct graphics_object_id;
+enum ddc_result;
+struct av_sync_data;
+struct dp_receiver_id_info;
+
+struct i2c_payloads;
+struct aux_payloads;
+
+struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count);
+struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p);
+uint32_t  dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p);
+void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p);
+
+struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count);
+struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p);
+uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p);
+void dal_ddc_aux_payloads_destroy(struct aux_payloads **p);
+
+void dal_ddc_i2c_payloads_add(
+		struct i2c_payloads *payloads,
+		uint32_t address,
+		uint32_t len,
+		uint8_t *data,
+		bool write);
+
+void dal_ddc_aux_payloads_add(
+		struct aux_payloads *payloads,
+		uint32_t address,
+		uint32_t len,
+		uint8_t *data,
+		bool write);
+
+struct ddc_service_init_data {
+	struct adapter_service *as;
+	struct graphics_object_id id;
+	struct dc_context *ctx;
+};
+
+struct ddc_service *dal_ddc_service_create(
+		struct ddc_service_init_data *ddc_init_data);
+
+void dal_ddc_service_destroy(struct ddc_service **ddc);
+
+enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc);
+
+void dal_ddc_service_set_transaction_type(
+		struct ddc_service *ddc,
+		enum ddc_transaction_type type);
+
+bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc);
+
+uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc);
+
+uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc);
+
+void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf);
+
+void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
+		struct ddc_service *ddc,
+		struct display_sink_capability *sink_cap);
+
+bool dal_ddc_service_query_ddc_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		uint8_t *write_buf,
+		uint32_t write_size,
+		uint8_t *read_buf,
+		uint32_t read_size);
+
+bool dal_ddc_service_get_dp_receiver_id_info(
+		struct ddc_service *ddc,
+		struct dp_receiver_id_info *info);
+
+enum ddc_result dal_ddc_service_read_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t len);
+
+enum ddc_result dal_ddc_service_write_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t len);
+
+void dal_ddc_service_write_scdc_data(
+		struct ddc_service *ddc_service,
+		uint32_t pix_clk,
+		bool lte_340_scramble);
+
+void dal_ddc_service_read_scdc_data(
+		struct ddc_service *ddc_service);
+
+void ddc_service_set_dongle_type(struct ddc_service *ddc,
+		enum display_dongle_type dongle_type);
+
+void dal_ddc_service_set_ddc_pin(
+		struct ddc_service *ddc_service,
+		struct ddc *ddc);
+
+struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service);
+void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service);
+
+enum ddc_result dal_ddc_service_read_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t len);
+enum ddc_result dal_ddc_service_write_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t len);
+
+#endif /* __DAL_DDC_SERVICE_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
new file mode 100644
index 000000000000..682c0b432bdb
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_LINK_DP_H__
+#define __DC_LINK_DP_H__
+
+struct core_link;
+struct core_stream;
+struct link_settings;
+
+bool dp_hbr_verify_link_cap(
+	struct core_link *link,
+	struct link_settings *known_limit_link_setting);
+
+bool dp_validate_mode_timing(
+	struct core_link *link,
+	const struct dc_crtc_timing *timing);
+
+void decide_link_settings(
+	struct core_stream *stream,
+	struct link_settings *link_setting);
+
+bool perform_link_training(
+	struct core_link *link,
+	const struct link_settings *link_setting,
+	bool skip_video_pattern);
+
+bool is_mst_supported(struct core_link *link);
+
+void detect_dp_sink_caps(struct core_link *link);
+
+bool is_dp_active_dongle(const struct core_link *link);
+
+#endif /* __DC_LINK_DP_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
new file mode 100644
index 000000000000..17cb10f117e1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef GAMMA_TYPES_H_
+
+#define GAMMA_TYPES_H_
+
+#include "dc_types.h"
+#include "dm_services_types.h"
+
+/* TODO: Used in IPP and OPP */
+struct dev_c_lut {
+	uint8_t red;
+	uint8_t green;
+	uint8_t blue;
+};
+
+struct dev_c_lut16 {
+	uint16_t red;
+	uint16_t green;
+	uint16_t blue;
+};
+
+struct regamma_ramp {
+	uint16_t gamma[RGB_256X3X16 * 3];
+};
+
+/* used by Graphics and Overlay gamma */
+struct gamma_coeff {
+	int32_t gamma[3];
+	int32_t a0[3]; /* index 0 for red, 1 for green, 2 for blue */
+	int32_t a1[3];
+	int32_t a2[3];
+	int32_t a3[3];
+};
+
+struct regamma_lut {
+	union {
+		struct {
+			uint32_t GRAPHICS_DEGAMMA_SRGB :1;
+			uint32_t OVERLAY_DEGAMMA_SRGB :1;
+			uint32_t GAMMA_RAMP_ARRAY :1;
+			uint32_t APPLY_DEGAMMA :1;
+			uint32_t RESERVED :28;
+		} bits;
+		uint32_t value;
+	} features;
+
+	union {
+		struct regamma_ramp regamma_ramp;
+		struct gamma_coeff gamma_coeff;
+	};
+};
+
+union gamma_flag {
+	struct {
+		uint32_t config_is_changed :1;
+		uint32_t both_pipe_req :1;
+		uint32_t regamma_update :1;
+		uint32_t gamma_update :1;
+		uint32_t reserved :28;
+	} bits;
+	uint32_t u_all;
+};
+
+enum graphics_regamma_adjust {
+	GRAPHICS_REGAMMA_ADJUST_BYPASS = 0, GRAPHICS_REGAMMA_ADJUST_HW, /* without adjustments */
+	GRAPHICS_REGAMMA_ADJUST_SW /* use adjustments */
+};
+
+enum graphics_gamma_lut {
+	GRAPHICS_GAMMA_LUT_LEGACY = 0, /* use only legacy LUT */
+	GRAPHICS_GAMMA_LUT_REGAMMA, /* use only regamma LUT */
+	GRAPHICS_GAMMA_LUT_LEGACY_AND_REGAMMA /* use legacy & regamma LUT's */
+};
+
+enum graphics_degamma_adjust {
+	GRAPHICS_DEGAMMA_ADJUST_BYPASS = 0, GRAPHICS_DEGAMMA_ADJUST_HW, /*without adjustments */
+	GRAPHICS_DEGAMMA_ADJUST_SW /* use adjustments */
+};
+
+struct gamma_parameters {
+	union gamma_flag flag;
+	enum pixel_format surface_pixel_format; /*OS surface pixel format*/
+	struct regamma_lut regamma;
+
+	enum graphics_regamma_adjust regamma_adjust_type;
+	enum graphics_degamma_adjust degamma_adjust_type;
+
+	enum graphics_gamma_lut selected_gamma_lut;
+
+	bool disable_adjustments;
+
+	/* here we grow with parameters if necessary */
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
new file mode 100644
index 000000000000..8460dd729e91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HW_SEQUENCER_H__
+#define __DC_HW_SEQUENCER_H__
+#include "core_types.h"
+
+struct gamma_parameters;
+
+enum pipe_gating_control {
+	PIPE_GATING_CONTROL_DISABLE = 0,
+	PIPE_GATING_CONTROL_ENABLE,
+	PIPE_GATING_CONTROL_INIT
+};
+
+
+struct hw_sequencer_funcs {
+
+	enum dc_status (*apply_ctx_to_hw)(
+			const struct dc *dc, struct validate_context *context);
+
+	void (*reset_hw_ctx)(
+				struct dc *dc,
+				struct validate_context *context,
+				uint8_t target_count);
+
+	bool (*set_plane_config)(
+				const struct dc *dc,
+				struct core_surface *surface,
+				struct core_target *target);
+
+	bool (*update_plane_address)(
+				const struct dc *dc,
+				const struct core_surface *surface,
+				struct core_target *target);
+
+	bool (*set_gamma_ramp)(
+				struct input_pixel_processor *ipp,
+				struct output_pixel_processor *opp,
+				const struct gamma_ramp *ramp,
+				const struct gamma_parameters *params);
+
+	void (*power_down)(struct dc *dc);
+
+	void (*enable_accelerated_mode)(struct dc *dc);
+
+	void (*enable_timing_synchronization)(
+					struct dc_context *dc_ctx,
+					uint32_t timing_generator_num,
+					struct timing_generator *tgs[]);
+
+	/* backlight control */
+	void (*encoder_set_lcd_backlight_level)(
+		struct link_encoder *enc, uint32_t level);
+
+
+	void (*crtc_switch_to_clk_src)(struct clock_source *, uint8_t);
+
+	/* power management */
+	void (*clock_gating_power_up)(struct dc_context *ctx, bool enable);
+
+	void (*enable_display_pipe_clock_gating)(
+					struct dc_context *ctx,
+					bool clock_gating);
+
+	bool (*enable_display_power_gating)(
+					struct dc_context *ctx,
+					uint8_t controller_id,
+					struct dc_bios *dcb,
+					enum pipe_gating_control power_gating);
+
+	void (*program_bw)(struct dc *dc, struct validate_context *context);
+
+	void (*enable_stream)(struct core_stream *stream);
+
+	void (*disable_stream)(struct core_stream *stream);
+
+	void (*enable_fe_clock)(
+		struct dc_context *ctx, uint8_t controller_id, bool enable);
+
+	bool (*pipe_control_lock)(
+				struct dc_context *ctx,
+				uint8_t controller_idx,
+				uint32_t control_mask,
+				bool lock);
+
+	void (*set_blender_mode)(
+				struct dc_context *ctx,
+				uint8_t controller_id,
+				uint32_t mode);
+
+	void (*set_displaymarks)(
+				const struct dc *dc,
+				struct validate_context *context);
+
+	void (*set_display_clock)(struct validate_context *context);
+};
+
+bool dc_construct_hw_sequencer(
+				struct adapter_service *adapter_serv,
+				struct dc *dc);
+
+
+#endif /* __DC_HW_SEQUENCER_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/ipp.h b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h
new file mode 100644
index 000000000000..8e7cc31dfb9c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h
@@ -0,0 +1,106 @@
+
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IPP_H__
+#define __DAL_IPP_H__
+
+#include "include/grph_object_id.h"
+#include "include/grph_csc_types.h"
+#include "include/video_csc_types.h"
+#include "include/hw_sequencer_types.h"
+
+struct dev_c_lut;
+
+#define MAXTRIX_COEFFICIENTS_NUMBER 12
+#define MAXTRIX_COEFFICIENTS_WRAP_NUMBER (MAXTRIX_COEFFICIENTS_NUMBER + 4)
+#define MAX_OVL_MATRIX_COUNT 12
+
+/* IPP RELATED */
+struct input_pixel_processor {
+	struct  dc_context *ctx;
+	uint32_t inst;
+	struct ipp_funcs *funcs;
+};
+
+enum wide_gamut_degamma_mode {
+	/*  00  - BITS1:0 Bypass */
+	WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_BYPASS,
+	/*  0x1 - PWL gamma ROM A */
+	WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_PWL_ROM_A,
+	/*  0x2 - PWL gamma ROM B */
+	WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_PWL_ROM_B,
+	/*  00  - BITS5:4 Bypass */
+	WIDE_GAMUT_DEGAMMA_MODE_OVL_BYPASS,
+	/*  0x1 - PWL gamma ROM A */
+	WIDE_GAMUT_DEGAMMA_MODE_OVL_PWL_ROM_A,
+	/*  0x2 - PWL gamma ROM B */
+	WIDE_GAMUT_DEGAMMA_MODE_OVL_PWL_ROM_B,
+};
+
+struct dcp_video_matrix {
+	enum ovl_color_space color_space;
+	int32_t value[MAXTRIX_COEFFICIENTS_NUMBER];
+};
+
+struct ipp_funcs {
+
+	/* CURSOR RELATED */
+	bool (*ipp_cursor_set_position)(
+		struct input_pixel_processor *ipp,
+		const struct dc_cursor_position *position);
+
+	bool (*ipp_cursor_set_attributes)(
+		struct input_pixel_processor *ipp,
+		const struct dc_cursor_attributes *attributes);
+
+	/* DEGAMMA RELATED */
+	bool (*ipp_set_degamma)(
+		struct input_pixel_processor *ipp,
+		const struct gamma_parameters *params,
+		bool force_bypass);
+
+	void (*ipp_program_prescale)(
+		struct input_pixel_processor *ipp,
+		enum pixel_format pixel_format);
+
+	void (*ipp_set_legacy_input_gamma_mode)(
+			struct input_pixel_processor *ipp,
+			bool is_legacy);
+
+	bool (*ipp_set_legacy_input_gamma_ramp)(
+		struct input_pixel_processor *ipp,
+		const struct gamma_ramp *gamma_ramp,
+		const struct gamma_parameters *params);
+
+	bool (*ipp_set_palette)(
+		struct input_pixel_processor *ipp,
+		const struct dev_c_lut *palette,
+		uint32_t start,
+		uint32_t length,
+		enum pixel_format surface_pixel_format);
+};
+
+#endif /* __DAL_IPP_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
new file mode 100644
index 000000000000..d60c59463fc2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef LINK_ENCODER_H_
+#define LINK_ENCODER_H_
+
+#include "grph_object_defs.h"
+#include "signal_types.h"
+#include "dc_types.h"
+
+struct dc_context;
+struct adapter_service;
+struct encoder_set_dp_phy_pattern_param;
+struct link_mst_stream_allocation_table;
+struct link_settings;
+struct link_training_settings;
+struct core_stream;
+
+struct encoder_init_data {
+	struct adapter_service *adapter_service;
+	enum channel_id channel;
+	struct graphics_object_id connector;
+	enum hpd_source_id hpd_source;
+	/* TODO: in DAL2, here was pointer to EventManagerInterface */
+	struct graphics_object_id encoder;
+	struct dc_context *ctx;
+	enum transmitter transmitter;
+};
+
+struct encoder_feature_support {
+	union {
+		struct {
+			/* 1 - external encoder; 0 - internal encoder */
+			uint32_t EXTERNAL_ENCODER:1;
+			uint32_t ANALOG_ENCODER:1;
+			uint32_t STEREO_SYNC:1;
+			/* check the DDC data pin
+			 * when performing DP Sink detection */
+			uint32_t DP_SINK_DETECT_POLL_DATA_PIN:1;
+			/* CPLIB authentication
+			 * for external DP chip supported */
+			uint32_t CPLIB_DP_AUTHENTICATION:1;
+			uint32_t IS_HBR2_CAPABLE:1;
+			uint32_t IS_HBR2_VALIDATED:1;
+			uint32_t IS_TPS3_CAPABLE:1;
+			uint32_t IS_AUDIO_CAPABLE:1;
+			uint32_t IS_VCE_SUPPORTED:1;
+			uint32_t IS_CONVERTER:1;
+			uint32_t IS_Y_ONLY_CAPABLE:1;
+			uint32_t IS_YCBCR_CAPABLE:1;
+		} bits;
+		uint32_t raw;
+	} flags;
+	/* maximum supported deep color depth */
+	enum dc_color_depth max_deep_color;
+	/* maximum supported clock */
+	uint32_t max_pixel_clock;
+};
+
+struct link_enc_status {
+	int dummy; /*TODO*/
+};
+struct link_encoder {
+	struct link_encoder_funcs *funcs;
+	struct adapter_service *adapter_service;
+	int32_t aux_channel_offset;
+	struct dc_context *ctx;
+	struct graphics_object_id id;
+	struct graphics_object_id connector;
+	uint32_t input_signals;
+	uint32_t output_signals;
+	enum engine_id preferred_engine;
+	struct encoder_feature_support features;
+	enum transmitter transmitter;
+	enum hpd_source_id hpd_source;
+};
+
+struct link_encoder_funcs {
+	bool (*validate_output_with_stream)(struct link_encoder *enc,
+		struct core_stream *stream);
+	void (*hw_init)(struct link_encoder *enc);
+	void (*setup)(struct link_encoder *enc,
+		enum signal_type signal);
+	void (*enable_tmds_output)(struct link_encoder *enc,
+		enum clock_source_id clock_source,
+		enum dc_color_depth color_depth,
+		bool hdmi,
+		bool dual_link,
+		uint32_t pixel_clock);
+	void (*enable_dp_output)(struct link_encoder *enc,
+		const struct link_settings *link_settings,
+		enum clock_source_id clock_source);
+	void (*enable_dp_mst_output)(struct link_encoder *enc,
+		const struct link_settings *link_settings,
+		enum clock_source_id clock_source);
+	void (*disable_output)(struct link_encoder *link_enc,
+		enum signal_type signal);
+	void (*dp_set_lane_settings)(struct link_encoder *enc,
+		const struct link_training_settings *link_settings);
+	void (*dp_set_phy_pattern)(struct link_encoder *enc,
+		const struct encoder_set_dp_phy_pattern_param *para);
+	void (*update_mst_stream_allocation_table)(
+		struct link_encoder *enc,
+		const struct link_mst_stream_allocation_table *table);
+	void (*set_lcd_backlight_level) (struct link_encoder *enc,
+		uint32_t level);
+	void (*backlight_control) (struct link_encoder *enc,
+		bool enable);
+	void (*power_control) (struct link_encoder *enc,
+		bool power_up);
+	void (*connect_dig_be_to_fe)(struct link_encoder *enc,
+		enum engine_id engine,
+		bool connect);
+};
+
+#endif /* LINK_ENCODER_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
new file mode 100644
index 000000000000..d9a48c037c3e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_LINK_HWSS_H__
+#define __DC_LINK_HWSS_H__
+
+#include "inc/core_status.h"
+
+enum dc_status core_link_read_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t size);
+
+enum dc_status core_link_write_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t size);
+
+void dp_enable_link_phy(
+	struct core_link *link,
+	enum signal_type signal,
+	const struct link_settings *link_settings);
+
+void dp_receiver_power_ctrl(struct core_link *link, bool on);
+
+void dp_disable_link_phy(struct core_link *link, enum signal_type signal);
+
+void dp_disable_link_phy_mst(struct core_link *link, struct core_stream *stream);
+
+bool dp_set_hw_training_pattern(
+	struct core_link *link,
+	enum hw_dp_training_pattern pattern);
+
+void dp_set_hw_lane_settings(
+	struct core_link *link,
+	const struct link_training_settings *link_settings);
+
+void dp_set_hw_test_pattern(
+	struct core_link *link,
+	enum dp_test_pattern test_pattern);
+
+enum dp_panel_mode dp_get_panel_mode(struct core_link *link);
+
+#endif /* __DC_LINK_HWSS_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h b/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
new file mode 100644
index 000000000000..7d6335d3bcf4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_MEM_INPUT_H__
+#define __DAL_MEM_INPUT_H__
+
+#include "include/grph_object_id.h"
+#include "dc.h"
+
+struct mem_input {
+	struct mem_input_funcs *funcs;
+	struct dc_context *ctx;
+	uint32_t inst;
+};
+
+struct mem_input_funcs {
+	void (*mem_input_program_safe_display_marks)(struct mem_input *mi);
+	void (*mem_input_program_display_marks)(
+		struct mem_input *mem_input,
+		struct bw_watermarks nbp,
+		struct bw_watermarks stutter,
+		struct bw_watermarks urgent,
+		uint32_t h_total,
+		uint32_t pixel_clk_in_khz,
+		uint32_t pstate_blackout_duration_ns);
+	void (*mem_input_allocate_dmif_buffer)(
+			struct mem_input *mem_input,
+			struct dc_crtc_timing *timing,
+			uint32_t paths_num);
+	void (*mem_input_deallocate_dmif_buffer)(
+		struct mem_input *mem_input, uint32_t paths_num);
+	bool (*mem_input_program_surface_flip_and_addr)(
+		struct mem_input *mem_input,
+		const struct dc_plane_address *address,
+		bool flip_immediate);
+	bool (*mem_input_program_surface_config)(
+		struct mem_input *mem_input,
+		enum surface_pixel_format format,
+		struct dc_tiling_info *tiling_info,
+		union plane_size *plane_size,
+		enum dc_rotation_angle rotation);
+};
+
+enum stutter_mode_type {
+	STUTTER_MODE_LEGACY = 0X00000001,
+	STUTTER_MODE_ENHANCED = 0X00000002,
+	STUTTER_MODE_FID_NBP_STATE = 0X00000004,
+	STUTTER_MODE_WATERMARK_NBP_STATE = 0X00000008,
+	STUTTER_MODE_SINGLE_DISPLAY_MODEL = 0X00000010,
+	STUTTER_MODE_MIXED_DISPLAY_MODEL = 0X00000020,
+	STUTTER_MODE_DUAL_DMIF_BUFFER = 0X00000040,
+	STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION = 0X00000080,
+	STUTTER_MODE_NO_ADVANCED_REQUEST = 0X00000100,
+	STUTTER_MODE_NO_LB_RESET = 0X00000200,
+	STUTTER_MODE_DISABLED = 0X00000400,
+	STUTTER_MODE_AGGRESSIVE_MARKS = 0X00000800,
+	STUTTER_MODE_URGENCY = 0X00001000,
+	STUTTER_MODE_QUAD_DMIF_BUFFER = 0X00002000,
+	STUTTER_MODE_NOT_USED = 0X00008000
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/opp.h b/drivers/gpu/drm/amd/dal/dc/inc/opp.h
new file mode 100644
index 000000000000..b097983246df
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/opp.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_OPP_H__
+#define __DAL_OPP_H__
+
+#include "dc_types.h"
+#include "grph_object_id.h"
+#include "grph_csc_types.h"
+#include "dm_services_types.h"
+
+struct fixed31_32;
+struct gamma_parameters;
+
+/* TODO: Need cleanup */
+
+enum clamping_range {
+	CLAMPING_FULL_RANGE = 0,	   /* No Clamping */
+	CLAMPING_LIMITED_RANGE_8BPC,   /* 8  bpc: Clamping 1  to FE */
+	CLAMPING_LIMITED_RANGE_10BPC, /* 10 bpc: Clamping 4  to 3FB */
+	CLAMPING_LIMITED_RANGE_12BPC, /* 12 bpc: Clamping 10 to FEF */
+	/* Use programmable clampping value on FMT_CLAMP_COMPONENT_R/G/B. */
+	CLAMPING_LIMITED_RANGE_PROGRAMMABLE
+};
+
+struct clamping_and_pixel_encoding_params {
+	enum dc_pixel_encoding pixel_encoding; /* Pixel Encoding */
+	enum clamping_range clamping_level; /* Clamping identifier */
+	enum dc_color_depth c_depth; /* Deep color use. */
+};
+
+struct bit_depth_reduction_params {
+	struct {
+		/* truncate/round */
+		/* trunc/round enabled*/
+		uint32_t TRUNCATE_ENABLED:1;
+		/* 2 bits: 0=6 bpc, 1=8 bpc, 2 = 10bpc*/
+		uint32_t TRUNCATE_DEPTH:2;
+		/* truncate or round*/
+		uint32_t TRUNCATE_MODE:1;
+
+		/* spatial dither */
+		/* Spatial Bit Depth Reduction enabled*/
+		uint32_t SPATIAL_DITHER_ENABLED:1;
+		/* 2 bits: 0=6 bpc, 1 = 8 bpc, 2 = 10bpc*/
+		uint32_t SPATIAL_DITHER_DEPTH:2;
+		/* 0-3 to select patterns*/
+		uint32_t SPATIAL_DITHER_MODE:2;
+		/* Enable RGB random dithering*/
+		uint32_t RGB_RANDOM:1;
+		/* Enable Frame random dithering*/
+		uint32_t FRAME_RANDOM:1;
+		/* Enable HighPass random dithering*/
+		uint32_t HIGHPASS_RANDOM:1;
+
+		/* temporal dither*/
+		 /* frame modulation enabled*/
+		uint32_t FRAME_MODULATION_ENABLED:1;
+		/* same as for trunc/spatial*/
+		uint32_t FRAME_MODULATION_DEPTH:2;
+		/* 2/4 gray levels*/
+		uint32_t TEMPORAL_LEVEL:1;
+		uint32_t FRC25:2;
+		uint32_t FRC50:2;
+		uint32_t FRC75:2;
+	} flags;
+
+	uint32_t r_seed_value;
+	uint32_t b_seed_value;
+	uint32_t g_seed_value;
+};
+
+
+
+enum wide_gamut_regamma_mode {
+	/*  0x0  - BITS2:0 Bypass */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS,
+	/*  0x1  - Fixed curve sRGB 2.4 */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24,
+	/*  0x2  - Fixed curve xvYCC 2.22 */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22,
+	/*  0x3  - Programmable control A */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A,
+	/*  0x4  - Programmable control B */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B,
+	/*  0x0  - BITS6:4 Bypass */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_BYPASS,
+	/*  0x1  - Fixed curve sRGB 2.4 */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_SRGB24,
+	/*  0x2  - Fixed curve xvYCC 2.22 */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_XYYCC22,
+	/*  0x3  - Programmable control A */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_A,
+	/*  0x4  - Programmable control B */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_B
+};
+
+struct pwl_result_data {
+	struct fixed31_32 red;
+	struct fixed31_32 green;
+	struct fixed31_32 blue;
+
+	struct fixed31_32 delta_red;
+	struct fixed31_32 delta_green;
+	struct fixed31_32 delta_blue;
+
+	uint32_t red_reg;
+	uint32_t green_reg;
+	uint32_t blue_reg;
+
+	uint32_t delta_red_reg;
+	uint32_t delta_green_reg;
+	uint32_t delta_blue_reg;
+};
+
+struct gamma_pixel {
+	struct fixed31_32 r;
+	struct fixed31_32 g;
+	struct fixed31_32 b;
+};
+
+struct gamma_curve {
+	uint32_t offset;
+	uint32_t segments_num;
+};
+
+struct curve_points {
+	struct fixed31_32 x;
+	struct fixed31_32 y;
+	struct fixed31_32 offset;
+	struct fixed31_32 slope;
+
+	uint32_t custom_float_x;
+	uint32_t custom_float_y;
+	uint32_t custom_float_offset;
+	uint32_t custom_float_slope;
+};
+
+enum channel_name {
+	CHANNEL_NAME_RED,
+	CHANNEL_NAME_GREEN,
+	CHANNEL_NAME_BLUE
+};
+
+struct custom_float_format {
+	uint32_t mantissa_bits;
+	uint32_t exponenta_bits;
+	bool sign;
+};
+
+struct custom_float_value {
+	uint32_t mantissa;
+	uint32_t exponenta;
+	uint32_t value;
+	bool negative;
+};
+
+struct hw_x_point {
+	uint32_t custom_float_x;
+	uint32_t custom_float_x_adjusted;
+	struct fixed31_32 x;
+	struct fixed31_32 adjusted_x;
+	struct fixed31_32 regamma_y_red;
+	struct fixed31_32 regamma_y_green;
+	struct fixed31_32 regamma_y_blue;
+
+};
+
+struct pwl_float_data_ex {
+	struct fixed31_32 r;
+	struct fixed31_32 g;
+	struct fixed31_32 b;
+	struct fixed31_32 delta_r;
+	struct fixed31_32 delta_g;
+	struct fixed31_32 delta_b;
+};
+
+enum hw_point_position {
+	/* hw point sits between left and right sw points */
+	HW_POINT_POSITION_MIDDLE,
+	/* hw point lays left from left (smaller) sw point */
+	HW_POINT_POSITION_LEFT,
+	/* hw point lays stays from right (bigger) sw point */
+	HW_POINT_POSITION_RIGHT
+};
+
+struct gamma_point {
+	int32_t left_index;
+	int32_t right_index;
+	enum hw_point_position pos;
+	struct fixed31_32 coeff;
+};
+
+struct pixel_gamma_point {
+	struct gamma_point r;
+	struct gamma_point g;
+	struct gamma_point b;
+};
+
+struct gamma_coefficients {
+	struct fixed31_32 a0[3];
+	struct fixed31_32 a1[3];
+	struct fixed31_32 a2[3];
+	struct fixed31_32 a3[3];
+	struct fixed31_32 user_gamma[3];
+	struct fixed31_32 user_contrast;
+	struct fixed31_32 user_brightness;
+};
+
+struct csc_adjustments {
+	struct fixed31_32 contrast;
+	struct fixed31_32 saturation;
+	struct fixed31_32 brightness;
+	struct fixed31_32 hue;
+};
+
+struct pwl_float_data {
+	struct fixed31_32 r;
+	struct fixed31_32 g;
+	struct fixed31_32 b;
+};
+
+
+/* TODO: Use when we redefine the OPP interface */
+enum opp_regamma {
+	OPP_REGAMMA_BYPASS = 0,
+	OPP_REGAMMA_SRGB,
+	OPP_REGAMMA_3_6,
+	OPP_REGAMMA_PQ,
+	OPP_REGAMMA_PQ_INTERIM,
+};
+
+struct output_pixel_processor {
+	struct dc_context *ctx;
+	uint32_t inst;
+	struct opp_funcs *funcs;
+};
+
+enum fmt_stereo_action {
+	FMT_STEREO_ACTION_ENABLE = 0,
+	FMT_STEREO_ACTION_DISABLE,
+	FMT_STEREO_ACTION_UPDATE_POLARITY
+};
+
+struct opp_funcs {
+	void (*opp_power_on_regamma_lut)(
+		struct output_pixel_processor *opp,
+		bool power_on);
+
+	bool (*opp_set_regamma)(
+		struct output_pixel_processor *opp,
+		const struct gamma_ramp *ramp,
+		const struct gamma_parameters *params,
+		bool force_bypass);
+
+	bool (*opp_map_legacy_and_regamma_hw_to_x_user)(
+		struct output_pixel_processor *opp,
+		const struct gamma_ramp *gamma_ramp,
+		const struct gamma_parameters *params);
+
+	void (*opp_set_csc_adjustment)(
+		struct output_pixel_processor *opp,
+		const struct grph_csc_adjustment *adjust);
+
+	void (*opp_set_csc_default)(
+		struct output_pixel_processor *opp,
+		const struct default_adjustment *default_adjust);
+
+	/* FORMATTER RELATED */
+	void (*opp_program_bit_depth_reduction)(
+		struct output_pixel_processor *opp,
+		const struct bit_depth_reduction_params *params);
+
+	void (*opp_program_clamping_and_pixel_encoding)(
+		struct output_pixel_processor *opp,
+		const struct clamping_and_pixel_encoding_params *params);
+
+
+	void (*opp_set_dyn_expansion)(
+		struct output_pixel_processor *opp,
+		enum color_space color_sp,
+		enum dc_color_depth color_dpth,
+		enum signal_type signal);
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/resource.h b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
new file mode 100644
index 000000000000..bda92e3c4f66
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ */
+
+#ifndef DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_
+#define DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_
+
+#include "core_types.h"
+#include "core_status.h"
+#include "core_dc.h"
+
+/* TODO unhardcode, 4 for CZ*/
+#define MEMORY_TYPE_MULTIPLIER 4
+
+bool dc_construct_resource_pool(struct adapter_service *adapter_serv,
+				struct dc *dc,
+				uint8_t num_virtual_links);
+
+void build_scaling_params(
+	const struct dc_surface *surface,
+	struct core_stream *stream);
+
+void build_scaling_params_for_context(
+	const struct dc *dc,
+	struct validate_context *context);
+
+void unreference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source);
+
+void reference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source);
+
+bool is_same_timing(
+	const struct dc_crtc_timing *timing1,
+	const struct dc_crtc_timing *timing2);
+
+struct clock_source *find_used_clk_src_for_sharing(
+		struct validate_context *context,
+		struct core_stream *stream);
+
+bool logical_attach_surfaces_to_target(
+		struct dc_surface *surfaces[],
+		uint8_t surface_count,
+		struct dc_target *dc_target);
+
+void pplib_apply_safe_state(const struct dc *dc);
+
+void pplib_apply_display_requirements(
+	const struct dc *dc,
+	const struct validate_context *context);
+
+void build_info_frame(struct core_stream *stream);
+
+enum dc_status map_resources(
+	const struct dc *dc,
+	struct validate_context *context);
+
+#endif /* DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
new file mode 100644
index 000000000000..6bb1d007de21
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
@@ -0,0 +1,88 @@
+/*
+ * stream_encoder.h
+ *
+ */
+
+#ifndef STREAM_ENCODER_H_
+#define STREAM_ENCODER_H_
+
+#include "include/hw_sequencer_types.h"
+
+struct dc_bios;
+struct dc_context;
+struct dc_crtc_timing;
+
+
+struct encoder_info_packet {
+	bool valid;
+	uint8_t hb0;
+	uint8_t hb1;
+	uint8_t hb2;
+	uint8_t hb3;
+	uint8_t sb[28];
+};
+
+struct encoder_info_frame {
+	/* auxiliary video information */
+	struct encoder_info_packet avi;
+	struct encoder_info_packet gamut;
+	struct encoder_info_packet vendor;
+	/* source product description */
+	struct encoder_info_packet spd;
+	/* video stream configuration */
+	struct encoder_info_packet vsc;
+};
+
+struct encoder_unblank_param {
+	struct hw_crtc_timing crtc_timing;
+	struct link_settings link_settings;
+};
+
+struct encoder_set_dp_phy_pattern_param {
+	enum dp_test_pattern dp_phy_pattern;
+	const uint8_t *custom_pattern;
+	uint32_t custom_pattern_size;
+	enum dp_panel_mode dp_panel_mode;
+};
+
+
+struct stream_encoder {
+	struct stream_encoder_funcs *funcs;
+	struct dc_context *ctx;
+	struct dc_bios *bp;
+	enum engine_id id;
+};
+
+struct stream_encoder_funcs {
+	void (*dp_set_stream_attribute)(
+		struct stream_encoder *enc,
+		struct dc_crtc_timing *crtc_timing);
+	void (*hdmi_set_stream_attribute)(
+		struct stream_encoder *enc,
+		struct dc_crtc_timing *crtc_timing,
+		bool enable_audio);
+	void (*dvi_set_stream_attribute)(
+		struct stream_encoder *enc,
+		struct dc_crtc_timing *crtc_timing,
+		bool is_dual_link);
+	void (*set_mst_bandwidth)(
+		struct stream_encoder *enc,
+		struct fixed31_32 avg_time_slots_per_mtp);
+	void (*update_hdmi_info_packets)(
+		struct stream_encoder *enc,
+		const struct encoder_info_frame *info_frame);
+	void (*stop_hdmi_info_packets)(
+		struct stream_encoder *enc);
+	void (*update_dp_info_packets)(
+		struct stream_encoder *enc,
+		const struct encoder_info_frame *info_frame);
+	void (*stop_dp_info_packets)(
+		struct stream_encoder *enc);
+	void (*dp_blank)(
+		struct stream_encoder *enc);
+	void (*dp_unblank)(
+		struct stream_encoder *enc,
+		const struct encoder_unblank_param *param);
+};
+
+#endif /* STREAM_ENCODER_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h b/drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
new file mode 100644
index 000000000000..e9ca16938572
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TIMING_GENERATOR_TYPES_H__
+#define __DAL_TIMING_GENERATOR_TYPES_H__
+
+#include "include/grph_csc_types.h"
+
+struct dc_bios;
+
+/**
+ *  These parameters are required as input when doing blanking/Unblanking
+*/
+struct crtc_black_color {
+	uint32_t black_color_r_cr;
+	uint32_t black_color_g_y;
+	uint32_t black_color_b_cb;
+};
+
+/* Contains CRTC vertical/horizontal pixel counters */
+struct crtc_position {
+	uint32_t vertical_count;
+	uint32_t horizontal_count;
+	uint32_t nominal_vcount;
+};
+
+
+enum dcp_gsl_purpose {
+	DCP_GSL_PURPOSE_SURFACE_FLIP = 0,
+	DCP_GSL_PURPOSE_STEREO3D_PHASE,
+	DCP_GSL_PURPOSE_UNDEFINED
+};
+
+struct dcp_gsl_params {
+	enum sync_source gsl_group;
+	enum dcp_gsl_purpose gsl_purpose;
+	bool timing_server;
+	bool overlay_present;
+	bool gsl_paused;
+};
+
+#define LEFT_EYE_3D_PRIMARY_SURFACE 1
+#define RIGHT_EYE_3D_PRIMARY_SURFACE 0
+
+enum test_pattern_dyn_range {
+	TEST_PATTERN_DYN_RANGE_VESA = 0,
+	TEST_PATTERN_DYN_RANGE_CEA
+};
+
+enum test_pattern_mode {
+	TEST_PATTERN_MODE_COLORSQUARES_RGB = 0,
+	TEST_PATTERN_MODE_COLORSQUARES_YCBCR601,
+	TEST_PATTERN_MODE_COLORSQUARES_YCBCR709,
+	TEST_PATTERN_MODE_VERTICALBARS,
+	TEST_PATTERN_MODE_HORIZONTALBARS,
+	TEST_PATTERN_MODE_SINGLERAMP_RGB,
+	TEST_PATTERN_MODE_DUALRAMP_RGB
+};
+
+enum test_pattern_color_format {
+	TEST_PATTERN_COLOR_FORMAT_BPC_6 = 0,
+	TEST_PATTERN_COLOR_FORMAT_BPC_8,
+	TEST_PATTERN_COLOR_FORMAT_BPC_10,
+	TEST_PATTERN_COLOR_FORMAT_BPC_12
+};
+
+enum controller_dp_test_pattern {
+	CONTROLLER_DP_TEST_PATTERN_D102 = 0,
+	CONTROLLER_DP_TEST_PATTERN_SYMBOLERROR,
+	CONTROLLER_DP_TEST_PATTERN_PRBS7,
+	CONTROLLER_DP_TEST_PATTERN_COLORSQUARES,
+	CONTROLLER_DP_TEST_PATTERN_VERTICALBARS,
+	CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS,
+	CONTROLLER_DP_TEST_PATTERN_COLORRAMP,
+	CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+	CONTROLLER_DP_TEST_PATTERN_RESERVED_8,
+	CONTROLLER_DP_TEST_PATTERN_RESERVED_9,
+	CONTROLLER_DP_TEST_PATTERN_RESERVED_A,
+	CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA
+};
+
+enum crtc_state {
+	CRTC_STATE_VBLANK = 0,
+	CRTC_STATE_VACTIVE
+};
+
+struct timing_generator {
+	struct timing_generator_funcs *funcs;
+	struct dc_bios *bp;
+	struct dc_context *ctx;
+};
+
+
+struct dc_crtc_timing;
+
+struct timing_generator_funcs {
+	bool (*validate_timing)(struct timing_generator *tg,
+							const struct dc_crtc_timing *timing);
+	void (*program_timing)(struct timing_generator *tg,
+							const struct dc_crtc_timing *timing,
+							bool use_vbios);
+	bool (*enable_crtc)(struct timing_generator *tg);
+	bool (*disable_crtc)(struct timing_generator *tg);
+	bool (*is_counter_moving)(struct timing_generator *tg);
+	void (*get_position)(struct timing_generator *tg,
+								int32_t *h_position,
+								int32_t *v_position);
+	uint32_t (*get_frame_count)(struct timing_generator *tg);
+	void (*set_early_control)(struct timing_generator *tg,
+							   uint32_t early_cntl);
+	void (*wait_for_state)(struct timing_generator *tg,
+							enum crtc_state state);
+	bool (*set_blank)(struct timing_generator *tg,
+					   bool enable_blanking);
+	void (*set_overscan_blank_color) (struct timing_generator *tg, enum color_space black_color);
+	void (*set_blank_color)(struct timing_generator *tg, enum color_space black_color);
+	void (*set_colors)(struct timing_generator *tg,
+						const struct crtc_black_color *blank_color,
+						const struct crtc_black_color *overscan_color);
+
+	void (*disable_vga)(struct timing_generator *tg);
+	bool (*did_triggered_reset_occur)(struct timing_generator *tg);
+	void (*setup_global_swap_lock)(struct timing_generator *tg,
+							const struct dcp_gsl_params *gsl_params);
+	void (*enable_reset_trigger)(struct timing_generator *tg,
+						const struct trigger_params *trigger_params);
+	void (*disable_reset_trigger)(struct timing_generator *tg);
+	void (*tear_down_global_swap_lock)(struct timing_generator *tg);
+	void (*enable_advanced_request)(struct timing_generator *tg,
+					bool enable, const struct dc_crtc_timing *timing);
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/transform.h b/drivers/gpu/drm/amd/dal/dc/inc/transform.h
new file mode 100644
index 000000000000..22803575ed72
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/transform.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TRANSFORM_H__
+#define __DAL_TRANSFORM_H__
+
+#include "include/scaler_types.h"
+#include "include/grph_csc_types.h"
+#include "calcs/scaler_filter.h"
+#include "grph_object_id.h"
+
+struct bit_depth_reduction_params;
+
+enum scaling_type {
+	SCALING_TYPE_NO_SCALING = 0,
+	SCALING_TYPE_UPSCALING,
+	SCALING_TYPE_DOWNSCALING
+};
+
+struct transform {
+	struct transform_funcs *funcs;
+	struct dc_context *ctx;
+	uint32_t inst;
+	struct scaler_filter *filter;
+};
+
+
+struct scaler_taps_and_ratio {
+	uint32_t h_tap;
+	uint32_t v_tap;
+	uint32_t lo_ratio;
+	uint32_t hi_ratio;
+};
+
+struct scaler_taps {
+	uint32_t h_tap;
+	uint32_t v_tap;
+};
+
+struct sclv_ratios_inits {
+	uint32_t chroma_enable;
+	uint32_t h_int_scale_ratio_luma;
+	uint32_t h_int_scale_ratio_chroma;
+	uint32_t v_int_scale_ratio_luma;
+	uint32_t v_int_scale_ratio_chroma;
+	struct init_int_and_frac h_init_luma;
+	struct init_int_and_frac h_init_chroma;
+	struct init_int_and_frac v_init_luma;
+	struct init_int_and_frac v_init_chroma;
+	struct init_int_and_frac h_init_lumabottom;
+	struct init_int_and_frac h_init_chromabottom;
+	struct init_int_and_frac v_init_lumabottom;
+	struct init_int_and_frac v_init_chromabottom;
+};
+
+enum lb_pixel_depth {
+	/* do not change the values because it is used as bit vector */
+	LB_PIXEL_DEPTH_18BPP = 1,
+	LB_PIXEL_DEPTH_24BPP = 2,
+	LB_PIXEL_DEPTH_30BPP = 4,
+	LB_PIXEL_DEPTH_36BPP = 8
+};
+
+
+struct raw_gamma_ramp_rgb {
+       uint32_t red;
+       uint32_t green;
+       uint32_t blue;
+};
+
+enum raw_gamma_ramp_type {
+       GAMMA_RAMP_TYPE_UNINITIALIZED,
+       GAMMA_RAMP_TYPE_DEFAULT,
+       GAMMA_RAMP_TYPE_RGB256,
+       GAMMA_RAMP_TYPE_FIXED_POINT
+};
+
+#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256
+struct raw_gamma_ramp {
+       enum raw_gamma_ramp_type type;
+       struct raw_gamma_ramp_rgb rgb_256[NUM_OF_RAW_GAMMA_RAMP_RGB_256];
+       uint32_t size;
+};
+
+
+/* Colorimetry */
+enum colorimetry {
+       COLORIMETRY_NO_DATA = 0,
+       COLORIMETRY_ITU601 = 1,
+       COLORIMETRY_ITU709 = 2,
+       COLORIMETRY_EXTENDED = 3
+};
+
+/* ColorimetryEx */
+enum colorimetry_ex {
+       COLORIMETRY_EX_XVYCC601 = 0,
+       COLORIMETRY_EX_XVYCC709 = 1,
+       COLORIMETRY_EX_SYCC601 = 2,
+       COLORIMETRY_EX_ADOBEYCC601 = 3,
+       COLORIMETRY_EX_ADOBERGB = 4,
+       COLORIMETRY_EX_RESERVED5 = 5,
+       COLORIMETRY_EX_RESERVED6 = 6,
+       COLORIMETRY_EX_RESERVED7 = 7
+};
+
+enum ds_color_space {
+       DS_COLOR_SPACE_UNKNOWN = 0,
+       DS_COLOR_SPACE_SRGB_FULLRANGE = 1,
+       DS_COLOR_SPACE_SRGB_LIMITEDRANGE,
+       DS_COLOR_SPACE_YPBPR601,
+       DS_COLOR_SPACE_YPBPR709,
+       DS_COLOR_SPACE_YCBCR601,
+       DS_COLOR_SPACE_YCBCR709,
+       DS_COLOR_SPACE_NMVPU_SUPERAA,
+       DS_COLOR_SPACE_YCBCR601_YONLY,
+       DS_COLOR_SPACE_YCBCR709_YONLY/*same as YCbCr, but Y in Full range*/
+};
+
+
+enum active_format_info {
+       ACTIVE_FORMAT_NO_DATA = 0,
+       ACTIVE_FORMAT_VALID = 1
+};
+
+/* Active format aspect ratio */
+enum active_format_aspect_ratio {
+       ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE = 8,
+       ACTIVE_FORMAT_ASPECT_RATIO_4_3 = 9,
+       ACTIVE_FORMAT_ASPECT_RATIO_16_9 = 0XA,
+       ACTIVE_FORMAT_ASPECT_RATIO_14_9 = 0XB
+};
+
+enum bar_info {
+       BAR_INFO_NOT_VALID = 0,
+       BAR_INFO_VERTICAL_VALID = 1,
+       BAR_INFO_HORIZONTAL_VALID = 2,
+       BAR_INFO_BOTH_VALID = 3
+};
+
+enum picture_scaling {
+       PICTURE_SCALING_UNIFORM = 0,
+       PICTURE_SCALING_HORIZONTAL = 1,
+       PICTURE_SCALING_VERTICAL = 2,
+       PICTURE_SCALING_BOTH = 3
+};
+
+/* RGB quantization range */
+enum rgb_quantization_range {
+       RGB_QUANTIZATION_DEFAULT_RANGE = 0,
+       RGB_QUANTIZATION_LIMITED_RANGE = 1,
+       RGB_QUANTIZATION_FULL_RANGE = 2,
+       RGB_QUANTIZATION_RESERVED = 3
+};
+
+/* YYC quantization range */
+enum yyc_quantization_range {
+       YYC_QUANTIZATION_LIMITED_RANGE = 0,
+       YYC_QUANTIZATION_FULL_RANGE = 1,
+       YYC_QUANTIZATION_RESERVED2 = 2,
+       YYC_QUANTIZATION_RESERVED3 = 3
+};
+
+struct transform_funcs {
+	bool (*transform_power_up)(struct transform *xfm);
+
+	bool (*transform_set_scaler)(
+		struct transform *xfm,
+		const struct scaler_data *data);
+
+	void (*transform_set_scaler_bypass)(struct transform *xfm);
+
+	bool (*transform_update_viewport)(
+		struct transform *xfm,
+		const struct rect *view_port,
+		bool is_fbc_attached);
+
+	void (*transform_set_scaler_filter)(
+		struct transform *xfm,
+		struct scaler_filter *filter);
+
+	void (*transform_set_gamut_remap)(
+		struct transform *xfm,
+		const struct grph_csc_adjustment *adjust);
+
+	bool (*transform_set_pixel_storage_depth)(
+		struct transform *xfm,
+		enum lb_pixel_depth depth,
+		const struct bit_depth_reduction_params *bit_depth_params);
+
+	bool (*transform_get_current_pixel_storage_depth)(
+		struct transform *xfm,
+		enum lb_pixel_depth *depth);
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/irq_types.h b/drivers/gpu/drm/amd/dal/dc/irq_types.h
new file mode 100644
index 000000000000..35a099166613
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq_types.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_TYPES_H__
+#define __DAL_IRQ_TYPES_H__
+
+struct dc_context;
+
+typedef void (*interrupt_handler)(void *);
+
+typedef void *irq_handler_idx;
+#define DAL_INVALID_IRQ_HANDLER_IDX NULL
+
+
+/* The order of the IRQ sources is important and MUST match the one's
+of base driver */
+enum dc_irq_source {
+	/* Use as mask to specify invalid irq source */
+	DC_IRQ_SOURCE_INVALID = 0,
+
+	DC_IRQ_SOURCE_HPD1,
+	DC_IRQ_SOURCE_HPD2,
+	DC_IRQ_SOURCE_HPD3,
+	DC_IRQ_SOURCE_HPD4,
+	DC_IRQ_SOURCE_HPD5,
+	DC_IRQ_SOURCE_HPD6,
+
+	DC_IRQ_SOURCE_HPD1RX,
+	DC_IRQ_SOURCE_HPD2RX,
+	DC_IRQ_SOURCE_HPD3RX,
+	DC_IRQ_SOURCE_HPD4RX,
+	DC_IRQ_SOURCE_HPD5RX,
+	DC_IRQ_SOURCE_HPD6RX,
+
+	DC_IRQ_SOURCE_I2C_DDC1,
+	DC_IRQ_SOURCE_I2C_DDC2,
+	DC_IRQ_SOURCE_I2C_DDC3,
+	DC_IRQ_SOURCE_I2C_DDC4,
+	DC_IRQ_SOURCE_I2C_DDC5,
+	DC_IRQ_SOURCE_I2C_DDC6,
+
+	DC_IRQ_SOURCE_AZALIA0,
+	DC_IRQ_SOURCE_AZALIA1,
+	DC_IRQ_SOURCE_AZALIA2,
+	DC_IRQ_SOURCE_AZALIA3,
+	DC_IRQ_SOURCE_AZALIA4,
+	DC_IRQ_SOURCE_AZALIA5,
+
+	DC_IRQ_SOURCE_DPSINK1,
+	DC_IRQ_SOURCE_DPSINK2,
+	DC_IRQ_SOURCE_DPSINK3,
+	DC_IRQ_SOURCE_DPSINK4,
+	DC_IRQ_SOURCE_DPSINK5,
+	DC_IRQ_SOURCE_DPSINK6,
+
+	DC_IRQ_SOURCE_CRTC1VSYNC,
+	DC_IRQ_SOURCE_CRTC2VSYNC,
+	DC_IRQ_SOURCE_CRTC3VSYNC,
+	DC_IRQ_SOURCE_CRTC4VSYNC,
+	DC_IRQ_SOURCE_CRTC5VSYNC,
+	DC_IRQ_SOURCE_CRTC6VSYNC,
+	DC_IRQ_SOURCE_TIMER,
+
+	DC_IRQ_SOURCE_PFLIP_FIRST,
+	DC_IRQ_SOURCE_PFLIP1 = DC_IRQ_SOURCE_PFLIP_FIRST,
+	DC_IRQ_SOURCE_PFLIP2,
+	DC_IRQ_SOURCE_PFLIP3,
+	DC_IRQ_SOURCE_PFLIP4,
+	DC_IRQ_SOURCE_PFLIP5,
+	DC_IRQ_SOURCE_PFLIP6,
+	DC_IRQ_SOURCE_PFLIP_UNDERLAY0,
+	DC_IRQ_SOURCE_PFLIP_LAST = DC_IRQ_SOURCE_PFLIP_UNDERLAY0,
+
+	DC_IRQ_SOURCE_GPIOPAD0,
+	DC_IRQ_SOURCE_GPIOPAD1,
+	DC_IRQ_SOURCE_GPIOPAD2,
+	DC_IRQ_SOURCE_GPIOPAD3,
+	DC_IRQ_SOURCE_GPIOPAD4,
+	DC_IRQ_SOURCE_GPIOPAD5,
+	DC_IRQ_SOURCE_GPIOPAD6,
+	DC_IRQ_SOURCE_GPIOPAD7,
+	DC_IRQ_SOURCE_GPIOPAD8,
+	DC_IRQ_SOURCE_GPIOPAD9,
+	DC_IRQ_SOURCE_GPIOPAD10,
+	DC_IRQ_SOURCE_GPIOPAD11,
+	DC_IRQ_SOURCE_GPIOPAD12,
+	DC_IRQ_SOURCE_GPIOPAD13,
+	DC_IRQ_SOURCE_GPIOPAD14,
+	DC_IRQ_SOURCE_GPIOPAD15,
+	DC_IRQ_SOURCE_GPIOPAD16,
+	DC_IRQ_SOURCE_GPIOPAD17,
+	DC_IRQ_SOURCE_GPIOPAD18,
+	DC_IRQ_SOURCE_GPIOPAD19,
+	DC_IRQ_SOURCE_GPIOPAD20,
+	DC_IRQ_SOURCE_GPIOPAD21,
+	DC_IRQ_SOURCE_GPIOPAD22,
+	DC_IRQ_SOURCE_GPIOPAD23,
+	DC_IRQ_SOURCE_GPIOPAD24,
+	DC_IRQ_SOURCE_GPIOPAD25,
+	DC_IRQ_SOURCE_GPIOPAD26,
+	DC_IRQ_SOURCE_GPIOPAD27,
+	DC_IRQ_SOURCE_GPIOPAD28,
+	DC_IRQ_SOURCE_GPIOPAD29,
+	DC_IRQ_SOURCE_GPIOPAD30,
+
+	DC_IRQ_SOURCE_DC1UNDERFLOW,
+	DC_IRQ_SOURCE_DC2UNDERFLOW,
+	DC_IRQ_SOURCE_DC3UNDERFLOW,
+	DC_IRQ_SOURCE_DC4UNDERFLOW,
+	DC_IRQ_SOURCE_DC5UNDERFLOW,
+	DC_IRQ_SOURCE_DC6UNDERFLOW,
+
+	DC_IRQ_SOURCE_DMCU_SCP,
+	DC_IRQ_SOURCE_VBIOS_SW,
+
+	DC_IRQ_SOURCE_VUPDATE1,
+	DC_IRQ_SOURCE_VUPDATE2,
+	DC_IRQ_SOURCE_VUPDATE3,
+	DC_IRQ_SOURCE_VUPDATE4,
+	DC_IRQ_SOURCE_VUPDATE5,
+	DC_IRQ_SOURCE_VUPDATE6,
+
+	DAL_IRQ_SOURCES_NUMBER
+};
+
+enum irq_type
+{
+	IRQ_TYPE_PFLIP = DC_IRQ_SOURCE_PFLIP1,
+	IRQ_TYPE_VUPDATE = DC_IRQ_SOURCE_VUPDATE1,
+};
+
+#define DAL_VALID_IRQ_SRC_NUM(src) \
+	((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID)
+
+/* Number of Page Flip IRQ Sources. */
+#define DAL_PFLIP_IRQ_SRC_NUM \
+	(DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1)
+
+/* the number of contexts may be expanded in the future based on needs */
+enum dc_interrupt_context {
+	INTERRUPT_LOW_IRQ_CONTEXT = 0,
+	INTERRUPT_HIGH_IRQ_CONTEXT,
+	INTERRUPT_CONTEXT_NUMBER
+};
+
+enum dc_interrupt_porlarity {
+	INTERRUPT_POLARITY_DEFAULT = 0,
+	INTERRUPT_POLARITY_LOW = INTERRUPT_POLARITY_DEFAULT,
+	INTERRUPT_POLARITY_HIGH,
+	INTERRUPT_POLARITY_BOTH
+};
+
+#define DC_DECODE_INTERRUPT_POLARITY(int_polarity) \
+	(int_polarity == INTERRUPT_POLARITY_LOW) ? "Low" : \
+	(int_polarity == INTERRUPT_POLARITY_HIGH) ? "High" : \
+	(int_polarity == INTERRUPT_POLARITY_BOTH) ? "Both" : "Invalid"
+
+struct dc_timer_interrupt_params {
+	uint32_t micro_sec_interval;
+	enum dc_interrupt_context int_context;
+};
+
+struct dc_interrupt_params {
+	/* The polarity *change* which will trigger an interrupt.
+	 * If 'requested_polarity == INTERRUPT_POLARITY_BOTH', then
+	 * 'current_polarity' must be initialised. */
+	enum dc_interrupt_porlarity requested_polarity;
+	/* If 'requested_polarity == INTERRUPT_POLARITY_BOTH',
+	 * 'current_polarity' should contain the current state, which means
+	 * the interrupt will be triggered when state changes from what is,
+	 * in 'current_polarity'. */
+	enum dc_interrupt_porlarity current_polarity;
+	enum dc_irq_source irq_source;
+	enum dc_interrupt_context int_context;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h b/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
new file mode 100644
index 000000000000..8ebbe650c124
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
@@ -0,0 +1,632 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ADAPTER_SERVICE_INTERFACE_H__
+#define __DAL_ADAPTER_SERVICE_INTERFACE_H__
+
+#include "grph_object_ctrl_defs.h"
+#include "gpio_interface.h"
+#include "ddc_interface.h"
+#include "irq_interface.h"
+#include "bios_parser_interface.h"
+#include "adapter_service_types.h"
+#include "dal_types.h"
+#include "asic_capability_types.h"
+
+/* forward declaration */
+struct i2caux;
+struct adapter_service;
+
+
+/*
+ * enum adapter_feature_id
+ *
+ * Definition of all adapter features
+ *
+ * The enumeration defines the IDs of all the adapter features. The enum
+ * organizes all the features into several feature sets. The range of feature
+ * set N is from ((N-1)*32+1) to (N*32). Because there may be three value-type
+ * feature, boolean-type, unsigned char-type and unsinged int-type, the number
+ * of features should be 32, 4 and 1 in the feature set accordingly.
+ *
+ * In a boolean-type feature set N, the enumeration value of the feature should
+ * be ((N-1)*32+1), ((N-1)*32+2), ..., (N*32).
+ *
+ * In an unsigned char-type feature set N, the enumeration value of the
+ * feature should be ((N-1)*32+1), ((N-1)*32+8), ((N-1)*32+16) and (N*32).
+ *
+ * In an unsigned int-type feature set N, the enumeration value of the feature
+ * should be ((N-1)*32+1)
+ */
+enum adapter_feature_id {
+	FEATURE_UNKNOWN = 0,
+
+	/* Boolean set, up to 32 entries */
+	FEATURE_ENABLE_HW_EDID_POLLING = 1,
+	FEATURE_SET_01_START = FEATURE_ENABLE_HW_EDID_POLLING,
+	FEATURE_DP_SINK_DETECT_POLL_DATA_PIN,
+	FEATURE_UNDERFLOW_INTERRUPT,
+	FEATURE_ALLOW_WATERMARK_ADJUSTMENT,
+	FEATURE_LIGHT_SLEEP,
+	FEATURE_DCP_DITHER_FRAME_RANDOM_ENABLE,
+	FEATURE_DCP_DITHER_RGB_RANDOM_ENABLE,
+	FEATURE_DCP_DITHER_HIGH_PASS_RANDOM_ENABLE,
+	FEATURE_DETECT_REQUIRE_HPD_HIGH,
+	FEATURE_LINE_BUFFER_ENHANCED_PIXEL_DEPTH, /* 10th */
+	FEATURE_MAXIMIZE_URGENCY_WATERMARKS,
+	FEATURE_MAXIMIZE_STUTTER_MARKS,
+	FEATURE_MAXIMIZE_NBP_MARKS,
+	FEATURE_RESTORE_USAGE_I2C_SW_ENGINE,
+	FEATURE_USE_MAX_DISPLAY_CLK,
+	FEATURE_ALLOW_EDP_RESOURCE_SHARING,
+	FEATURE_SUPPORT_DP_YUV,
+	FEATURE_SUPPORT_DP_Y_ONLY,
+	FEATURE_DISABLE_DP_GTC_SYNC,
+	FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, /* 20th */
+	FEATURE_ENABLE_DFS_BYPASS,
+	FEATURE_LB_HIGH_RESOLUTION,
+	FEATURE_DP_DISPLAY_FORCE_SS_ENABLE,
+	FEATURE_REPORT_CE_MODE_ONLY,
+	FEATURE_ALLOW_OPTIMIZED_MODE_AS_DEFAULT,
+	FEATURE_DDC_READ_FORCE_REPEATED_START,
+	FEATURE_FORCE_TIMING_RESYNC,
+	FEATURE_TMDS_DISABLE_DITHERING,
+	FEATURE_HDMI_DISABLE_DITHERING,
+	FEATURE_DP_DISABLE_DITHERING, /* 30th */
+	FEATURE_EMBEDDED_DISABLE_DITHERING,
+	FEATURE_DISABLE_AZ_CLOCK_GATING, /* 32th. This set is full */
+	FEATURE_SET_01_END = FEATURE_SET_01_START + 31,
+
+	/* Boolean set, up to 32 entries */
+	FEATURE_WIRELESS_ENABLE = FEATURE_SET_01_END + 1,
+	FEATURE_SET_02_START = FEATURE_WIRELESS_ENABLE,
+	FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT,
+	FEATURE_WIRELESS_LIMIT_720P,
+	FEATURE_WIRELESS_ENABLE_COMPRESSED_AUDIO,
+	FEATURE_WIRELESS_INCLUDE_UNVERIFIED_TIMINGS,
+	FEATURE_MODIFY_TIMINGS_FOR_WIRELESS,
+	FEATURE_ALLOW_SELF_REFRESH,
+	FEATURE_ALLOW_DYNAMIC_PIXEL_ENCODING_CHANGE,
+	FEATURE_ALLOW_HSYNC_VSYNC_ADJUSTMENT,
+	FEATURE_FORCE_PSR, /* 10th */
+	FEATURE_PREFER_3D_TIMING,
+	FEATURE_VARI_BRIGHT_ENABLE,
+	FEATURE_PSR_ENABLE,
+	FEATURE_EDID_STRESS_READ,
+	FEATURE_DP_FRAME_PACK_STEREO3D,
+	FEATURE_ALLOW_HDMI_WITHOUT_AUDIO,
+	FEATURE_RESTORE_USAGE_I2C_SW_ENGING,
+	FEATURE_ABM_2_0,
+	FEATURE_SUPPORT_MIRABILIS,
+	FEATURE_LOAD_DMCU_FIRMWARE, /* 20th */
+	FEATURE_ENABLE_GPU_SCALING,
+	FEATURE_DONGLE_SINK_COUNT_CHECK,
+	FEATURE_INSTANT_UP_SCALE_DOWN_SCALE,
+	FEATURE_TILED_DISPLAY,
+	FEATURE_CHANGE_I2C_SPEED_CONTROL,
+	FEATURE_REPORT_SINGLE_SELECTED_TIMING,
+	FEATURE_ALLOW_HDMI_HIGH_CLK_DP_DONGLE,
+	FEATURE_SUPPORT_EXTERNAL_PANEL_DRR,
+	FEATURE_SUPPORT_SMOOTH_BRIGHTNESS,
+	FEATURE_ALLOW_DIRECT_MEMORY_ACCESS_TRIG, /* 30th */
+	FEATURE_POWER_GATING_LB_PORTION, /* 31nd. One more left. */
+	FEATURE_SET_02_END = FEATURE_SET_02_START + 31,
+
+	/* UInt set, 1 entry: DCP Bit Depth Reduction Mode */
+	FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE = FEATURE_SET_02_END + 1,
+	FEATURE_SET_03_START = FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE,
+	FEATURE_SET_03_END = FEATURE_SET_03_START + 31,
+
+	/* UInt set, 1 entry: DCP Dither Mode */
+	FEATURE_DCP_DITHER_MODE = FEATURE_SET_03_END + 1,
+	FEATURE_SET_04_START = FEATURE_DCP_DITHER_MODE,
+	FEATURE_SET_04_END = FEATURE_SET_04_START + 31,
+
+	/* UInt set, 1 entry: DCP Programming WA(workaround) */
+	FEATURE_DCP_PROGRAMMING_WA = FEATURE_SET_04_END + 1,
+	FEATURE_SET_06_START = FEATURE_DCP_PROGRAMMING_WA,
+	FEATURE_SET_06_END = FEATURE_SET_06_START + 31,
+
+	/* UInt set, 1 entry: Maximum co-functional non-DP displays */
+	FEATURE_MAX_COFUNC_NON_DP_DISPLAYS = FEATURE_SET_06_END + 1,
+	FEATURE_SET_07_START = FEATURE_MAX_COFUNC_NON_DP_DISPLAYS,
+	FEATURE_SET_07_END = FEATURE_SET_07_START + 31,
+
+	/* UInt set, 1 entry: Number of supported HDMI connection */
+	FEATURE_SUPPORTED_HDMI_CONNECTION_NUM = FEATURE_SET_07_END + 1,
+	FEATURE_SET_08_START = FEATURE_SUPPORTED_HDMI_CONNECTION_NUM,
+	FEATURE_SET_08_END = FEATURE_SET_08_START + 31,
+
+	/* UInt set, 1 entry: Maximum number of controllers */
+	FEATURE_MAX_CONTROLLER_NUM = FEATURE_SET_08_END + 1,
+	FEATURE_SET_09_START = FEATURE_MAX_CONTROLLER_NUM,
+	FEATURE_SET_09_END = FEATURE_SET_09_START + 31,
+
+	/* UInt set, 1 entry: Type of DRR support */
+	FEATURE_DRR_SUPPORT = FEATURE_SET_09_END + 1,
+	FEATURE_SET_10_START = FEATURE_DRR_SUPPORT,
+	FEATURE_SET_10_END = FEATURE_SET_10_START + 31,
+
+	/* UInt set, 1 entry: Stutter mode support */
+	FEATURE_STUTTER_MODE = FEATURE_SET_10_END + 1,
+	FEATURE_SET_11_START = FEATURE_STUTTER_MODE,
+	FEATURE_SET_11_END = FEATURE_SET_11_START + 31,
+
+	/* UInt set, 1 entry: Measure PSR setup time */
+	FEATURE_PSR_SETUP_TIME_TEST = FEATURE_SET_11_END + 1,
+	FEATURE_SET_12_START = FEATURE_PSR_SETUP_TIME_TEST,
+	FEATURE_SET_12_END = FEATURE_SET_12_START + 31,
+
+	/* Boolean set, up to 32 entries */
+	FEATURE_POWER_GATING_PIPE_IN_TILE = FEATURE_SET_12_END + 1,
+	FEATURE_SET_13_START = FEATURE_POWER_GATING_PIPE_IN_TILE,
+	FEATURE_USE_PPLIB,
+	FEATURE_DISABLE_LPT_SUPPORT,
+	FEATURE_DUMMY_FBC_BACKEND,
+	FEATURE_DISABLE_FBC_COMP_CLK_GATE,
+	FEATURE_DPMS_AUDIO_ENDPOINT_CONTROL,
+	FEATURE_PIXEL_PERFECT_OUTPUT,
+	FEATURE_8BPP_SUPPORTED,
+	FEATURE_SET_13_END = FEATURE_SET_13_START + 31,
+
+	/* UInt set, 1 entry: Display preferred view
+	 * 0: no preferred view
+	 * 1: native and preferred timing of embedded display will have high
+	 *    priority, so other displays will support it always
+	 */
+	FEATURE_DISPLAY_PREFERRED_VIEW = FEATURE_SET_13_END + 1,
+	FEATURE_SET_15_START = FEATURE_DISPLAY_PREFERRED_VIEW,
+	FEATURE_SET_15_END = FEATURE_SET_15_START + 31,
+
+	/* UInt set, 1 entry: DAL optimization */
+	FEATURE_OPTIMIZATION = FEATURE_SET_15_END + 1,
+	FEATURE_SET_16_START = FEATURE_OPTIMIZATION,
+	FEATURE_SET_16_END = FEATURE_SET_16_START + 31,
+
+	/* UInt set, 1 entry: Performance measurement */
+	FEATURE_PERF_MEASURE = FEATURE_SET_16_END + 1,
+	FEATURE_SET_17_START = FEATURE_PERF_MEASURE,
+	FEATURE_SET_17_END = FEATURE_SET_17_START + 31,
+
+	/* UInt set, 1 entry: Minimum backlight value [0-255] */
+	FEATURE_MIN_BACKLIGHT_LEVEL = FEATURE_SET_17_END + 1,
+	FEATURE_SET_18_START = FEATURE_MIN_BACKLIGHT_LEVEL,
+	FEATURE_SET_18_END = FEATURE_SET_18_START + 31,
+
+	/* UInt set, 1 entry: Maximum backlight value [0-255] */
+	FEATURE_MAX_BACKLIGHT_LEVEL = FEATURE_SET_18_END + 1,
+	FEATURE_SET_19_START = FEATURE_MAX_BACKLIGHT_LEVEL,
+	FEATURE_SET_19_END = FEATURE_SET_19_START + 31,
+
+	/* UInt set, 1 entry: AMB setting
+	 *
+	 * Each byte will control the ABM configuration to use for a specific
+	 * ABM level.
+	 *
+	 * HW team provided 12 different ABM min/max reduction pairs to choose
+	 * between for each ABM level.
+	 *
+	 * ABM level Byte Setting
+	 *       1    0   Default = 0 (setting 3), can be override to 1-12
+	 *       2    1   Default = 0 (setting 7), can be override to 1-12
+	 *       3    2   Default = 0 (setting 8), can be override to 1-12
+	 *       4    3   Default = 0 (setting 10), can be override to 1-12
+	 *
+	 * For example,
+	 * FEATURE_PREFERRED_ABM_CONFIG_SET = 0x0C060500, this represents:
+	 * ABM level 1 use default setting (setting 3)
+	 * ABM level 2 uses setting 5
+	 * ABM level 3 uses setting 6
+	 * ABM level 4 uses setting 12
+	 * Internal use only!
+	 */
+	FEATURE_PREFERRED_ABM_CONFIG_SET = FEATURE_SET_19_END + 1,
+	FEATURE_SET_20_START = FEATURE_PREFERRED_ABM_CONFIG_SET,
+	FEATURE_SET_20_END = FEATURE_SET_20_START + 31,
+
+	/* UInt set, 1 entry: Change SW I2C speed */
+	FEATURE_CHANGE_SW_I2C_SPEED = FEATURE_SET_20_END + 1,
+	FEATURE_SET_21_START = FEATURE_CHANGE_SW_I2C_SPEED,
+	FEATURE_SET_21_END = FEATURE_SET_21_START + 31,
+
+	/* UInt set, 1 entry: Change HW I2C speed */
+	FEATURE_CHANGE_HW_I2C_SPEED = FEATURE_SET_21_END + 1,
+	FEATURE_SET_22_START = FEATURE_CHANGE_HW_I2C_SPEED,
+	FEATURE_SET_22_END = FEATURE_SET_22_START + 31,
+
+	/* UInt set, 1 entry:
+	 * When PSR issue occurs, it is sometimes hard to debug since the
+	 * failure occurs immediately at boot. Use this setting to skip or
+	 * postpone PSR functionality and re-enable through DSAT. */
+	FEATURE_DEFAULT_PSR_LEVEL = FEATURE_SET_22_END + 1,
+	FEATURE_SET_23_START = FEATURE_DEFAULT_PSR_LEVEL,
+	FEATURE_SET_23_END = FEATURE_SET_23_START + 31,
+
+	/* UInt set, 1 entry: Allowed pixel clock range for LVDS */
+	FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE = FEATURE_SET_23_END + 1,
+	FEATURE_SET_24_START = FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE,
+	FEATURE_SET_24_END = FEATURE_SET_24_START + 31,
+
+	/* UInt set, 1 entry: Max number of clock sources */
+	FEATURE_MAX_CLOCK_SOURCE_NUM = FEATURE_SET_24_END + 1,
+	FEATURE_SET_25_START = FEATURE_MAX_CLOCK_SOURCE_NUM,
+	FEATURE_SET_25_END = FEATURE_SET_25_START + 31,
+
+	/* UInt set, 1 entry: Select the ABM configuration to use.
+	 *
+	 * This feature set is used to allow packaging option to be defined
+	 * to allow OEM to select between the default ABM configuration or
+	 * alternative predefined configurations that may be more aggressive.
+	 *
+	 * Note that this regkey is meant for external use to select the
+	 * configuration OEM wants. Whereas the other PREFERRED_ABM_CONFIG_SET
+	 * key is only used for internal use and allows full reconfiguration.
+	 */
+	FEATURE_ABM_CONFIG = FEATURE_SET_25_END + 1,
+	FEATURE_SET_26_START = FEATURE_ABM_CONFIG,
+	FEATURE_SET_26_END = FEATURE_SET_26_START + 31,
+
+	/* UInt set, 1 entry: Select the default speed in which smooth
+	 * brightness feature should converge towards target backlight level.
+	 *
+	 * For example, a setting of 500 means it takes 500ms to transition
+	 * from current backlight level to the new requested backlight level.
+	 */
+	FEATURE_SMOOTH_BRTN_ADJ_TIME_IN_MS = FEATURE_SET_26_END + 1,
+	FEATURE_SET_27_START = FEATURE_SMOOTH_BRTN_ADJ_TIME_IN_MS,
+	FEATURE_SET_27_END = FEATURE_SET_27_START + 31,
+
+	/* Set 28: UInt set, 1 entry: Allow runtime parameter to force specific
+	 * Static Screen Event triggers for test purposes. */
+	FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS = FEATURE_SET_27_END + 1,
+	FEATURE_SET_28_START = FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS,
+	FEATURE_SET_28_END = FEATURE_SET_28_START + 31,
+
+	FEATURE_MAXIMUM
+};
+
+/* Adapter Service type of DRR support*/
+enum as_drr_support {
+	AS_DRR_SUPPORT_DISABLED = 0x0,
+	AS_DRR_SUPPORT_ENABLED = 0x1,
+	AS_DRR_SUPPORT_MIN_FORCED_FPS = 0xA
+};
+
+/* Adapter service initialize data structure*/
+struct as_init_data {
+	struct hw_asic_id hw_init_data;
+	struct bp_init_data bp_init_data;
+	struct dc_context *ctx;
+	struct bdf_info bdf_info;
+	const struct dal_override_parameters *display_param;
+	struct dc_bios *vbios_override;
+	enum dce_environment dce_environment;
+};
+
+/* Create adapter service */
+struct adapter_service *dal_adapter_service_create(
+	struct as_init_data *init_data);
+
+/* Destroy adapter service and objects it contains */
+void dal_adapter_service_destroy(
+	struct adapter_service **as);
+
+/* Get the DCE version of current ASIC */
+enum dce_version dal_adapter_service_get_dce_version(
+	const struct adapter_service *as);
+
+enum dce_environment dal_adapter_service_get_dce_environment(
+	const struct adapter_service *as);
+
+/* Get firmware information from BIOS */
+bool dal_adapter_service_get_firmware_info(
+	struct adapter_service *as,
+	struct firmware_info *info);
+
+
+/* functions to get a total number of objects of specific type */
+uint8_t dal_adapter_service_get_connectors_num(
+	struct adapter_service *as);
+
+/* Get number of controllers */
+uint8_t dal_adapter_service_get_controllers_num(
+	struct adapter_service *as);
+
+/* Get number of clock sources */
+uint8_t dal_adapter_service_get_clock_sources_num(
+	struct adapter_service *as);
+
+/* Get number of controllers */
+uint8_t dal_adapter_service_get_func_controllers_num(
+	struct adapter_service *as);
+
+/* Get number of stream engines */
+uint8_t dal_adapter_service_get_stream_engines_num(
+	struct adapter_service *as);
+
+/* functions to get object id based on object index */
+struct graphics_object_id dal_adapter_service_get_connector_obj_id(
+	struct adapter_service *as,
+	uint8_t connector_index);
+
+/* Get number of spread spectrum entries from BIOS */
+uint32_t dal_adapter_service_get_ss_info_num(
+	struct adapter_service *as,
+	enum as_signal_type signal);
+
+/* Get spread spectrum info from BIOS */
+bool dal_adapter_service_get_ss_info(
+	struct adapter_service *as,
+	enum as_signal_type signal,
+	uint32_t idx,
+	struct spread_spectrum_info *info);
+
+/* Check if DFS bypass is enabled */
+bool dal_adapter_service_is_dfs_bypass_enabled(struct adapter_service *as);
+
+/* Get memory controller latency */
+uint32_t dal_adapter_service_get_mc_latency(
+	struct adapter_service *as);
+
+/* Get the video RAM bit width set on the ASIC */
+uint32_t dal_adapter_service_get_asic_vram_bit_width(
+	struct adapter_service *as);
+
+/* Get the bug flags set on this ASIC */
+struct asic_bugs dal_adapter_service_get_asic_bugs(
+	struct adapter_service *as);
+
+/* Get efficiency of DRAM */
+uint32_t dal_adapter_service_get_dram_bandwidth_efficiency(
+	struct adapter_service *as);
+
+/* Get multiplier for the memory type */
+uint32_t dal_adapter_service_get_memory_type_multiplier(
+	struct adapter_service *as);
+
+/* Get parameters for bandwidth tuning */
+bool dal_adapter_service_get_bandwidth_tuning_params(
+	struct adapter_service *as,
+	union bandwidth_tuning_params *params);
+
+/* Get integrated information on BIOS */
+bool dal_adapter_service_get_integrated_info(
+	struct adapter_service *as,
+	struct integrated_info *info);
+
+/* Return if a given feature is supported by the ASIC */
+bool dal_adapter_service_is_feature_supported(
+	enum adapter_feature_id feature_id);
+
+/* Get the cached value of a given feature */
+bool dal_adapter_service_get_feature_value(
+	const enum adapter_feature_id feature_id,
+	void *data,
+	uint32_t size);
+
+/* Get a copy of ASIC feature flags */
+struct asic_feature_flags dal_adapter_service_get_feature_flags(
+	struct adapter_service *as);
+
+/* Obtain DDC */
+struct ddc *dal_adapter_service_obtain_ddc(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+/* Release DDC */
+void dal_adapter_service_release_ddc(
+	struct adapter_service *as,
+	struct ddc *ddc);
+
+/* Obtain HPD interrupt request */
+struct irq *dal_adapter_service_obtain_hpd_irq(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+/* Release interrupt request */
+void dal_adapter_service_release_irq(
+	struct adapter_service *as,
+	struct irq *irq);
+
+/* Obtain GPIO */
+struct gpio *dal_adapter_service_obtain_gpio(
+	struct adapter_service *as,
+	enum gpio_id id,
+	uint32_t en);
+
+/* Obtain GPIO for stereo3D*/
+struct gpio *dal_adapter_service_obtain_stereo_gpio(struct adapter_service *as);
+
+/* Release GPIO */
+void dal_adapter_service_release_gpio(
+		struct adapter_service *as,
+		struct gpio *gpio);
+
+/* Get SW I2C speed */
+uint32_t dal_adapter_service_get_sw_i2c_speed(struct adapter_service *as);
+
+/* Get HW I2C speed */
+uint32_t dal_adapter_service_get_hw_i2c_speed(struct adapter_service *as);
+
+/* Get line buffer size */
+uint32_t dal_adapter_service_get_line_buffer_size(struct adapter_service *as);
+
+/* Get information on audio support */
+union audio_support dal_adapter_service_get_audio_support(
+		struct adapter_service *as);
+
+/* Get I2C information from BIOS */
+bool dal_adapter_service_get_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	struct graphics_object_i2c_info *i2c_info);
+
+/* Get bios parser handler */
+struct dc_bios *dal_adapter_service_get_bios_parser(
+	struct adapter_service *as);
+
+/* Get i2c aux handler */
+struct i2caux *dal_adapter_service_get_i2caux(
+	struct adapter_service *as);
+
+struct dal_asic_runtime_flags dal_adapter_service_get_asic_runtime_flags(
+	struct adapter_service *as);
+
+bool dal_adapter_service_initialize_hw_data(
+	struct adapter_service *as);
+
+struct graphics_object_id dal_adapter_service_enum_fake_path_resource(
+	struct adapter_service *as,
+	uint32_t index);
+
+struct graphics_object_id dal_adapter_service_enum_stereo_sync_object(
+	struct adapter_service *as,
+	uint32_t index);
+
+struct graphics_object_id dal_adapter_service_enum_sync_output_object(
+	struct adapter_service *as,
+	uint32_t index);
+
+struct graphics_object_id dal_adapter_service_enum_audio_object(
+	struct adapter_service *as,
+	uint32_t index);
+
+void dal_adapter_service_update_audio_connectivity(
+	struct adapter_service *as,
+	uint32_t number_of_audio_capable_display_path);
+
+bool dal_adapter_service_has_embedded_display_connector(
+	struct adapter_service *as);
+
+bool dal_adapter_service_get_embedded_panel_info(
+	struct adapter_service *as,
+	struct embedded_panel_info *info);
+
+bool dal_adapter_service_enum_embedded_panel_patch_mode(
+	struct adapter_service *as,
+	uint32_t index,
+	struct embedded_panel_patch_mode *mode);
+
+bool dal_adapter_service_get_faked_edid_len(
+	struct adapter_service *as,
+	uint32_t *len);
+
+bool dal_adapter_service_get_faked_edid_buf(
+	struct adapter_service *as,
+	uint8_t *buf,
+	uint32_t len);
+
+uint32_t dal_adapter_service_get_max_cofunc_non_dp_displays(void);
+
+uint32_t dal_adapter_service_get_single_selected_timing_signals(void);
+
+bool dal_adapter_service_get_device_tag(
+	struct adapter_service *as,
+	struct graphics_object_id connector_object_id,
+	uint32_t device_tag_index,
+	struct connector_device_tag_info *info);
+
+bool dal_adapter_service_is_device_id_supported(
+	struct adapter_service *as,
+	struct device_id id);
+
+bool dal_adapter_service_is_meet_underscan_req(struct adapter_service *as);
+
+bool dal_adapter_service_underscan_for_hdmi_only(struct adapter_service *as);
+
+uint32_t dal_adapter_service_get_src_num(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+struct graphics_object_id dal_adapter_service_get_src_obj(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	uint32_t index);
+
+/* Is this Fusion ASIC */
+bool dal_adapter_service_is_fusion(struct adapter_service *as);
+
+/* Is this ASIC support dynamic DFSbypass switch */
+bool dal_adapter_service_is_dfsbyass_dynamic(struct adapter_service *as);
+
+/* Reports whether driver settings allow requested optimization */
+bool dal_adapter_service_should_optimize(
+		struct adapter_service *as, enum optimization_feature feature);
+
+/* Determine if driver is in accelerated mode */
+bool dal_adapter_service_is_in_accelerated_mode(struct adapter_service *as);
+
+struct ddc *dal_adapter_service_obtain_ddc_from_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_i2c_info *info);
+
+struct bdf_info dal_adapter_service_get_adapter_info(
+	struct adapter_service *as);
+
+
+/* Determine if this ASIC needs to wait on PLL lock bit */
+bool dal_adapter_service_should_psr_skip_wait_for_pll_lock(
+	struct adapter_service *as);
+
+#define SIZEOF_BACKLIGHT_LUT 101
+#define ABSOLUTE_BACKLIGHT_MAX 255
+#define DEFAULT_MIN_BACKLIGHT 12
+#define DEFAULT_MAX_BACKLIGHT 255
+#define BACKLIGHT_CURVE_COEFFB 100
+#define BACKLIGHT_CURVE_COEFFA_FACTOR 10000
+#define BACKLIGHT_CURVE_COEFFB_FACTOR 100
+
+struct panel_backlight_levels {
+	uint32_t ac_level_percentage;
+	uint32_t dc_level_percentage;
+};
+
+bool dal_adapter_service_is_lid_open(struct adapter_service *as);
+
+bool dal_adapter_service_get_panel_backlight_default_levels(
+	struct adapter_service *as,
+	struct panel_backlight_levels *levels);
+
+bool dal_adapter_service_get_panel_backlight_boundaries(
+	struct adapter_service *as,
+	struct panel_backlight_boundaries *boundaries);
+
+uint32_t dal_adapter_service_get_view_port_pixel_granularity(
+	struct adapter_service *as);
+
+uint32_t dal_adapter_service_get_num_of_path_per_dp_mst_connector(
+		struct adapter_service *as);
+
+uint32_t dal_adapter_service_get_num_of_underlays(
+		struct adapter_service *as);
+
+bool dal_adapter_service_get_encoder_cap_info(
+		struct adapter_service *as,
+		struct graphics_object_id id,
+		struct graphics_object_encoder_cap_info *info);
+
+bool dal_adapter_service_is_mc_tuning_req(struct adapter_service *as);
+
+#endif /* __DAL_ADAPTER_SERVICE_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/adapter_service_types.h b/drivers/gpu/drm/amd/dal/include/adapter_service_types.h
new file mode 100644
index 000000000000..4cb4b4b6eeed
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/adapter_service_types.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ADAPTER_SERVICE_TYPES_H__
+#define __DAL_ADAPTER_SERVICE_TYPES_H__
+
+/* TODO: include signal_types.h and remove this enum */
+enum as_signal_type {
+	AS_SIGNAL_TYPE_NONE = 0L, /* no signal */
+	AS_SIGNAL_TYPE_DVI,
+	AS_SIGNAL_TYPE_HDMI,
+	AS_SIGNAL_TYPE_LVDS,
+	AS_SIGNAL_TYPE_DISPLAY_PORT,
+	AS_SIGNAL_TYPE_GPU_PLL,
+	AS_SIGNAL_TYPE_UNKNOWN
+};
+
+/*
+ * Struct used for algorithm of Bandwidth tuning parameters
+ * the sequence of the fields is binded with runtime parameter.
+ */
+union bandwidth_tuning_params {
+	struct bandwidth_tuning_params_struct {
+		uint32_t read_delay_stutter_off_usec;
+		uint32_t ignore_hblank_time;/*bool*/
+		uint32_t extra_reordering_latency_usec;
+		uint32_t extra_mc_latency_usec;
+		uint32_t data_return_bandwidth_eff;/*in %*/
+		uint32_t dmif_request_bandwidth_eff;/*in %*/
+		uint32_t sclock_latency_multiplier;/*in unit of 0.01*/
+		uint32_t mclock_latency_multiplier;/*in unit of 0.01*/
+		uint32_t fix_latency_multiplier;/*in unit of 0.01*/
+		 /*in unit represent in watermark*/
+		uint32_t use_urgency_watermark_offset;
+	} tuning_info;
+	uint32_t arr_info[sizeof(struct bandwidth_tuning_params_struct)
+		/ sizeof(uint32_t)];
+};
+
+union audio_support {
+	struct {
+		uint32_t DP_AUDIO:1;
+		uint32_t HDMI_AUDIO_ON_DONGLE:1;
+		uint32_t HDMI_AUDIO_NATIVE:1;
+	} bits;
+	uint32_t raw;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h b/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
new file mode 100644
index 000000000000..bdeaaf9066a2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of enc software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and enc permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ASIC_CAPABILITY_INTERFACE_H__
+#define __DAL_ASIC_CAPABILITY_INTERFACE_H__
+
+/* Include */
+#include "include/asic_capability_types.h"
+
+/* Forward declaration */
+struct hw_asic_id;
+
+
+/* ASIC capability */
+struct asic_capability {
+	struct dc_context *ctx;
+	struct asic_caps caps;
+	struct asic_stereo_3d_caps stereo_3d_caps;
+	struct asic_bugs bugs;
+	struct dal_asic_runtime_flags runtime_flags;
+	uint32_t data[ASIC_DATA_MAX_NUMBER];
+};
+
+
+/**
+ * Interfaces
+ */
+
+/* Create and initialize ASIC capability */
+struct asic_capability *dal_asic_capability_create(struct hw_asic_id *init,
+		struct dc_context *ctx);
+
+/* Destroy ASIC capability and free memory space */
+void dal_asic_capability_destroy(struct asic_capability **cap);
+
+#endif /* __DAL_ASIC_CAPABILITY_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/asic_capability_types.h b/drivers/gpu/drm/amd/dal/include/asic_capability_types.h
new file mode 100644
index 000000000000..1cb977618bdf
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/asic_capability_types.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_ASIC_CAPABILITY_TYPES_H__
+#define __DAL_ASIC_CAPABILITY_TYPES_H__
+
+/*
+ * ASIC Capabilities
+ */
+struct asic_caps {
+	bool CONSUMER_SINGLE_SELECTED_TIMING:1;
+	bool UNDERSCAN_ADJUST:1;
+	bool DELTA_SIGMA_SUPPORT:1;
+	bool PANEL_SELF_REFRESH_SUPPORTED:1;
+	bool IS_FUSION:1;
+	bool DP_MST_SUPPORTED:1;
+	bool UNDERSCAN_FOR_HDMI_ONLY:1;
+	bool DVI_CLOCK_SHARE_CAPABILITY:1;
+	bool SUPPORT_CEA861E_FINAL:1;
+	bool MIRABILIS_SUPPORTED:1;
+	bool MIRABILIS_ENABLED_BY_DEFAULT:1;
+	bool DEVICE_TAG_REMAP_SUPPORTED:1;
+	bool HEADLESS_NO_OPM_SUPPORTED:1;
+	bool WIRELESS_LIMIT_TO_720P:1;
+	bool WIRELESS_FULL_TIMING_ADJUSTMENT:1;
+	bool WIRELESS_TIMING_ADJUSTMENT:1;
+	bool WIRELESS_COMPRESSED_AUDIO:1;
+	bool VCE_SUPPORTED:1;
+	bool HPD_CHECK_FOR_EDID:1;
+	bool NO_VCC_OFF_HPD_POLLING:1;
+	bool NEED_MC_TUNING:1;
+	bool SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT:1;
+	bool DFSBYPASS_DYNAMIC_SUPPORT:1;
+	bool SUPPORT_8BPP:1;
+};
+
+
+/*
+ * ASIC Stereo 3D Caps
+ */
+struct asic_stereo_3d_caps {
+	bool SUPPORTED:1;
+	bool DISPLAY_BASED_ON_WS:1;
+	bool HDMI_FRAME_PACK:1;
+	bool INTERLACE_FRAME_PACK:1;
+	bool DISPLAYPORT_FRAME_PACK:1;
+	bool DISPLAYPORT_FRAME_ALT:1;
+	bool INTERLEAVE:1;
+};
+
+
+/*
+ * ASIC Bugs
+ */
+struct asic_bugs {
+	bool MST_SYMBOL_MISALIGNMENT:1;
+	bool PSR_2X_LANE_GANGING:1;
+	bool LB_WA_IS_SUPPORTED:1;
+	bool ROM_REGISTER_ACCESS:1;
+	bool PSR_WA_OVERSCAN_CRC_ERROR:1;
+};
+
+
+/*
+ * ASIC Data
+ */
+enum asic_data {
+	ASIC_DATA_FIRST = 0,
+	ASIC_DATA_CONTROLLERS_NUM = ASIC_DATA_FIRST,
+	ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM,
+	ASIC_DATA_DCE_VERSION,
+	ASIC_DATA_DCE_VERSION_MINOR,
+	ASIC_DATA_VRAM_TYPE,
+	ASIC_DATA_VRAM_BITWIDTH,
+	ASIC_DATA_FEATURE_FLAGS,
+	ASIC_DATA_LINEBUFFER_NUM,
+	ASIC_DATA_LINEBUFFER_SIZE,
+	ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY,
+	ASIC_DATA_MC_LATENCY,
+	ASIC_DATA_MC_LATENCY_SLOW,
+	ASIC_DATA_CLOCKSOURCES_NUM,
+	ASIC_DATA_MEMORYTYPE_MULTIPLIER,
+	ASIC_DATA_STUTTERMODE,
+	ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR,
+	ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS,
+	ASIC_DATA_REVISION_ID,
+	ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE,
+	ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY,
+	ASIC_DATA_DIGFE_NUM,
+	ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM,
+	ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN,
+	ASIC_DATA_NUM_OF_VIDEO_PLANES,
+	ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ,
+	ASIC_DATA_MAX_NUMBER /* end of enum */
+};
+
+
+/*
+ * ASIC Feature Flags
+ */
+struct asic_feature_flags {
+	union {
+		uint32_t raw;
+		struct {
+			uint32_t LEGACY_CLIENT:1;
+			uint32_t PACKED_PIXEL_FORMAT:1;
+			uint32_t WORKSTATION_STEREO:1;
+			uint32_t WORKSTATION:1;
+		} bits;
+	};
+};
+
+#endif /* __DAL_ASIC_CAPABILITY_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/audio_interface.h b/drivers/gpu/drm/amd/dal/include/audio_interface.h
new file mode 100644
index 000000000000..bf2176279f0e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/audio_interface.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUDIO_INTERFACE_H__
+#define __DAL_AUDIO_INTERFACE_H__
+
+#include "audio_types.h"
+#include "adapter_service_interface.h"
+#include "signal_types.h"
+#include "link_service_types.h"
+
+/* forward declaration */
+struct audio;
+struct dal_adapter_service;
+
+/*****  audio initialization data  *****/
+/*
+ * by audio, it means audio endpoint id. ASIC may have many endpoints.
+ * upper sw layer will create one audio object instance for each endpoints.
+ * ASIC support internal audio only. So enum number is used to differ
+ * each endpoint
+ */
+struct audio_init_data {
+	struct adapter_service *as;
+	struct graphics_object_id audio_stream_id;
+	struct dc_context *ctx;
+};
+
+enum audio_result {
+	AUDIO_RESULT_OK,
+	AUDIO_RESULT_ERROR,
+};
+
+/****** audio object create, destroy ******/
+struct audio *dal_audio_create(
+	const struct audio_init_data *init_data);
+
+void dal_audio_destroy(
+	struct audio **audio);
+
+/****** graphics object interface ******/
+const struct graphics_object_id dal_audio_get_graphics_object_id(
+	const struct audio *audio);
+
+/* Enumerate Graphics Object supported Input/Output Signal Types */
+uint32_t dal_audio_enumerate_input_signals(
+	struct audio *audio);
+
+uint32_t dal_audio_enumerate_output_signals(
+	struct audio *audio);
+
+/*  Check if signal supported by GraphicsObject  */
+bool dal_audio_is_input_signal_supported(
+	struct audio *audio,
+	enum signal_type signal);
+
+bool dal_audio_is_output_signal_supported(
+	struct audio *audio,
+	enum signal_type signal);
+
+
+/***** programming interface *****/
+
+/* perform power up sequence (boot up, resume, recovery) */
+enum audio_result dal_audio_power_up(
+	struct audio *audio);
+
+/* perform power down (shut down, stand by) */
+enum audio_result dal_audio_power_down(
+	struct audio *audio);
+
+/* setup audio */
+enum audio_result dal_audio_setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info);
+
+/* enable audio */
+enum audio_result dal_audio_enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+/* disable audio */
+enum audio_result dal_audio_disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+/* enable azalia audio endpoint */
+enum audio_result dal_audio_enable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id);
+
+/* disable azalia audio endpoint */
+enum audio_result dal_audio_disable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id);
+
+/* unmute audio */
+enum audio_result dal_audio_unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+/* mute audio */
+enum audio_result dal_audio_mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+
+/***** information interface *****/
+
+struct audio_feature_support dal_audio_get_supported_features(
+	struct audio *audio);
+
+/* get audio bandwidth information */
+void dal_audio_check_audio_bandwidth(
+	struct audio *audio,
+	const struct audio_crtc_info *info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates);
+
+/* Enable multi channel split */
+void dal_audio_enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable);
+
+/* get current multi channel split. */
+enum audio_result dal_audio_get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping);
+
+/* set payload value for the unsolicited response */
+void dal_audio_set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload);
+
+/*Assign GTC group and enable GTC value embedding*/
+void dal_audio_enable_gtc_embedding_with_group(
+	struct audio *audio,
+	uint32_t group_num,
+	uint32_t audio_latency);
+
+/* Disable GTC value embedding */
+void dal_audio_disable_gtc_embedding(
+	struct audio *audio);
+
+/* Update audio wall clock source */
+void dal_audio_setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/audio_types.h b/drivers/gpu/drm/amd/dal/include/audio_types.h
new file mode 100644
index 000000000000..54f5546a574c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/audio_types.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AUDIO_TYPES_H__
+#define __AUDIO_TYPES_H__
+
+#include "grph_object_defs.h"
+#include "signal_types.h"
+
+#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20
+#define MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 18
+#define MULTI_CHANNEL_SPLIT_NO_ASSO_INFO 0xFFFFFFFF
+
+
+struct audio_pll_hw_settings {
+	uint32_t feed_back_divider;
+	uint32_t step_size_integer;
+	uint32_t step_size_fraction;
+	uint32_t step_range;
+};
+
+struct audio_clock_info {
+	/* pixel clock frequency*/
+	uint32_t pixel_clock_in_10khz;
+	/* N - 32KHz audio */
+	uint32_t n_32khz;
+	/* CTS - 32KHz audio*/
+	uint32_t cts_32khz;
+	uint32_t n_44khz;
+	uint32_t cts_44khz;
+	uint32_t n_48khz;
+	uint32_t cts_48khz;
+};
+
+struct azalia_clock_info {
+	uint32_t pixel_clock_in_10khz;
+	uint32_t audio_dto_phase;
+	uint32_t audio_dto_module;
+	uint32_t audio_dto_wall_clock_ratio;
+};
+
+enum audio_dto_source {
+	DTO_SOURCE_UNKNOWN = 0,
+	DTO_SOURCE_ID0,
+	DTO_SOURCE_ID1,
+	DTO_SOURCE_ID2,
+	DTO_SOURCE_ID3,
+	DTO_SOURCE_ID4,
+	DTO_SOURCE_ID5
+};
+
+union audio_sample_rates {
+	struct sample_rates {
+		uint8_t RATE_32:1;
+		uint8_t RATE_44_1:1;
+		uint8_t RATE_48:1;
+		uint8_t RATE_88_2:1;
+		uint8_t RATE_96:1;
+		uint8_t RATE_176_4:1;
+		uint8_t RATE_192:1;
+	} rate;
+
+	uint8_t all;
+};
+
+enum audio_format_code {
+	AUDIO_FORMAT_CODE_FIRST = 1,
+	AUDIO_FORMAT_CODE_LINEARPCM = AUDIO_FORMAT_CODE_FIRST,
+
+	AUDIO_FORMAT_CODE_AC3,
+	/*Layers 1 & 2 */
+	AUDIO_FORMAT_CODE_MPEG1,
+	/*MPEG1 Layer 3 */
+	AUDIO_FORMAT_CODE_MP3,
+	/*multichannel */
+	AUDIO_FORMAT_CODE_MPEG2,
+	AUDIO_FORMAT_CODE_AAC,
+	AUDIO_FORMAT_CODE_DTS,
+	AUDIO_FORMAT_CODE_ATRAC,
+	AUDIO_FORMAT_CODE_1BITAUDIO,
+	AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS,
+	AUDIO_FORMAT_CODE_DTS_HD,
+	AUDIO_FORMAT_CODE_MAT_MLP,
+	AUDIO_FORMAT_CODE_DST,
+	AUDIO_FORMAT_CODE_WMAPRO,
+	AUDIO_FORMAT_CODE_LAST,
+	AUDIO_FORMAT_CODE_COUNT =
+		AUDIO_FORMAT_CODE_LAST - AUDIO_FORMAT_CODE_FIRST
+};
+
+struct audio_mode {
+	 /* ucData[0] [6:3] */
+	enum audio_format_code format_code;
+	/* ucData[0] [2:0] */
+	uint8_t channel_count;
+	/* ucData[1] */
+	union audio_sample_rates sample_rates;
+	union {
+		/* for LPCM */
+		uint8_t sample_size;
+		/* for Audio Formats 2-8 (Max bit rate divided by 8 kHz) */
+		uint8_t max_bit_rate;
+		/* for Audio Formats 9-15 */
+		uint8_t vendor_specific;
+	};
+};
+
+struct audio_speaker_flags {
+    uint32_t FL_FR:1;
+    uint32_t LFE:1;
+    uint32_t FC:1;
+    uint32_t RL_RR:1;
+    uint32_t RC:1;
+    uint32_t FLC_FRC:1;
+    uint32_t RLC_RRC:1;
+    uint32_t SUPPORT_AI:1;
+};
+
+struct audio_speaker_info {
+    uint32_t ALLSPEAKERS:7;
+    uint32_t SUPPORT_AI:1;
+};
+
+struct audio_info_flags {
+
+	union {
+
+		struct audio_speaker_flags speaker_flags;
+		struct audio_speaker_info   info;
+
+		uint8_t all;
+	};
+};
+
+
+/*struct audio_info_flags {
+	struct audio_speaker_flags {
+		uint32_t FL_FR:1;
+		uint32_t LFE:1;
+		uint32_t FC:1;
+		uint32_t RL_RR:1;
+		uint32_t RC:1;
+		uint32_t FLC_FRC:1;
+		uint32_t RLC_RRC:1;
+		uint32_t SUPPORT_AI:1;
+	};
+
+	struct audio_speaker_info {
+		uint32_t ALLSPEAKERS:7;
+		uint32_t SUPPORT_AI:1;
+	};
+
+	union {
+		struct audio_speaker_flags speaker_flags;
+		struct audio_speaker_info info;
+	};
+};
+*/
+
+union audio_cea_channels {
+	uint8_t all;
+	struct audio_cea_channels_bits {
+		uint32_t FL:1;
+		uint32_t FR:1;
+		uint32_t LFE:1;
+		uint32_t FC:1;
+		uint32_t RL_RC:1;
+		uint32_t RR:1;
+		uint32_t RC_RLC_FLC:1;
+		uint32_t RRC_FRC:1;
+	} channels;
+};
+
+struct audio_info {
+	struct audio_info_flags flags;
+	uint32_t video_latency;
+	uint32_t audio_latency;
+	uint32_t display_index;
+	uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS];
+	uint32_t manufacture_id;
+	uint32_t product_id;
+	/* PortID used for ContainerID when defined */
+	uint32_t port_id[2];
+	uint32_t mode_count;
+	/* this field must be last in this struct */
+	struct audio_mode modes[DC_MAX_AUDIO_DESC_COUNT];
+};
+
+struct audio_crtc_info {
+	uint32_t h_total;
+	uint32_t h_active;
+	uint32_t v_active;
+	uint32_t pixel_repetition;
+	uint32_t requested_pixel_clock; /* in KHz */
+	uint32_t calculated_pixel_clock; /* in KHz */
+	uint32_t refresh_rate;
+	enum dc_color_depth color_depth;
+	bool interlaced;
+};
+
+/* PLL information required for AZALIA DTO calculation */
+
+struct audio_pll_info {
+	uint32_t dp_dto_source_clock_in_khz;
+	uint32_t feed_back_divider;
+	enum audio_dto_source dto_source;
+	bool ss_enabled;
+	uint32_t ss_percentage;
+	uint32_t ss_percentage_divider;
+};
+
+struct audio_channel_associate_info {
+	union {
+		struct {
+			uint32_t ALL_CHANNEL_FL:4;
+			uint32_t ALL_CHANNEL_FR:4;
+			uint32_t ALL_CHANNEL_FC:4;
+			uint32_t ALL_CHANNEL_Sub:4;
+			uint32_t ALL_CHANNEL_SL:4;
+			uint32_t ALL_CHANNEL_SR:4;
+			uint32_t ALL_CHANNEL_BL:4;
+			uint32_t ALL_CHANNEL_BR:4;
+		} bits;
+		uint32_t u32all;
+	};
+};
+
+struct audio_output {
+	/* Front DIG id. */
+	enum engine_id engine_id;
+	/* encoder output signal */
+	enum signal_type signal;
+	/* video timing */
+	struct audio_crtc_info crtc_info;
+	/* PLL for audio */
+	struct audio_pll_info pll_info;
+};
+
+struct audio_feature_support {
+	/* supported engines*/
+	uint32_t ENGINE_DIGA:1;
+	uint32_t ENGINE_DIGB:1;
+	uint32_t ENGINE_DIGC:1;
+	uint32_t ENGINE_DIGD:1;
+	uint32_t ENGINE_DIGE:1;
+	uint32_t ENGINE_DIGF:1;
+	uint32_t ENGINE_DIGG:1;
+	uint32_t MULTISTREAM_AUDIO:1;
+};
+
+enum audio_payload {
+	CHANNEL_SPLIT_MAPPINGCHANG = 0x9,
+};
+
+#endif /* __AUDIO_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h b/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
new file mode 100644
index 000000000000..e4291b9ff320
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_INTERFACE_H__
+#define __DAL_BIOS_PARSER_INTERFACE_H__
+
+#include "dc_bios_types.h"
+
+struct adapter_service;
+struct bios_parser;
+
+struct bp_init_data {
+	struct dc_context *ctx;
+	uint8_t *bios;
+};
+
+struct dc_bios *dal_bios_parser_create(
+	struct bp_init_data *init,
+	struct adapter_service *as);
+
+void dal_bios_parser_destroy(
+	struct dc_bios **dcb);
+
+/*****************************************************************************/
+/* Interfaces of BIOS Parser Helper */
+bool dal_bios_parser_is_lid_open(
+	struct bios_parser *bp);
+bool dal_bios_parser_is_lid_status_changed(
+	struct bios_parser *bp);
+bool dal_bios_parser_is_display_config_changed(
+	struct bios_parser *bp);
+bool dal_bios_parser_is_accelerated_mode(
+	struct bios_parser *bp);
+void dal_bios_parser_set_scratch_lcd_scale(
+	struct bios_parser *bp,
+	enum lcd_scale scale);
+enum lcd_scale  dal_bios_parser_get_scratch_lcd_scale(
+	struct bios_parser *bp);
+void dal_bios_parser_get_bios_event_info(
+	struct bios_parser *bp,
+	struct bios_event_info *info);
+void dal_bios_parser_update_requested_backlight_level(
+	struct bios_parser *bp,
+	uint32_t backlight_8bit);
+uint32_t dal_bios_parser_get_requested_backlight_level(
+	struct bios_parser *bp);
+void dal_bios_parser_take_backlight_control(
+	struct bios_parser *bp,
+	bool cntl);
+bool dal_bios_parser_is_active_display(
+	struct bios_parser *bp,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag);
+enum controller_id dal_bios_parser_get_embedded_display_controller_id(
+	struct bios_parser *bp);
+uint32_t dal_bios_parser_get_embedded_display_refresh_rate(
+	struct bios_parser *bp);
+void dal_bios_parser_set_scratch_connected(
+	struct bios_parser *bp,
+	struct graphics_object_id connector_id,
+	bool connected,
+	const struct connector_device_tag_info *device_tag);
+void dal_bios_parser_prepare_scratch_active_and_requested(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag);
+void dal_bios_parser_set_scratch_active_and_requested(
+	struct bios_parser *bp);
+void dal_bios_parser_set_scratch_critical_state(
+	struct bios_parser *bp,
+	bool state);
+void dal_bios_parser_set_scratch_acc_mode_change(
+	struct bios_parser *bp);
+
+#endif /* __DAL_BIOS_PARSER_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/bios_parser_types.h b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h
new file mode 100644
index 000000000000..550ac874985b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_TYPES_H__
+
+#define __DAL_BIOS_PARSER_TYPES_H__
+
+#include "dm_services.h"
+#include "include/signal_types.h"
+#include "include/grph_object_ctrl_defs.h"
+#include "include/gpio_types.h"
+#include "include/adapter_service_types.h" /* for as_signal_type */
+#include "include/link_service_types.h"
+
+enum bp_result {
+	BP_RESULT_OK = 0, /* There was no error */
+	BP_RESULT_BADINPUT, /*Bad input parameter */
+	BP_RESULT_BADBIOSTABLE, /* Bad BIOS table */
+	BP_RESULT_UNSUPPORTED, /* BIOS Table is not supported */
+	BP_RESULT_NORECORD, /* Record can't be found */
+	BP_RESULT_FAILURE
+};
+
+enum bp_encoder_control_action {
+	/* direct VBIOS translation! Just to simplify the translation */
+	ENCODER_CONTROL_DISABLE = 0,
+	ENCODER_CONTROL_ENABLE,
+	ENCODER_CONTROL_SETUP,
+	ENCODER_CONTROL_INIT
+};
+
+enum bp_transmitter_control_action {
+	/* direct VBIOS translation! Just to simplify the translation */
+	TRANSMITTER_CONTROL_DISABLE = 0,
+	TRANSMITTER_CONTROL_ENABLE,
+	TRANSMITTER_CONTROL_BACKLIGHT_OFF,
+	TRANSMITTER_CONTROL_BACKLIGHT_ON,
+	TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS,
+	TRANSMITTER_CONTROL_LCD_SETF_TEST_START,
+	TRANSMITTER_CONTROL_LCD_SELF_TEST_STOP,
+	TRANSMITTER_CONTROL_INIT,
+	TRANSMITTER_CONTROL_DEACTIVATE,
+	TRANSMITTER_CONTROL_ACTIAVATE,
+	TRANSMITTER_CONTROL_SETUP,
+	TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS,
+	/* ATOM_TRANSMITTER_ACTION_POWER_ON. This action is for eDP only
+	 * (power up the panel)
+	 */
+	TRANSMITTER_CONTROL_POWER_ON,
+	/* ATOM_TRANSMITTER_ACTION_POWER_OFF. This action is for eDP only
+	 * (power down the panel)
+	 */
+	TRANSMITTER_CONTROL_POWER_OFF
+};
+
+enum bp_external_encoder_control_action {
+	EXTERNAL_ENCODER_CONTROL_DISABLE = 0,
+	EXTERNAL_ENCODER_CONTROL_ENABLE = 1,
+	EXTERNAL_ENCODER_CONTROL_INIT = 0x7,
+	EXTERNAL_ENCODER_CONTROL_SETUP = 0xf,
+	EXTERNAL_ENCODER_CONTROL_UNBLANK = 0x10,
+	EXTERNAL_ENCODER_CONTROL_BLANK = 0x11,
+	EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT = 0x12
+};
+
+enum bp_pipe_control_action {
+	ASIC_PIPE_DISABLE = 0,
+	ASIC_PIPE_ENABLE,
+	ASIC_PIPE_INIT
+};
+
+struct bp_encoder_control {
+	enum bp_encoder_control_action action;
+	enum engine_id engine_id;
+	enum transmitter transmitter;
+	enum signal_type signal;
+	enum lane_count lanes_number;
+	enum dc_color_depth color_depth;
+	bool enable_dp_audio;
+	uint32_t pixel_clock; /* khz */
+};
+
+struct bp_external_encoder_control {
+	enum bp_external_encoder_control_action action;
+	enum engine_id engine_id;
+	enum link_rate link_rate;
+	enum lane_count lanes_number;
+	enum signal_type signal;
+	enum dc_color_depth color_depth;
+	bool coherent;
+	struct graphics_object_id encoder_id;
+	struct graphics_object_id connector_obj_id;
+	uint32_t pixel_clock; /* in KHz */
+};
+
+struct bp_crtc_source_select {
+	enum engine_id engine_id;
+	enum controller_id controller_id;
+	/* from GPU Tx aka asic_signal */
+	enum signal_type signal;
+	/* sink_signal may differ from asicSignal if Translator encoder */
+	enum signal_type sink_signal;
+	enum display_output_bit_depth display_output_bit_depth;
+	bool enable_dp_audio;
+};
+
+struct bp_transmitter_control {
+	enum bp_transmitter_control_action action;
+	enum engine_id engine_id;
+	enum transmitter transmitter; /* PhyId */
+	enum lane_count lanes_number;
+	enum clock_source_id pll_id; /* needed for DCE 4.0 */
+	enum signal_type signal;
+	enum dc_color_depth color_depth; /* not used for DCE6.0 */
+	enum hpd_source_id hpd_sel; /* ucHPDSel, used for DCe6.0 */
+	struct graphics_object_id connector_obj_id;
+	/* symClock; in 10kHz, pixel clock, in HDMI deep color mode, it should
+	 * be pixel clock * deep_color_ratio (in KHz)
+	 */
+	uint32_t pixel_clock;
+	uint32_t lane_select;
+	uint32_t lane_settings;
+	bool coherent;
+	bool multi_path;
+	bool single_pll_mode;
+};
+
+struct bp_blank_crtc_parameters {
+	enum controller_id controller_id;
+	uint32_t black_color_rcr;
+	uint32_t black_color_gy;
+	uint32_t black_color_bcb;
+};
+
+struct bp_hw_crtc_timing_parameters {
+	enum controller_id controller_id;
+	/* horizontal part */
+	uint32_t h_total;
+	uint32_t h_addressable;
+	uint32_t h_overscan_left;
+	uint32_t h_overscan_right;
+	uint32_t h_sync_start;
+	uint32_t h_sync_width;
+
+	/* vertical part */
+	uint32_t v_total;
+	uint32_t v_addressable;
+	uint32_t v_overscan_top;
+	uint32_t v_overscan_bottom;
+	uint32_t v_sync_start;
+	uint32_t v_sync_width;
+
+	struct timing_flags {
+		uint32_t INTERLACE:1;
+		uint32_t PIXEL_REPETITION:4;
+		uint32_t HSYNC_POSITIVE_POLARITY:1;
+		uint32_t VSYNC_POSITIVE_POLARITY:1;
+		uint32_t HORZ_COUNT_BY_TWO:1;
+	} flags;
+};
+
+struct bp_hw_crtc_overscan_parameters {
+	enum controller_id controller_id;
+	uint32_t h_overscan_left;
+	uint32_t h_overscan_right;
+	uint32_t v_overscan_top;
+	uint32_t v_overscan_bottom;
+};
+
+struct bp_adjust_pixel_clock_parameters {
+	/* Input: Signal Type - to be converted to Encoder mode */
+	enum signal_type signal_type;
+	/* Input: Encoder object id */
+	struct graphics_object_id encoder_object_id;
+	/* Input: Pixel Clock (requested Pixel clock based on Video timing
+	 * standard used) in KHz
+	 */
+	uint32_t pixel_clock;
+	/* Output: Adjusted Pixel Clock (after VBIOS exec table) in KHz */
+	uint32_t adjusted_pixel_clock;
+	/* Output: If non-zero, this refDiv value should be used to calculate
+	 * other ppll params */
+	uint32_t reference_divider;
+	/* Output: If non-zero, this postDiv value should be used to calculate
+	 * other ppll params */
+	uint32_t pixel_clock_post_divider;
+	/* Input: Enable spread spectrum */
+	bool ss_enable;
+};
+
+struct bp_pixel_clock_parameters {
+	enum controller_id controller_id; /* (Which CRTC uses this PLL) */
+	enum clock_source_id pll_id; /* Clock Source Id */
+	/* signal_type -> Encoder Mode - needed by VBIOS Exec table */
+	enum signal_type signal_type;
+	/* Adjusted Pixel Clock (after VBIOS exec table)
+	 * that becomes Target Pixel Clock (KHz) */
+	uint32_t target_pixel_clock;
+	/* Calculated Reference divider of Display PLL */
+	uint32_t reference_divider;
+	/* Calculated Feedback divider of Display PLL */
+	uint32_t feedback_divider;
+	/* Calculated Fractional Feedback divider of Display PLL */
+	uint32_t fractional_feedback_divider;
+	/* Calculated Pixel Clock Post divider of Display PLL */
+	uint32_t pixel_clock_post_divider;
+	struct graphics_object_id encoder_object_id; /* Encoder object id */
+	/* VBIOS returns a fixed display clock when DFS-bypass feature
+	 * is enabled (KHz) */
+	uint32_t dfs_bypass_display_clock;
+	/* color depth to support HDMI deep color */
+	enum transmitter_color_depth color_depth;
+
+	struct program_pixel_clock_flags {
+		uint32_t FORCE_PROGRAMMING_OF_PLL:1;
+		/* Use Engine Clock as source for Display Clock when
+		 * programming PLL */
+		uint32_t USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK:1;
+		/* Use external reference clock (refDivSrc for PLL) */
+		uint32_t SET_EXTERNAL_REF_DIV_SRC:1;
+		/* Force program PHY PLL only */
+		uint32_t PROGRAM_PHY_PLL_ONLY:1;
+		/* Support for YUV420 */
+		uint32_t SUPPORT_YUV_420:1;
+		/* Use XTALIN reference clock source */
+		uint32_t SET_XTALIN_REF_SRC:1;
+		/* Use GENLK reference clock source */
+		uint32_t SET_GENLOCK_REF_DIV_SRC:1;
+	} flags;
+};
+
+struct bp_display_clock_parameters {
+	uint32_t target_display_clock; /* KHz */
+	/* Actual Display Clock set due to clock divider granularity KHz */
+	uint32_t actual_display_clock;
+	/* Actual Post Divider ID used to generate the actual clock */
+	uint32_t actual_post_divider_id;
+};
+
+enum bp_dce_clock_type {
+	DCECLOCK_TYPE_DISPLAY_CLOCK = 0,
+	DCECLOCK_TYPE_DPREFCLK      = 1
+};
+
+/* DCE Clock Parameters structure for SetDceClock Exec command table */
+struct bp_set_dce_clock_parameters {
+	enum clock_source_id pll_id; /* Clock Source Id */
+	/* Display clock or DPREFCLK value */
+	uint32_t target_clock_frequency;
+	/* Clock to set: =0: DISPCLK  =1: DPREFCLK  =2: PIXCLK */
+	enum bp_dce_clock_type clock_type;
+
+	struct set_dce_clock_flags {
+		uint32_t USE_GENERICA_AS_SOURCE_FOR_DPREFCLK:1;
+		/* Use XTALIN reference clock source */
+		uint32_t USE_XTALIN_AS_SOURCE_FOR_DPREFCLK:1;
+		/* Use PCIE reference clock source */
+		uint32_t USE_PCIE_AS_SOURCE_FOR_DPREFCLK:1;
+		/* Use GENLK reference clock source */
+		uint32_t USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK:1;
+	} flags;
+};
+
+struct spread_spectrum_flags {
+	/* 1 = Center Spread; 0 = down spread */
+	uint32_t CENTER_SPREAD:1;
+	/* 1 = external; 0 = internal */
+	uint32_t EXTERNAL_SS:1;
+	/* 1 = delta-sigma type parameter; 0 = ver1 */
+	uint32_t DS_TYPE:1;
+};
+
+struct bp_spread_spectrum_parameters {
+	enum clock_source_id pll_id;
+	uint32_t percentage;
+	uint32_t ds_frac_amount;
+
+	union {
+		struct {
+			uint32_t step;
+			uint32_t delay;
+			uint32_t range; /* In Hz unit */
+		} ver1;
+		struct {
+			uint32_t feedback_amount;
+			uint32_t nfrac_amount;
+			uint32_t ds_frac_size;
+		} ds;
+	};
+
+	struct spread_spectrum_flags flags;
+};
+
+struct bp_encoder_cap_info {
+	uint32_t DP_HBR2_CAP:1;
+	uint32_t DP_HBR2_EN:1;
+	uint32_t RESERVED:30;
+};
+
+struct bp_gpio_cntl_info {
+	uint32_t id;
+	enum gpio_pin_output_state state;
+};
+
+#endif /*__DAL_BIOS_PARSER_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_asic_id.h b/drivers/gpu/drm/amd/dal/include/dal_asic_id.h
new file mode 100644
index 000000000000..78f88b129a35
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_asic_id.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ASIC_ID_H__
+#define __DAL_ASIC_ID_H__
+
+/*
+ * ASIC internal revision ID
+ */
+
+/* DCE80 (based on ci_id.h in Perforce) */
+
+#define	CI_BONAIRE_M_A0 0x14
+#define	CI_BONAIRE_M_A1	0x15
+#define	CI_HAWAII_P_A0	0x28
+
+#define CI_UNKNOWN	0xFF
+
+#define ASIC_REV_IS_BONAIRE_M(rev) \
+	((rev >= CI_BONAIRE_M_A0) && (rev < CI_HAWAII_P_A0))
+
+#define ASIC_REV_IS_HAWAII_P(rev) \
+	(rev >= CI_HAWAII_P_A0)
+
+/* KV1 with Spectre GFX core, 8-8-1-2 (CU-Pix-Primitive-RB) */
+#define KV_SPECTRE_A0 0x01
+
+/* KV2 with Spooky GFX core, including downgraded from Spectre core,
+ * 3-4-1-1 (CU-Pix-Primitive-RB) */
+#define KV_SPOOKY_A0 0x41
+
+/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define KB_KALINDI_A0 0x81
+
+/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define KB_KALINDI_A1 0x82
+
+/* BV with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define BV_KALINDI_A2 0x85
+
+/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define ML_GODAVARI_A0 0xA1
+
+/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define ML_GODAVARI_A1 0xA2
+
+#define KV_UNKNOWN 0xFF
+
+#define ASIC_REV_IS_KALINDI(rev) \
+	((rev >= KB_KALINDI_A0) && (rev < KV_UNKNOWN))
+
+#define ASIC_REV_IS_BHAVANI(rev) \
+	((rev >= BV_KALINDI_A2) && (rev < ML_GODAVARI_A0))
+
+#define ASIC_REV_IS_GODAVARI(rev) \
+	((rev >= ML_GODAVARI_A0) && (rev < KV_UNKNOWN))
+
+/* VI Family */
+/* DCE10 */
+#define VI_TONGA_P_A0 20
+#define VI_TONGA_P_A1 21
+#define VI_FIJI_P_A0 60
+
+#define ASIC_REV_IS_TONGA_P(eChipRev) ((eChipRev >= VI_TONGA_P_A0) && \
+		(eChipRev < 40))
+#define ASIC_REV_IS_FIJI_P(eChipRev) ((eChipRev >= VI_FIJI_P_A0) && \
+		(eChipRev < 80))
+
+/* DCE11 */
+#define CZ_CARRIZO_A0 0x01
+
+#define STONEY_A0 0x61
+#define CZ_UNKNOWN 0xFF
+
+#define ASIC_REV_IS_STONEY(rev) \
+	((rev >= STONEY_A0) && (rev < CZ_UNKNOWN))
+
+/*
+ * ASIC chip ID
+ */
+/* DCE80 */
+#define DEVICE_ID_KALINDI_9834 0x9834
+#define DEVICE_ID_TEMASH_9839 0x9839
+#define DEVICE_ID_TEMASH_983D 0x983D
+
+
+/* Asic Family IDs for different asic family. */
+#define FAMILY_CI 120 /* Sea Islands: Hawaii (P), Bonaire (M) */
+#define FAMILY_KV 125 /* Fusion => Kaveri: Spectre, Spooky; Kabini: Kalindi */
+#define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */
+#define FAMILY_CZ 135 /* Carrizo */
+
+#define	FAMILY_UNKNOWN 0xFF
+
+#endif /* __DAL_ASIC_ID_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_register_logger.h b/drivers/gpu/drm/amd/dal/include/dal_register_logger.h
new file mode 100644
index 000000000000..176d811327af
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_register_logger.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_REGISTER_LOGGER__
+#define __DAL_REGISTER_LOGGER__
+
+/****************
+ * API functions
+ ***************/
+
+/* dal_reg_logger_push - begin Register Logging */
+void dal_reg_logger_push(const char *caller_func);
+/* dal_reg_logger_pop - stop Register Logging */
+void dal_reg_logger_pop(void);
+
+
+/* for internal use of the Logger only */
+void dal_reg_logger_rw_count_increment(void);
+bool dal_reg_logger_should_dump_register(void);
+
+#endif /* __DAL_REGISTER_LOGGER__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_types.h b/drivers/gpu/drm/amd/dal/include/dal_types.h
new file mode 100644
index 000000000000..373977685b70
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_types.h
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TYPES_H__
+#define __DAL_TYPES_H__
+
+#include "signal_types.h"
+#include "dc_types.h"
+
+struct dal_logger;
+struct dc_bios;
+
+enum dce_version {
+	DCE_VERSION_UNKNOWN = (-1),
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	DCE_VERSION_10_0,
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	DCE_VERSION_11_0,
+#endif
+	DCE_VERSION_MAX
+};
+
+/*
+ * ASIC Runtime Flags
+ */
+struct dal_asic_runtime_flags {
+	union {
+		uint32_t raw;
+		struct {
+			uint32_t EMULATE_REPLUG_ON_CAP_CHANGE:1;
+			uint32_t SUPPORT_XRBIAS:1;
+			uint32_t SKIP_POWER_DOWN_ON_RESUME:1;
+			uint32_t FULL_DETECT_ON_RESUME:1;
+			uint32_t GSL_FRAMELOCK:1;
+			uint32_t NO_LOW_BPP_MODES:1;
+			uint32_t BLOCK_ON_INITIAL_DETECTION:1;
+			uint32_t OPTIMIZED_DISPLAY_PROGRAMMING_ON_BOOT:1;
+			uint32_t DRIVER_CONTROLLED_BRIGHTNESS:1;
+			uint32_t MODIFIABLE_FRAME_DURATION:1;
+			uint32_t MIRACAST_SUPPORTED:1;
+			uint32_t CONNECTED_STANDBY_SUPPORTED:1;
+			uint32_t GNB_WAKEUP_SUPPORTED:1;
+		} bits;
+	} flags;
+};
+
+struct hw_asic_id {
+	uint32_t chip_id;
+	uint32_t chip_family;
+	uint32_t pci_revision_id;
+	uint32_t hw_internal_rev;
+	uint32_t vram_type;
+	uint32_t vram_width;
+	uint32_t feature_flags;
+	struct dal_asic_runtime_flags runtime_flags;
+	uint32_t fake_paths_num;
+	void *atombios_base_address;
+};
+
+/* this is pci information. BDF stands for BUS,DEVICE,FUNCTION*/
+
+struct bdf_info {
+	uint16_t BUS_NUMBER:8;
+	uint16_t DEVICE_NUMBER:5;
+	uint16_t FUNCTION_NUMBER:3;
+};
+
+#define DAL_PARAM_INVALID_INT 0x80000000
+
+/* shift values for bool override parameter mask
+ * bmask is for this struct,if we touch this feature
+ * bval indicates every bit fields for this struct too,1 is enable this feature
+ * amdgpu.disp_bval=1594, amdgpu.disp_bmask=1594 ,
+ * finally will show log like this:
+ * Overridden FEATURE_LIGHT_SLEEP is enabled now
+ * Overridden FEATURE_USE_MAX_DISPLAY_CLK is enabled now
+ * Overridden FEATURE_ENABLE_DFS_BYPASS is enabled now
+ * Overridden FEATURE_POWER_GATING_PIPE_IN_TILE is enabled now
+ * Overridden FEATURE_USE_PPLIB is enabled now
+ * Overridden FEATURE_DISABLE_LPT_SUPPORT is enabled now
+ * Overridden FEATURE_DUMMY_FBC_BACKEND is enabled now */
+enum bool_param_shift {
+	DAL_PARAM_MAXIMIZE_STUTTER_MARKS = 0,
+	DAL_PARAM_LIGHT_SLEEP,
+	DAL_PARAM_MAXIMIZE_URGENCY_WATERMARKS,
+	DAL_PARAM_USE_MAX_DISPLAY_CLK,
+	DAL_PARAM_ENABLE_DFS_BYPASS,
+	DAL_PARAM_POWER_GATING_PIPE_IN_TILE,
+	DAL_PARAM_POWER_GATING_LB_PORTION,
+	DAL_PARAM_PSR_ENABLE,
+	DAL_PARAM_VARI_BRIGHT_ENABLE,
+	DAL_PARAM_USE_PPLIB,
+	DAL_PARAM_DISABLE_LPT_SUPPORT,
+	DAL_PARAM_DUMMY_FBC_BACKEND,
+	DAL_PARAM_ENABLE_GPU_SCALING,
+	DAL_BOOL_PARAM_MAX
+};
+
+/* array index for integer override parameters*/
+enum int_param_array_index {
+	DAL_PARAM_MAX_COFUNC_NON_DP_DISPLAYS = 0,
+	DAL_PARAM_DRR_SUPPORT,
+	DAL_INT_PARAM_MAX
+};
+
+struct dal_override_parameters {
+	uint32_t bool_param_enable_mask;
+	uint32_t bool_param_values;
+	uint32_t int_param_values[DAL_INT_PARAM_MAX];
+};
+
+
+struct dal_init_data {
+	struct hw_asic_id asic_id;
+	struct view_port_alignment vp_alignment;
+	struct bdf_info bdf_info;
+	struct dal_override_parameters display_param;
+	void *driver; /* ctx */
+	void *cgs_device;
+	uint8_t num_virtual_links;
+	/* If 'vbios_override' not NULL, it will be called instead
+	 * of the real VBIOS. Intended use is Diagnostics on FPGA. */
+	struct dc_bios *vbios_override;
+	enum dce_environment dce_environment;
+};
+
+struct dal_dc_init_data {
+	struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */
+	struct adapter_service *adapter_srv;
+};
+
+struct dal_dev_c_lut {
+	uint8_t red;
+	uint8_t green;
+	uint8_t blue;
+	uint8_t reserved;
+};
+
+struct dal_dev_gamma_lut {
+	uint16_t red;
+	uint16_t green;
+	uint16_t blue;
+};
+
+struct dc_context {
+	struct dc *dc;
+
+	void *driver_context; /* e.g. amdgpu_device */
+
+	struct dal_logger *logger;
+	void *cgs_device;
+
+	enum dce_environment dce_environment;
+};
+
+/* Wireless display structs */
+
+union dal_remote_display_cea_mode_bitmap {
+	struct {
+		uint32_t CEA_640X480_60P:1;/*0*/
+		uint32_t CEA_720X480_60P:1;/*1*/
+		uint32_t CEA_720X480_60I:1;/*2*/
+		uint32_t CEA_720X576_50P:1;/*3*/
+		uint32_t CEA_720X576_50I:1;/*4*/
+		uint32_t CEA_1280X720_30P:1;/*5*/
+		uint32_t CEA_1280X720_60P:1;/*6*/
+		uint32_t CEA_1920X1080_30P:1;/*7*/
+		uint32_t CEA_1920X1080_60P:1;/*8*/
+		uint32_t CEA_1920X1080_60I:1;/*9*/
+		uint32_t CEA_1280X720_25P:1;/*10*/
+		uint32_t CEA_1280X728_50P:1;/*11*/
+		uint32_t CEA_1920X1080_25P:1;/*12*/
+		uint32_t CEA_1920X1080_50P:1;/*13*/
+		uint32_t CEA_1920X1080_50I:1;/*14*/
+		uint32_t CEA_1280X1024_24P:1;/*15*/
+		uint32_t CEA_1920X1080_24P:1;/*16*/
+		uint32_t RESERVED:15;/*[17-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_vesa_mode_bitmap {
+	struct {
+		uint32_t VESA_800X600_30P:1;/*0*/
+		uint32_t VESA_800X600_60P:1;/*1*/
+		uint32_t VESA_1024X768_30P:1;/*2*/
+		uint32_t VESA_1024X768_60P:1;/*3*/
+		uint32_t VESA_1152X864_30P:1;/*4*/
+		uint32_t VESA_1152X864_60P:1;/*5*/
+		uint32_t VESA_1280X768_30P:1;/*6*/
+		uint32_t VESA_1280X768_60P:1;/*7*/
+		uint32_t VESA_1280X800_30P:1;/*8*/
+		uint32_t VESA_1280X800_60P:1;/*9*/
+		uint32_t VESA_1360X768_30P:1;/*10*/
+		uint32_t VESA_1360X768_60P:1;/*11*/
+		uint32_t VESA_1366X768_30P:1;/*12*/
+		uint32_t VESA_1366X768_60P:1;/*13*/
+		uint32_t VESA_1280X1024_30P:1;/*14*/
+		uint32_t VESA_1280X1024_60P:1;/*15*/
+		uint32_t VESA_1400X1050_30P:1;/*16*/
+		uint32_t VESA_1400X1050_60P:1;/*17*/
+		uint32_t VESA_1440X900_30P:1;/*18*/
+		uint32_t VESA_1440X900_60P:1;/*19*/
+		uint32_t VESA_1600X900_30P:1;/*20*/
+		uint32_t VESA_1600X900_60P:1;/*21*/
+		uint32_t VESA_1600X1200_30P:1;/*22*/
+		uint32_t VESA_1600X1200_60P:1;/*23*/
+		uint32_t VESA_1680X1024_30P:1;/*24*/
+		uint32_t VESA_1680X1024_60P:1;/*25*/
+		uint32_t VESA_1680X1050_30P:1;/*26*/
+		uint32_t VESA_1680X1050_60P:1;/*27*/
+		uint32_t VESA_1920X1200_30P:1;/*28*/
+		uint32_t VESA_1920X1200_60P:1;/*29*/
+		uint32_t RESERVED:2;/*[30-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_hh_mode_bitmap {
+	struct {
+		uint32_t HH_800X480_30P:1;/*0*/
+		uint32_t HH_800X480_60P:1;/*1*/
+		uint32_t HH_854X480_30P:1;/*2*/
+		uint32_t HH_854X480_60P:1;/*3*/
+		uint32_t HH_864X480_30P:1;/*4*/
+		uint32_t HH_864X480_60P:1;/*5*/
+		uint32_t HH_640X360_30P:1;/*6*/
+		uint32_t HH_640X360_60P:1;/*7*/
+		uint32_t HH_960X540_30P:1;/*8*/
+		uint32_t HH_960X540_60P:1;/*9*/
+		uint32_t HH_848X480_30P:1;/*10*/
+		uint32_t HH_848X480_60P:1;/*11*/
+		uint32_t RESERVED:20;/*[12-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_stereo_3d_mode_bitmap {
+	struct {
+		uint32_t STEREO_1920X1080_24P_TOP_AND_BOTTOM:1;/*0*/
+		uint32_t STEREO_1280X720_60P_TOP_AND_BOTTOM:1;/*1*/
+		uint32_t STEREO_1280X720_50P_TOP_AND_BOTTOM:1;/*2*/
+		uint32_t STEREO_1920X1080_24X2P_FRAME_ALTERNATE:1;/*3*/
+		uint32_t STEREO_1280X720_60X2P_FRAME_ALTERNATE:1;/*4*/
+		uint32_t STEREO_1280X720_30X2P_FRAME_ALTERNATE:1;/*5*/
+		uint32_t STEREO_1280X720_50X2P_FRAME_ALTERNATE:1;/*6*/
+		uint32_t STEREO_1280X720_25X2P_FRAME_ALTERNATE:1;/*7*/
+		uint32_t STEREO_1920X1080_24P_FRAME_PACKING:1;/* 8*/
+		uint32_t STEREO_1280X720_60P_FRAME_PACKING:1;/* 9*/
+		uint32_t STEREO_1280X720_30P_FRAME_PACKING:1;/*10*/
+		uint32_t STEREO_1280X720_50P_FRAME_PACKING:1;/*11*/
+		uint32_t STEREO_1280X720_25P_FRAME_PACKING:1;/*12*/
+		uint32_t RESERVED:19; /*[13-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_audio_bitmap {
+	struct {
+		uint32_t LPCM_44100HZ_16BITS_2_CHANNELS:1;/*0*/
+		uint32_t LPCM_48000HZ_16BITS_2_CHANNELS:1;/*1*/
+		uint32_t AAC_48000HZ_16BITS_2_CHANNELS:1;/*2*/
+		uint32_t AAC_48000HZ_16BITS_4_CHANNELS:1;/*3*/
+		uint32_t AAC_48000HZ_16BITS_6_CHANNELS:1;/*4*/
+		uint32_t AAC_48000HZ_16BITS_8_CHANNELS:1;/*5*/
+		uint32_t AC3_48000HZ_16BITS_2_CHANNELS:1;/*6*/
+		uint32_t AC3_48000HZ_16BITS_4_CHANNELS:1;/*7*/
+		uint32_t AC3_48000HZ_16BITS_6_CHANNELS:1;/*8*/
+		uint32_t RESERVED:23;/*[9-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+struct dal_remote_display_receiver_capability {
+	union dal_remote_display_cea_mode_bitmap cea_mode;
+	union dal_remote_display_vesa_mode_bitmap vesa_mode;
+	union dal_remote_display_hh_mode_bitmap hh_mode;
+	union dal_remote_display_stereo_3d_mode_bitmap stereo_3d_mode;
+	union dal_remote_display_audio_bitmap audio;
+};
+
+#endif /* __DAL_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h b/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
new file mode 100644
index 000000000000..b7fb9ff16a97
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_CLOCK_GENERATOR_INTERFACE_H__
+#define __DC_CLOCK_GENERATOR_INTERFACE_H__
+
+#include "grph_object_ctrl_defs.h"
+#include "set_mode_types.h"
+
+/* Parameter for programming the DCCP_DISP_SLOW_SELECT*/
+struct dccg_mapping_params {
+	uint32_t controllers_num;
+	enum controller_id *controllers;
+};
+
+/* Parameters related to HW DeSpread of DP Reference Clock*/
+struct dccg_dp_ref_clk_ds_params {
+	struct {
+		/* Flag for Enabled SS on DP Reference Clock*/
+		bool SS_ENABLED:1;
+		/* Flag for HW De Spread enabled
+		 * (if enabled SS on DP Reference Clock)*/
+		bool DS_ENABLED:1;
+		/* Flag for HW De Spread Calculations enabled for DS_DTO_INCR
+		 * and DS_DTO_MODULO (if 0 SW programs DS_DTO_INCR and
+		 * DS_DTO_MODULO)*/
+		bool DS_CALCULATIONS:1;
+	} flags;
+	/*DP Reference clock SS percentage
+	 * (if enabled downspread on DP Reference Clock)*/
+	uint32_t ss_percentage;
+	/*DP Reference clock SS percentage Divider (1000 or 100)*/
+	uint32_t ss_percentage_divider;
+};
+
+struct dc_clock_generator;
+
+void dal_dc_clock_generator_destroy(struct dc_clock_generator **dc);
+void dal_dc_clock_generator_set_display_pipe_mapping(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_mapping_params *params);
+bool dal_dc_clock_generator_get_dp_ref_clk_ds_params(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_dp_ref_clk_ds_params *params);
+bool dal_dc_clock_generator_enable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen,
+	uint32_t dprefclk);
+void dal_dc_clock_generator_disable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen);
+void dal_dc_clock_generator_set_gtc_group_offset(
+	struct dc_clock_generator *dc_clk_gen,
+	enum gtc_group group_num,
+	uint32_t offset);
+
+#endif /* __DC_CLOCK_GENERATOR_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dcs_types.h b/drivers/gpu/drm/amd/dal/include/dcs_types.h
new file mode 100644
index 000000000000..8c650571ff69
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dcs_types.h
@@ -0,0 +1,742 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DCS_TYPES_H__
+#define __DAL_DCS_TYPES_H__
+
+#include "signal_types.h"
+
+#include "dc_types.h"
+
+#define NUM_OF_BYTE_EDID_COLOR_CHARACTERISTICS 10
+#define MAX_NUMBER_OF_HDMI_VSDB_3D_EXTENDED_SUPPORT 21
+#define MAX_NUMBER_OF_HDMI_VSDB_VICS 7
+
+struct drr_config {
+	/* minimum frame per second for dynamic
+	 * refresh rate feature; 0 if drr support not found*/
+	uint32_t min_fps_in_microhz;
+	bool force_lock_on_event;
+	bool lock_to_master_vsync;
+
+	struct {
+		uint8_t FORCED_BY_REGKEY_OR_ESCAPE:1;
+		uint8_t FORCED_BY_VBIOS:1;
+		uint8_t SUPPORTED_BY_EDID:1;
+	} support_method;
+};
+
+struct timing_limits {
+	uint32_t min_pixel_clock_in_khz;
+	uint32_t max_pixel_clock_in_khz;
+};
+
+struct vendor_product_id_info {
+	uint32_t manufacturer_id;
+	uint32_t product_id;
+	uint32_t serial_id;
+	uint32_t manufacture_week;
+	uint32_t manufacture_year;
+};
+
+struct display_range_limits {
+	uint32_t min_v_rate_hz;
+	uint32_t max_v_rate_hz;
+	uint32_t min_h_rate_khz;
+	uint32_t max_h_rateIn_khz;
+	uint32_t max_pix_clk_khz;
+	bool use_override;
+};
+
+struct monitor_user_select_limits {
+	bool use_ati_override;
+	uint32_t max_h_res;
+	uint32_t max_v_res;
+	uint32_t max_refresh_rate;
+};
+
+enum edid_screen_aspect_ratio {
+	EDID_SCREEN_AR_UNKNOWN = 0,
+	EDID_SCREEN_AR_PROJECTOR,
+	EDID_SCREEN_AR_16X9,
+	EDID_SCREEN_AR_16X10,
+	EDID_SCREEN_AR_4X3,
+	EDID_SCREEN_AR_5X4,
+	EDID_SCREEN_AR_9X16,
+	EDID_SCREEN_AR_10X16,
+	EDID_SCREEN_AR_3X4,
+	EDID_SCREEN_AR_4X5
+};
+
+struct edid_screen_info {
+	enum edid_screen_aspect_ratio aspect_ratio;
+	uint32_t width;
+	uint32_t height;
+};
+
+struct display_characteristics {
+	uint8_t gamma;
+	uint8_t color_characteristics[NUM_OF_BYTE_EDID_COLOR_CHARACTERISTICS];
+};
+
+union cv_smart_dongle_modes {
+	uint8_t all;
+	struct cv_smart_dongle_switches {
+		uint8_t MODE_1080I:1;
+		uint8_t MODE_720P:1;
+		uint8_t MODE_540P:1;
+		uint8_t MODE_480P:1;
+		uint8_t MODE_480I:1;
+		uint8_t MODE_16_9:1;
+	} switches;
+};
+
+struct cea_audio_mode {
+	uint8_t format_code; /* ucData[0] [6:3]*/
+	uint8_t channel_count; /* ucData[0] [2:0]*/
+	uint8_t sample_rate; /* ucData[1]*/
+	union {
+		uint8_t sample_size; /* for LPCM*/
+		/*  for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/
+		uint8_t max_bit_rate;
+		uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/
+	};
+};
+
+union cea_speaker_allocation_data_block {
+	struct {
+		uint32_t FL_FR:1;
+		uint32_t LFE:1;
+		uint32_t FC:1;
+		uint32_t RL_RR:1;
+		uint32_t RC:1;
+		uint32_t FLC_FRC:1;
+		uint32_t RLC_RRC:1;
+	} bits;
+	uint32_t raw;
+};
+
+struct cea_colorimetry_data_block {
+	struct {
+		uint32_t XV_YCC601:1;
+		uint32_t XV_YCC709:1;
+		uint32_t S_YCC601:1;
+		uint32_t ADOBE_YCC601:1;
+		uint32_t ADOBE_RGB:1;
+
+	} flag;
+	struct {
+		uint32_t MD0:1;
+		uint32_t MD1:1;
+		uint32_t MD2:1;
+		uint32_t MD3:1;
+	} metadata_flag;
+};
+
+union cea_video_capability_data_block {
+	struct {
+		uint8_t S_CE0:1;
+		uint8_t S_CE1:1;
+		uint8_t S_IT0:1;
+		uint8_t S_IT1:1;
+		uint8_t S_PT0:1;
+		uint8_t S_PT1:1;
+		uint8_t QS:1;
+		uint8_t QY:1;
+	} bits;
+	uint8_t raw;
+};
+
+enum stereo_3d_multi_presence {
+	STEREO_3D_MULTI_NOT_PRESENT = 0,
+	STEREO_3D_MULTI_ALL_FORMATS,
+	STEREO_3D_MULTI_MASKED_FORMATS,
+	STEREO_3D_MULTI_RESERVED
+};
+
+enum cea_hdmi_vic {
+	CEA_HDMI_VIC_RESERVED = 0,
+	CEA_HDMI_VIC_4KX2K_30,
+	CEA_HDMI_VIC_4KX2K_25,
+	CEA_HDMI_VIC_4KX2K_24,
+	CEA_HDMI_VIC_4KX2K_24_SMPTE
+};
+
+struct cea_hdmi_vsdb_extended_caps {
+	uint32_t reserved;
+	uint32_t image_size;
+	enum stereo_3d_multi_presence stereo_3d_multi_present;
+	bool stereo_3d_present;
+	uint32_t hdmi_3d_len;
+	uint32_t hdmi_vic_len;
+};
+
+struct cea_vendor_specific_data_block {
+
+	uint32_t ieee_id;
+
+	struct commonent_phy {
+		uint32_t PHY_ADDR_A:4;
+		uint32_t PHY_ADDR_B:4;
+		uint32_t PHY_ADDR_C:4;
+		uint32_t PHY_ADDR_D:4;
+	} commonent_phy_addr;
+
+	struct byte6 {
+		uint32_t SUPPORTS_AI:1;
+		uint32_t DC_48BIT:1;
+		uint32_t DC_36BIT:1;
+		uint32_t DC_30BIT:1;
+		uint32_t DC_Y444:1;
+		uint32_t DVI_DUAL:1;
+		uint32_t RESERVED:2;
+	} byte6;/* link capabilities*/
+	bool byte6_valid;
+
+	uint32_t max_tmds_clk_mhz;
+
+	struct byte8 {
+		uint32_t LATENCY_FIELDS_PRESENT:1;
+		uint32_t ILATENCY_FIELDS_PRESENT:1;
+		uint32_t HDMI_VIDEO_PRESENT:1;
+		uint32_t RESERVED:1;
+		uint32_t CNC3_GAME:1;
+		uint32_t CNC2_CINEMA:1;
+		uint32_t CNC1_PHOTO:1;
+		uint32_t CNC0_GRAPHICS:1;
+	} byte8;
+	/*bit 6-7: latency flags to indicate valid latency fields*/
+	/*bit 5: support of additional video format capabilities*/
+	/* bit 0-3: flags indicating which content type is supported*/
+	uint32_t video_latency;
+	uint32_t audio_latency;
+	uint32_t i_video_latency;
+	uint32_t i_audio_latency;
+
+	struct cea_hdmi_vsdb_extended_caps hdmi_vsdb_extended_caps;
+
+	enum stereo_3d_multi_presence stereo_3d_multi_present;
+
+	struct {
+		bool FRAME_PACKING:1;
+		bool SIDE_BY_SIDE_HALF:1;
+		bool TOP_AND_BOTTOM:1;
+	} stereo_3d_all_support;
+	uint16_t stereo_3d_mask;
+
+	enum cea_hdmi_vic hdmi_vic[MAX_NUMBER_OF_HDMI_VSDB_VICS];
+	struct stereo_3d_extended_support {
+		struct {
+			bool FRAME_PACKING:1;
+			bool SIDE_BY_SIDE_HALF:1;
+			bool TOP_AND_BOTTOM:1;
+		} format;
+		uint32_t vic_index;
+		uint32_t value;
+		uint32_t size;
+	} stereo_3d_extended_support[MAX_NUMBER_OF_HDMI_VSDB_3D_EXTENDED_SUPPORT];
+};
+
+struct cea861_support {
+
+	uint32_t revision;
+	union {
+		struct {
+			uint32_t NATIVE_COUNT:4;
+			uint32_t BASE_AUDIO:1;
+			uint32_t YCRCB444:1;
+			uint32_t YCRCB422:1;
+			uint32_t UNDER_SCAN:1;
+		} features;
+		uint8_t raw_features;
+	};
+};
+
+struct dcs_customized_mode {
+	struct {
+		uint32_t READ_ONLY:1;
+		uint32_t ADD_BY_DRIVER:1;
+		uint32_t INTERLACED:1;
+		uint32_t BASE_MODE:1;
+	} flags;
+	struct dc_mode_info base_mode_info;
+	struct dc_mode_info customized_mode_info;
+};
+
+struct dcs_override_mode_timing {
+	/* possible timing standards, bit vector of TimingStandard*/
+	uint32_t possible_timing_standards;
+	/* indicate driver default timing is used , no override*/
+	bool use_driver_default_timing;
+	struct dc_mode_timing mode_timing;
+};
+
+struct dcs_override_mode_timing_list {
+	uint32_t max_num_overrides;
+	uint32_t num_overrides;
+	struct dcs_override_mode_timing mode_timings[1];
+};
+
+/* "interface type" is different from Signal Type because
+ * an "interface type" can be driven by more than one Signal Type.
+ * For example, INTERFACE_TYPE_DVI can be driven by
+ * Single or Dual link DVI signal. */
+enum dcs_interface_type {
+	INTERFACE_TYPE_VGA = 0,
+	INTERFACE_TYPE_DVI,
+	INTERFACE_TYPE_CV,
+	INTERFACE_TYPE_TV,
+	INTERFACE_TYPE_LVDS,
+	INTERFACE_TYPE_DP,
+	INTERFACE_TYPE_WIRELESS,
+	INTERFACE_TYPE_CF,
+	INTERFACE_TYPE_EDP
+};
+
+
+union panel_misc_info {
+	struct {
+		uint32_t H_CUT_OFF:1;
+		uint32_t H_SYNC_POLARITY:1;/*0=Active High, 1=Active Low*/
+		uint32_t V_SYNC_POLARITY:1; /*0=Active High, 1=Active Low*/
+		uint32_t V_CUT_OFF:1;
+		uint32_t H_REPLICATION_BY_2:1;
+		uint32_t V_REPLICATION_BY_2:1;
+		uint32_t COMPOSITE_SYNC:1;
+		uint32_t INTERLACE:1;
+		uint32_t DOUBLE_CLOCK:1;
+		uint32_t RGB888:1;
+		uint32_t GREY_LEVEL:2;
+		uint32_t SPATIAL:1;
+		uint32_t TEMPORAL:1;
+		uint32_t API_ENABLED:1;
+	} bits;
+	uint32_t raw;
+};
+
+union hdtv_mode_support {
+	struct {
+		uint32_t HDTV_SUPPORT_480I:1;
+		uint32_t HDTV_SUPPORT_480P:1;
+		uint32_t HDTV_SUPPORT_576I25:1;
+		uint32_t HDTV_SUPPORT_576P50:1;
+		uint32_t HDTV_SUPPORT_720P:1;
+		uint32_t HDTV_SUPPORT_720P50:1;
+		uint32_t HDTV_SUPPORT_1080I:1;
+		uint32_t HDTV_SUPPORT_1080I25:1;
+		uint32_t HDTV_SUPPORT_1080P:1;
+		uint32_t HDTV_SUPPORT_1080P50:1;
+		uint32_t HDTV_SUPPORT_1080P24:1;
+		uint32_t HDTV_SUPPORT_1080P25:1;
+		uint32_t HDTV_SUPPORT_1080P30:1;
+		uint32_t HDTV_SUPPORT_16X9:1;
+	} bits;
+	uint32_t raw;
+};
+
+enum edid_retrieve_status {
+	EDID_RETRIEVE_SUCCESS = 0,
+	EDID_RETRIEVE_FAIL,
+	EDID_RETRIEVE_SAME_EDID,
+	EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS
+};
+
+#define DCS_DECODE_EDID_RETRIEVE_STATUS(status) \
+	(status == EDID_RETRIEVE_SUCCESS) ? "EDID_RETRIEVE_SUCCESS" : \
+	(status == EDID_RETRIEVE_FAIL) ? "EDID_RETRIEVE_FAIL" : \
+	(status == EDID_RETRIEVE_SAME_EDID) ? "EDID_RETRIEVE_SAME_EDID" : \
+	(status == EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS) ? \
+		"EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS" : "Unknown"
+
+
+#ifndef TV_SIGNALFORMAT_DEFINED
+#define TV_SIGNALFORMAT_DEFINED
+enum tv_signal_format {
+	TV_SIGNAL_FORMAT_UNKNOWN,
+	TV_SIGNAL_FORMAT_NTSC,
+	TV_SIGNAL_FORMAT_NTSC_J,
+	TV_SIGNAL_FORMAT_PAL,
+	TV_SIGNAL_FORMAT_PAL_M,
+	TV_SIGNAL_FORMAT_PAL_CN,
+	TV_SIGNAL_FORMAT_SECAM
+};
+#endif
+
+enum tv_signal_format_result {
+	TV_SIGNAL_FORMAT_RESULT_OK,
+	TV_SIGNAL_FORMAT_SET_MODE_REQ,
+	TV_SIGNAL_FORMAT_REBOOT_REQ,
+	TV_SIGNAL_FORMAT_ERROR
+};
+
+enum pixel_encoding_mask {
+	PIXEL_ENCODING_MASK_YCBCR444 = 0x01,
+	PIXEL_ENCODING_MASK_YCBCR422 = 0x02,
+	PIXEL_ENCODING_MASK_RGB = 0x04,
+};
+
+struct display_pixel_encoding_support {
+	uint32_t mask;
+};
+
+enum color_depth_index {
+	COLOR_DEPTH_INDEX_UNKNOWN,
+	COLOR_DEPTH_INDEX_666 = 0x01,
+	COLOR_DEPTH_INDEX_888 = 0x02,
+	COLOR_DEPTH_INDEX_101010 = 0x04,
+	COLOR_DEPTH_INDEX_121212 = 0x08,
+	COLOR_DEPTH_INDEX_141414 = 0x10,
+	COLOR_DEPTH_INDEX_161616 = 0x20,
+	COLOR_DEPTH_INDEX_LAST = 0x40,
+};
+
+struct display_color_depth_support {
+	uint32_t mask;
+	bool deep_color_native_res_only;
+};
+
+struct display_color_and_pixel_support {
+	struct display_color_depth_support color_depth_support;
+	struct display_pixel_encoding_support pixel_encoding_support;
+	bool deep_color_y444_support;
+};
+
+enum dcs_packed_pixel_format {
+	DCS_PACKED_PIXEL_FORMAT_NOT_PACKED = 0,
+	DCS_PACKED_PIXEL_FORMAT_SPLIT_G70_B54_R70_B10 = 1,
+	DCS_PACKED_PIXEL_FORMAT_R70_G76 = 2,
+	DCS_PACKED_PIXEL_FORMAT_SPLIT_B70_G10_R70_G76 = 3,
+	DCS_PACKED_PIXEL_FORMAT_G70_B54_R70_B10 = 4,
+	DCS_PACKED_PIXEL_FORMAT_G70_B54 = 5,
+	DCS_PACKED_PIXEL_FORMAT_B70_R30_G70_R74 = 6,
+	DCS_PACKED_PIXEL_FORMAT_B70_G70_R70 = 7,
+	DCS_PACKED_PIXEL_FORMAT_B70_R32_G70_R76 = 8,
+};
+
+enum monitor_manufacturer_id {
+	MONITOR_MANUFACTURER_ID_0 = 0x0000,
+	MONITOR_MANUFACTURER_ID_1 = 0x3834,
+	MONITOR_MANUFACTURER_ID_2 = 0x4d24,
+	MONITOR_MANUFACTURER_ID_3 = 0x293E,
+	MONITOR_MANUFACTURER_ID_4 = 0x635a,
+	MONITOR_MANUFACTURER_ID_5 = 0x1006,
+	MONITOR_MANUFACTURER_ID_6 = 0xc32a,
+	MONITOR_MANUFACTURER_ID_7 = 0x4d24,
+	MONITOR_MANUFACTURER_ID_8 = 0x110e,
+	MONITOR_MANUFACTURER_ID_9 = 0xaf0d,
+	MONITOR_MANUFACTURER_ID_10 = 0x6D1E,
+	MONITOR_MANUFACTURER_ID_11 = 0xA338,
+	MONITOR_MANUFACTURER_ID_12 = 0xC315,
+	MONITOR_MANUFACTURER_ID_13 = 0xD94D,
+	MONITOR_MANUFACTURER_ID_14 = 0x104D,
+	MONITOR_MANUFACTURER_ID_15 = 0x855C,
+	MONITOR_MANUFACTURER_ID_16 = 0x4251,
+	MONITOR_MANUFACTURER_ID_17 = 0xA934,
+	MONITOR_MANUFACTURER_ID_18 = 0x0C41,
+	/* TODO: Update when EDID is available */
+	MONITOR_MANUFACTURER_ID_19 = 0xDEAD,
+	MONITOR_MANUFACTURER_ID_20 = 0x6904,
+	MONITOR_MANUFACTURER_ID_21 = 0xAC10,
+	MONITOR_MANUFACTURER_ID_22 = 0x2D4C,
+	MONITOR_MANUFACTURER_ID_23 = 0x144E,
+	MONITOR_MANUFACTURER_ID_24 = 0x6c50,
+	MONITOR_MANUFACTURER_ID_26 = 0x0c41,
+	MONITOR_MANUFACTURER_ID_27 = 0x143E,
+	MONITOR_MANUFACTURER_ID_25 = 0xffff,
+	MONITOR_MANUFACTURER_ID_28 = 0x3421,
+	MONITOR_MANUFACTURER_ID_29 = 0x2D19,
+	MONITOR_MANUFACTURER_ID_30 = 0x8B52,
+	MONITOR_MANUFACTURER_ID_31 = 0x7204,
+	MONITOR_MANUFACTURER_ID_32 = 0xF022,
+	MONITOR_MANUFACTURER_ID_33 = 0x0E11,
+	MONITOR_MANUFACTURER_ID_34 = 0xD241,
+	MONITOR_MANUFACTURER_ID_35 = 0xAE30,
+	MONITOR_MANUFACTURER_ID_36 = 0xF91E,
+	MONITOR_MANUFACTURER_ID_37 = 0xAB4C,
+};
+
+enum monitor_product_id {
+	MONITOR_PRODUCT_ID_0 = 0x0000,
+	MONITOR_PRODUCT_ID_1 = 0x0BCC,
+	MONITOR_PRODUCT_ID_2 = 0x251F,
+	MONITOR_PRODUCT_ID_3 = 0x5241,
+	MONITOR_PRODUCT_ID_4 = 0x6919,
+	MONITOR_PRODUCT_ID_5 = 0xee18,
+	MONITOR_PRODUCT_ID_6 = 0xf008,
+	MONITOR_PRODUCT_ID_7 = 0x2f0c,
+	MONITOR_PRODUCT_ID_7_2 = 0x3411,
+	MONITOR_PRODUCT_ID_9 = 0x4208,
+	MONITOR_PRODUCT_ID_10 = 0xE51D,
+	MONITOR_PRODUCT_ID_11 = 0x7E22,
+	MONITOR_PRODUCT_ID_12 = 0x0E23,
+	MONITOR_PRODUCT_ID_13 = 0x9d08,
+	MONITOR_PRODUCT_ID_14 = 0x9236,
+	MONITOR_PRODUCT_ID_15 = 0x9227,
+	MONITOR_PRODUCT_ID_16 = 0x0220,
+	MONITOR_PRODUCT_ID_17 = 0x4920,
+	MONITOR_PRODUCT_ID_18 = 0x251f,
+	MONITOR_PRODUCT_ID_19 = 0x1395,
+	MONITOR_PRODUCT_ID_20 = 0xc04e,
+	MONITOR_PRODUCT_ID_21 = 0x5787,
+	MONITOR_PRODUCT_ID_22 = 0x5A71,
+	MONITOR_PRODUCT_ID_23 = 0x6622,
+	MONITOR_PRODUCT_ID_24 = 0x20C1,
+	MONITOR_PRODUCT_ID_25 = 0x2110,
+	MONITOR_PRODUCT_ID_26 = 0x2006,
+	MONITOR_PRODUCT_ID_27 = 0x1827,
+	MONITOR_PRODUCT_ID_28 = 0x0EA0,
+	MONITOR_PRODUCT_ID_29 = 0x03D0,
+	MONITOR_PRODUCT_ID_30 = 0x01D2,
+	MONITOR_PRODUCT_ID_31 = 0x2801,
+	MONITOR_PRODUCT_ID_32 = 0x0FB3,
+	MONITOR_PRODUCT_ID_33 = 0x0FB1,
+	MONITOR_PRODUCT_ID_34 = 0xA045,
+	MONITOR_PRODUCT_ID_35 = 0x0001,
+	MONITOR_PRODUCT_ID_36 = 0xA296,
+	MONITOR_PRODUCT_ID_38 = 0x21DC,
+	MONITOR_PRODUCT_ID_37 = 0x21EA,
+	MONITOR_PRODUCT_ID_39 = 0x4093,
+	MONITOR_PRODUCT_ID_40 = 0x4094,
+	MONITOR_PRODUCT_ID_41 = 0x4094,
+	MONITOR_PRODUCT_ID_42 = 0x32A2,
+	MONITOR_PRODUCT_ID_43 = 0xE009,
+	MONITOR_PRODUCT_ID_44 = 0xA010,
+	MONITOR_PRODUCT_ID_45 = 0x405C,
+	MONITOR_PRODUCT_ID_46 = 0xF017,
+	MONITOR_PRODUCT_ID_47 = 0xD026,
+	MONITOR_PRODUCT_ID_48 = 0x4036,
+	MONITOR_PRODUCT_ID_49 = 0x4065,
+	MONITOR_PRODUCT_ID_50 = 0xA02A,
+	MONITOR_PRODUCT_ID_51 = 0xA02C,
+	MONITOR_PRODUCT_ID_46_HDMI = 0xF016,
+	MONITOR_PRODUCT_ID_53 = 0xF048,
+	MONITOR_PRODUCT_ID_54 = 0xA0A2,
+	MONITOR_PRODUCT_ID_55 = 0x4083,
+	MONITOR_PRODUCT_ID_56 = 0x0E74,
+	MONITOR_PRODUCT_ID_57 = 0x2771,
+	MONITOR_PRODUCT_ID_58 = 0x0814,
+	MONITOR_PRODUCT_ID_59 = 0xffff,
+	MONITOR_PRODUCT_ID_60 = 0x3339,
+	MONITOR_PRODUCT_ID_61 = 0x01F5,
+	MONITOR_PRODUCT_ID_62 = 0x02A5,
+	MONITOR_PRODUCT_ID_63 = 0x06AC,
+	MONITOR_PRODUCT_ID_64 = 0x04D5,
+	MONITOR_PRODUCT_ID_65 = 0x079D,
+	MONITOR_PRODUCT_ID_66 = 0x079F,
+	MONITOR_PRODUCT_ID_67 = 0x0797,
+	MONITOR_PRODUCT_ID_68 = 0x0B80,
+	MONITOR_PRODUCT_ID_69 = 0x7D06,
+	MONITOR_PRODUCT_ID_70 = 0x0131,
+	MONITOR_PRODUCT_ID_71 = 0x8545,
+	MONITOR_PRODUCT_ID_72 = 0x0002,
+	MONITOR_PRODUCT_ID_73 = 0x0125,
+	MONITOR_PRODUCT_ID_74 = 0x00D0,
+	MONITOR_PRODUCT_ID_75 = 0x26F7,
+	MONITOR_PRODUCT_ID_76 = 0x26F9,
+	MONITOR_PRODUCT_ID_77 = 0x2807,
+	MONITOR_PRODUCT_ID_78 = 0x26F3,
+	MONITOR_PRODUCT_ID_79 = 0x2676,
+	MONITOR_PRODUCT_ID_80 = 0x0A72,
+	MONITOR_PRODUCT_ID_81 = 0x2693,
+	MONITOR_PRODUCT_ID_82 = 0x2615,
+	MONITOR_PRODUCT_ID_83 = 0x2613,
+	MONITOR_PRODUCT_ID_84 = 0x262D,
+	MONITOR_PRODUCT_ID_85 = 0x264B,
+	MONITOR_PRODUCT_ID_86 = 0x2869,
+	MONITOR_PRODUCT_ID_87 = 0x286C,
+	MONITOR_PRODUCT_ID_88 = 0x288F,
+	MONITOR_PRODUCT_ID_89 = 0x2954,
+	MONITOR_PRODUCT_ID_90 = 0x6522,
+	MONITOR_PRODUCT_ID_91 = 0x0FAE,
+	MONITOR_PRODUCT_ID_92 = 0x0A0C,
+	MONITOR_PRODUCT_ID_93 = 0x00BF,
+	MONITOR_PRODUCT_ID_94 = 0x0,
+};
+
+enum monitor_patch_type {
+	MONITOR_PATCH_TYPE_NONE,
+	MONITOR_PATCH_TYPE_ERROR_CHECKSUM,
+	MONITOR_PATCH_TYPE_HDTV_WITH_PURE_DFP_EDID,
+	MONITOR_PATCH_TYPE_DO_NOT_USE_DETAILED_TIMING,
+	MONITOR_PATCH_TYPE_DO_NOT_USE_RANGE_LIMITATION,
+	MONITOR_PATCH_TYPE_EDID_EXTENTION_ERROR_CHECK_SUM,
+	MONITOR_PATCH_TYPE_TURN_OFF_DISPLAY_BEFORE_MODE_CHANGE,
+	MONITOR_PATCH_TYPE_RESTRICT_VESA_MODE_TIMING,
+	MONITOR_PATCH_TYPE_DO_NOT_USE_EDID_MAX_PIX_CLK,
+	MONITOR_PATCH_TYPE_VENDOR_0,
+	MONITOR_PATCH_TYPE_RANDOM_CRT,
+	MONITOR_PATCH_TYPE_VENDOR_1,
+	MONITOR_PATCH_TYPE_LIMIT_PANEL_SUPPORT_RGB_ONLY,
+	MONITOR_PATCH_TYPE_PACKED_PIXEL_FORMAT,
+	MONITOR_PATCH_TYPE_LARGE_PANEL,
+	MONITOR_PATCH_TYPE_STEREO_SUPPORT,
+	/* 0 (default) - mean patch will not be applied, however it can be
+	 * explicitly set to 1
+	 */
+	MONITOR_PATCH_TYPE_DUAL_EDID_PANEL,
+	MONITOR_PATCH_TYPE_IGNORE_19X12_STD_TIMING,
+	MONITOR_PATCH_TYPE_MULTIPLE_PACKED_TYPE,
+	MONITOR_PATCH_TYPE_RESET_TX_ON_DISPLAY_POWER_ON,
+	MONITOR_PATCH_TYPE_VENDOR_2,
+	MONITOR_PATCH_TYPE_RESTRICT_PROT_DUAL_LINK_DVI,
+	MONITOR_PATCH_TYPE_FORCE_LINK_RATE,
+	MONITOR_PATCH_TYPE_DELAY_AFTER_DP_RECEIVER_POWER_UP,
+	MONITOR_PATCH_TYPE_KEEP_DP_RECEIVER_POWERED,
+	MONITOR_PATCH_TYPE_DELAY_BEFORE_READ_EDID,
+	MONITOR_PATCH_TYPE_DELAY_AFTER_PIXEL_FORMAT_CHANGE,
+	MONITOR_PATCH_TYPE_INCREASE_DEFER_WRITE_RETRY_I2C_OVER_AUX,
+	MONITOR_PATCH_TYPE_NO_DEFAULT_TIMINGS,
+	MONITOR_PATCH_TYPE_ADD_CEA861_DETAILED_TIMING_VIC16,
+	MONITOR_PATCH_TYPE_ADD_CEA861_DETAILED_TIMING_VIC31,
+	MONITOR_PATCH_TYPE_DELAY_BEFORE_UNMUTE,
+	MONITOR_PATCH_TYPE_RETRY_LINK_TRAINING_ON_FAILURE,
+	MONITOR_PATCH_TYPE_ALLOW_AUX_WHEN_HPD_LOW,
+	MONITOR_PATCH_TYPE_TILED_DISPLAY,
+	MONITOR_PATCH_TYPE_DISABLE_PSR_ENTRY_ABORT,
+	MONITOR_PATCH_TYPE_EDID_EXTENTION_ERROR_CHECKSUM,
+	MONITOR_PATCH_TYPE_ALLOW_ONLY_CE_MODE,
+	MONITOR_PATCH_TYPE_VID_STREAM_DIFFER_TO_SYNC,
+	MONITOR_PATCH_TYPE_EXTRA_DELAY_ON_DISCONNECT,
+	MONITOR_PATCH_TYPE_DELAY_AFTER_DISABLE_BACKLIGHT_DFS_BYPASS,
+	MONITOR_PATCH_TYPE_SINGLE_MODE_PACKED_PIXEL
+};
+
+/* Single entry in the monitor table */
+struct monitor_patch_info {
+	enum monitor_manufacturer_id manufacturer_id;
+	enum monitor_product_id product_id;
+	enum monitor_patch_type type;
+	uint32_t param;
+};
+
+union dcs_monitor_patch_flags {
+        struct {
+                bool ERROR_CHECKSUM:1;
+                bool HDTV_WITH_PURE_DFP_EDID:1;
+                bool DO_NOT_USE_DETAILED_TIMING:1;
+                bool DO_NOT_USE_RANGE_LIMITATION:1;
+                bool EDID_EXTENTION_ERROR_CHECKSUM:1;
+                bool TURN_OFF_DISPLAY_BEFORE_MODE_CHANGE:1;
+                bool RESTRICT_VESA_MODE_TIMING:1;
+                bool DO_NOT_USE_EDID_MAX_PIX_CLK:1;
+                bool VENDOR_0:1;
+                bool RANDOM_CRT:1;/* 10 bits used including this one-*/
+                bool VENDOR_1:1;
+                bool LIMIT_PANEL_SUPPORT_RGB_ONLY:1;
+                bool PACKED_PIXEL_FORMAT:1;
+                bool LARGE_PANEL:1;
+                bool STEREO_SUPPORT:1;
+                bool DUAL_EDID_PANEL:1;
+                bool IGNORE_19X12_STD_TIMING:1;
+                bool MULTIPLE_PACKED_TYPE:1;
+                bool RESET_TX_ON_DISPLAY_POWER_ON:1;
+                bool ALLOW_ONLY_CE_MODE:1;/* 20 bits used including this one*/
+                bool RESTRICT_PROT_DUAL_LINK_DVI:1;
+                bool FORCE_LINK_RATE:1;
+                bool DELAY_AFTER_DP_RECEIVER_POWER_UP:1;
+                bool KEEP_DP_RECEIVER_POWERED:1;
+                bool DELAY_BEFORE_READ_EDID:1;
+                bool DELAY_AFTER_PIXEL_FORMAT_CHANGE:1;
+                bool INCREASE_DEFER_WRITE_RETRY_I2C_OVER_AUX:1;
+                bool NO_DEFAULT_TIMINGS:1;
+                bool ADD_CEA861_DETAILED_TIMING_VIC16:1;
+                bool ADD_CEA861_DETAILED_TIMING_VIC31:1; /* 30 bits*/
+                bool DELAY_BEFORE_UNMUTE:1;
+                bool RETRY_LINK_TRAINING_ON_FAILURE:1;
+                bool ALLOW_AUX_WHEN_HPD_LOW:1;
+                bool TILED_DISPLAY:1;
+                bool DISABLE_PSR_ENTRY_ABORT:1;
+                bool INTERMITTENT_EDID_ERROR:1;/* 36 bits total*/
+                bool VID_STREAM_DIFFER_TO_SYNC:1;/* 37 bits total*/
+                bool EXTRA_DELAY_ON_DISCONNECT:1;/* 38 bits total*/
+                bool DELAY_AFTER_DISABLE_BACKLIGHT_DFS_BYPASS:1;/* 39 bits total*/
+        } flags;
+        uint64_t raw;
+};
+
+struct dcs_edid_supported_max_bw {
+	uint32_t pix_clock_khz;
+	uint32_t bits_per_pixel;
+};
+
+struct dcs_stereo_3d_features {
+	struct {
+/* 3D Format supported by monitor (implies supported by driver)*/
+		uint32_t SUPPORTED:1;
+/* 3D Format supported on all timings
+(no need to check every timing for 3D support)*/
+		uint32_t ALL_TIMINGS:1;
+/* 3D Format supported in clone mode*/
+		uint32_t CLONE_MODE:1;
+/* Scaling allowed when driving 3D Format*/
+		uint32_t SCALING:1;
+/* Left and right images packed by SW within single frame*/
+		uint32_t SINGLE_FRAME_SW_PACKED:1;
+	} flags;
+};
+
+struct dcs_container_id {
+	/*128bit GUID in binary form*/
+	uint8_t guid[16];
+	/* 8 byte port ID -> ELD.PortID*/
+	uint32_t port_id[2];
+	/* 2 byte manufacturer name -> ELD.ManufacturerName*/
+	uint16_t manufacturer_name;
+	/* 2 byte product code -> ELD.ProductCode*/
+	uint16_t product_code;
+};
+
+struct dcs_display_tile {
+/*unique Id of Tiled Display. 0 - means display is not part in Tiled Display*/
+	uint64_t id;
+	uint32_t rows;/* size of Tiled Display in tiles*/
+	uint32_t cols;/* size of Tiled Display in tiles*/
+	uint32_t width;/* size of current Tile in pixels*/
+	uint32_t height;/* size of current Tile in pixels*/
+	uint32_t row;/* location of current Tile*/
+	uint32_t col;/* location of current Tile*/
+	struct {
+		/*in pixels*/
+		uint32_t left;
+		uint32_t right;
+		uint32_t top;
+		uint32_t bottom;
+	} bezel;/* bezel information of current tile*/
+
+	struct {
+		uint32_t SEPARATE_ENCLOSURE:1;
+		uint32_t BEZEL_INFO_PRESENT:1;
+		uint32_t CAN_SCALE:1;
+	} flags;
+
+	struct {
+		uint32_t manufacturer_id;
+		uint32_t product_id;
+		uint32_t serial_id;
+	} topology_id;
+};
+
+#endif /* __DAL_DCS_TYPES_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/include/ddc_interface.h b/drivers/gpu/drm/amd/dal/include/ddc_interface.h
new file mode 100644
index 000000000000..22fd31f6de7f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/ddc_interface.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DDC_INTERFACE_H__
+#define __DAL_DDC_INTERFACE_H__
+
+#include "gpio_types.h"
+
+struct ddc;
+
+enum gpio_result dal_ddc_open(
+	struct ddc *ddc,
+	enum gpio_mode mode,
+	enum gpio_ddc_config_type config_type);
+
+enum gpio_result dal_ddc_get_clock(
+	const struct ddc *ddc,
+	uint32_t *value);
+
+enum gpio_result dal_ddc_set_clock(
+	const struct ddc *ddc,
+	uint32_t value);
+
+enum gpio_result dal_ddc_get_data(
+	const struct ddc *ddc,
+	uint32_t *value);
+
+enum gpio_result dal_ddc_set_data(
+	const struct ddc *ddc,
+	uint32_t value);
+
+enum gpio_result dal_ddc_change_mode(
+	struct ddc *ddc,
+	enum gpio_mode mode);
+
+bool dal_ddc_is_hw_supported(
+	const struct ddc *ddc);
+
+enum gpio_ddc_line dal_ddc_get_line(
+	const struct ddc *ddc);
+
+bool dal_ddc_check_line_aborted(
+	const struct ddc *ddc);
+
+enum gpio_result dal_ddc_set_config(
+	struct ddc *ddc,
+	enum gpio_ddc_config_type config_type);
+
+void dal_ddc_close(
+	struct ddc *ddc);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/ddc_service_types.h b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h
new file mode 100644
index 000000000000..cbdb6dfe4ff3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_DDC_SERVICE_TYPES_H__
+#define __DAL_DDC_SERVICE_TYPES_H__
+
+#define DP_BRANCH_DEVICE_ID_1 0x0010FA
+#define DP_BRANCH_DEVICE_ID_2 0x0022B9
+#define DP_SINK_DEVICE_ID_1 0x4CE000
+#define DP_BRANCH_DEVICE_ID_3 0x00001A
+#define DP_BRANCH_DEVICE_ID_4 0x0080e1
+#define DP_BRANCH_DEVICE_ID_5 0x006037
+#define DP_SINK_DEVICE_ID_2 0x001CF8
+
+
+enum ddc_result {
+	DDC_RESULT_UNKNOWN = 0,
+	DDC_RESULT_SUCESSFULL,
+	DDC_RESULT_FAILED_CHANNEL_BUSY,
+	DDC_RESULT_FAILED_TIMEOUT,
+	DDC_RESULT_FAILED_PROTOCOL_ERROR,
+	DDC_RESULT_FAILED_NACK,
+	DDC_RESULT_FAILED_INCOMPLETE,
+	DDC_RESULT_FAILED_OPERATION,
+	DDC_RESULT_FAILED_INVALID_OPERATION,
+	DDC_RESULT_FAILED_BUFFER_OVERFLOW
+};
+
+enum ddc_service_type {
+	DDC_SERVICE_TYPE_CONNECTOR,
+	DDC_SERVICE_TYPE_DISPLAY_PORT_MST,
+};
+
+enum ddc_transaction_type {
+	DDC_TRANSACTION_TYPE_NONE = 0,
+	DDC_TRANSACTION_TYPE_I2C,
+	DDC_TRANSACTION_TYPE_I2C_OVER_AUX,
+	DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER,
+	DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER
+};
+
+enum display_dongle_type {
+	DISPLAY_DONGLE_NONE = 0,
+	/* Active converter types*/
+	DISPLAY_DONGLE_DP_VGA_CONVERTER,
+	DISPLAY_DONGLE_DP_DVI_CONVERTER,
+	DISPLAY_DONGLE_DP_HDMI_CONVERTER,
+	/* DP-HDMI/DVI passive dongles (Type 1 and Type 2)*/
+	DISPLAY_DONGLE_DP_DVI_DONGLE,
+	DISPLAY_DONGLE_DP_HDMI_DONGLE,
+	/* Other types of dongle*/
+	DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE,
+};
+
+enum dcs_dpcd_revision {
+	DCS_DPCD_REV_10 = 0x10,
+	DCS_DPCD_REV_11 = 0x11,
+	DCS_DPCD_REV_12 = 0x12
+};
+
+/**
+ * display sink capability
+ */
+struct display_sink_capability {
+	/* dongle type (DP converter, CV smart dongle) */
+	enum display_dongle_type dongle_type;
+
+	/**********************************************************
+	 capabilities going INTO SINK DEVICE (stream capabilities)
+	 **********************************************************/
+	/* Dongle's downstream count. */
+	uint32_t downstrm_sink_count;
+	/* Is dongle's downstream count info field (downstrm_sink_count)
+	 * valid. */
+	bool downstrm_sink_count_valid;
+
+	/* Maximum additional audio delay in microsecond (us) */
+	uint32_t additional_audio_delay;
+	/* Audio latency value in microsecond (us) */
+	uint32_t audio_latency;
+	/* Interlace video latency value in microsecond (us) */
+	uint32_t video_latency_interlace;
+	/* Progressive video latency value in microsecond (us) */
+	uint32_t video_latency_progressive;
+	/* Dongle caps: Maximum pixel clock supported over dongle for HDMI */
+	uint32_t max_hdmi_pixel_clock;
+	/* Dongle caps: Maximum deep color supported over dongle for HDMI */
+	enum dc_color_depth max_hdmi_deep_color;
+
+	/************************************************************
+	 capabilities going OUT OF SOURCE DEVICE (link capabilities)
+	 ************************************************************/
+	/* support for Spread Spectrum(SS) */
+	bool ss_supported;
+	/* DP link settings (laneCount, linkRate, Spread) */
+	uint32_t dp_link_lane_count;
+	uint32_t dp_link_rate;
+	uint32_t dp_link_spead;
+
+	enum dcs_dpcd_revision dpcd_revision;
+	/* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER,
+	indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/
+	bool is_dp_hdmi_s3d_converter;
+	/* to check if we have queried the display capability
+	 * for eDP panel already. */
+	bool is_edp_sink_cap_valid;
+
+	enum ddc_transaction_type transaction_type;
+	enum signal_type signal;
+};
+
+struct dp_receiver_id_info {
+	uint32_t dpcd_rev;
+	uint32_t sink_id;
+	int8_t sink_id_str[6];
+	int8_t sink_hw_revision;
+	int8_t sink_fw_revision[2];
+	uint32_t branch_id;
+	int8_t branch_name[6];
+	enum display_dongle_type dongle_type;
+};
+
+struct av_sync_data {
+	uint8_t av_granularity;/* DPCD 00023h */
+	uint8_t aud_dec_lat1;/* DPCD 00024h */
+	uint8_t aud_dec_lat2;/* DPCD 00025h */
+	uint8_t aud_pp_lat1;/* DPCD 00026h */
+	uint8_t aud_pp_lat2;/* DPCD 00027h */
+	uint8_t vid_inter_lat;/* DPCD 00028h */
+	uint8_t vid_prog_lat;/* DPCD 00029h */
+	uint8_t aud_del_ins1;/* DPCD 0002Bh */
+	uint8_t aud_del_ins2;/* DPCD 0002Ch */
+	uint8_t aud_del_ins3;/* DPCD 0002Dh */
+};
+
+/** EDID retrieval related constants, also used by MstMgr **/
+
+#define DDC_EDID_SEGMENT_SIZE 256
+#define DDC_EDID_BLOCK_SIZE 128
+#define DDC_EDID_BLOCKS_PER_SEGMENT \
+	(DDC_EDID_SEGMENT_SIZE / DDC_EDID_BLOCK_SIZE)
+
+#define DDC_EDID_EXT_COUNT_OFFSET 0x7E
+
+#define DDC_EDID_ADDRESS_START 0x50
+#define DDC_EDID_ADDRESS_END 0x52
+#define DDC_EDID_SEGMENT_ADDRESS 0x30
+
+/* signatures for Edid 1x */
+#define DDC_EDID1X_VENDORID_SIGNATURE_OFFSET 8
+#define DDC_EDID1X_VENDORID_SIGNATURE_LEN 4
+#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_OFFSET 126
+#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_LEN 2
+#define DDC_EDID1X_CHECKSUM_OFFSET 127
+/* signatures for Edid 20*/
+#define DDC_EDID_20_SIGNATURE_OFFSET 0
+#define DDC_EDID_20_SIGNATURE 0x20
+
+#define DDC_EDID20_VENDORID_SIGNATURE_OFFSET 1
+#define DDC_EDID20_VENDORID_SIGNATURE_LEN 4
+#define DDC_EDID20_CHECKSUM_OFFSET 255
+#define DDC_EDID20_CHECKSUM_LEN 1
+
+/*DP to VGA converter*/
+static const uint8_t DP_VGA_CONVERTER_ID_1[] = "mVGAa";
+/*DP to Dual link DVI converter*/
+static const uint8_t DP_DVI_CONVERTER_ID_1[] = "m2DVIa";
+/*Travis*/
+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
+/*Nutmeg*/
+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
+/*DP to VGA converter*/
+static const uint8_t DP_VGA_CONVERTER_ID_4[] = "DpVga";
+/*DP to Dual link DVI converter*/
+static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa";
+/*DP to Dual link DVI converter 2*/
+static const uint8_t DP_DVI_CONVERTER_ID_42[] = "v2DVIa";
+
+static const uint8_t DP_SINK_DEV_STRING_ID2_REV0[] = "\0\0\0\0\0\0";
+
+/* Identifies second generation PSR TCON from Parade: Device ID string:
+ * yy-xx-**-**-**-**
+ */
+/* xx - Hw ID high byte */
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_HIGH_BYTE =
+	0x06;
+
+/* yy - HW ID low byte, the same silicon has several package/feature flavors */
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE1 =
+	0x61;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE2 =
+	0x62;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE3 =
+	0x63;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE4 =
+	0x72;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE5 =
+	0x73;
+
+#endif /* __DAL_DDC_SERVICE_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/display_clock_interface.h b/drivers/gpu/drm/amd/dal/include/display_clock_interface.h
new file mode 100644
index 000000000000..211847cefe80
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/display_clock_interface.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DISPLAY_CLOCK_INTERFACE_H__
+#define __DISPLAY_CLOCK_INTERFACE_H__
+
+#include "hw_sequencer_types.h"
+#include "grph_object_defs.h"
+#include "signal_types.h"
+#include "scaler_types.h"
+
+/* Timing related information*/
+struct dc_timing_params {
+	uint32_t INTERLACED:1;
+	uint32_t HCOUNT_BY_TWO:1;
+	uint32_t PIXEL_REPETITION:4; /*< values 1 to 10 supported*/
+	uint32_t PREFETCH:1;
+
+	uint32_t h_total;
+	uint32_t h_addressable;
+	uint32_t h_sync_width;
+};
+
+/* Scaling related information*/
+struct dc_scaling_params {
+	uint32_t h_overscan_right;
+	uint32_t h_overscan_left;
+	uint32_t h_taps;
+	uint32_t v_taps;
+};
+
+/*Display Request Mode (1 and 2 valid when scaler is OFF)*/
+enum display_request_mode {
+	REQUEST_ONLY_AT_EVERY_READ_POINTER_INCREMENT = 0,
+	REQUEST_WAITING_FOR_THE_FIRST_READ_POINTER_ONLY,
+	REQUEST_WITHOUT_WAITING_FOR_READ_POINTER
+};
+
+/* FBC minimum CompressionRatio*/
+enum fbc_compression_ratio {
+	FBC_COMPRESSION_NOT_USED = 0,
+	FBC_MINIMUM_COMPRESSION_RATIO_1 = 1,
+	FBC_MINIMUM_COMPRESSION_RATIO_2 = 2,
+	FBC_MINIMUM_COMPRESSION_RATIO_4 = 4,
+	FBC_MINIMUM_COMPRESSION_RATIO_8 = 8
+};
+
+/* VScalerEfficiency */
+enum v_scaler_efficiency {
+	V_SCALER_EFFICIENCY_LB36BPP = 0,
+	V_SCALER_EFFICIENCY_LB30BPP = 1,
+	V_SCALER_EFFICIENCY_LB24BPP = 2,
+	V_SCALER_EFFICIENCY_LB18BPP = 3
+};
+
+/* Parameters required for minimum Engine
+ * and minimum Display clock calculations*/
+struct min_clock_params {
+	uint32_t id;
+	uint32_t requested_pixel_clock; /* in KHz */
+	uint32_t actual_pixel_clock; /* in KHz */
+	struct view source_view;
+	struct view dest_view;
+	struct dc_timing_params timing_info;
+	struct dc_scaling_params scaling_info;
+	struct color_quality color_info;
+	enum signal_type signal_type;
+	enum dc_color_depth deep_color_depth;
+	enum v_scaler_efficiency scaler_efficiency;
+	bool line_buffer_prefetch_enabled;
+};
+
+/* Enumerations for Source selection of the Display clock */
+enum display_clock_source_select {
+	USE_PIXEL_CLOCK_PLL = 0,
+	USE_EXTERNAL_CLOCK,
+	USE_ENGINE_CLOCK
+};
+
+/* Result of Minimum System and Display clock calculations.
+ * Minimum System clock and Display clock, source and path to be used
+ * for Display clock*/
+struct minimum_clocks_calculation_result {
+	uint32_t min_sclk_khz;
+	uint32_t min_dclk_khz;
+	uint32_t min_mclk_khz;
+	uint32_t min_deep_sleep_sclk;
+};
+
+/* Enumeration of all clocks states */
+enum clocks_state {
+	CLOCKS_STATE_INVALID,
+	CLOCKS_STATE_ULTRA_LOW,
+	CLOCKS_STATE_LOW,
+	CLOCKS_STATE_NOMINAL,
+	CLOCKS_STATE_PERFORMANCE
+};
+
+/* Structure containing all state-dependent clocks
+ * (dependent on "enum clocks_state") */
+struct state_dependent_clocks {
+	uint32_t display_clk_khz;
+	uint32_t pixel_clk_khz;
+};
+
+struct display_clock_state {
+	uint32_t DFS_BYPASS_ACTIVE:1;
+};
+
+struct display_clock;
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+struct display_clock *dal_display_clock_dce110_create(
+	struct dc_context *ctx,
+	struct adapter_service *as);
+#endif
+
+void dal_display_clock_destroy(struct display_clock **to_destroy);
+bool dal_display_clock_validate(
+	struct display_clock *disp_clk,
+	struct min_clock_params *params);
+uint32_t dal_display_clock_calculate_min_clock(
+	struct display_clock *disp_clk,
+	uint32_t path_num,
+	struct min_clock_params *params);
+uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk);
+void dal_display_clock_set_clock(
+	struct display_clock *disp_clk,
+	uint32_t requested_clock_khz);
+uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk);
+enum clocks_state dal_display_clock_get_min_clocks_state(
+	struct display_clock *disp_clk);
+enum clocks_state dal_display_clock_get_required_clocks_state(
+	struct display_clock *disp_clk,
+	struct state_dependent_clocks *req_clocks);
+bool dal_display_clock_set_min_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state clocks_state);
+uint32_t dal_display_clock_get_dp_ref_clk_frequency(
+	struct display_clock *disp_clk);
+/*the second parameter of "switchreferenceclock" is
+ * a dummy argument for all pre dce 6.0 versions*/
+void dal_display_clock_switch_reference_clock(
+	struct display_clock *disp_clk,
+	bool use_external_ref_clk,
+	uint32_t requested_clock_khz);
+void dal_display_clock_set_dp_ref_clock_source(
+	struct display_clock *disp_clk,
+	enum clock_source_id clk_src);
+void dal_display_clock_store_max_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state max_clocks_state);
+void dal_display_clock_set_clock_state(
+	struct display_clock *disp_clk,
+	struct display_clock_state clk_state);
+struct display_clock_state dal_display_clock_get_clock_state(
+	struct display_clock *disp_clk);
+uint32_t dal_display_clock_get_dfs_bypass_threshold(
+	struct display_clock *disp_clk);
+void dal_display_clock_invalid_clock_state(
+	struct display_clock *disp_clk);
+
+
+#endif /* __DISPLAY_CLOCK_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/display_path_interface.h b/drivers/gpu/drm/amd/dal/include/display_path_interface.h
new file mode 100644
index 000000000000..7bf2ef28f455
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/display_path_interface.h
@@ -0,0 +1,436 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DISPLAY_PATH_INTERFACE_H__
+#define __DISPLAY_PATH_INTERFACE_H__
+
+#include "display_path_types.h"
+#include "dcs_types.h"
+#include "grph_object_ctrl_defs.h"
+#include "signal_types.h"
+#include "controller_types.h"
+
+struct encoder;
+struct controller;
+struct connector;
+struct audio;
+struct clock_source;
+struct link_service;
+struct goc_link_service_data;
+struct drr_config;
+
+struct display_path;
+
+struct display_path *dal_display_path_create(void);
+
+struct display_path *dal_display_path_clone(
+	const struct display_path *self,
+	bool copy_active_state);
+
+void dal_display_path_destroy(
+	struct display_path **to_destroy);
+
+bool dal_display_path_validate(
+	struct display_path *path,
+	enum signal_type sink_signal);
+
+bool dal_display_path_add_link(
+	struct display_path *path,
+	struct encoder *encoder);
+
+bool dal_display_path_add_connector(
+	struct display_path *path,
+	struct connector *connector);
+
+struct connector *dal_display_path_get_connector(
+	struct display_path *path);
+
+int32_t dal_display_path_acquire(
+	struct display_path *path);
+
+bool dal_display_path_is_acquired(
+	const struct display_path *path);
+
+int32_t dal_display_path_get_ref_counter(
+	const struct display_path *path);
+
+int32_t dal_display_path_release(
+	struct display_path *path);
+
+void dal_display_path_release_resources(
+	struct display_path *path);
+
+void dal_display_path_acquire_links(
+	struct display_path *path);
+
+bool dal_display_path_is_source_blanked(
+	const struct display_path *path);
+
+bool dal_display_path_is_source_unblanked(
+	const struct display_path *path);
+
+void dal_display_path_set_source_blanked(
+	struct display_path *path,
+	enum display_tri_state state);
+
+bool dal_display_path_is_target_blanked(
+	const struct display_path *path);
+
+bool dal_display_path_is_target_unblanked(
+	const struct display_path *path);
+
+void dal_display_path_set_target_blanked(
+	struct display_path *path,
+	enum display_tri_state state);
+
+bool dal_display_path_is_target_powered_on(
+	const struct display_path *path);
+
+bool dal_display_path_is_target_powered_off(
+	const struct display_path *path);
+
+void dal_display_path_set_target_powered_on(
+	struct display_path *path,
+	enum display_tri_state state);
+
+bool dal_display_path_is_target_connected(
+	const struct display_path *path);
+
+void dal_display_path_set_target_connected(
+	struct display_path *path,
+	bool c);
+
+uint32_t dal_display_path_get_display_index(
+	const struct display_path *path);
+
+void dal_display_path_set_display_index(
+	struct display_path *path,
+	uint32_t index);
+
+struct connector_device_tag_info *dal_display_path_get_device_tag(
+	struct display_path *path);
+
+void dal_display_path_set_device_tag(
+	struct display_path *path,
+	struct connector_device_tag_info tag);
+
+enum clock_sharing_group dal_display_path_get_clock_sharing_group(
+	const struct display_path *path);
+
+void dal_display_path_set_clock_sharing_group(
+	struct display_path *path,
+	enum clock_sharing_group clock);
+
+union display_path_properties dal_display_path_get_properties(
+	const struct display_path *path);
+
+void dal_display_path_set_properties(
+	struct display_path *path,
+	union display_path_properties p);
+
+struct dcs *dal_display_path_get_dcs(
+	const struct display_path *path);
+
+void dal_display_path_set_dcs(
+	struct display_path *path,
+	struct dcs *dcs);
+
+uint32_t dal_display_path_get_number_of_links(
+	const struct display_path *path);
+
+void dal_display_path_set_controller(
+	struct display_path *path,
+	struct controller *controller);
+
+struct controller *dal_display_path_get_controller(
+	const struct display_path *path);
+
+void dal_display_path_set_clock_source(
+	struct display_path *path,
+	struct clock_source *clock);
+
+struct clock_source *dal_display_path_get_clock_source(
+	const struct display_path *path);
+
+void dal_display_path_set_alt_clock_source(
+	struct display_path *path,
+	struct clock_source *clock);
+
+struct clock_source *dal_display_path_get_alt_clock_source(
+	const struct display_path *path);
+
+void dal_display_path_set_fbc_info(
+	struct display_path *path,
+	struct fbc_info *clock);
+
+struct fbc_info *dal_display_path_get_fbc_info(
+	struct display_path *path);
+
+void dal_display_path_set_drr_config(
+	struct display_path *path,
+	struct drr_config *clock);
+
+void dal_display_path_get_drr_config(
+	const struct display_path *path,
+	struct drr_config *clock);
+
+void dal_display_path_set_static_screen_triggers(
+	struct display_path *path,
+	const struct static_screen_events *events);
+
+void dal_display_path_get_static_screen_triggers(
+	const struct display_path *path,
+	struct static_screen_events *events);
+
+bool dal_display_path_is_psr_supported(
+	const struct display_path *path);
+
+bool dal_display_path_is_drr_supported(
+	const struct display_path *path);
+
+void dal_display_path_set_link_service_data(
+	struct display_path *path,
+	uint32_t idx,
+	const struct goc_link_service_data *data);
+
+bool dal_display_path_get_link_service_data(
+	const struct display_path *path,
+	uint32_t idx,
+	struct goc_link_service_data *data);
+
+struct link_service *dal_display_path_get_link_query_interface(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_link_query_interface(
+	struct display_path *path,
+	uint32_t idx,
+	struct link_service *link);
+
+struct link_service *dal_display_path_get_link_config_interface(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct link_service *dal_display_path_get_link_service_interface(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_upstream_encoder(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_upstream_object(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_downstream_encoder(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_downstream_object(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct audio *dal_display_path_get_audio(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_audio(
+	struct display_path *path,
+	uint32_t idx,
+	struct audio *a);
+
+struct audio *dal_display_path_get_audio_object(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_audio_active_state(
+	struct display_path *path,
+	uint32_t idx,
+	bool state);
+
+enum engine_id dal_display_path_get_stream_engine(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_stream_engine(
+	struct display_path *path,
+	uint32_t idx,
+	enum engine_id id);
+
+bool dal_display_path_is_link_active(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_link_active_state(
+	struct display_path *path,
+	uint32_t idx,
+	bool state);
+
+enum signal_type dal_display_path_get_config_signal(
+	const struct display_path *path,
+	uint32_t idx);
+
+enum signal_type dal_display_path_get_query_signal(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct link_service *dal_display_path_get_mst_link_service(
+	const struct display_path *path);
+
+void dal_display_path_set_sync_output_object(
+	struct display_path *path,
+	enum sync_source o_source,
+	struct encoder *o_object);
+
+struct encoder *dal_display_path_get_sync_output_object(
+	const struct display_path *path);
+
+void dal_display_path_set_stereo_sync_object(
+	struct display_path *path,
+	struct encoder *stereo_sync);
+
+struct encoder *dal_display_path_get_stereo_sync_object(
+	const struct display_path *path);
+
+void dal_display_path_set_sync_input_source(
+	struct display_path *path,
+	enum sync_source s);
+
+enum sync_source dal_display_path_get_sync_input_source(
+	const struct display_path *path);
+
+void dal_display_path_set_sync_output_source(
+	struct display_path *path,
+	enum sync_source s);
+
+enum sync_source dal_display_path_get_sync_output_source(
+	const struct display_path *path);
+
+bool dal_display_path_set_pixel_clock_safe_range(
+	struct display_path *path,
+	struct pixel_clock_safe_range *range);
+
+bool dal_display_path_get_pixel_clock_safe_range(
+	const struct display_path *path,
+	struct pixel_clock_safe_range *range);
+
+void dal_display_path_set_ddi_channel_mapping(
+	struct display_path *path,
+	union ddi_channel_mapping mapping);
+
+bool dal_display_path_set_sink_signal(
+	struct display_path *path,
+	enum signal_type sink_signal);
+
+enum signal_type dal_display_path_sink_signal_to_asic_signal(
+	struct display_path *path,
+	enum signal_type sink_signal);
+
+enum signal_type dal_display_path_sink_signal_to_link_signal(
+	struct display_path *path,
+	enum signal_type sink_signal,
+	uint32_t idx);
+
+enum signal_type dal_display_path_downstream_to_upstream_signal(
+	struct display_path *path,
+	enum signal_type signal,
+	uint32_t idx);
+
+bool dal_display_path_is_audio_present(
+	const struct display_path *path,
+	uint32_t *audio_pin);
+
+bool dal_display_path_is_dp_auth_supported(
+	struct display_path *path);
+
+bool dal_display_path_is_vce_supported(
+	const struct display_path *path);
+
+bool dal_display_path_is_sls_capable(
+	const struct display_path *path);
+
+bool dal_display_path_is_gen_lock_capable(
+	const struct display_path *path);
+
+struct transmitter_configuration dal_display_path_get_transmitter_configuration(
+	const struct display_path *path,
+	bool physical);
+
+bool dal_display_path_is_ss_supported(
+	const struct display_path *path);
+
+bool dal_display_path_is_ss_configurable(
+	const struct display_path *path);
+
+void dal_display_path_set_ss_support(
+	struct display_path *path,
+	bool s);
+
+enum signal_type dal_display_path_get_active_signal(
+	struct display_path *path,
+	uint32_t idx);
+
+bool dal_display_path_contains_object(
+	struct display_path *path,
+	struct graphics_object_id id);
+
+/* Multi-plane declarations.
+ * This structure should also be used for Stereo. */
+struct display_path_plane {
+	struct controller *controller;
+	/* During dal_tm_acquire_plane_resources() set blnd_mode, because
+	 * "layer index" is known at that point, and we must decide how
+	 * "controller" should do the blending */
+	enum blender_mode blnd_mode;
+	/* Some use-cases allow to power-gate FE.
+	 * For example, with Full Screen Video on Underlay we can
+	 * disable the 'root' plane.
+	 * This flag indicates that FE should be power-gated */
+	bool disabled;
+};
+
+bool dal_display_path_add_plane(
+	struct display_path *path,
+	struct display_path_plane *plane);
+
+uint8_t dal_display_path_get_number_of_planes(
+	const struct display_path *path);
+
+struct display_path_plane *dal_display_path_get_plane_at_index(
+	const struct display_path *path,
+	uint8_t index);
+
+struct controller *dal_display_path_get_controller_for_layer_index(
+	const struct display_path *path,
+	uint8_t layer_index);
+
+void dal_display_path_release_planes(
+	struct display_path *path);
+
+void dal_display_path_release_non_root_planes(
+	struct display_path *path);
+
+#endif /* __DISPLAY_PATH_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dmcu_interface.h b/drivers/gpu/drm/amd/dal/include/dmcu_interface.h
new file mode 100644
index 000000000000..c712cc25e731
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dmcu_interface.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DMCU_INTERFACE_H__
+#define __DAL_DMCU_INTERFACE_H__
+
+#include "grph_object_defs.h"
+#include "dmcu_types.h"
+
+/* Interface functions */
+
+/* DMCU setup related interface functions */
+struct dmcu *dal_dmcu_create(
+	struct dmcu_init_data *init_data);
+void dal_dmcu_destroy(struct dmcu **dmcu);
+void dal_dmcu_release_hw(struct dmcu *dmcu);
+
+void dal_dmcu_power_up(struct dmcu *dmcu);
+void dal_dmcu_power_down(struct dmcu *dmcu);
+
+void dal_dmcu_configure_wait_loop(
+		struct dmcu *dmcu,
+		uint32_t display_clock);
+
+/* PSR feature related interface functions */
+void dal_dmcu_psr_setup(
+		struct dmcu *dmcu,
+		struct dmcu_context *dmcu_context);
+void dal_dmcu_psr_enable(struct dmcu *dmcu);
+void dal_dmcu_psr_disable(struct dmcu *dmcu);
+void dal_dmcu_psr_block(struct dmcu *dmcu, bool block_psr);
+bool dal_dmcu_psr_is_blocked(struct dmcu *dmcu);
+void dal_dmcu_psr_set_level(
+		struct dmcu *dmcu,
+		union dmcu_psr_level psr_level);
+void dal_dmcu_psr_allow_power_down_crtc(
+		struct dmcu *dmcu,
+		bool should_allow_crtc_power_down);
+bool dal_dmcu_psr_submit_command(
+		struct dmcu *dmcu,
+		struct dmcu_context *dmcu_context,
+		struct dmcu_config_data *config_data);
+void dal_dmcu_psr_get_config_data(
+		struct dmcu *dmcu,
+		uint32_t v_total,
+		struct dmcu_config_data *config_data);
+
+/* ABM feature related interface functions */
+void dal_dmcu_abm_enable(
+		struct dmcu *dmcu,
+		enum controller_id controller_id,
+		uint32_t vsync_rate_hz);
+void dal_dmcu_abm_disable(struct dmcu *dmcu);
+bool dal_dmcu_abm_enable_smooth_brightness(struct dmcu *dmcu);
+bool dal_dmcu_abm_disable_smooth_brightness(struct dmcu *dmcu);
+void dal_dmcu_abm_varibright_control(
+		struct dmcu *dmcu,
+		const struct varibright_control *varibright_control);
+bool dal_dmcu_abm_set_backlight_level(
+		struct dmcu *dmcu,
+		uint8_t backlight_8_bit);
+uint8_t dal_dmcu_abm_get_user_backlight_level(struct dmcu *dmcu);
+uint8_t dal_dmcu_abm_get_current_backlight_level(struct dmcu *dmcu);
+
+#endif /* __DAL_DMCU_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dmcu_types.h b/drivers/gpu/drm/amd/dal/include/dmcu_types.h
new file mode 100644
index 000000000000..1f3107d5b9b8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dmcu_types.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DMCU_TYPES_H__
+#define __DAL_DMCU_TYPES_H__
+
+/* Forward declaration */
+struct dmcu;
+
+/* Required information for creation and initialization of a controller */
+struct dmcu_init_data {
+	struct dal_context *dal_context;
+	struct adapter_service *as;
+	uint32_t max_engine_clock_in_khz;
+};
+
+/* Interface structure defines */
+
+enum dmcu_action {
+	DMCU_ACTION_PSR_ENABLE,
+	DMCU_ACTION_PSR_EXIT,
+	DMCU_ACTION_PSR_RFB_UPDATE,
+	DMCU_ACTION_PSR_SET,
+	DMCU_ACTION_PSR_CLEAR_COUNT,
+	DMCU_ACTION_PSR_COUNT_REQUEST,
+	DMCU_ACTION_PSR_STATE_REQUEST,
+	DMCU_ACTION_PSR_SET_LEVEL,
+	DMCU_ACTION_PSR_ADVANCE_STATE,
+	DMCU_ACTION_PSR_SET_WAITLOOP
+};
+
+enum dmcu_output {
+	DMCU_OUTPUT_PSR_ACK,
+	DMCU_OUTPUT_PSR_NACK,
+	DMCU_OUTPUT_PSR_AUX_ERR,
+	DMCU_OUTPUT_PSR_COUNT_STATUS,
+	DMCU_OUTPUT_PSR_STATE_STATUS,
+	DMCU_OUTPUT_PSR_RFB_UPDATE_ERR,
+	DMCU_OUTPUT_PSR_ERR,
+	DMCU_OUTPUT_PSR_GET_REPLY,
+	DMCU_OUTPUT_PSR_ENTRY_ERROR,
+	DMCU_OUTPUT_PSR_LT_ERROR,
+	DMCU_OUTPUT_PSR_FORCE_SR_ERROR,
+	DMCU_OUTPUT_PSR_SDP_SEND_TIMEOUT
+};
+
+/* PSR states, based similarly on states defined in eDP specification. */
+enum psr_state {
+	STATE0,		/* PSR is disabled */
+	STATE1,		/* PSR is enabled, but inactive */
+	STATE1A,
+	STATE2,		/* PSR is transitioning to active state */
+	STATE2A,
+	STATE3,		/* PSR is active; Display is in self refresh */
+	STATE3INIT,
+	STATE4,		/* RFB single frame update */
+	STATE4A,
+	STATE4B,
+	STATE4C,
+	STATE4D,
+	STATE5,		/* Exiting from PSR active state */
+	STATE5A,
+	STATE5B,
+	STATE5C
+};
+
+enum phy_type {
+	PHY_TYPE_UNKNOWN = 1,
+	PHY_TYPE_PCIE_PHY = 2,
+	PHY_TYPE_UNIPHY = 3,
+};
+
+struct dmcu_context {
+	enum channel_id channel;
+	enum transmitter transmitter_id;
+	enum engine_id engine_id;
+	enum controller_id controller_id;
+	enum phy_type phy_type;
+	enum physical_phy_id smu_physical_phy_id;
+
+	/* Vertical total pixels from crtc timing.
+	 * This is used for static screen detection.
+	 * ie. If we want to detect half a frame,
+	 * we use this to determine the hyst lines.*/
+	uint32_t crtc_timing_vertical_total;
+
+	/* PSR supported from panel capabilities
+	 * and current display configuration */
+	bool psr_supported_display_config;
+
+	/* Whether fast link training is supported by the panel */
+	bool psr_exit_link_training_required;
+
+	/* If RFB setup time is greater than the total VBLANK time, it is not
+	 * possible for the sink to capture the video frame in the same frame
+	 * the SDP is sent. In this case, the frame capture indication bit
+	 * should be set and an extra static frame should be transmitted to
+	 * the sink */
+	bool psr_frame_capture_indication_required;
+
+	/* Set the last possible line SDP may be transmitted without violating
+	 * the RFB setup time */
+	bool sdp_transmit_line_num_deadline;
+
+	/* The VSync rate in Hz used to calculate the step size
+	 * for smooth brightness feature */
+	uint32_t vsync_rate_hz;
+};
+
+union dmcu_psr_level {
+	struct {
+		bool SKIP_CRC:1;
+		bool SKIP_DP_VID_STREAM_DISABLE:1;
+		bool SKIP_PHY_POWER_DOWN:1;
+		bool SKIP_AUX_ACK_CHECK:1;
+		bool SKIP_CRTC_DISABLE:1;
+		bool SKIP_AUX_RFB_CAPTURE_CHECK:1;
+		bool SKIP_SMU_NOTIFICATION:1;
+		bool SKIP_AUTO_STATE_ADVANCE:1;
+		bool DISABLE_PSR_ENTRY_ABORT:1;
+	} bits;
+	uint32_t u32all;
+};
+
+struct dmcu_config_data {
+	/* Command sent to DMCU. */
+	enum dmcu_action action;
+	/* PSR Level controls which HW blocks to power down during PSR active,
+	 * and also other sequence modifications. */
+	union dmcu_psr_level psr_level;
+	/* To indicate that first changed frame from active state should not
+	 * result in exit to inactive state, but instead perform an automatic
+	 * single frame RFB update. */
+	bool rfb_update_auto_en;
+	/* Number of consecutive static frames to detect before entering PSR
+	 * active state. */
+	uint32_t hyst_frames;
+	/* Partial frames before entering PSR active. Note this parameter is in
+	 * units of 100 lines. i.e. Wait a value of 5 means wait 500 additional
+	 * lines. */
+	uint32_t hyst_lines;
+	/* Number of repeated AUX retries before indicating failure to driver.
+	 * In a working case, first attempt to write/read AUX should pass. */
+	uint32_t aux_repeat;
+	/* Additional delay after remote frame capture before continuing to
+	 * power down. This is mainly for debug purposes to identify timing
+	 * issues. */
+	uint32_t frame_delay;
+	/* Controls how long the delay of a wait loop is. It should be tuned
+	 * to 1 us, and needs to be reconfigured every time DISPCLK changes. */
+	uint32_t wait_loop_num;
+};
+
+struct dmcu_output_data {
+	/* DMCU reply */
+	enum dmcu_output output;
+	/* The current PSR state. */
+	uint32_t psr_state;
+	/* The number of frames during PSR active state. */
+	uint32_t psr_count;
+};
+
+enum varibright_command {
+	VARIBRIGHT_CMD_SET_VB_LEVEL = 0,
+	VARIBRIGHT_CMD_USER_ENABLE,
+	VARIBRIGHT_CMD_POST_DISPLAY_CONFIG,
+	VARIBRIGHT_CMD_UNKNOWN
+};
+
+struct varibright_control {
+	enum varibright_command command;
+	uint8_t level;
+	bool enable;
+	bool activate;
+};
+
+#endif /* __DAL_DMCU_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dpcd_defs.h b/drivers/gpu/drm/amd/dal/include/dpcd_defs.h
new file mode 100644
index 000000000000..bd410ccdc3a5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dpcd_defs.h
@@ -0,0 +1,873 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DPCD_DEFS_H__
+#define __DAL_DPCD_DEFS_H__
+
+enum dpcd_address {
+/* addresses marked with 1.2 are only defined since DP 1.2 spec */
+
+	/* Reciever Capability Field */
+	DPCD_ADDRESS_DPCD_REV = 0x00000,
+	DPCD_ADDRESS_MAX_LINK_RATE = 0x00001,
+	DPCD_ADDRESS_MAX_LANE_COUNT = 0x00002,
+	DPCD_ADDRESS_MAX_DOWNSPREAD = 0x00003,
+	DPCD_ADDRESS_NORP = 0x00004,
+	DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT = 0x00005,
+	DPCD_ADDRESS_MAIN_LINK_CHANNEL_CODING = 0x00006,
+	DPCD_ADDRESS_DOWNSTREAM_PORT_COUNT = 0x00007,
+	DPCD_ADDRESS_RECEIVE_PORT0_CAP0 = 0x00008,
+	DPCD_ADDRESS_RECEIVE_PORT0_CAP1 = 0x00009,
+	DPCD_ADDRESS_RECEIVE_PORT1_CAP0 = 0x0000A,
+	DPCD_ADDRESS_RECEIVE_PORT1_CAP1 = 0x0000B,
+
+	DPCD_ADDRESS_I2C_SPEED_CNTL_CAP = 0x0000C,/*1.2*/
+	DPCD_ADDRESS_EDP_CONFIG_CAP = 0x0000D,/*1.2*/
+	DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL = 0x000E,/*1.2*/
+
+	DPCD_ADDRESS_MSTM_CAP = 0x00021,/*1.2*/
+
+	/* Audio Video Sync Data Feild */
+	DPCD_ADDRESS_AV_GRANULARITY = 0x0023,
+	DPCD_ADDRESS_AUDIO_DECODE_LATENCY1 = 0x0024,
+	DPCD_ADDRESS_AUDIO_DECODE_LATENCY2 = 0x0025,
+	DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY1 = 0x0026,
+	DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY2 = 0x0027,
+	DPCD_ADDRESS_VIDEO_INTERLACED_LATENCY = 0x0028,
+	DPCD_ADDRESS_VIDEO_PROGRESSIVE_LATENCY = 0x0029,
+	DPCD_ADDRESS_AUDIO_DELAY_INSERT1 = 0x0002B,
+	DPCD_ADDRESS_AUDIO_DELAY_INSERT2 = 0x0002C,
+	DPCD_ADDRESS_AUDIO_DELAY_INSERT3 = 0x0002D,
+
+	/* Audio capability */
+	DPCD_ADDRESS_NUM_OF_AUDIO_ENDPOINTS = 0x00022,
+
+	DPCD_ADDRESS_GUID_START = 0x00030,/*1.2*/
+	DPCD_ADDRESS_GUID_END = 0x0003f,/*1.2*/
+
+	DPCD_ADDRESS_PSR_SUPPORT_VER = 0x00070,
+	DPCD_ADDRESS_PSR_CAPABILITY = 0x00071,
+
+	DPCD_ADDRESS_DWN_STRM_PORT0_CAPS = 0x00080,/*1.2a*/
+
+	/* Link Configuration Field */
+	DPCD_ADDRESS_LINK_BW_SET = 0x00100,
+	DPCD_ADDRESS_LANE_COUNT_SET = 0x00101,
+	DPCD_ADDRESS_TRAINING_PATTERN_SET = 0x00102,
+	DPCD_ADDRESS_LANE0_SET = 0x00103,
+	DPCD_ADDRESS_LANE1_SET = 0x00104,
+	DPCD_ADDRESS_LANE2_SET = 0x00105,
+	DPCD_ADDRESS_LANE3_SET = 0x00106,
+	DPCD_ADDRESS_DOWNSPREAD_CNTL = 0x00107,
+	DPCD_ADDRESS_I2C_SPEED_CNTL = 0x00109,/*1.2*/
+
+	DPCD_ADDRESS_EDP_CONFIG_SET = 0x0010A,
+	DPCD_ADDRESS_LINK_QUAL_LANE0_SET = 0x0010B,
+	DPCD_ADDRESS_LINK_QUAL_LANE1_SET = 0x0010C,
+	DPCD_ADDRESS_LINK_QUAL_LANE2_SET = 0x0010D,
+	DPCD_ADDRESS_LINK_QUAL_LANE3_SET = 0x0010E,
+
+	DPCD_ADDRESS_LANE0_SET2 = 0x0010F,/*1.2*/
+	DPCD_ADDRESS_LANE2_SET2 = 0x00110,/*1.2*/
+
+	DPCD_ADDRESS_MSTM_CNTL = 0x00111,/*1.2*/
+
+	DPCD_ADDRESS_PSR_ENABLE_CFG = 0x0170,
+
+	/* Payload Table Configuration Field 1.2 */
+	DPCD_ADDRESS_PAYLOAD_ALLOCATE_SET = 0x001C0,
+	DPCD_ADDRESS_PAYLOAD_ALLOCATE_START_TIMESLOT = 0x001C1,
+	DPCD_ADDRESS_PAYLOAD_ALLOCATE_TIMESLOT_COUNT = 0x001C2,
+
+	DPCD_ADDRESS_SINK_COUNT = 0x0200,
+	DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR = 0x0201,
+
+	/* Link / Sink Status Field */
+	DPCD_ADDRESS_LANE_01_STATUS = 0x00202,
+	DPCD_ADDRESS_LANE_23_STATUS = 0x00203,
+	DPCD_ADDRESS_LANE_ALIGN_STATUS_UPDATED = 0x0204,
+	DPCD_ADDRESS_SINK_STATUS = 0x0205,
+
+	/* Adjust Request Field */
+	DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1 = 0x0206,
+	DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3 = 0x0207,
+	DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2 = 0x020C,
+
+	/* Test Request Field */
+	DPCD_ADDRESS_TEST_REQUEST = 0x0218,
+	DPCD_ADDRESS_TEST_LINK_RATE = 0x0219,
+	DPCD_ADDRESS_TEST_LANE_COUNT = 0x0220,
+	DPCD_ADDRESS_TEST_PATTERN = 0x0221,
+	DPCD_ADDRESS_TEST_MISC1 = 0x0232,
+
+	/* Phy Test Pattern Field */
+	DPCD_ADDRESS_TEST_PHY_PATTERN = 0x0248,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0 = 0x0250,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_15_8 = 0x0251,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_23_16 = 0x0252,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_31_24 = 0x0253,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_39_32 = 0x0254,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_47_40 = 0x0255,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_55_48 = 0x0256,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_63_56 = 0x0257,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_71_64 = 0x0258,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 = 0x0259,
+
+	/* Test Response Field*/
+	DPCD_ADDRESS_TEST_RESPONSE = 0x0260,
+
+	/* Audio Test Pattern Field 1.2*/
+	DPCD_ADDRESS_TEST_AUDIO_MODE = 0x0271,
+	DPCD_ADDRESS_TEST_AUDIO_PATTERN_TYPE = 0x0272,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_1 = 0x0273,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_2 = 0x0274,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_3 = 0x0275,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_4 = 0x0276,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_5 = 0x0277,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_6 = 0x0278,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_7 = 0x0279,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_8 = 0x027A,
+
+	/* Payload Table Status Field */
+	DPCD_ADDRESS_PAYLOAD_TABLE_UPDATE_STATUS = 0x002C0,/*1.2*/
+	DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT1 = 0x002C1,/*1.2*/
+	DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT63 = 0x002FF,/*1.2*/
+
+	/* Source Device Specific Field */
+	DPCD_ADDRESS_SOURCE_DEVICE_ID_START = 0x0300,
+	DPCD_ADDRESS_SOURCE_DEVICE_ID_END = 0x0301,
+	DPCD_ADDRESS_AMD_INTERNAL_DEBUG_START       = 0x030C,
+	DPCD_ADDRESS_AMD_INTERNAL_DEBUG_END         = 0x030F,
+	DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_START    = 0x0310,
+	DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_END      = 0x037F,
+	DPCD_ADDRESS_SOURCE_RESERVED_START         = 0x0380,
+	DPCD_ADDRESS_SOURCE_RESERVED_END           = 0x03FF,
+
+	/* Sink Device Specific Field */
+	DPCD_ADDRESS_SINK_DEVICE_ID_START = 0x0400,
+	DPCD_ADDRESS_SINK_DEVICE_ID_END = 0x0402,
+	DPCD_ADDRESS_SINK_DEVICE_STR_START = 0x0403,
+	DPCD_ADDRESS_SINK_DEVICE_STR_END = 0x0408,
+	DPCD_ADDRESS_SINK_REVISION_START = 0x409,
+	DPCD_ADDRESS_SINK_REVISION_END = 0x40B,
+
+	/* Branch Device Specific Field */
+	DPCD_ADDRESS_BRANCH_DEVICE_ID_START = 0x0500,
+	DPCD_ADDRESS_BRANCH_DEVICE_ID_END = 0x0502,
+	DPCD_ADDRESS_BRANCH_DEVICE_STR_START = 0x0503,
+	DPCD_ADDRESS_BRANCH_DEVICE_STR_END = 0x0508,
+
+	DPCD_ADDRESS_POWER_STATE = 0x0600,
+
+	/* EDP related */
+	DPCD_ADDRESS_EDP_REV = 0x0700,
+	DPCD_ADDRESS_EDP_CAPABILITY = 0x0701,
+	DPCD_ADDRESS_EDP_BACKLIGHT_ADJUST_CAP = 0x0702,
+	DPCD_ADDRESS_EDP_GENERAL_CAP2 = 0x0703,
+
+	DPCD_ADDRESS_EDP_DISPLAY_CONTROL = 0x0720,
+	DPCD_ADDRESS_EDP_BACKLIGHT_SET = 0x0721,
+	DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_MSB = 0x0722,
+	DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_LSB = 0x0723,
+	DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT = 0x0724,
+	DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MIN = 0x0725,
+	DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MAX = 0x0726,
+	DPCD_ADDRESS_EDP_BACKLIGHT_CONTROL_STATUS = 0x0727,
+	DPCD_ADDRESS_EDP_BACKLIGHT_FREQ_SET = 0x0728,
+	DPCD_ADDRESS_EDP_REVERVED = 0x0729,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MSB = 0x072A,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MID = 0x072B,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_LSB = 0x072C,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MSB = 0x072D,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MID = 0x072E,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_LSB = 0x072F,
+
+	DPCD_ADDRESS_EDP_DBC_MINIMUM_BRIGHTNESS_SET = 0x0732,
+	DPCD_ADDRESS_EDP_DBC_MAXIMUM_BRIGHTNESS_SET = 0x0733,
+
+	/* Sideband MSG Buffers 1.2 */
+	DPCD_ADDRESS_DOWN_REQ_START = 0x01000,
+	DPCD_ADDRESS_DOWN_REQ_END = 0x011ff,
+
+	DPCD_ADDRESS_UP_REP_START = 0x01200,
+	DPCD_ADDRESS_UP_REP_END = 0x013ff,
+
+	DPCD_ADDRESS_DOWN_REP_START = 0x01400,
+	DPCD_ADDRESS_DOWN_REP_END = 0x015ff,
+
+	DPCD_ADDRESS_UP_REQ_START = 0x01600,
+	DPCD_ADDRESS_UP_REQ_END = 0x017ff,
+
+	/* ESI (Event Status Indicator) Field 1.2 */
+	DPCD_ADDRESS_SINK_COUNT_ESI = 0x02002,
+	DPCD_ADDRESS_DEVICE_IRQ_ESI0 = 0x02003,
+	DPCD_ADDRESS_DEVICE_IRQ_ESI1 = 0x02004,
+	/*@todo move dpcd_address_Lane01Status back here*/
+
+	DPCD_ADDRESS_PSR_ERROR_STATUS = 0x2006,
+	DPCD_ADDRESS_PSR_EVENT_STATUS = 0x2007,
+	DPCD_ADDRESS_PSR_SINK_STATUS = 0x2008,
+	DPCD_ADDRESS_PSR_DBG_REGISTER0 = 0x2009,
+	DPCD_ADDRESS_PSR_DBG_REGISTER1 = 0x200A,
+
+	/* Travis specific addresses */
+	DPCD_ADDRESS_TRAVIS_SINK_DEV_SEL = 0x5f0,
+	DPCD_ADDRESS_TRAVIS_SINK_ACCESS_OFFSET	= 0x5f1,
+	DPCD_ADDRESS_TRAVIS_SINK_ACCESS_REG = 0x5f2,
+};
+
+enum dpcd_revision {
+	DPCD_REV_10 = 0x10,
+	DPCD_REV_11 = 0x11,
+	DPCD_REV_12 = 0x12
+};
+
+enum dp_pwr_state {
+	DP_PWR_STATE_D0 = 1,/* direct HW translation! */
+	DP_PWR_STATE_D3
+};
+
+/* these are the types stored at DOWNSTREAMPORT_PRESENT */
+enum dpcd_downstream_port_type {
+	DOWNSTREAM_DP = 0,
+	DOWNSTREAM_VGA,
+	DOWNSTREAM_DVI_HDMI,
+	DOWNSTREAM_NONDDC /* has no EDID (TV,CV) */
+};
+
+enum dpcd_link_test_patterns {
+	LINK_TEST_PATTERN_NONE = 0,
+	LINK_TEST_PATTERN_COLOR_RAMP,
+	LINK_TEST_PATTERN_VERTICAL_BARS,
+	LINK_TEST_PATTERN_COLOR_SQUARES
+};
+
+enum dpcd_test_color_format {
+	TEST_COLOR_FORMAT_RGB = 0,
+	TEST_COLOR_FORMAT_YCBCR422,
+	TEST_COLOR_FORMAT_YCBCR444
+};
+
+enum dpcd_test_bit_depth {
+	TEST_BIT_DEPTH_6 = 0,
+	TEST_BIT_DEPTH_8,
+	TEST_BIT_DEPTH_10,
+	TEST_BIT_DEPTH_12,
+	TEST_BIT_DEPTH_16
+};
+
+/* PHY (encoder) test patterns
+The order of test patterns follows DPCD register PHY_TEST_PATTERN (0x248) */
+enum dpcd_phy_test_patterns {
+	PHY_TEST_PATTERN_NONE = 0,
+	PHY_TEST_PATTERN_D10_2,
+	PHY_TEST_PATTERN_SYMBOL_ERROR,
+	PHY_TEST_PATTERN_PRBS7,
+	PHY_TEST_PATTERN_80BIT_CUSTOM,/* For DP1.2 only */
+	PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE/* For DP1.2 only */
+};
+
+enum dpcd_test_dyn_range {
+	TEST_DYN_RANGE_VESA = 0,
+	TEST_DYN_RANGE_CEA
+};
+
+enum dpcd_audio_test_pattern {
+	AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0,/* direct HW translation */
+	AUDIO_TEST_PATTERN_SAWTOOTH
+};
+
+enum dpcd_audio_sampling_rate {
+	AUDIO_SAMPLING_RATE_32KHZ = 0,/* direct HW translation */
+	AUDIO_SAMPLING_RATE_44_1KHZ,
+	AUDIO_SAMPLING_RATE_48KHZ,
+	AUDIO_SAMPLING_RATE_88_2KHZ,
+	AUDIO_SAMPLING_RATE_96KHZ,
+	AUDIO_SAMPLING_RATE_176_4KHZ,
+	AUDIO_SAMPLING_RATE_192KHZ
+};
+
+enum dpcd_audio_channels {
+	AUDIO_CHANNELS_1 = 0,/* direct HW translation */
+	AUDIO_CHANNELS_2,
+	AUDIO_CHANNELS_3,
+	AUDIO_CHANNELS_4,
+	AUDIO_CHANNELS_5,
+	AUDIO_CHANNELS_6,
+	AUDIO_CHANNELS_7,
+	AUDIO_CHANNELS_8,
+
+	AUDIO_CHANNELS_COUNT
+};
+
+enum dpcd_audio_test_pattern_periods {
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_NOTUSED = 0,/* direct HW translation */
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_3,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_6,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_12,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_24,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_48,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_96,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_192,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_384,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_768,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_1536
+};
+
+/* This enum is for programming DPCD TRAINING_PATTERN_SET */
+enum dpcd_training_patterns {
+	DPCD_TRAINING_PATTERN_VIDEOIDLE = 0,/* direct HW translation! */
+	DPCD_TRAINING_PATTERN_1,
+	DPCD_TRAINING_PATTERN_2,
+	DPCD_TRAINING_PATTERN_3
+};
+
+/* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus
+It defines the possible PSR states. */
+enum dpcd_psr_sink_states {
+	PSR_SINK_STATE_INACTIVE = 0,
+	PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SOURCE_TIMING = 1,
+	PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB = 2,
+	PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SINK_TIMING = 3,
+	PSR_SINK_STATE_ACTIVE_CAPTURE_TIMING_RESYNC = 4,
+	PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7,
+};
+
+/* This enum defines the Panel's eDP revision at DPCD 700h
+ * 00h = eDP v1.1 or lower
+ * 01h = eDP v1.2
+ * 02h = eDP v1.3 (PSR support starts here)
+ * 03h = eDP v1.4
+ * If unknown revision, treat as eDP v1.1, meaning least functionality set.
+ * This enum has values matched to eDP spec, thus values should not change.
+ */
+enum dpcd_edp_revision {
+	DPCD_EDP_REVISION_EDP_V1_1 = 0,
+	DPCD_EDP_REVISION_EDP_V1_2 = 1,
+	DPCD_EDP_REVISION_EDP_V1_3 = 2,
+	DPCD_EDP_REVISION_EDP_V1_4 = 3,
+	DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1,
+};
+
+union dpcd_rev {
+	struct {
+		uint8_t MINOR:4;
+		uint8_t MAJOR:4;
+	} bits;
+	uint8_t raw;
+};
+
+union max_lane_count {
+	struct {
+		uint8_t MAX_LANE_COUNT:5;
+		uint8_t POST_LT_ADJ_REQ_SUPPORTED:1;
+		uint8_t TPS3_SUPPORTED:1;
+		uint8_t ENHANCED_FRAME_CAP:1;
+	} bits;
+	uint8_t raw;
+};
+
+union max_down_spread {
+	struct {
+		uint8_t MAX_DOWN_SPREAD:1;
+		uint8_t RESERVED:5;
+		uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1;
+		uint8_t RESERVED1:1;
+	} bits;
+	uint8_t raw;
+};
+
+union mstm_cap {
+	struct {
+		uint8_t MST_CAP:1;
+		uint8_t RESERVED:7;
+	} bits;
+	uint8_t raw;
+};
+
+union mstm_cntl {
+	struct {
+		uint8_t MST_EN:1;
+		uint8_t UP_REQ_EN:1;
+		uint8_t UPSTREAM_IS_SRC:1;
+		uint8_t RESERVED:5;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_count_set {
+	struct {
+		uint8_t LANE_COUNT_SET:5;
+		uint8_t POST_LT_ADJ_REQ_GRANTED:1;
+		uint8_t RESERVED:1;
+		uint8_t ENHANCED_FRAMING:1;
+	} bits;
+	uint8_t raw;
+};
+
+/* for DPCD_ADDRESS_I2C_SPEED_CNTL_CAP
+ * and DPCD_ADDRESS_I2C_SPEED_CNTL
+ */
+union i2c_speed {
+	struct {
+		uint8_t _1KBPS:1;
+		uint8_t _5KBPS:1;
+		uint8_t _10KBPS:1;
+		uint8_t _100KBPS:1;
+		uint8_t _400KBPS:1;
+		uint8_t _1MBPS:1;
+		uint8_t reserved:2;
+	} bits;
+	uint8_t raw;
+};
+
+union payload_table_update_status {
+	struct {
+		uint8_t VC_PAYLOAD_TABLE_UPDATED:1;
+		uint8_t ACT_HANDLED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union device_irq_esi_0 {
+	struct {
+		uint8_t REMOTE_CONTROL_CMD_PENDING:1;
+		uint8_t AUTOMATED_TEST_REQUEST:1;
+		uint8_t CP_IRQ:1;
+		uint8_t MCCS_IRQ:1;
+		uint8_t DOWN_REP_MSG_RDY:1;
+		uint8_t UP_REQ_MSG_RDY:1;
+		uint8_t SINK_SPECIFIC_IRQ:1;
+		uint8_t RESERVED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_status {
+	struct {
+		uint8_t CR_DONE_0:1;
+		uint8_t CHANNEL_EQ_DONE_0:1;
+		uint8_t SYMBOL_LOCKED_0:1;
+		uint8_t RESERVED0:1;
+		uint8_t CR_DONE_1:1;
+		uint8_t CHANNEL_EQ_DONE_1:1;
+		uint8_t SYMBOL_LOCKED_1:1;
+		uint8_t RESERVED_1:1;
+	} bits;
+	uint8_t raw;
+};
+
+union device_service_irq {
+	struct {
+		uint8_t REMOTE_CONTROL_CMD_PENDING:1;
+		uint8_t AUTOMATED_TEST:1;
+		uint8_t CP_IRQ:1;
+		uint8_t MCCS_IRQ:1;
+		uint8_t DOWN_REP_MSG_RDY:1;
+		uint8_t UP_REQ_MSG_RDY:1;
+		uint8_t SINK_SPECIFIC:1;
+		uint8_t reserved:1;
+	} bits;
+	uint8_t raw;
+};
+
+union downstream_port {
+	struct {
+		uint8_t PRESENT:1;
+		uint8_t TYPE:2;
+		uint8_t FORMAT_CONV:1;
+		uint8_t DETAILED_CAPS:1;
+		uint8_t RESERVED:3;
+	} bits;
+	uint8_t raw;
+};
+
+union sink_count {
+	struct {
+		uint8_t SINK_COUNT:6;
+		uint8_t CPREADY:1;
+		uint8_t RESERVED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_align_status_updated {
+	struct {
+		uint8_t INTERLANE_ALIGN_DONE:1;
+		uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1;
+		uint8_t RESERVED:4;
+		uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1;
+		uint8_t LINK_STATUS_UPDATED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_adjust {
+	struct {
+		uint8_t VOLTAGE_SWING_LANE:2;
+		uint8_t PRE_EMPHASIS_LANE:2;
+		uint8_t RESERVED:4;
+	} bits;
+	uint8_t raw;
+};
+
+/* Automated test structures */
+union test_request {
+	struct {
+		uint8_t LINK_TRAINING:1;
+		uint8_t LINK_TEST_PATTERN:1;
+		uint8_t EDID_READ:1;
+		uint8_t PHY_TEST_PATTERN:1;
+		uint8_t AUDIO_TEST_PATTERN:1;
+		uint8_t AUDIO_TEST_NO_VIDEO:1;
+		uint8_t RESERVED:1;
+		uint8_t TEST_STEREO_3D:1;
+	} bits;
+	uint8_t raw;
+};
+
+union test_response {
+	struct {
+		uint8_t ACK:1;
+		uint8_t NO_ACK:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union link_test_pattern {
+	struct {
+		uint8_t PATTERN:2;/*DpcdLinkTestPatterns*/
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union test_misc {
+	struct dpcd_test_misc_bits {
+		uint8_t SYNC_CLOCK:1;
+		uint8_t CLR_FORMAT:2;/*DpcdTestColorFormat*/
+		uint8_t DYN_RANGE:1;/*DpcdTestDynRange*/
+		uint8_t YCBCR:1;/*DpcdTestYCbCrStandard*/
+		uint8_t BPC:3;/*DpcdTestBitDepth*/
+	} bits;
+	uint8_t raw;
+};
+
+union phy_test_pattern {
+	struct {
+		/* This field is 2 bits for DP1.1 and 3 bits for DP1.2.*/
+		uint8_t PATTERN:3;
+		uint8_t RESERVED:5;/* BY spec, bit7:2 is 0 for DP1.1.*/
+	} bits;
+	uint8_t raw;
+};
+
+union audio_test_mode {
+	struct {
+		uint8_t SAMPLING_RATE:4;
+		uint8_t CHANNEL_COUNT:4;
+	} bits;
+	uint8_t raw;
+};
+
+union audio_tes_tpattern_period {
+	struct {
+		uint8_t PATTERN_PERIOD:4;
+		uint8_t RESERVED:4;
+	} bits;
+	uint8_t raw;
+};
+
+struct audio_test_pattern_type {
+	uint8_t value;
+};
+
+union dpcd_training_pattern {
+	struct {
+		uint8_t TRAINING_PATTERN_SET:2;
+		uint8_t LINK_QUAL_PATTERN_SET:2;
+		uint8_t RECOVERED_CLOCK_OUT_EN:1;
+		uint8_t SCRAMBLING_DISABLE:1;
+		uint8_t RESERVED:2;
+	} bits;
+	uint8_t raw;
+};
+
+/* Training Lane is used to configure downstream DP device's voltage swing
+and pre-emphasis levels*/
+/* The DPCD addresses are from 0x103 to 0x106*/
+union dpcd_training_lane {
+	struct {
+		uint8_t VOLTAGE_SWING_SET:2;
+		uint8_t MAX_SWING_REACHED:1;
+		uint8_t PRE_EMPHASIS_SET:2;
+		uint8_t MAX_PRE_EMPHASIS_REACHED:1;
+		uint8_t RESERVED:2;
+	} bits;
+	uint8_t raw;
+};
+
+/*Training Lane Set 2 is used to configure downstream DP device's
+post cursor 2 level of Training Pattern 2 or 3*/
+/* The DPCD addresses are 0x10F (TRAINING_LANE0_1_SET2)
+and 0x110 (TRAINING_LANE2_3_SET2)*/
+union dpcd_training_lane_set2 {
+	struct {
+		uint8_t POST_CURSOR2_SET:2;
+		uint8_t MAX_POST_CURSOR2_REACHED:1;
+		uint8_t RESERVED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union dpcd_psr_configuration {
+	struct {
+		uint8_t ENABLE:1;
+		uint8_t TRANSMITTER_ACTIVE_IN_PSR:1;
+		uint8_t CRC_VERIFICATION:1;
+		uint8_t FRAME_CAPTURE_INDICATION:1;
+		uint8_t LINE_CAPTURE_INDICATION:1;
+		uint8_t IRQ_HPD_WITH_CRC_ERROR:1;
+		uint8_t RESERVED:2;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_error_status {
+	struct {
+		uint8_t LINK_CRC_ERROR:1;
+		uint8_t RFB_STORAGE_ERROR:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_event_status_ind {
+	struct {
+		uint8_t SINK_PSR_CAP_CHANGE:1;
+		uint8_t RESERVED:7;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_sink_psr_status {
+	struct {
+		uint8_t SINK_SELF_REFRESH_STATUS:3;
+		uint8_t RESERVED:5;
+	} bits;
+	uint8_t raw;
+};
+
+/* EDP related 0x701 */
+union edp_generial_cap1 {
+	struct {
+		uint8_t TCON_BACKLIGHT_ADJUSTMENT_CAPABLE:1;
+		uint8_t BACKLIGHT_PIN_ENABLE_CAPABLE:1;
+		uint8_t BACKLIGHT_AUX_ENABLE_CAPABLE:1;
+		uint8_t PANEL_SELFTEST_PIN_ENABLE_CAPABLE:1;
+		uint8_t BACKLIGHT_SELFTEST_AUX_ENABLE_CAPABLE:1;
+		uint8_t FRC_ENABLE_CAPABLE:1;
+		uint8_t COLOR_ENGINE_CAPABLE:1;
+		/*bit 7, pane can be controlled by 0x600*/
+		uint8_t SET_POWER_CAPABLE:1;
+	} bits;
+	uint8_t raw;
+};
+
+/* TMDS-converter related */
+union dwnstream_port_caps_byte0 {
+	struct {
+		uint8_t DWN_STRM_PORTX_TYPE:3;
+		uint8_t DWN_STRM_PORTX_HPD:1;
+		uint8_t RESERVERD:4;
+	} bits;
+	uint8_t raw;
+};
+
+/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/
+enum dpcd_downstream_port_detailed_type {
+	DOWN_STREAM_DETAILED_DP = 0,
+	DOWN_STREAM_DETAILED_VGA,
+	DOWN_STREAM_DETAILED_DVI,
+	DOWN_STREAM_DETAILED_HDMI,
+	DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/
+	DOWN_STREAM_DETAILED_DP_PLUS_PLUS
+};
+
+union dwnstream_port_caps_byte2 {
+	struct {
+		uint8_t MAX_BITS_PER_COLOR_COMPONENT:2;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union dp_downstream_port_present {
+	uint8_t byte;
+	struct {
+		uint8_t PORT_PRESENT:1;
+		uint8_t PORT_TYPE:2;
+		uint8_t FMT_CONVERSION:1;
+		uint8_t DETAILED_CAPS:1;
+		uint8_t RESERVED:3;
+	} fields;
+};
+
+
+union dwnstream_port_caps_byte3_dvi {
+	struct {
+		uint8_t RESERVED1:1;
+		uint8_t DUAL_LINK:1;
+		uint8_t HIGH_COLOR_DEPTH:1;
+		uint8_t RESERVED2:5;
+	} bits;
+	uint8_t raw;
+};
+
+union dwnstream_port_caps_byte3_hdmi {
+	struct {
+		uint8_t FRAME_SEQ_TO_FRAME_PACK:1;
+		uint8_t RESERVED:7;
+	} bits;
+	uint8_t raw;
+};
+
+/*4-byte structure for detailed capabilities of a down-stream port
+(DP-to-TMDS converter).*/
+union dwnstream_portx_caps {
+	struct {
+		union dwnstream_port_caps_byte0 byte0;
+		uint8_t max_tmds_clk;/* byte1 */
+		union dwnstream_port_caps_byte2 byte2;
+
+		union {
+			union dwnstream_port_caps_byte3_dvi byte_dvi;
+			union dwnstream_port_caps_byte3_hdmi byte_hdmi;
+		} byte3;
+	} bytes;
+	uint8_t raw[4];
+};
+
+union sink_status {
+	struct {
+		uint8_t RX_PORT0_STATUS:1;
+		uint8_t RX_PORT1_STATUS:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+/*6-byte structure corresponding to 6 registers (200h-205h)
+read during handling of HPD-IRQ*/
+union hpd_irq_data {
+	struct {
+		union sink_count sink_cnt;/* 200h */
+		union device_service_irq device_service_irq;/* 201h */
+		union lane_status lane01_status;/* 202h */
+		union lane_status lane23_status;/* 203h */
+		union lane_align_status_updated lane_status_updated;/* 204h */
+		union sink_status sink_status;
+	} bytes;
+	uint8_t raw[6];
+};
+
+union down_stream_port_count {
+	struct {
+		uint8_t DOWN_STR_PORT_COUNT:4;
+		uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/
+		/*Bit 6 = MSA_TIMING_PAR_IGNORED
+		0 = Sink device requires the MSA timing parameters
+		1 = Sink device is capable of rendering incoming video
+		 stream without MSA timing parameters*/
+		uint8_t IGNORE_MSA_TIMING_PARAM:1;
+		/*Bit 7 = OUI Support
+		0 = OUI not supported
+		1 = OUI supported
+		(OUI and Device Identification mandatory for DP 1.2)*/
+		uint8_t OUI_SUPPORT:1;
+	} bits;
+	uint8_t raw;
+};
+
+union down_spread_ctrl {
+	struct {
+		uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/
+	/* Bits 4 = SPREAD_AMP. Spreading amplitude
+	0 = Main link signal is not downspread
+	1 = Main link signal is downspread <= 0.5%
+	with frequency in the range of 30kHz ~ 33kHz*/
+		uint8_t SPREAD_AMP:1;
+		uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/
+	/*Bit 7 = MSA_TIMING_PAR_IGNORE_EN
+	0 = Source device will send valid data for the MSA Timing Params
+	1 = Source device may send invalid data for these MSA Timing Params*/
+		uint8_t IGNORE_MSA_TIMING_PARAM:1;
+	} bits;
+	uint8_t raw;
+};
+
+union dpcd_edp_config {
+	struct {
+		uint8_t PANEL_MODE_EDP:1;
+		uint8_t FRAMING_CHANGE_ENABLE:1;
+		uint8_t RESERVED:5;
+		uint8_t PANEL_SELF_TEST_ENABLE:1;
+	} bits;
+	uint8_t raw;
+};
+
+struct dp_device_vendor_id {
+	uint8_t ieee_oui[3];/*24-bit IEEE OUI*/
+	uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/
+};
+
+struct dp_sink_hw_fw_revision {
+	uint8_t ieee_hw_rev;
+	uint8_t ieee_fw_rev[2];
+};
+
+/*DPCD register of DP receiver capability field bits-*/
+union edp_configuration_cap {
+	struct {
+		uint8_t ALT_SCRAMBLER_RESET:1;
+		uint8_t FRAMING_CHANGE:1;
+		uint8_t RESERVED:1;
+		uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1;
+		uint8_t RESERVED2:4;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_capabilities {
+	struct {
+		uint8_t EXIT_LT_NOT_REQ:1;
+		uint8_t RFB_SETUP_TIME:3;
+		uint8_t RESERVED:4;
+	} bits;
+	uint8_t raw;
+};
+
+#endif /* __DAL_DPCD_DEFS_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/encoder_interface.h b/drivers/gpu/drm/amd/dal/include/encoder_interface.h
new file mode 100644
index 000000000000..5fbf816cf96e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/encoder_interface.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of enc software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and enc permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ENCODER_INTERFACE_H__
+#define __DAL_ENCODER_INTERFACE_H__
+
+#include "encoder_types.h"
+#include "adapter_service_interface.h"
+#include "fixed31_32.h"
+
+enum encoder_result {
+	ENCODER_RESULT_OK,
+	ENCODER_RESULT_ERROR,
+	ENCODER_RESULT_NOBANDWIDTH,
+	ENCODER_RESULT_SINKCONNECTIVITYCHANGED,
+};
+
+struct encoder_init_data {
+	struct adapter_service *adapter_service;
+	enum channel_id channel;
+	struct graphics_object_id connector;
+	enum hpd_source_id hpd_source;
+	/* TODO: in DAL2, here was pointer to EventManagerInterface */
+	struct graphics_object_id encoder;
+	struct dc_context *ctx;
+};
+
+/* forward declaration */
+struct encoder;
+
+struct encoder *dal_encoder_create(
+	const struct encoder_init_data *init_data);
+
+/* access graphics object base */
+const struct graphics_object_id dal_encoder_get_graphics_object_id(
+	const struct encoder *enc);
+
+/*
+ * Signal types support
+ */
+uint32_t dal_encoder_enumerate_input_signals(
+	const struct encoder *enc);
+uint32_t dal_encoder_enumerate_output_signals(
+	const struct encoder *enc);
+bool dal_encoder_is_input_signal_supported(
+	const struct encoder *enc,
+	enum signal_type signal);
+bool dal_encoder_is_output_signal_supported(
+	const struct encoder *enc,
+	enum signal_type signal);
+void dal_encoder_set_input_signals(
+	struct encoder *enc,
+	uint32_t signals);
+void dal_encoder_set_output_signals(
+	struct encoder *enc,
+	uint32_t signals);
+
+/*
+ * Programming interface
+ */
+/* perform power-up sequence (boot up, resume, recovery) */
+enum encoder_result dal_encoder_power_up(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* perform power-down (shut down, stand-by */
+enum encoder_result dal_encoder_power_down(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* setup encoder block (DIG, DVO, DAC), does not enables encoder */
+enum encoder_result dal_encoder_setup(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* activate transmitter,
+ * do preparation before enables the actual stream output */
+enum encoder_result dal_encoder_pre_enable_output(
+	struct encoder *enc,
+	const struct encoder_pre_enable_output_param *param);
+/* activate transmitter, enables actual stream output */
+enum encoder_result dal_encoder_enable_output(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* deactivate transmitter, disables stream output */
+enum encoder_result dal_encoder_disable_output(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* output blank data,
+ *prevents output of the actual surface data on active transmitter */
+enum encoder_result dal_encoder_blank(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* stop sending blank data,
+ * output the actual surface data on active transmitter */
+enum encoder_result dal_encoder_unblank(
+	struct encoder *enc,
+	const struct encoder_unblank_param *param);
+/* setup stereo signal from given controller */
+enum encoder_result dal_encoder_setup_stereo(
+	struct encoder *enc,
+	const struct encoder_3d_setup *setup);
+/* enable HSync/VSync output from given controller */
+enum encoder_result dal_encoder_enable_sync_output(
+	struct encoder *enc,
+	enum sync_source src);
+/* disable HSync/VSync output */
+enum encoder_result dal_encoder_disable_sync_output(
+	struct encoder *enc);
+/* action of encoder before DDC transaction */
+enum encoder_result dal_encoder_pre_ddc(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* action of encoder after DDC transaction */
+enum encoder_result dal_encoder_post_ddc(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* CRT DDC EDID polling interrupt interface */
+enum encoder_result dal_encoder_update_implementation(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* set test pattern signal */
+enum encoder_result dal_encoder_set_dp_phy_pattern(
+	struct encoder *enc,
+	const struct encoder_set_dp_phy_pattern_param *param);
+
+void dal_encoder_release_hw(struct encoder *enc);
+/*
+ * Information interface
+ */
+/* check whether sink is present based on SENSE detection,
+ * analog encoders will return true */
+bool dal_encoder_is_sink_present(
+	struct encoder *enc,
+	struct graphics_object_id downstream);
+/* detect load on the sink,
+ * for analog signal,
+ * load detection will be called for the specified signal */
+enum signal_type dal_encoder_detect_load(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* detect output sink type,
+ * for digital perform sense detection,
+ * for analog return encoder's signal type */
+enum signal_type dal_encoder_detect_sink(
+	struct encoder *enc,
+	struct graphics_object_id downstream);
+/* get transmitter id */
+enum transmitter dal_encoder_get_transmitter(
+	const struct encoder *enc);
+/*  */
+enum transmitter dal_encoder_get_paired_transmitter(
+	const struct encoder *enc);
+/*  */
+enum physical_phy_id dal_encoder_get_phy(
+	const struct encoder *enc);
+/*  */
+enum physical_phy_id dal_encoder_get_paired_phy(
+	const struct encoder *enc);
+/* reports if the encoder supports given link settings */
+bool dal_encoder_is_link_settings_supported(
+	struct encoder *enc,
+	const struct link_settings *link_settings);
+/* options and features supported by encoder */
+struct encoder_feature_support dal_encoder_get_supported_features(
+	const struct encoder *enc);
+/* reports list of supported stream engines */
+union supported_stream_engines dal_encoder_get_supported_stream_engines(
+	const struct encoder *enc);
+/* reports preferred stream engine */
+enum engine_id dal_encoder_get_preferred_stream_engine(
+	const struct encoder *enc);
+/* reports whether clock source can be used with enc encoder */
+bool dal_encoder_is_clock_source_supported(
+	const struct encoder *enc,
+	enum clock_source_id clock_source);
+/* check encoder capabilities to confirm
+ * specified timing is in the encoder limits
+ * when outputting certain signal */
+enum encoder_result dal_encoder_validate_output(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* retrieves sync source which outputs VSync signal from encoder */
+enum sync_source dal_encoder_get_vsync_output_source(
+	const struct encoder *enc);
+/*
+ * Adjustments
+ */
+/* update AVI info frame */
+void dal_encoder_update_info_frame(
+	struct encoder *enc,
+	const struct encoder_info_frame_param *param);
+/*  */
+void dal_encoder_stop_info_frame(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/*  */
+enum encoder_result dal_encoder_set_lcd_backlight_level(
+	struct encoder *enc,
+	uint32_t level);
+/* backlight control interface */
+enum encoder_result dal_encoder_backlight_control(
+	struct encoder *enc,
+	bool enable);
+/*
+ * DP MST programming
+ */
+/* update payload slot allocation for each DP MST stream */
+enum encoder_result dal_encoder_update_mst_alloc_table(
+	struct encoder *enc,
+	const struct dp_mst_stream_allocation_table *table,
+	bool is_removal);
+/* enable virtual channel stream with throttled value X.Y */
+enum encoder_result dal_encoder_enable_stream(
+	struct encoder *enc,
+	enum engine_id engine,
+	struct fixed31_32 throttled_vcp_size);
+/* disable virtual channel stream */
+enum encoder_result dal_encoder_disable_stream(
+	struct encoder *enc,
+	enum engine_id engine);
+void dal_encoder_set_multi_path(struct encoder *enc, bool is_multi_path);
+/*
+ * Test harness
+ */
+/* check whether Test Pattern enabled */
+bool dal_encoder_is_test_pattern_enabled(
+	struct encoder *enc,
+	enum engine_id engine);
+/* set lane parameters */
+enum encoder_result dal_encoder_set_lane_settings(
+	struct encoder *enc,
+	const struct encoder_context *ctx,
+	const struct link_training_settings *link_settings);
+/* get lane parameters */
+enum encoder_result dal_encoder_get_lane_settings(
+	struct encoder *enc,
+	const struct encoder_context *ctx,
+	struct link_training_settings *link_settings);
+/* enable master clock of HPD interrupt */
+void dal_encoder_enable_hpd(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* disable all HPD interrupts */
+void dal_encoder_disable_hpd(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+
+/* get current HW state - used for optimization code path only */
+enum clock_source_id dal_encoder_get_active_clock_source(
+	const struct encoder *enc);
+enum engine_id dal_encoder_get_active_engine(
+	const struct encoder *enc);
+
+/* destroy encoder instance */
+void dal_encoder_destroy(
+	struct encoder **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/fixed31_32.h b/drivers/gpu/drm/amd/dal/include/fixed31_32.h
new file mode 100644
index 000000000000..507f9f639099
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/fixed31_32.h
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_FIXED31_32_H__
+#define __DAL_FIXED31_32_H__
+
+/*
+ * @brief
+ * Arithmetic operations on real numbers
+ * represented as fixed-point numbers.
+ * There are: 1 bit for sign,
+ * 31 bit for integer part,
+ * 32 bits for fractional part.
+ *
+ * @note
+ * Currently, overflows and underflows are asserted;
+ * no special result returned.
+ */
+
+struct fixed31_32 {
+	int64_t value;
+};
+
+/*
+ * @brief
+ * Useful constants
+ */
+
+static const struct fixed31_32 dal_fixed31_32_zero = { 0 };
+static const struct fixed31_32 dal_fixed31_32_epsilon = { 1LL };
+static const struct fixed31_32 dal_fixed31_32_half = { 0x80000000LL };
+static const struct fixed31_32 dal_fixed31_32_one = { 0x100000000LL };
+
+static const struct fixed31_32 dal_fixed31_32_pi = { 13493037705LL };
+static const struct fixed31_32 dal_fixed31_32_two_pi = { 26986075409LL };
+static const struct fixed31_32 dal_fixed31_32_e = { 11674931555LL };
+static const struct fixed31_32 dal_fixed31_32_ln2 = { 2977044471LL };
+static const struct fixed31_32 dal_fixed31_32_ln2_div_2 = { 1488522236LL };
+
+/*
+ * @brief
+ * Initialization routines
+ */
+
+/*
+ * @brief
+ * result = numerator / denominator
+ */
+struct fixed31_32 dal_fixed31_32_from_fraction(
+	int64_t numerator,
+	int64_t denominator);
+
+/*
+ * @brief
+ * result = arg
+ */
+struct fixed31_32 dal_fixed31_32_from_int(
+	int64_t arg);
+
+/*
+ * @brief
+ * Unary operators
+ */
+
+/*
+ * @brief
+ * result = -arg
+ */
+struct fixed31_32 dal_fixed31_32_neg(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = abs(arg) := (arg >= 0) ? arg : -arg
+ */
+struct fixed31_32 dal_fixed31_32_abs(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Binary relational operators
+ */
+
+/*
+ * @brief
+ * result = arg1 < arg2
+ */
+bool dal_fixed31_32_lt(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = arg1 <= arg2
+ */
+bool dal_fixed31_32_le(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = arg1 == arg2
+ */
+bool dal_fixed31_32_eq(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2
+ */
+struct fixed31_32 dal_fixed31_32_min(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1
+ */
+struct fixed31_32 dal_fixed31_32_max(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ *          | min_value, when arg <= min_value
+ * result = | arg, when min_value < arg < max_value
+ *          | max_value, when arg >= max_value
+ */
+struct fixed31_32 dal_fixed31_32_clamp(
+	struct fixed31_32 arg,
+	struct fixed31_32 min_value,
+	struct fixed31_32 max_value);
+
+/*
+ * @brief
+ * Binary shift operators
+ */
+
+/*
+ * @brief
+ * result = arg << shift
+ */
+struct fixed31_32 dal_fixed31_32_shl(
+	struct fixed31_32 arg,
+	uint8_t shift);
+
+/*
+ * @brief
+ * result = arg >> shift
+ */
+struct fixed31_32 dal_fixed31_32_shr(
+	struct fixed31_32 arg,
+	uint8_t shift);
+
+/*
+ * @brief
+ * Binary additive operators
+ */
+
+/*
+ * @brief
+ * result = arg1 + arg2
+ */
+struct fixed31_32 dal_fixed31_32_add(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = arg1 - arg2
+ */
+struct fixed31_32 dal_fixed31_32_sub_int(
+	struct fixed31_32 arg1,
+	int32_t arg2);
+
+/*
+ * @brief
+ * result = arg1 - arg2
+ */
+struct fixed31_32 dal_fixed31_32_sub(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * Binary multiplicative operators
+ */
+
+/*
+ * @brief
+ * result = arg1 * arg2
+ */
+struct fixed31_32 dal_fixed31_32_mul_int(
+	struct fixed31_32 arg1,
+	int32_t arg2);
+
+/*
+ * @brief
+ * result = arg1 * arg2
+ */
+struct fixed31_32 dal_fixed31_32_mul(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = square(arg) := arg * arg
+ */
+struct fixed31_32 dal_fixed31_32_sqr(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = arg1 / arg2
+ */
+struct fixed31_32 dal_fixed31_32_div_int(
+	struct fixed31_32 arg1,
+	int64_t arg2);
+
+/*
+ * @brief
+ * result = arg1 / arg2
+ */
+struct fixed31_32 dal_fixed31_32_div(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * Reciprocal function
+ */
+
+/*
+ * @brief
+ * result = reciprocal(arg) := 1 / arg
+ *
+ * @note
+ * No special actions taken in case argument is zero.
+ */
+struct fixed31_32 dal_fixed31_32_recip(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Trigonometric functions
+ */
+
+/*
+ * @brief
+ * result = sinc(arg) := sin(arg) / arg
+ *
+ * @note
+ * Argument specified in radians,
+ * internally it's normalized to [-2pi...2pi] range.
+ */
+struct fixed31_32 dal_fixed31_32_sinc(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = sin(arg)
+ *
+ * @note
+ * Argument specified in radians,
+ * internally it's normalized to [-2pi...2pi] range.
+ */
+struct fixed31_32 dal_fixed31_32_sin(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = cos(arg)
+ *
+ * @note
+ * Argument specified in radians
+ * and should be in [-2pi...2pi] range -
+ * passing arguments outside that range
+ * will cause incorrect result!
+ */
+struct fixed31_32 dal_fixed31_32_cos(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Transcendent functions
+ */
+
+/*
+ * @brief
+ * result = exp(arg)
+ *
+ * @note
+ * Currently, function is verified for abs(arg) <= 1.
+ */
+struct fixed31_32 dal_fixed31_32_exp(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = log(arg)
+ *
+ * @note
+ * Currently, abs(arg) should be less than 1.
+ * No normalization is done.
+ * Currently, no special actions taken
+ * in case of invalid argument(s). Take care!
+ */
+struct fixed31_32 dal_fixed31_32_log(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Power function
+ */
+
+/*
+ * @brief
+ * result = pow(arg1, arg2)
+ *
+ * @note
+ * Currently, abs(arg1) should be less than 1. Take care!
+ */
+struct fixed31_32 dal_fixed31_32_pow(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * Rounding functions
+ */
+
+/*
+ * @brief
+ * result = floor(arg) := greatest integer lower than or equal to arg
+ */
+int32_t dal_fixed31_32_floor(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = round(arg) := integer nearest to arg
+ */
+int32_t dal_fixed31_32_round(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = ceil(arg) := lowest integer greater than or equal to arg
+ */
+int32_t dal_fixed31_32_ceil(
+	struct fixed31_32 arg);
+
+/* the following two function are used in scaler hw programming to convert fixed
+ * point value to format 2 bits from integer part and 19 bits from fractional
+ * part. The same applies for u0d19, 0 bits from integer part and 19 bits from
+ * fractional
+ */
+
+uint32_t dal_fixed31_32_u2d19(
+	struct fixed31_32 arg);
+
+uint32_t dal_fixed31_32_u0d19(
+	struct fixed31_32 arg);
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/fixed32_32.h b/drivers/gpu/drm/amd/dal/include/fixed32_32.h
new file mode 100644
index 000000000000..f393e953e91a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/fixed32_32.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_FIXED32_32_H__
+#define __DAL_FIXED32_32_H__
+
+#include "dm_services_types.h"
+
+struct fixed32_32 {
+	uint64_t value;
+};
+
+static const struct fixed32_32 dal_fixed32_32_zero = { 0 };
+static const struct fixed32_32 dal_fixed32_32_one = { 0x100000000LL };
+static const struct fixed32_32 dal_fixed32_32_half = { 0x80000000LL };
+
+struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d);
+struct fixed32_32 dal_fixed32_32_from_int(uint32_t value);
+struct fixed32_32 dal_fixed32_32_add(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_add_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_sub(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_sub_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_mul(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_mul_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_div(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_div_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_min(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_max(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs);
+bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs);
+bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs);
+bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs);
+bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs);
+bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs);
+bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs);
+uint32_t dal_fixed32_32_ceil(struct fixed32_32 value);
+uint32_t dal_fixed32_32_floor(struct fixed32_32 value);
+uint32_t dal_fixed32_32_round(struct fixed32_32 value);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/gpio_interface.h b/drivers/gpu/drm/amd/dal/include/gpio_interface.h
new file mode 100644
index 000000000000..a084d7923e2f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/gpio_interface.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_INTERFACE_H__
+#define __DAL_GPIO_INTERFACE_H__
+
+#include "gpio_types.h"
+#include "grph_object_defs.h"
+
+struct gpio;
+
+/* Open the handle for future use */
+enum gpio_result dal_gpio_open(
+	struct gpio *gpio,
+	enum gpio_mode mode);
+
+enum gpio_result dal_gpio_open_ex(
+	struct gpio *gpio,
+	enum gpio_mode mode,
+	void *options);
+
+/* Get high or low from the pin */
+enum gpio_result dal_gpio_get_value(
+	const struct gpio *gpio,
+	uint32_t *value);
+
+/* Set pin high or low */
+enum gpio_result dal_gpio_set_value(
+	const struct gpio *gpio,
+	uint32_t value);
+
+/* Get current mode */
+enum gpio_mode dal_gpio_get_mode(
+	const struct gpio *gpio);
+
+/* Change mode of the handle */
+enum gpio_result dal_gpio_change_mode(
+	struct gpio *gpio,
+	enum gpio_mode mode);
+
+/* Get the GPIO id */
+enum gpio_id dal_gpio_get_id(
+	const struct gpio *gpio);
+
+/* Get the GPIO enum */
+uint32_t dal_gpio_get_enum(
+	const struct gpio *gpio);
+
+/* Set the GPIO pin configuration */
+enum gpio_result dal_gpio_set_config(
+	struct gpio *gpio,
+	const struct gpio_config_data *config_data);
+
+/* Obtain GPIO pin info */
+enum gpio_result dal_gpio_get_pin_info(
+	const struct gpio *gpio,
+	struct gpio_pin_info *pin_info);
+
+/* Obtain GPIO sync source */
+enum sync_source dal_gpio_get_sync_source(
+	const struct gpio *gpio);
+
+/* Obtain GPIO pin output state (active low or active high) */
+enum gpio_pin_output_state dal_gpio_get_output_state(
+	const struct gpio *gpio);
+
+/* Close the handle */
+void dal_gpio_close(
+	struct gpio *gpio);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h b/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
new file mode 100644
index 000000000000..3f1b923c1885
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_SERVICE_INTERFACE_H__
+#define __DAL_GPIO_SERVICE_INTERFACE_H__
+
+#include "gpio_types.h"
+#include "gpio_interface.h"
+#include "ddc_interface.h"
+#include "irq_interface.h"
+
+struct gpio_service;
+
+struct gpio_service *dal_gpio_service_create(
+	enum dce_version dce_version_major,
+	enum dce_version dce_version_minor,
+	struct dc_context *ctx);
+
+struct gpio *dal_gpio_service_create_gpio(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	enum gpio_pin_output_state output_state);
+
+struct gpio *dal_gpio_service_create_gpio_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state);
+
+void dal_gpio_service_destroy_gpio(
+	struct gpio **gpio);
+
+struct ddc *dal_gpio_service_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info);
+
+void dal_gpio_service_destroy_ddc(
+	struct ddc **ddc);
+
+struct irq *dal_gpio_service_create_irq(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask);
+
+struct irq *dal_gpio_service_create_irq_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en);
+
+void dal_gpio_service_destroy_irq(
+	struct irq **ptr);
+
+void dal_gpio_service_destroy(
+	struct gpio_service **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/gpio_types.h b/drivers/gpu/drm/amd/dal/include/gpio_types.h
new file mode 100644
index 000000000000..6d3214b36cf4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/gpio_types.h
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_TYPES_H__
+#define __DAL_GPIO_TYPES_H__
+
+#define BUNDLE_A_MASK 0x00FFF000L
+#define BUNDLE_B_MASK 0x00000FFFL
+
+/*
+ * gpio_result
+ *
+ * @brief
+ * The possible return codes that the GPIO object can return.
+ * These return codes can be generated
+ * directly by the GPIO object or from the GPIOPin object.
+ */
+enum gpio_result {
+	GPIO_RESULT_OK,
+	GPIO_RESULT_NULL_HANDLE,
+	GPIO_RESULT_INVALID_DATA,
+	GPIO_RESULT_DEVICE_BUSY,
+	GPIO_RESULT_OPEN_FAILED,
+	GPIO_RESULT_ALREADY_OPENED,
+	GPIO_RESULT_NON_SPECIFIC_ERROR
+};
+
+/*
+ * @brief
+ * Used to identify the specific GPIO device
+ *
+ * @notes
+ * These constants are used as indices in a vector.
+ * Thus they should start from zero and be contiguous.
+ */
+enum gpio_id {
+	GPIO_ID_UNKNOWN = (-1),
+	GPIO_ID_DDC_DATA,
+	GPIO_ID_DDC_CLOCK,
+	GPIO_ID_GENERIC,
+	GPIO_ID_HPD,
+	GPIO_ID_GPIO_PAD,
+	GPIO_ID_VIP_PAD,
+	GPIO_ID_SYNC,
+	GPIO_ID_GSL, /* global swap lock */
+	GPIO_ID_COUNT,
+	GPIO_ID_MIN = GPIO_ID_DDC_DATA,
+	GPIO_ID_MAX = GPIO_ID_GSL
+};
+
+#define GPIO_ENUM_UNKNOWN \
+	32
+
+struct gpio_pin_info {
+	uint32_t offset;
+	uint32_t offset_y;
+	uint32_t offset_en;
+	uint32_t offset_mask;
+
+	uint32_t mask;
+	uint32_t mask_y;
+	uint32_t mask_en;
+	uint32_t mask_mask;
+};
+
+enum gpio_pin_output_state {
+	GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW,
+	GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH,
+	GPIO_PIN_OUTPUT_STATE_DEFAULT = GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW
+};
+
+enum gpio_generic {
+	GPIO_GENERIC_UNKNOWN = (-1),
+	GPIO_GENERIC_A,
+	GPIO_GENERIC_B,
+	GPIO_GENERIC_C,
+	GPIO_GENERIC_D,
+	GPIO_GENERIC_E,
+	GPIO_GENERIC_F,
+	GPIO_GENERIC_G,
+	GPIO_GENERIC_COUNT,
+	GPIO_GENERIC_MIN = GPIO_GENERIC_A,
+	GPIO_GENERIC_MAX = GPIO_GENERIC_B
+};
+
+enum gpio_hpd {
+	GPIO_HPD_UNKNOWN = (-1),
+	GPIO_HPD_1,
+	GPIO_HPD_2,
+	GPIO_HPD_3,
+	GPIO_HPD_4,
+	GPIO_HPD_5,
+	GPIO_HPD_6,
+	GPIO_HPD_COUNT,
+	GPIO_HPD_MIN = GPIO_HPD_1,
+	GPIO_HPD_MAX = GPIO_HPD_6
+};
+
+enum gpio_gpio_pad {
+	GPIO_GPIO_PAD_UNKNOWN = (-1),
+	GPIO_GPIO_PAD_0,
+	GPIO_GPIO_PAD_1,
+	GPIO_GPIO_PAD_2,
+	GPIO_GPIO_PAD_3,
+	GPIO_GPIO_PAD_4,
+	GPIO_GPIO_PAD_5,
+	GPIO_GPIO_PAD_6,
+	GPIO_GPIO_PAD_7,
+	GPIO_GPIO_PAD_8,
+	GPIO_GPIO_PAD_9,
+	GPIO_GPIO_PAD_10,
+	GPIO_GPIO_PAD_11,
+	GPIO_GPIO_PAD_12,
+	GPIO_GPIO_PAD_13,
+	GPIO_GPIO_PAD_14,
+	GPIO_GPIO_PAD_15,
+	GPIO_GPIO_PAD_16,
+	GPIO_GPIO_PAD_17,
+	GPIO_GPIO_PAD_18,
+	GPIO_GPIO_PAD_19,
+	GPIO_GPIO_PAD_20,
+	GPIO_GPIO_PAD_21,
+	GPIO_GPIO_PAD_22,
+	GPIO_GPIO_PAD_23,
+	GPIO_GPIO_PAD_24,
+	GPIO_GPIO_PAD_25,
+	GPIO_GPIO_PAD_26,
+	GPIO_GPIO_PAD_27,
+	GPIO_GPIO_PAD_28,
+	GPIO_GPIO_PAD_29,
+	GPIO_GPIO_PAD_30,
+	GPIO_GPIO_PAD_COUNT,
+	GPIO_GPIO_PAD_MIN = GPIO_GPIO_PAD_0,
+	GPIO_GPIO_PAD_MAX = GPIO_GPIO_PAD_30
+};
+
+enum gpio_vip_pad {
+	GPIO_VIP_PAD_UNKNOWN = (-1),
+	/* following never used -
+	 * GPIO_ID_DDC_CLOCK::GPIO_DDC_LINE_VIP_PAD defined instead */
+	GPIO_VIP_PAD_SCL,
+	/* following never used -
+	 * GPIO_ID_DDC_DATA::GPIO_DDC_LINE_VIP_PAD defined instead */
+	GPIO_VIP_PAD_SDA,
+	GPIO_VIP_PAD_VHAD,
+	GPIO_VIP_PAD_VPHCTL,
+	GPIO_VIP_PAD_VIPCLK,
+	GPIO_VIP_PAD_VID,
+	GPIO_VIP_PAD_VPCLK0,
+	GPIO_VIP_PAD_DVALID,
+	GPIO_VIP_PAD_PSYNC,
+	GPIO_VIP_PAD_COUNT,
+	GPIO_VIP_PAD_MIN = GPIO_VIP_PAD_SCL,
+	GPIO_VIP_PAD_MAX = GPIO_VIP_PAD_PSYNC
+};
+
+enum gpio_sync {
+	GPIO_SYNC_UNKNOWN = (-1),
+	GPIO_SYNC_HSYNC_A,
+	GPIO_SYNC_VSYNC_A,
+	GPIO_SYNC_HSYNC_B,
+	GPIO_SYNC_VSYNC_B,
+	GPIO_SYNC_COUNT,
+	GPIO_SYNC_MIN = GPIO_SYNC_HSYNC_A,
+	GPIO_SYNC_MAX = GPIO_SYNC_VSYNC_B
+};
+
+enum gpio_gsl {
+	GPIO_GSL_UNKNOWN = (-1),
+	GPIO_GSL_GENLOCK_CLOCK,
+	GPIO_GSL_GENLOCK_VSYNC,
+	GPIO_GSL_SWAPLOCK_A,
+	GPIO_GSL_SWAPLOCK_B,
+	GPIO_GSL_COUNT,
+	GPIO_GSL_MIN = GPIO_GSL_GENLOCK_CLOCK,
+	GPIO_GSL_MAX = GPIO_GSL_SWAPLOCK_B
+};
+
+/*
+ * @brief
+ * Unique Id for DDC handle.
+ * Values are meaningful (used as indexes to array)
+ */
+enum gpio_ddc_line {
+	GPIO_DDC_LINE_UNKNOWN = (-1),
+	GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_DDC2,
+	GPIO_DDC_LINE_DDC3,
+	GPIO_DDC_LINE_DDC4,
+	GPIO_DDC_LINE_DDC5,
+	GPIO_DDC_LINE_DDC6,
+	GPIO_DDC_LINE_DDC_VGA,
+	GPIO_DDC_LINE_VIP_PAD,
+	GPIO_DDC_LINE_I2C_PAD = GPIO_DDC_LINE_VIP_PAD,
+	GPIO_DDC_LINE_COUNT,
+	GPIO_DDC_LINE_MIN = GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_MAX = GPIO_DDC_LINE_I2C_PAD
+};
+
+/*
+ * @brief
+ * Identifies the mode of operation to open a GPIO device.
+ * A GPIO device (pin) can be programmed in only one of these modes at a time.
+ */
+enum gpio_mode {
+	GPIO_MODE_UNKNOWN = (-1),
+	GPIO_MODE_INPUT,
+	GPIO_MODE_OUTPUT,
+	GPIO_MODE_FAST_OUTPUT,
+	GPIO_MODE_HARDWARE,
+	GPIO_MODE_INTERRUPT
+};
+
+/*
+ * @brief
+ * Identifies the source of the signal when GPIO is in HW mode.
+ * get_signal_source() will return GPIO_SYGNAL_SOURCE__UNKNOWN
+ * when one of the following holds:
+ *    1. GPIO is input GPIO
+ *    2. GPIO is not opened in HW mode
+ *    3. GPIO does not have fixed signal source
+ *    (like DC_GenericA have mux instead fixed)
+ */
+enum gpio_signal_source {
+	GPIO_SIGNAL_SOURCE_UNKNOWN = (-1),
+	GPIO_SIGNAL_SOURCE_DACA_STEREO_SYNC,
+	GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC,
+	GPIO_SIGNAL_SOURCE_DACB_STEREO_SYNC,
+	GPIO_SIGNAL_SOURCE_DACA_HSYNC,
+	GPIO_SIGNAL_SOURCE_DACB_HSYNC,
+	GPIO_SIGNAL_SOURCE_DACA_VSYNC,
+	GPIO_SIGNAL_SOURCE_DACB_VSYNC,
+};
+
+enum gpio_stereo_source {
+	GPIO_STEREO_SOURCE_UNKNOWN = (-1),
+	GPIO_STEREO_SOURCE_D1,
+	GPIO_STEREO_SOURCE_D2,
+	GPIO_STEREO_SOURCE_D3,
+	GPIO_STEREO_SOURCE_D4,
+	GPIO_STEREO_SOURCE_D5,
+	GPIO_STEREO_SOURCE_D6
+};
+
+/*
+ * GPIO config
+ */
+
+enum gpio_config_type {
+	GPIO_CONFIG_TYPE_NONE,
+	GPIO_CONFIG_TYPE_DDC,
+	GPIO_CONFIG_TYPE_HPD,
+	GPIO_CONFIG_TYPE_GENERIC_MUX,
+	GPIO_CONFIG_TYPE_GSL_MUX,
+	GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE
+};
+
+/* DDC configuration */
+
+enum gpio_ddc_config_type {
+	GPIO_DDC_CONFIG_TYPE_MODE_AUX,
+	GPIO_DDC_CONFIG_TYPE_MODE_I2C,
+	GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT,
+	GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT,
+	GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING
+};
+
+struct gpio_ddc_config {
+	enum gpio_ddc_config_type type;
+	bool data_en_bit_present;
+	bool clock_en_bit_present;
+};
+
+/* HPD configuration */
+
+struct gpio_hpd_config {
+	uint32_t delay_on_connect; /* milliseconds */
+	uint32_t delay_on_disconnect; /* milliseconds */
+};
+
+struct gpio_generic_mux_config {
+	bool enable_output_from_mux;
+	enum gpio_signal_source mux_select;
+	enum gpio_stereo_source stereo_select;
+};
+
+enum gpio_gsl_mux_config_type {
+	GPIO_GSL_MUX_CONFIG_TYPE_DISABLE,
+	GPIO_GSL_MUX_CONFIG_TYPE_TIMING_SYNC,
+	GPIO_GSL_MUX_CONFIG_TYPE_FLIP_SYNC
+};
+
+struct gpio_gsl_mux_config {
+	enum gpio_gsl_mux_config_type type;
+	/* Actually sync_source type,
+	 * however we want to avoid inter-component includes here */
+	uint32_t gsl_group;
+};
+
+struct gpio_config_data {
+	enum gpio_config_type type;
+	union {
+		struct gpio_ddc_config ddc;
+		struct gpio_hpd_config hpd;
+		struct gpio_generic_mux_config generic_mux;
+		struct gpio_gsl_mux_config gsl_mux;
+	} config;
+};
+
+struct gpio_ddc_hw_info {
+	bool hw_supported;
+	uint32_t ddc_channel;
+};
+
+struct gpio_ddc_open_options {
+	bool en_bit_present;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_csc_types.h b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h
new file mode 100644
index 000000000000..711b458ff564
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_CSC_TYPES_H__
+#define __DAL_GRPH_CSC_TYPES_H__
+
+#include "set_mode_types.h"
+
+enum color_space {
+	COLOR_SPACE_UNKNOWN,
+	COLOR_SPACE_SRGB_FULL_RANGE,
+	COLOR_SPACE_SRGB_LIMITED_RANGE,
+	COLOR_SPACE_YPBPR601,
+	COLOR_SPACE_YPBPR709,
+	COLOR_SPACE_YCBCR601,
+	COLOR_SPACE_YCBCR709,
+	COLOR_SPACE_YCBCR601_YONLY,
+	COLOR_SPACE_YCBCR709_YONLY,
+	COLOR_SPACE_N_MVPU_SUPER_AA,
+};
+
+enum grph_color_adjust_option {
+	GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
+	GRPH_COLOR_MATRIX_SW
+};
+
+enum grph_csc_adjust_item {
+	GRPH_ADJUSTMENT_CONTRAST = 1,
+	GRPH_ADJUSTMENT_SATURATION,
+	GRPH_ADJUSTMENT_BRIGHTNESS,
+	GRPH_ADJUSTMENT_HUE,
+	GRPH_ADJUSTMENT_COLOR_TEMPERATURE
+};
+
+#define CSC_TEMPERATURE_MATRIX_SIZE 9
+
+enum graphics_csc_adjust_type {
+	GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0,
+	GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */
+	GRAPHICS_CSC_ADJUST_TYPE_SW  /*use adjustments */
+};
+
+enum graphics_gamut_adjust_type {
+	GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS = 0,
+	GRAPHICS_GAMUT_ADJUST_TYPE_HW, /* without adjustments */
+	GRAPHICS_GAMUT_ADJUST_TYPE_SW  /* use adjustments */
+};
+
+struct grph_csc_adjustment {
+	enum grph_color_adjust_option color_adjust_option;
+	enum color_space c_space;
+	int32_t grph_cont;
+	int32_t grph_sat;
+	int32_t grph_bright;
+	int32_t grph_hue;
+	int32_t adjust_divider;
+	int32_t temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE];
+	int32_t temperature_divider;
+	uint32_t lb_color_depth;
+	uint8_t gamma; /* gamma from Edid */
+	enum dc_color_depth color_depth; /* clean up to uint32_t */
+	enum pixel_format surface_pixel_format;
+	enum graphics_csc_adjust_type   csc_adjust_type;
+	enum graphics_gamut_adjust_type gamut_adjust_type;
+};
+
+struct default_adjustment {
+	uint32_t lb_color_depth;
+	enum color_space color_space;
+	enum dc_color_depth color_depth;
+	enum pixel_format surface_pixel_format;
+	enum graphics_csc_adjust_type csc_adjust_type;
+	bool force_hw_default;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
new file mode 100644
index 000000000000..2ed01bd43c37
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
@@ -0,0 +1,593 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_OBJECT_CTRL_DEFS_H__
+#define __DAL_GRPH_OBJECT_CTRL_DEFS_H__
+
+#include "grph_object_defs.h"
+
+/*
+ * #####################################################
+ * #####################################################
+ *
+ * These defines shared between asic_control/bios_parser and other
+ * DAL components
+ *
+ * #####################################################
+ * #####################################################
+ */
+
+enum tv_standard {
+	TV_STANDARD_UNKNOWN = 0, /* direct HW (mmBIOS_SCRATCH_2) translation! */
+	TV_STANDARD_NTSC,
+	TV_STANDARD_NTSCJ,
+	TV_STANDARD_PAL,
+	TV_STANDARD_PALM,
+	TV_STANDARD_PALCN,
+	TV_STANDARD_PALN,
+	TV_STANDARD_PAL60,
+	TV_STANDARD_SECAM
+};
+
+enum cv_standard {
+	CV_STANDARD_UNKNOWN = 0x0000,
+	CV_STANDARD_HD_MASK = 0x0800,		/* Flag mask HDTV output */
+	CV_STANDARD_SD_NTSC_MASK = 0x1000,	/* Flag mask NTSC output */
+	CV_STANDARD_SD_NTSC_M,		/* NTSC (North America) output 1001 */
+	CV_STANDARD_SD_NTSC_J,		/* NTSC (Japan) output 1002 */
+	CV_STANDARD_SD_480I,		/* SDTV 480i output 1003 */
+	CV_STANDARD_SD_480P,		/* SDTV 480p output 1004 */
+	CV_STANDARD_HD_720_60P = 0x1800,/* HDTV 720/60p output 1800 */
+	CV_STANDARD_HD_1080_60I,	/* HDTV 1080/60i output 1801 */
+	CV_STANDARD_SD_PAL_MASK = 0x2000,/* Flag mask PAL output */
+	CV_STANDARD_SD_PAL_B,			/* PAL B output 2001 */
+	CV_STANDARD_SD_PAL_D,			/* PAL D output 2002 */
+	CV_STANDARD_SD_PAL_G,			/* PAL G output 2003 */
+	CV_STANDARD_SD_PAL_H,			/* PAL H output 2004 */
+	CV_STANDARD_SD_PAL_I,			/* PAL I output 2005 */
+	CV_STANDARD_SD_PAL_M,			/* PAL M output 2006 */
+	CV_STANDARD_SD_PAL_N,			/* PAL N output 2007 */
+	CV_STANDARD_SD_PAL_N_COMB,	/* PAL Combination N output 2008 */
+	CV_STANDARD_SD_PAL_60,		/* PAL 60 output (test mode) 2009 */
+	CV_STANDARD_SD_576I,		/* SDTV 576i output 2010 */
+	CV_STANDARD_SD_576P,		/* SDTV 576p output 2011 */
+	CV_STANDARD_HD_720_50P = 0x2800,/* HDTV 720/50p output 2800 */
+	CV_STANDARD_HD_1080_50I,	/* HDTV 1080/50i output 2801 */
+	CV_STANDARD_SD_SECAM_MASK = 0x4000, /* Flag mask SECAM output */
+	CV_STANDARD_SD_SECAM_B,		/* SECAM B output 4001 */
+	CV_STANDARD_SD_SECAM_D,		/* SECAM D output 4002 */
+	CV_STANDARD_SD_SECAM_G,		/* SECAM G output 4003 */
+	CV_STANDARD_SD_SECAM_H,		/* SECAM H output 4004 */
+	CV_STANDARD_SD_SECAM_K,		/* SECAM K output 4005 */
+	CV_STANDARD_SD_SECAM_K1,	/* SECAM K1 output 4006 */
+	CV_STANDARD_SD_SECAM_L,		/* SECAM L output 4007 */
+	CV_STANDARD_SD_SECAM_L1		/* SECAM L1 output 4009 */
+};
+
+enum display_output_bit_depth {
+	PANEL_UNDEFINE = 0,
+	PANEL_6BIT_COLOR = 1,
+	PANEL_8BIT_COLOR = 2,
+	PANEL_10BIT_COLOR = 3,
+	PANEL_12BIT_COLOR = 4,
+	PANEL_16BIT_COLOR = 5,
+};
+
+enum lcd_scale {
+	/* No request to turn on LCD SCALER (Centering or Replication) */
+	LCD_SCALE_NONE = 0,
+	/* Request LCD SCALER in full panel mode */
+	LCD_SCALE_FULLPANEL,
+	/* Request LCD SCALER in aspect-ratio mode */
+	LCD_SCALE_ASPECTRATIO,
+
+	LCD_SCALE_UNKNOWN = (-1L),
+};
+
+/* Device type as abstracted by ATOM BIOS */
+enum dal_device_type {
+	DEVICE_TYPE_UNKNOWN = 0,
+	DEVICE_TYPE_LCD,
+	DEVICE_TYPE_CRT,
+	DEVICE_TYPE_DFP,
+	DEVICE_TYPE_CV,
+	DEVICE_TYPE_TV,
+	DEVICE_TYPE_CF,
+	DEVICE_TYPE_WIRELESS
+};
+
+/* Device ID as abstracted by ATOM BIOS */
+struct device_id {
+	enum dal_device_type device_type:16;
+	uint32_t enum_id:16;	/* 1 based enum */
+};
+
+struct graphics_object_i2c_info {
+	struct gpio_info {
+		uint32_t clk_mask_register_index;
+		uint32_t clk_en_register_index;
+		uint32_t clk_y_register_index;
+		uint32_t clk_a_register_index;
+		uint32_t data_mask_register_index;
+		uint32_t data_en_register_index;
+		uint32_t data_y_register_index;
+		uint32_t data_a_register_index;
+
+		uint32_t clk_mask_shift;
+		uint32_t clk_en_shift;
+		uint32_t clk_y_shift;
+		uint32_t clk_a_shift;
+		uint32_t data_mask_shift;
+		uint32_t data_en_shift;
+		uint32_t data_y_shift;
+		uint32_t data_a_shift;
+	} gpio_info;
+
+	bool i2c_hw_assist;
+	uint32_t i2c_line;
+	uint32_t i2c_engine_id;
+	uint32_t i2c_slave_address;
+};
+
+
+struct graphics_object_hpd_info {
+	uint8_t hpd_int_gpio_uid;
+	uint8_t hpd_active;
+};
+
+struct connector_device_tag_info {
+	uint32_t acpi_device;
+	struct device_id dev_id;
+};
+
+struct device_timing {
+	struct misc_info {
+		uint32_t HORIZONTAL_CUT_OFF:1;
+		/* 0=Active High, 1=Active Low */
+		uint32_t H_SYNC_POLARITY:1;
+		/* 0=Active High, 1=Active Low */
+		uint32_t V_SYNC_POLARITY:1;
+		uint32_t VERTICAL_CUT_OFF:1;
+		uint32_t H_REPLICATION_BY2:1;
+		uint32_t V_REPLICATION_BY2:1;
+		uint32_t COMPOSITE_SYNC:1;
+		uint32_t INTERLACE:1;
+		uint32_t DOUBLE_CLOCK:1;
+		uint32_t RGB888:1;
+		uint32_t GREY_LEVEL:2;
+		uint32_t SPATIAL:1;
+		uint32_t TEMPORAL:1;
+		uint32_t API_ENABLED:1;
+	} misc_info;
+
+	uint32_t pixel_clk; /* in KHz */
+	uint32_t horizontal_addressable;
+	uint32_t horizontal_blanking_time;
+	uint32_t vertical_addressable;
+	uint32_t vertical_blanking_time;
+	uint32_t horizontal_sync_offset;
+	uint32_t horizontal_sync_width;
+	uint32_t vertical_sync_offset;
+	uint32_t vertical_sync_width;
+	uint32_t horizontal_border;
+	uint32_t vertical_border;
+};
+
+struct supported_refresh_rate {
+	uint32_t REFRESH_RATE_30HZ:1;
+	uint32_t REFRESH_RATE_40HZ:1;
+	uint32_t REFRESH_RATE_48HZ:1;
+	uint32_t REFRESH_RATE_50HZ:1;
+	uint32_t REFRESH_RATE_60HZ:1;
+};
+
+struct embedded_panel_info {
+	struct device_timing lcd_timing;
+	uint32_t ss_id;
+	struct supported_refresh_rate supported_rr;
+	uint32_t drr_enabled;
+	uint32_t min_drr_refresh_rate;
+};
+
+struct embedded_panel_patch_mode {
+	uint32_t width;
+	uint32_t height;
+};
+
+struct firmware_info {
+	struct pll_info {
+		uint32_t crystal_frequency; /* in KHz */
+		uint32_t min_input_pxl_clk_pll_frequency; /* in KHz */
+		uint32_t max_input_pxl_clk_pll_frequency; /* in KHz */
+		uint32_t min_output_pxl_clk_pll_frequency; /* in KHz */
+		uint32_t max_output_pxl_clk_pll_frequency; /* in KHz */
+	} pll_info;
+
+	struct firmware_feature {
+		uint32_t memory_clk_ss_percentage;
+		uint32_t engine_clk_ss_percentage;
+	} feature;
+
+	uint32_t default_display_engine_pll_frequency; /* in KHz */
+	uint32_t external_clock_source_frequency_for_dp; /* in KHz */
+	uint32_t smu_gpu_pll_output_freq; /* in KHz */
+	uint8_t min_allowed_bl_level;
+	uint8_t remote_display_config;
+};
+
+/* direct HW (mmBIOS_SCRATCH_2) translation! */
+union tv_standard_support {
+	uint8_t u_all;
+	struct {
+		bool TV_SUPPORT_NTSC:1;
+		bool TV_SUPPORT_NTSCJ:1;
+
+		bool TV_SUPPORT_PAL:1;
+		bool TV_SUPPORT_PALM:1;
+		bool TV_SUPPORT_PALCN:1;
+		bool TV_SUPPORT_PALN:1;
+		bool TV_SUPPORT_PAL60:1;
+
+		bool TV_SUPPORT_SECAM:1;
+	} bits;
+};
+
+struct analog_tv_info {
+	union tv_standard_support tv_suppported;
+	union tv_standard_support tv_boot_up_default;
+};
+
+struct step_and_delay_info {
+    uint32_t step;
+    uint32_t delay;
+    uint32_t recommended_ref_div;
+};
+
+struct spread_spectrum_info {
+	struct spread_spectrum_type {
+		bool CENTER_MODE:1;
+		bool EXTERNAL:1;
+		bool STEP_AND_DELAY_INFO:1;
+	} type;
+
+	/* in unit of 0.01% (spreadPercentageDivider = 100),
+	otherwise in 0.001% units (spreadPercentageDivider = 1000); */
+	uint32_t spread_spectrum_percentage;
+	uint32_t spread_percentage_divider; /* 100 or 1000 */
+	uint32_t spread_spectrum_range; /* modulation freq (HZ)*/
+
+	union {
+		struct step_and_delay_info step_and_delay_info;
+		/* For mem/engine/uvd, Clock Out frequence (VCO ),
+		in unit of kHz. For TMDS/HDMI/LVDS, it is pixel clock,
+		for DP, it is link clock ( 270000 or 162000 ) */
+		uint32_t target_clock_range; /* in KHz */
+	};
+
+};
+
+struct graphics_object_encoder_cap_info {
+	uint32_t dp_hbr2_cap:1;
+	uint32_t dp_hbr2_validated:1;
+	uint32_t reserved:15;
+};
+
+struct din_connector_info {
+	uint32_t gpio_id;
+	bool gpio_tv_active_state;
+};
+
+/* Invalid channel mapping */
+enum { INVALID_DDI_CHANNEL_MAPPING = 0x0 };
+
+/**
+ * DDI PHY channel mapping reflecting XBAR setting
+ */
+union ddi_channel_mapping {
+	struct mapping {
+		uint8_t lane0:2;	/* Mapping for lane 0 */
+		uint8_t lane1:2;	/* Mapping for lane 1 */
+		uint8_t lane2:2;	/* Mapping for lane 2 */
+		uint8_t lane3:2;	/* Mapping for lane 3 */
+	} mapping;
+	uint8_t raw;
+};
+
+/**
+* Transmitter output configuration description
+*/
+struct transmitter_configuration_info {
+	/* DDI PHY ID for the transmitter */
+	enum transmitter transmitter_phy_id;
+	/* DDI PHY channel mapping reflecting crossbar setting */
+	union ddi_channel_mapping output_channel_mapping;
+};
+
+struct transmitter_configuration {
+	/* Configuration for the primary transmitter */
+	struct transmitter_configuration_info primary_transmitter_config;
+	/* Secondary transmitter configuration for Dual-link DVI */
+	struct transmitter_configuration_info secondary_transmitter_config;
+};
+
+
+/* These size should be sufficient to store info coming from BIOS */
+#define NUMBER_OF_UCHAR_FOR_GUID 16
+#define MAX_NUMBER_OF_EXT_DISPLAY_PATH 7
+#define NUMBER_OF_CSR_M3_ARB 10
+#define NUMBER_OF_DISP_CLK_VOLTAGE 4
+#define NUMBER_OF_AVAILABLE_SCLK 5
+
+/* V6 */
+struct integrated_info {
+	struct clock_voltage_caps {
+		/* The Voltage Index indicated by FUSE, same voltage index
+		shared with SCLK DPM fuse table */
+		uint32_t voltage_index;
+		/* Maximum clock supported with specified voltage index */
+		uint32_t max_supported_clk; /* in KHz */
+	} disp_clk_voltage[NUMBER_OF_DISP_CLK_VOLTAGE];
+
+	struct display_connection_info {
+		struct external_display_path {
+			/* A bit vector to show what devices are supported */
+			uint32_t device_tag;
+			/* 16bit device ACPI id. */
+			uint32_t device_acpi_enum;
+			/* A physical connector for displays to plug in,
+			using object connector definitions */
+			struct graphics_object_id device_connector_id;
+			/* An index into external AUX/DDC channel LUT */
+			uint8_t ext_aux_ddc_lut_index;
+			/* An index into external HPD pin LUT */
+			uint8_t ext_hpd_pin_lut_index;
+			/* external encoder object id */
+			struct graphics_object_id ext_encoder_obj_id;
+			/* XBAR mapping of the PHY channels */
+			union ddi_channel_mapping channel_mapping;
+		} path[MAX_NUMBER_OF_EXT_DISPLAY_PATH];
+
+		uint8_t gu_id[NUMBER_OF_UCHAR_FOR_GUID];
+		uint8_t checksum;
+	} ext_disp_conn_info; /* exiting long long time */
+
+	struct available_s_clk_list {
+		/* Maximum clock supported with specified voltage index */
+		uint32_t supported_s_clk; /* in KHz */
+		/* The Voltage Index indicated by FUSE for specified SCLK */
+		uint32_t voltage_index;
+		/* The Voltage ID indicated by FUSE for specified SCLK */
+		uint32_t voltage_id;
+	} avail_s_clk[NUMBER_OF_AVAILABLE_SCLK];
+
+	uint8_t memory_type;
+	uint8_t ma_channel_number;
+	uint32_t boot_up_engine_clock; /* in KHz */
+	uint32_t dentist_vco_freq; /* in KHz */
+	uint32_t boot_up_uma_clock; /* in KHz */
+	uint32_t boot_up_req_display_vector;
+	uint32_t other_display_misc;
+	uint32_t gpu_cap_info;
+	uint32_t sb_mmio_base_addr;
+	uint32_t system_config;
+	uint32_t cpu_cap_info;
+	uint32_t max_nb_voltage;
+	uint32_t min_nb_voltage;
+	uint32_t boot_up_nb_voltage;
+	uint32_t ext_disp_conn_info_offset;
+	uint32_t csr_m3_arb_cntl_default[NUMBER_OF_CSR_M3_ARB];
+	uint32_t csr_m3_arb_cntl_uvd[NUMBER_OF_CSR_M3_ARB];
+	uint32_t csr_m3_arb_cntl_fs3d[NUMBER_OF_CSR_M3_ARB];
+	uint32_t gmc_restore_reset_time;
+	uint32_t minimum_n_clk;
+	uint32_t idle_n_clk;
+	uint32_t ddr_dll_power_up_time;
+	uint32_t ddr_pll_power_up_time;
+	/* start for V6 */
+	uint32_t pcie_clk_ss_type;
+	uint32_t lvds_ss_percentage;
+	uint32_t lvds_sspread_rate_in_10hz;
+	uint32_t hdmi_ss_percentage;
+	uint32_t hdmi_sspread_rate_in_10hz;
+	uint32_t dvi_ss_percentage;
+	uint32_t dvi_sspread_rate_in_10_hz;
+	uint32_t sclk_dpm_boost_margin;
+	uint32_t sclk_dpm_throttle_margin;
+	uint32_t sclk_dpm_tdp_limit_pg;
+	uint32_t sclk_dpm_tdp_limit_boost;
+	uint32_t boost_engine_clock;
+	uint32_t boost_vid_2bit;
+	uint32_t enable_boost;
+	uint32_t gnb_tdp_limit;
+	/* Start from V7 */
+	uint32_t max_lvds_pclk_freq_in_single_link;
+	uint32_t lvds_misc;
+	uint32_t lvds_pwr_on_seq_dig_on_to_de_in_4ms;
+	uint32_t lvds_pwr_on_seq_de_to_vary_bl_in_4ms;
+	uint32_t lvds_pwr_off_seq_vary_bl_to_de_in4ms;
+	uint32_t lvds_pwr_off_seq_de_to_dig_on_in4ms;
+	uint32_t lvds_off_to_on_delay_in_4ms;
+	uint32_t lvds_pwr_on_seq_vary_bl_to_blon_in_4ms;
+	uint32_t lvds_pwr_off_seq_blon_to_vary_bl_in_4ms;
+	uint32_t lvds_reserved1;
+	uint32_t lvds_bit_depth_control_val;
+};
+
+/**
+* Power source ids.
+*/
+enum power_source {
+	POWER_SOURCE_AC = 0,
+	POWER_SOURCE_DC,
+	POWER_SOURCE_LIMITED_POWER,
+	POWER_SOURCE_LIMITED_POWER_2,
+	POWER_SOURCE_MAX
+};
+
+struct bios_event_info {
+	uint32_t thermal_state;
+	uint32_t backlight_level;
+	enum power_source powerSource;
+	bool has_thermal_state_changed;
+	bool has_power_source_changed;
+	bool has_forced_mode_changed;
+	bool forced_mode;
+	bool backlight_changed;
+};
+
+union stereo_3d_support {
+	struct {
+		/* HW can alter left and right image sequentially */
+		uint32_t FRAME_ALTERNATE:1;
+		/* Frame Alternate + HW can integrate stereosync
+		signal into TMDS stream */
+		uint32_t DVI_FRAME_ALT:1;
+		/* Frame Alternate + HW can integrate stereosync
+		signal into DP stream */
+		uint32_t DISPLAY_PORT_FRAME_ALT:1;
+		/* Frame Alternate + HW can drive stereosync signal
+		on separate line */
+		uint32_t SIDEBAND_FRAME_ALT:1;
+		/* SW allowed to pack left and right image into single frame.
+		Used for HDMI only, DP has it's own flags. */
+		uint32_t SW_FRAME_PACK:1;
+		/* HW can pack left and right image into single HDMI frame */
+		uint32_t PROGRESSIVE_FRAME_PACK:1;
+		/* HW can pack left and right interlaced images into
+		single HDMI frame */
+		uint32_t INTERLACE_FRAME_PACK:1;
+		/* HW can pack left and right images into single DP frame */
+		uint32_t DISPLAY_PORT_FRAME_PACK:1;
+		/* SW can pack left and right images into single DP frame */
+		uint32_t DISPLAY_PORT_SW_FRAME_PACK:1;
+		/* HW can mix left and right images into single image */
+		uint32_t INTERLEAVE:1;
+		/* HW can mix left and right interlaced images
+		into single image */
+		uint32_t INTERLACE_INTERLEAVE:1;
+		/* Allow display-based formats (whatever supported)
+		in WS stereo mode */
+		uint32_t DISPLAY_3DIN_WS_MODE:1;
+		/* Side-by-side, packed by application/driver into 2D frame */
+		uint32_t SIDE_BY_SIDE_SW_PACKED:1;
+		/* Top-and-bottom, packed by application/driver into 2D frame */
+		uint32_t TOP_AND_BOTTOM_SW_PACKED:1;
+	} bits;
+	uint32_t u_all;
+};
+
+/* Bitvector and bitfields of possible optimizations
+ #IMPORTANT# Keep bitfields match bitvector! */
+enum optimization_feature {
+	/* Don't do HW programming on panels that were enabled by VBIOS */
+	OF_SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY = 0x1,
+	OF_SKIP_RESET_OF_ALL_HW_ON_S3RESUME = 0x2,
+	OF_SKIP_HW_RESET_OF_EMBEDDED_DISPLAY_ON_S3RESUME = 0x4,
+	OF_SKIP_POWER_UP_VBIOS_ENABLED_ENCODER = 0x8,
+	/* Do not turn off VCC while powering down on boot or resume */
+	OF_KEEP_VCC_DURING_POWER_DOWN_ON_BOOT_OR_RESUME = 0x10,
+	/* Do not turn off VCC while performing SetMode */
+	OF_KEEP_VCC_DURING_SET_MODE = 0x20,
+	OF_DO_NOT_WAIT_FOR_HPD_LOW = 0x40,
+	OF_SKIP_POWER_DOWN_INACTIVE_ENCODER = 0x80
+};
+
+union optimization_flags {
+	struct {
+		/* Don't do HW programming if panels were enabled by VBIOS */
+		uint32_t SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY:1;
+		uint32_t SKIP_RESET_OF_ALL_HW_ON_S3RESUME:1;
+		uint32_t SKIP_HW_RESET_OF_EMBEDDED_DISPLAY_ON_S3RESUME:1;
+		uint32_t SKIP_POWER_UP_VBIOS_ENABLED_ENCODER:1;
+		/* Do not turn off VCC while powering down on boot or resume */
+		uint32_t KEEP_VCC_DURING_POWER_DOWN_ON_BOOT_OR_RESUME:1;
+		/* Do not turn off VCC while performing SetMode */
+		uint32_t KEEP_VCC_DURING_SET_MODE:1;
+		uint32_t DO_NOT_WAIT_FOR_HPD_LOW:1;
+	} bits;
+	uint32_t u_all;
+};
+
+/* Bitvector and bitfields of performance measurements
+ #IMPORTANT# Keep bitfields match bitvector! */
+enum perf_measure {
+	PERF_MEASURE_ADAPTER_POWER_STATE = 0x1,
+	PERF_MEASURE_DISPLAY_POWER_STATE = 0x2,
+	PERF_MEASURE_SET_MODE_SEQ = 0x4,
+	PERF_MEASURE_DETECT_AT_RESUME = 0x8,
+	PERF_MEASURE_MEMORY_READ_CONTROL = 0x10,
+};
+
+union perf_measure_flags {
+	struct {
+		uint32_t ADAPTER_POWER_STATE:1;
+		uint32_t DISPLAY_POWER_STATE:1;
+		uint32_t SET_MODE_SEQ:1;
+		uint32_t DETECT_AT_RESUME:1;
+		uint32_t MEMORY_READ_CONTROL:1;
+
+	} bits;
+	uint32_t u_all;
+};
+
+enum {
+	PERF_MEASURE_POWERCODE_OFFSET = 0x0,
+	PERF_MEASURE_POWER_CODE_MASK = 0xFF,
+	PERF_MEASURE_POWER_STATE_OFFSET = 8,
+	PERF_MEASURE_POWER_STATE_MASK = 0x000FF00,
+	PERF_MEASURE_PREV_POWER_STATE_OFFSET = 16,
+	PERF_MEASURE_PREV_POWER_STATE_MASK = 0x00FF0000,
+	PERF_MEASURE_DISPLAY_INDEX_OFFSET = 24,
+	PERF_MEASURE_DISPLAY_INDEX_MASK = 0xFF000000
+};
+
+enum {
+	HDMI_PIXEL_CLOCK_IN_KHZ_297 = 297000,
+	TMDS_PIXEL_CLOCK_IN_KHZ_165 = 165000
+};
+
+/*
+ * DFS-bypass flag
+ */
+/* Copy of SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS from atombios.h */
+enum {
+	DFS_BYPASS_ENABLE = 0x10
+};
+
+enum {
+	INVALID_BACKLIGHT = -1
+};
+
+struct panel_backlight_boundaries {
+	uint32_t min_signal_level;
+	uint32_t max_signal_level;
+};
+
+struct panel_backlight_default_levels {
+	uint32_t ac_level_percentage;
+	uint32_t dc_level_percentage;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_defs.h b/drivers/gpu/drm/amd/dal/include/grph_object_defs.h
new file mode 100644
index 000000000000..a1e468fbbb2b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_object_defs.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_OBJECT_DEFS_H__
+#define __DAL_GRPH_OBJECT_DEFS_H__
+
+#include "grph_object_id.h"
+
+/* ********************************************************************
+ * ********************************************************************
+ *
+ *  These defines shared between All Graphics Objects
+ *
+ * ********************************************************************
+ * ********************************************************************
+ */
+
+/* HPD unit id - HW direct translation */
+enum hpd_source_id {
+	HPD_SOURCEID1 = 0,
+	HPD_SOURCEID2,
+	HPD_SOURCEID3,
+	HPD_SOURCEID4,
+	HPD_SOURCEID5,
+	HPD_SOURCEID6,
+
+	HPD_SOURCEID_COUNT,
+	HPD_SOURCEID_UNKNOWN
+};
+
+/* DDC unit id - HW direct translation */
+enum channel_id {
+	CHANNEL_ID_UNKNOWN = 0,
+	CHANNEL_ID_DDC1,
+	CHANNEL_ID_DDC2,
+	CHANNEL_ID_DDC3,
+	CHANNEL_ID_DDC4,
+	CHANNEL_ID_DDC5,
+	CHANNEL_ID_DDC6,
+	CHANNEL_ID_DDC_VGA,
+	CHANNEL_ID_I2C_PAD,
+	CHANNEL_ID_COUNT
+};
+
+#define DECODE_CHANNEL_ID(ch_id) \
+	(ch_id) == CHANNEL_ID_DDC1 ? "CHANNEL_ID_DDC1" : \
+	(ch_id) == CHANNEL_ID_DDC2 ? "CHANNEL_ID_DDC2" : \
+	(ch_id) == CHANNEL_ID_DDC3 ? "CHANNEL_ID_DDC3" : \
+	(ch_id) == CHANNEL_ID_DDC4 ? "CHANNEL_ID_DDC4" : \
+	(ch_id) == CHANNEL_ID_DDC5 ? "CHANNEL_ID_DDC5" : \
+	(ch_id) == CHANNEL_ID_DDC6 ? "CHANNEL_ID_DDC6" : \
+	(ch_id) == CHANNEL_ID_DDC_VGA ? "CHANNEL_ID_DDC_VGA" : \
+	(ch_id) == CHANNEL_ID_I2C_PAD ? "CHANNEL_ID_I2C_PAD" : "Invalid"
+
+enum transmitter {
+	TRANSMITTER_UNKNOWN = (-1L),
+	TRANSMITTER_UNIPHY_A,
+	TRANSMITTER_UNIPHY_B,
+	TRANSMITTER_UNIPHY_C,
+	TRANSMITTER_UNIPHY_D,
+	TRANSMITTER_UNIPHY_E,
+	TRANSMITTER_UNIPHY_F,
+	TRANSMITTER_NUTMEG_CRT,
+	TRANSMITTER_TRAVIS_CRT,
+	TRANSMITTER_TRAVIS_LCD,
+	TRANSMITTER_UNIPHY_G,
+	TRANSMITTER_COUNT
+};
+
+enum physical_phy_id {
+	PHY_ID_UNKNOWN = (-1L),
+	PHY_ID_0,
+	PHY_ID_1,
+	PHY_ID_2,
+	PHY_ID_3,
+	PHY_ID_4,
+	PHY_ID_5,
+	PHY_ID_6,
+	PHY_ID_7,
+	PHY_ID_8,
+	PHY_ID_9,
+	PHY_ID_COUNT
+};
+
+/* Generic source of the synchronisation input/output signal */
+/* Can be used for flow control, stereo sync, timing sync, frame sync, etc */
+enum sync_source {
+	SYNC_SOURCE_NONE = 0,
+
+	/* Source based on controllers */
+	SYNC_SOURCE_CONTROLLER0,
+	SYNC_SOURCE_CONTROLLER1,
+	SYNC_SOURCE_CONTROLLER2,
+	SYNC_SOURCE_CONTROLLER3,
+	SYNC_SOURCE_CONTROLLER4,
+	SYNC_SOURCE_CONTROLLER5,
+
+	/* Source based on GSL group */
+	SYNC_SOURCE_GSL_GROUP0,
+	SYNC_SOURCE_GSL_GROUP1,
+	SYNC_SOURCE_GSL_GROUP2,
+
+	/* Source based on GSL IOs */
+	/* These IOs normally used as GSL input/output */
+	SYNC_SOURCE_GSL_IO_FIRST,
+	SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK = SYNC_SOURCE_GSL_IO_FIRST,
+	SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC,
+	SYNC_SOURCE_GSL_IO_SWAPLOCK_A,
+	SYNC_SOURCE_GSL_IO_SWAPLOCK_B,
+	SYNC_SOURCE_GSL_IO_LAST = SYNC_SOURCE_GSL_IO_SWAPLOCK_B,
+
+	/* Source based on regular IOs */
+	SYNC_SOURCE_IO_FIRST,
+	SYNC_SOURCE_IO_GENERIC_A = SYNC_SOURCE_IO_FIRST,
+	SYNC_SOURCE_IO_GENERIC_B,
+	SYNC_SOURCE_IO_GENERIC_C,
+	SYNC_SOURCE_IO_GENERIC_D,
+	SYNC_SOURCE_IO_GENERIC_E,
+	SYNC_SOURCE_IO_GENERIC_F,
+	SYNC_SOURCE_IO_HPD1,
+	SYNC_SOURCE_IO_HPD2,
+	SYNC_SOURCE_IO_HSYNC_A,
+	SYNC_SOURCE_IO_VSYNC_A,
+	SYNC_SOURCE_IO_HSYNC_B,
+	SYNC_SOURCE_IO_VSYNC_B,
+	SYNC_SOURCE_IO_LAST = SYNC_SOURCE_IO_VSYNC_B,
+
+	/* Misc. flow control sources */
+	SYNC_SOURCE_DUAL_GPU_PIN
+};
+
+enum trigger_edge {
+	TRIGGER_EDGE_RISING = 0,
+	TRIGGER_EDGE_FALLING,
+	TRIGGER_EDGE_BOTH,
+	TRIGGER_EDGE_DEFAULT
+};
+
+/* Parameters to enable CRTC trigger */
+struct trigger_params {
+	enum sync_source source;
+	enum trigger_edge edge;
+};
+
+/* CRTC Static Screen event triggers */
+struct static_screen_events {
+	union {
+		/* event mask to enable/disable various
+		   trigger sources for static screen detection */
+		struct {
+			/* Force event high */
+			uint32_t FRAME_START:1;
+			/* Cursor register change */
+			uint32_t CURSOR_MOVE:1;
+			/* Memory write to any client other than MCIF */
+			uint32_t MEM_WRITE:1;
+			/* Memory write to hit memory region 0 */
+			uint32_t MEM_REGION0_WRITE:1;
+			/* Memory write to hit memory region 1 */
+			uint32_t MEM_REGION1_WRITE:1;
+			/* Memory write to hit memory region 2 */
+			uint32_t MEM_REGION2_WRITE:1;
+			/* Memory write to hit memory region 3 */
+			uint32_t MEM_REGION3_WRITE:1;
+			/* Graphics Surface Update Pending */
+			uint32_t GFX_UPDATE:1;
+			/* Overlay Surface Update Pending */
+			uint32_t OVL_UPDATE:1;
+			/* Compressed surface invalidated in FBC */
+			uint32_t INVALIDATE_FBC_SURFACE:1;
+			/* Register pending update in any double buffered
+			register group in the display pipe
+			(i.e. Blender, DCP, or SCL) */
+			uint32_t REG_PENDING_UPDATE:1;
+			/* Crtc_trig_a: Based on signal from any other CRTC */
+			uint32_t CRTC_TRIG_A:1;
+			/* Crtc_trig_b: Based on signal from any other CRTC */
+			uint32_t CRTC_TRIG_B:1;
+			/* Readback of CRTC nominal vertical count register
+			by driver  indicates that OS may be trying to change
+			mode or contents of the display therefore need to
+			switch to higher refresh rate */
+			uint32_t READBACK_NOMINAL_VERTICAL:1;
+			/* Readback of CRTC dynamic vertical count register
+			by driver  indicates that OS may be trying to change
+			mode or contents of the display therefore need to
+			switch to higher refresh rate */
+			uint32_t READBACK_DYNAMIC_VERTICAL:1;
+			/* Reserved */
+			uint32_t RESERVED:1;
+		} bits;
+		uint32_t u_all;
+	};
+};
+
+
+/*
+ * ***************************************************************
+ * ********************* Register programming sequences ********
+ * ***************************************************************
+ */
+
+/* GPIO/Register access sequences */
+enum io_register_sequence {
+	/* GLSync sequences to access SwapReady & SwapRequest
+	GPIOs - GLSync Connector parameter */
+	IO_REG_SEQUENCE_SWAPREADY_SET = 0,
+	IO_REG_SEQUENCE_SWAPREADY_RESET,
+	IO_REG_SEQUENCE_SWAPREADY_READ,
+	IO_REG_SEQUENCE_SWAPREQUEST_SET,
+	IO_REG_SEQUENCE_SWAPREQUEST_RESET,
+	IO_REG_SEQUENCE_SWAPREQUEST_READ,
+
+	/* Frame synchronization start/stop - display index parameter */
+	IO_REG_SEQUENCE_FRAMELOCK_STOP,
+	IO_REG_SEQUENCE_FRAMELOCK_START,
+
+	/* Flip lock/unlock - GLSync Connector parameter */
+	IO_REG_SEQUENCE_GLOBALSWAP_LOCK,
+	IO_REG_SEQUENCE_GLOBALSWAP_UNLOCK,
+
+	IO_REG_SEQUENCEENUM_MAX
+};
+
+#define IO_REGISTER_SEQUENCE_MAX_LENGTH 5
+
+/*
+ *****************************************************************************
+ *                             struct io_register
+ *****************************************************************************
+ * Generic struct for read/write register or GPIO.
+ * It allows controlling only some bit section of register, rather then the
+ * whole one.
+ * For write operation should be used as following:
+ *   1. data  = READ(Base + RegisterOffset)
+ *   2. data &= ANDMask
+ *   3. data |= ORMask
+ *   4. WRITE(Base + RegisterOffset, data)
+ *
+ * Note: In case of regular register, ANDMask will be typically 0.
+ *	In case of GPIO, ANDMask will have typically all bits set
+ *	except the specific GPIO bit.
+ *
+ * For read operation should be used as following:
+ *   1. data   = READ(Base + RegisterOffset)
+ *   2. data  &= ANDMask
+ *   3. data >>= BitShift
+ *
+ * Note: In case of regular register, ANDMask will be typically 0xFFFFFFFF.
+ *	In case of GPIO, ANDMask will have typically only specific GPIO bit set
+ *
+ * Note: Base Address is not exposed in this structure due to
+ *	security consideration.
+ */
+
+/*
+ * The generic sequence to program/access registers or GPIOs.
+ * There could be 2 types of sequences - read and write.
+ * Read sequence may have 0 or more writes and in the end one read
+ * Write sequence may have 1 or more writes.
+ */
+struct io_reg_sequence {
+	/* Ordered array of register to program */
+	struct {
+		/* Offset of memory mapped register or GPIO */
+		uint32_t register_offset;
+		/* Mask to use at AND operation (Mandatory, comes
+		before OR operation) */
+		uint32_t and_mask;
+		union {
+			/* Mask to use at OR operation (For write
+			sequence only, comes after AND operation) */
+			uint32_t or_mask;
+			/* Number of bits to shift to get the actual value
+			(For read  sequence only, comes after AND operation) */
+			uint32_t bit_shift;
+		};
+	} io_registers[IO_REGISTER_SEQUENCE_MAX_LENGTH];
+
+	uint32_t steps_num; /* Total number of r/w steps in the sequence */
+};
+
+/* Sequence ID - uniqly defines sequence on single adapter */
+struct io_reg_sequence_id {
+	enum io_register_sequence sequence; /* Sequence enumeration Index/ID */
+	union {
+		/* Refers to object to which the sequence applies.*/
+		uint32_t index;
+		uint32_t display_index;
+		uint32_t controller_index;
+		uint32_t glsync_connector_index;
+	};
+};
+
+struct fbc_info {
+	bool fbc_enable;
+	bool lpt_enable;
+};
+
+/* Event to request TM change IRQ registration state */
+struct hotplug_irq_data {
+	bool disable;
+	struct graphics_object_id connector;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_id.h b/drivers/gpu/drm/amd/dal/include/grph_object_id.h
new file mode 100644
index 000000000000..372e46c9f0dd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_object_id.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_OBJECT_ID_H__
+#define __DAL_GRPH_OBJECT_ID_H__
+
+/* Types of graphics objects */
+enum object_type {
+	OBJECT_TYPE_UNKNOWN  = 0,
+
+	/* Direct ATOM BIOS translation */
+	OBJECT_TYPE_GPU,
+	OBJECT_TYPE_ENCODER,
+	OBJECT_TYPE_CONNECTOR,
+	OBJECT_TYPE_ROUTER,
+	OBJECT_TYPE_GENERIC,
+
+	/* Driver specific */
+	OBJECT_TYPE_AUDIO,
+	OBJECT_TYPE_CONTROLLER,
+	OBJECT_TYPE_CLOCK_SOURCE,
+	OBJECT_TYPE_ENGINE,
+
+	OBJECT_TYPE_COUNT
+};
+
+/* Enumeration inside one type of graphics objects */
+enum object_enum_id {
+	ENUM_ID_UNKNOWN = 0,
+	ENUM_ID_1,
+	ENUM_ID_2,
+	ENUM_ID_3,
+	ENUM_ID_4,
+	ENUM_ID_5,
+	ENUM_ID_6,
+	ENUM_ID_7,
+
+	ENUM_ID_COUNT
+};
+
+/* Generic object ids */
+enum generic_id {
+	GENERIC_ID_UNKNOWN = 0,
+	GENERIC_ID_MXM_OPM,
+	GENERIC_ID_GLSYNC,
+	GENERIC_ID_STEREO,
+
+	GENERIC_ID_COUNT
+};
+
+/* Controller object ids */
+enum controller_id {
+	CONTROLLER_ID_UNDEFINED = 0,
+	CONTROLLER_ID_D0,
+	CONTROLLER_ID_D1,
+	CONTROLLER_ID_D2,
+	CONTROLLER_ID_D3,
+	CONTROLLER_ID_D4,
+	CONTROLLER_ID_D5,
+	CONTROLLER_ID_UNDERLAY0,
+	CONTROLLER_ID_MAX = CONTROLLER_ID_UNDERLAY0
+};
+
+#define IS_UNDERLAY_CONTROLLER(ctrlr_id) (ctrlr_id >= CONTROLLER_ID_UNDERLAY0)
+
+/*
+ * ClockSource object ids.
+ * We maintain the order matching (more or less) ATOM BIOS
+ * to improve optimized acquire
+ */
+enum clock_source_id {
+	CLOCK_SOURCE_ID_UNDEFINED = 0,
+	CLOCK_SOURCE_ID_PLL0,
+	CLOCK_SOURCE_ID_PLL1,
+	CLOCK_SOURCE_ID_PLL2,
+	CLOCK_SOURCE_ID_EXTERNAL, /* ID (Phy) ref. clk. for DP */
+	CLOCK_SOURCE_ID_DCPLL,
+	CLOCK_SOURCE_ID_DFS,	/* DENTIST */
+	CLOCK_SOURCE_ID_VCE,	/* VCE does not need a real PLL */
+	/* Used to distinguish between programming pixel clock and ID (Phy) clock */
+	CLOCK_SOURCE_ID_DP_DTO,
+
+	CLOCK_SOURCE_COMBO_PHY_PLL0,
+	CLOCK_SOURCE_COMBO_PHY_PLL1,
+	CLOCK_SOURCE_COMBO_PHY_PLL2,
+	CLOCK_SOURCE_COMBO_PHY_PLL3,
+	CLOCK_SOURCE_COMBO_PHY_PLL4,
+	CLOCK_SOURCE_COMBO_PHY_PLL5,
+	CLOCK_SOURCE_COMBO_DISPLAY_PLL0
+};
+
+
+/* Encoder object ids */
+enum encoder_id {
+	ENCODER_ID_UNKNOWN = 0,
+
+	/* Radeon Class Display Hardware */
+	ENCODER_ID_INTERNAL_LVDS,
+	ENCODER_ID_INTERNAL_TMDS1,
+	ENCODER_ID_INTERNAL_TMDS2,
+	ENCODER_ID_INTERNAL_DAC1,
+	ENCODER_ID_INTERNAL_DAC2,	/* TV/CV DAC */
+
+	/* External Third Party Encoders */
+	ENCODER_ID_INTERNAL_LVTM1,	/* not used for Radeon */
+	ENCODER_ID_INTERNAL_HDMI,
+
+	/* Kaledisope (KLDSCP) Class Display Hardware */
+	ENCODER_ID_INTERNAL_KLDSCP_TMDS1,
+	ENCODER_ID_INTERNAL_KLDSCP_DAC1,
+	ENCODER_ID_INTERNAL_KLDSCP_DAC2,	/* Shared with CV/TV and CRT */
+	/* External TMDS (dual link) */
+	ENCODER_ID_EXTERNAL_MVPU_FPGA,	/* MVPU FPGA chip */
+	ENCODER_ID_INTERNAL_DDI,
+	ENCODER_ID_INTERNAL_UNIPHY,
+	ENCODER_ID_INTERNAL_KLDSCP_LVTMA,
+	ENCODER_ID_INTERNAL_UNIPHY1,
+	ENCODER_ID_INTERNAL_UNIPHY2,
+	ENCODER_ID_EXTERNAL_NUTMEG,
+	ENCODER_ID_EXTERNAL_TRAVIS,
+
+	ENCODER_ID_INTERNAL_WIRELESS,	/* Internal wireless display encoder */
+	ENCODER_ID_INTERNAL_UNIPHY3,
+	ENCODER_ID_INTERNAL_VIRTUAL,
+};
+
+
+/* Connector object ids */
+enum connector_id {
+	CONNECTOR_ID_UNKNOWN = 0,
+	CONNECTOR_ID_SINGLE_LINK_DVII = 1,
+	CONNECTOR_ID_DUAL_LINK_DVII = 2,
+	CONNECTOR_ID_SINGLE_LINK_DVID = 3,
+	CONNECTOR_ID_DUAL_LINK_DVID = 4,
+	CONNECTOR_ID_VGA = 5,
+	CONNECTOR_ID_HDMI_TYPE_A = 12,
+	CONNECTOR_ID_LVDS = 14,
+	CONNECTOR_ID_PCIE = 16,
+	CONNECTOR_ID_HARDCODE_DVI = 18,
+	CONNECTOR_ID_DISPLAY_PORT = 19,
+	CONNECTOR_ID_EDP = 20,
+	CONNECTOR_ID_MXM = 21,
+	CONNECTOR_ID_WIRELESS = 22,
+	CONNECTOR_ID_MIRACAST = 23,
+
+	CONNECTOR_ID_VIRTUAL = 100
+};
+
+
+/* Audio object ids */
+enum audio_id {
+	AUDIO_ID_UNKNOWN = 0,
+	AUDIO_ID_INTERNAL_AZALIA
+};
+
+
+/* Engine object ids */
+enum engine_id {
+	ENGINE_ID_DIGA,
+	ENGINE_ID_DIGB,
+	ENGINE_ID_DIGC,
+	ENGINE_ID_DIGD,
+	ENGINE_ID_DIGE,
+	ENGINE_ID_DIGF,
+	ENGINE_ID_DIGG,
+	ENGINE_ID_DACA,
+	ENGINE_ID_DACB,
+	ENGINE_ID_VCE,	/* wireless display pseudo-encoder */
+	ENGINE_ID_VIRTUAL,
+
+	ENGINE_ID_COUNT,
+	ENGINE_ID_UNKNOWN = (-1L)
+};
+
+union supported_stream_engines {
+	struct {
+		uint32_t ENGINE_ID_DIGA:1;
+		uint32_t ENGINE_ID_DIGB:1;
+		uint32_t ENGINE_ID_DIGC:1;
+		uint32_t ENGINE_ID_DIGD:1;
+		uint32_t ENGINE_ID_DIGE:1;
+		uint32_t ENGINE_ID_DIGF:1;
+		uint32_t ENGINE_ID_DIGG:1;
+		uint32_t ENGINE_ID_DACA:1;
+		uint32_t ENGINE_ID_DACB:1;
+		uint32_t ENGINE_ID_VCE:1;
+	} engine;
+	uint32_t u_all;
+};
+
+enum transmitter_color_depth {
+	TRANSMITTER_COLOR_DEPTH_24 = 0,  /* 8  bits */
+	TRANSMITTER_COLOR_DEPTH_30,      /* 10 bits */
+	TRANSMITTER_COLOR_DEPTH_36,      /* 12 bits */
+	TRANSMITTER_COLOR_DEPTH_48       /* 16 bits */
+};
+
+/*
+ *****************************************************************************
+ * graphics_object_id struct
+ *
+ * graphics_object_id is a very simple struct wrapping 32bit Graphics
+ * Object identication
+ *
+ * This struct should stay very simple
+ *  No dependencies at all (no includes)
+ *  No debug messages or asserts
+ *  No #ifndef and preprocessor directives
+ *  No grow in space (no more data member)
+ *****************************************************************************
+ */
+
+struct graphics_object_id {
+	uint32_t  id:8;
+	uint32_t  enum_id:4;
+	uint32_t  type:4;
+	uint32_t  reserved:16; /* for padding. total size should be u32 */
+};
+
+/* some simple functions for convenient graphics_object_id handle */
+
+static inline struct graphics_object_id dal_graphics_object_id_init(
+	uint32_t id,
+	enum object_enum_id enum_id,
+	enum object_type type)
+{
+	struct graphics_object_id result = {
+		id, enum_id, type, 0
+	};
+
+	return result;
+}
+
+bool dal_graphics_object_id_is_valid(
+	struct graphics_object_id id);
+bool dal_graphics_object_id_is_equal(
+	struct graphics_object_id id1,
+	struct graphics_object_id id2);
+uint32_t dal_graphics_object_id_to_uint(
+	struct graphics_object_id id);
+
+
+enum controller_id dal_graphics_object_id_get_controller_id(
+	struct graphics_object_id id);
+enum clock_source_id dal_graphics_object_id_get_clock_source_id(
+	struct graphics_object_id id);
+enum encoder_id dal_graphics_object_id_get_encoder_id(
+	struct graphics_object_id id);
+enum connector_id dal_graphics_object_id_get_connector_id(
+	struct graphics_object_id id);
+enum audio_id dal_graphics_object_id_get_audio_id(
+	struct graphics_object_id id);
+enum engine_id dal_graphics_object_id_get_engine_id(
+	struct graphics_object_id id);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h b/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
new file mode 100644
index 000000000000..ddd78d6c97e3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_SEQUENCER_INTERFACE_H__
+#define __DAL_HW_SEQUENCER_INTERFACE_H__
+
+#include "hw_sequencer_types.h"
+#include "hw_adjustment_types.h"
+#include "include/display_clock_interface.h"
+#include "include/scaler_types.h"
+#include "include/grph_csc_types.h"
+#include "plane_types.h"
+
+#include "adapter_service_interface.h"
+
+enum hwss_result {
+	HWSS_RESULT_OK,
+	HWSS_RESULT_ERROR,
+	HWSS_RESULT_NO_BANDWIDTH,
+	HWSS_RESULT_OUT_OF_RANGE,
+	HWSS_RESULT_NOT_SUPPORTED,
+	HWSS_RESULT_UNKNOWN
+};
+
+struct hws_init_data {
+	struct adapter_service *as;
+	struct dal_context *dal_context;
+};
+
+/* TODO: below is three almost equal structures.
+ * We should decide what to do with them */
+struct blank_stream_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	struct hw_crtc_timing timing;
+	struct link_settings link_settings;
+};
+
+struct enable_stream_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	struct hw_crtc_timing timing;
+	struct link_settings link_settings;
+
+	const struct hw_path_mode *path_mode;
+};
+
+struct enable_link_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	struct hw_crtc_timing timing;
+	struct link_settings link_settings;
+
+	bool optimized_programming;
+	const struct hw_path_mode *path_mode;
+};
+
+struct validate_link_param {
+	const struct display_path *display_path;
+	uint32_t link_idx;
+	struct link_settings link_settings;
+};
+
+struct set_dp_phy_pattern_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	enum dp_test_pattern test_pattern;
+	const uint8_t *custom_pattern;
+	uint32_t cust_pattern_size;
+};
+
+struct hw_global_objects;
+struct hw_sequencer;
+struct hw_adjustment;
+struct hw_path_mode_set;
+struct hw_path_mode;
+struct hwss_build_params;
+struct controller;
+
+void dal_hw_sequencer_mute_audio_endpoint(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	bool mute);
+
+void dal_hw_sequencer_enable_audio_endpoint(
+	struct hw_sequencer *hws,
+	struct link_settings *ls,
+	struct display_path *display_path,
+	bool enable);
+
+enum hwss_result dal_hw_sequencer_reset_audio_device(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum hwss_result dal_hw_sequencer_validate_link(
+	struct hw_sequencer *hws,
+	const struct validate_link_param *param);
+
+bool dal_hw_sequencer_is_supported_dp_training_pattern3(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	uint32_t link_idx);
+
+enum hwss_result dal_hw_sequencer_set_dp_phy_pattern(
+	struct hw_sequencer *hws,
+	const struct set_dp_phy_pattern_param *param);
+
+enum hwss_result dal_hw_sequencer_set_lane_settings(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	const struct link_training_settings *link_settings);
+
+void dal_hw_sequencer_set_test_pattern(
+	struct hw_sequencer *hws,
+	struct hw_path_mode *path_mode,
+	enum dp_test_pattern test_pattern,
+	const struct link_training_settings *link_settings,
+	const uint8_t *custom_pattern,
+	uint8_t cust_pattern_size);
+
+bool dal_hw_sequencer_has_audio_bandwidth_changed(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *old,
+	const struct hw_path_mode *new);
+
+void dal_hw_sequencer_enable_azalia_audio_jack_presence(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_disable_azalia_audio_jack_presence(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_enable_memory_requests(
+	struct hw_sequencer *hws,
+	struct hw_path_mode *path_mode);
+
+void dal_hw_sequencer_update_info_packets(
+	struct hw_sequencer *hws,
+	struct hw_path_mode *path_mode);
+
+/* Static validation for a SINGLE path mode.
+ * Already "active" paths (if any) are NOT taken into account. */
+enum hwss_result dal_hw_sequencer_validate_display_path_mode(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *path_mode);
+
+/* Validation for a SET of path modes, including Video Memory Bandwidth
+ * validation. */
+enum hwss_result dal_hw_sequencer_validate_display_hwpms(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set);
+
+struct hw_adjustment_gamma_ramp;
+
+enum hwss_result dal_hw_sequencer_set_gamma_ramp_adjustment(
+	struct hw_sequencer *hws,
+	const struct display_path *display_path,
+	struct hw_adjustment_gamma_ramp *adjusment);
+
+enum hwss_result dal_hw_sequencer_set_color_control_adjustment(
+	struct hw_sequencer *hws,
+	struct controller *crtc,
+	struct hw_adjustment_color_control *adjustment);
+
+enum hwss_result dal_hw_sequencer_set_vertical_sync_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+enum hwss_result dal_hw_sequencer_set_horizontal_sync_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+enum hwss_result dal_hw_sequencer_set_composite_sync_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+enum hwss_result dal_hw_sequencer_enable_sync_output(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum hwss_result dal_hw_sequencer_disable_sync_output(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum hwss_result dal_hw_sequencer_set_backlight_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+void dal_hw_sequencer_disable_memory_requests(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *path_mode);
+
+enum hwss_result dal_hw_sequencer_enable_link(
+	struct hw_sequencer *hws,
+	const struct enable_link_param *in);
+
+void dal_hw_sequencer_disable_link(
+	struct hw_sequencer *hws,
+	const struct enable_link_param *in);
+
+void dal_hw_sequencer_enable_stream(
+	struct hw_sequencer *hws,
+	const struct enable_stream_param *in);
+
+void dal_hw_sequencer_disable_stream(
+	struct hw_sequencer *hws,
+	const struct enable_stream_param *in);
+
+void dal_hw_sequencer_blank_stream(
+	struct hw_sequencer *hws,
+	const struct blank_stream_param *in);
+
+void dal_hw_sequencer_unblank_stream(
+	struct hw_sequencer *hws,
+	const struct blank_stream_param *in);
+
+enum hwss_result dal_hw_sequencer_set_clocks_and_clock_state(
+		struct hw_sequencer *hws,
+		struct hw_global_objects *g_obj,
+		const struct minimum_clocks_calculation_result *min_clk_in,
+		enum clocks_state required_clocks_state);
+
+enum hwss_result dal_hw_sequencer_set_mode(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set);
+
+enum signal_type dal_hw_sequencer_detect_sink(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum signal_type dal_hw_sequencer_detect_load(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+bool dal_hw_sequencer_is_sink_present(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_psr_setup(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *path_mode,
+	const struct psr_caps *psr_caps);
+
+void dal_hw_sequencer_psr_enable(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_psr_disable(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_program_drr(
+		struct hw_sequencer *hws,
+		const struct hw_path_mode *path_mode);
+
+enum hwss_result dal_hw_sequencer_set_safe_displaymark(
+		struct hw_sequencer *hws,
+		struct hw_path_mode_set *path_set);
+
+enum hwss_result dal_hw_sequencer_set_displaymark(
+		struct hw_sequencer *hws,
+		struct hw_path_mode_set *path_set);
+
+void dal_hw_sequencer_destroy(struct hw_sequencer **hws);
+
+struct hw_sequencer *dal_hw_sequencer_create(
+		struct hws_init_data *hws_init_data);
+
+enum hwss_result dal_hw_sequencer_set_overscan_adj(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *set,
+	struct hw_underscan_adjustment_data *hw_underscan);
+
+bool dal_hw_sequencer_enable_line_buffer_power_gating(
+	struct line_buffer *lb,
+	enum controller_id id,
+	enum pixel_type pixel_type,
+	uint32_t src_pixel_width,
+	uint32_t dst_pixel_width,
+	struct scaling_taps *taps,
+	enum lb_pixel_depth lb_depth,
+	uint32_t src_height,
+	uint32_t dst_height,
+	bool interlaced);
+
+void dal_hw_sequencer_build_scaler_parameter(
+	const struct hw_path_mode *path_mode,
+	const struct scaling_taps *taps,
+	bool build_timing_required,
+	struct scaler_data *scaler_data);
+
+void dal_hw_sequencer_update_info_frame(
+	const struct hw_path_mode *hw_path_mode);
+
+enum hwss_result dal_hw_sequencer_set_bit_depth_reduction_adj(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	union hw_adjustment_bit_depth_reduction *bit_depth);
+
+bool dal_hw_sequencer_is_support_custom_gamut_adj(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	enum hw_surface_type surface_type);
+
+enum hwss_result dal_hw_sequencer_get_hw_color_adj_range(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	struct hw_color_control_range *hw_color_range);
+
+bool dal_hw_sequencer_is_support_custom_gamma_coefficients(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	enum hw_surface_type surface_type);
+
+enum hwss_result dal_hw_sequencer_build_csc_adjust(
+	struct hw_sequencer *hws,
+	struct hw_adjustment_color_control *color_control,
+	struct grph_csc_adjustment *adjust);
+
+void dal_hw_sequencer_build_gamma_ramp_adj_params(
+		const struct hw_adjustment_gamma_ramp *adjusment,
+		struct gamma_parameters *gamma_param,
+		struct gamma_ramp *ramp);
+
+void translate_from_hw_to_controller_regamma(
+		const struct hw_regamma_lut *hw_regamma,
+		struct regamma_lut *regamma);
+
+void dal_hw_sequencer_enable_wireless_idle_detection(
+		struct hw_sequencer *hws,
+		bool enable);
+
+/* Cursor interface */
+enum hwss_result dal_hw_sequencer_set_cursor_position(
+		struct hw_sequencer *hws,
+		struct display_path *dp,
+		const struct dc_cursor_position *position);
+
+enum hwss_result dal_hw_sequencer_set_cursor_attributes(
+		struct hw_sequencer *hws,
+		struct display_path *dp,
+		const struct dc_cursor_attributes *attributes);
+
+/* Underlay/MPO interface */
+enum hwss_result dal_hw_sequencer_set_plane_config(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set,
+	uint32_t display_index);
+
+bool dal_hw_sequencer_update_plane_address(
+	struct hw_sequencer *hws,
+	struct display_path *dp,
+	uint32_t num_planes,
+	struct plane_addr_flip_info *info);
+
+void dal_hw_sequencer_prepare_to_release_planes(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set,
+	uint32_t display_index);
+
+#endif /* __DAL_HW_SEQUENCER_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
new file mode 100644
index 000000000000..ad7b90605d75
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_SEQUENCER_TYPES_H__
+#define __DAL_HW_SEQUENCER_TYPES_H__
+
+#include "signal_types.h"
+#include "grph_object_defs.h"
+#include "link_service_types.h"
+
+struct color_quality {
+	uint32_t bpp_graphics;
+	uint32_t bpp_backend_video;
+};
+
+enum {
+	HW_MAX_NUM_VIEWPORTS = 2,
+	HW_CURRENT_PIPE_INDEX = 0,
+	HW_OTHER_PIPE_INDEX = 1
+};
+
+struct hw_view_port_adjustment {
+	int32_t start_adjustment;
+	int32_t width;
+
+	enum controller_id controller_id;
+};
+
+struct hw_view_port_adjustments {
+	uint32_t view_ports_num;
+	struct hw_view_port_adjustment adjustments[HW_MAX_NUM_VIEWPORTS];
+};
+
+/* Timing standard */
+enum hw_timing_standard {
+	HW_TIMING_STANDARD_UNDEFINED,
+	HW_TIMING_STANDARD_DMT,
+	HW_TIMING_STANDARD_GTF,
+	HW_TIMING_STANDARD_CVT,
+	HW_TIMING_STANDARD_CVT_RB,
+	HW_TIMING_STANDARD_CEA770,
+	HW_TIMING_STANDARD_CEA861,
+	HW_TIMING_STANDARD_HDMI,
+	HW_TIMING_STANDARD_TV_NTSC,
+	HW_TIMING_STANDARD_TV_NTSC_J,
+	HW_TIMING_STANDARD_TV_PAL,
+	HW_TIMING_STANDARD_TV_PAL_M,
+	HW_TIMING_STANDARD_TV_PAL_CN,
+	HW_TIMING_STANDARD_TV_SECAM,
+	/* for explicit timings from VBIOS, EDID etc. */
+	HW_TIMING_STANDARD_EXPLICIT
+};
+
+/* TODO: identical to struct crtc_ranged_timing_control
+ * defined in inc\timing_generator_types.h */
+struct hw_ranged_timing_control {
+	/* set to 1 to force dynamic counter V_COUNT
+	 * to lock to constant rate counter V_COUNT_NOM
+	 * on page flip event in dynamic refresh mode
+	 * when switching from a low refresh rate to nominal refresh rate */
+	bool force_lock_on_event;
+	/* set to 1 to force CRTC2 (slave) to lock to CRTC1 (master) VSync
+	 * in order to overlap their blank regions for MC clock changes */
+	bool lock_to_master_vsync;
+
+	/* set to 1 to program Static Screen Detection Masks
+	 * without enabling dynamic refresh rate */
+	bool program_static_screen_mask;
+	/* set to 1 to program Dynamic Refresh Rate */
+	bool program_dynamic_refresh_rate;
+	/* set to 1 to force disable Dynamic Refresh Rate */
+	bool force_disable_drr;
+
+	/* event mask to enable/disable various trigger sources
+	 * for static screen detection */
+	struct static_screen_events event_mask;
+
+	/* Number of consecutive static screen frames before static state is
+	 * asserted. */
+	uint32_t static_frame_count;
+};
+
+/* define the structure of Dynamic Refresh Mode */
+struct hw_ranged_timing {
+	/* defines the minimum possible vertical dimension of display timing
+	 * for CRTC as supported by the panel */
+	uint32_t vertical_total_min;
+	/* defines the maximum possible vertical dimension of display timing
+	 * for CRTC as supported by the panel */
+	uint32_t vertical_total_max;
+
+	struct hw_ranged_timing_control control;
+};
+
+/* CRTC timing structure */
+struct hw_crtc_timing {
+	uint32_t h_total;
+	uint32_t h_addressable;
+	uint32_t h_overscan_left;
+	uint32_t h_overscan_right;
+	uint32_t h_sync_start;
+	uint32_t h_sync_width;
+
+	uint32_t v_total;
+	uint32_t v_addressable;
+	uint32_t v_overscan_top;
+	uint32_t v_overscan_bottom;
+	uint32_t v_sync_start;
+	uint32_t v_sync_width;
+
+	struct hw_ranged_timing ranged_timing;
+
+	/* in KHz */
+	uint32_t pixel_clock;
+
+	enum hw_timing_standard timing_standard;
+	enum dc_color_depth color_depth;
+	enum dc_pixel_encoding pixel_encoding;
+
+	struct {
+		uint32_t INTERLACED:1;
+		uint32_t DOUBLESCAN:1;
+		uint32_t PIXEL_REPETITION:4; /* 1...10 */
+		uint32_t HSYNC_POSITIVE_POLARITY:1;
+		uint32_t VSYNC_POSITIVE_POLARITY:1;
+		/* frame should be packed for 3D
+		 * (currently this refers to HDMI 1.4a FramePacking format */
+		uint32_t HORZ_COUNT_BY_TWO:1;
+		uint32_t PACK_3D_FRAME:1;
+		/* 0 - left eye polarity, 1 - right eye polarity */
+		uint32_t RIGHT_EYE_3D_POLARITY:1;
+		/* DVI-DL High-Color mode */
+		uint32_t HIGH_COLOR_DL_MODE:1;
+		uint32_t Y_ONLY:1;
+		/* HDMI 2.0 - Support scrambling for TMDS character
+		 * rates less than or equal to 340Mcsc */
+		uint32_t LTE_340MCSC_SCRAMBLE:1;
+	} flags;
+};
+
+struct hw_scaling_info {
+	struct view src;
+	struct view dst;
+	enum signal_type signal;
+};
+
+enum hw_color_space {
+	HW_COLOR_SPACE_UNKNOWN = 0,
+	HW_COLOR_SPACE_SRGB_FULL_RANGE,
+	HW_COLOR_SPACE_SRGB_LIMITED_RANGE,
+	HW_COLOR_SPACE_YPBPR601,
+	HW_COLOR_SPACE_YPBPR709,
+	HW_COLOR_SPACE_YCBCR601,
+	HW_COLOR_SPACE_YCBCR709,
+	HW_COLOR_SPACE_YCBCR601_YONLY,
+	HW_COLOR_SPACE_YCBCR709_YONLY,
+	HW_COLOR_SPACE_NMVPU_SUPERAA,
+};
+
+enum hw_overlay_color_space {
+	HW_OVERLAY_COLOR_SPACE_UNKNOWN,
+	HW_OVERLAY_COLOR_SPACE_BT709,
+	HW_OVERLAY_COLOR_SPACE_BT601,
+	HW_OVERLAY_COLOR_SPACE_SMPTE240,
+	HW_OVERLAY_COLOR_SPACE_RGB
+};
+
+enum hw_overlay_backend_bpp {
+	HW_OVERLAY_BACKEND_BPP_UNKNOWN,
+	HW_OVERLAY_BACKEND_BPP32_FULL_BANDWIDTH,
+	HW_OVERLAY_BACKEND_BPP16_FULL_BANDWIDTH,
+	HW_OVERLAY_BACKEND_BPP32_HALF_BANDWIDTH,
+};
+enum hw_overlay_format {
+	HW_OVERLAY_FORMAT_UNKNOWN,
+	HW_OVERLAY_FORMAT_YUY2,
+	HW_OVERLAY_FORMAT_UYVY,
+	HW_OVERLAY_FORMAT_RGB565,
+	HW_OVERLAY_FORMAT_RGB555,
+	HW_OVERLAY_FORMAT_RGB32,
+	HW_OVERLAY_FORMAT_YUV444,
+	HW_OVERLAY_FORMAT_RGB32_2101010
+};
+
+enum hw_scale_options {
+	HW_SCALE_OPTION_UNKNOWN,
+	HW_SCALE_OPTION_OVERSCAN, /* multimedia pass through mode */
+	HW_SCALE_OPTION_UNDERSCAN
+};
+
+enum hw_stereo_format {
+	HW_STEREO_FORMAT_NONE = 0,
+	HW_STEREO_FORMAT_SIDE_BY_SIDE = 1,
+	HW_STEREO_FORMAT_TOP_AND_BOTTOM = 2,
+	HW_STEREO_FORMAT_FRAME_ALTERNATE = 3,
+	HW_STEREO_FORMAT_ROW_INTERLEAVED = 5,
+	HW_STEREO_FORMAT_COLUMN_INTERLEAVED = 6,
+	HW_STEREO_FORMAT_CHECKER_BOARD = 7 /* the same as pixel interleave */
+};
+
+enum hw_dithering_options {
+	HW_DITHERING_OPTION_UNKNOWN,
+	HW_DITHERING_OPTION_SKIP_PROGRAMMING,
+	HW_DITHERING_OPTION_ENABLE,
+	HW_DITHERING_OPTION_DISABLE
+};
+
+struct hw_stereo_mixer_params {
+	bool sub_sampling;
+	bool single_pipe;
+};
+
+
+
+struct hw_action_flags {
+	uint32_t RESYNC_PATH:1;
+	uint32_t TIMING_CHANGED:1;
+	uint32_t PIXEL_ENCODING_CHANGED:1;
+	uint32_t GAMUT_CHANGED:1;
+	uint32_t TURN_OFF_VCC:1;
+};
+
+enum hw_sync_request {
+	HW_SYNC_REQUEST_NONE = 0,
+	HW_SYNC_REQUEST_SET_INTERPATH,
+	HW_SYNC_REQUEST_SET_GL_SYNC_GENLOCK,
+	HW_SYNC_REQUEST_SET_GL_SYNC_FREE_RUN,
+	HW_SYNC_REQUEST_SET_GL_SYNC_SHADOW,
+	HW_SYNC_REQUEST_RESET_GLSYNC,
+	HW_SYNC_REQUEST_RESYNC_GLSYNC,
+	HW_SYNC_REQUEST_SET_STEREO3D
+};
+
+struct hw_sync_info {
+	enum hw_sync_request sync_request;
+	uint32_t target_pixel_clock; /* in KHz */
+	enum sync_source sync_source;
+};
+
+/* TODO hw_info_frame and hw_info_packet structures are same as in encoder
+ * merge it*/
+struct hw_info_packet {
+	bool valid;
+	uint8_t hb0;
+	uint8_t hb1;
+	uint8_t hb2;
+	uint8_t hb3;
+	uint8_t sb[28];
+};
+
+struct hw_info_frame {
+	/* Auxiliary Video Information */
+	struct hw_info_packet avi_info_packet;
+	struct hw_info_packet gamut_packet;
+	struct hw_info_packet vendor_info_packet;
+	/* Source Product Description */
+	struct hw_info_packet spd_packet;
+	/* Video Stream Configuration */
+	struct hw_info_packet vsc_packet;
+};
+
+
+enum channel_command_type {
+	CHANNEL_COMMAND_I2C,
+	CHANNEL_COMMAND_I2C_OVER_AUX,
+	CHANNEL_COMMAND_AUX
+};
+
+
+/* maximum TMDS transmitter pixel clock is 165 MHz. So it is KHz */
+#define	TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
+#define	NATIVE_HDMI_MAX_PIXEL_CLOCK_IN_KHZ 297000
+
+struct hw_adjustment_range {
+	int32_t hw_default;
+	int32_t min;
+	int32_t max;
+	int32_t step;
+	uint32_t divider; /* (actually HW range is min/divider; divider !=0) */
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/i2caux_interface.h b/drivers/gpu/drm/amd/dal/include/i2caux_interface.h
new file mode 100644
index 000000000000..b961d24d0e70
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/i2caux_interface.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2CAUX_INTERFACE_H__
+#define __DAL_I2CAUX_INTERFACE_H__
+
+#include "ddc_interface.h"
+#include "adapter_service_interface.h"
+
+struct i2c_payload {
+	bool write;
+	uint8_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum i2c_command_engine {
+	I2C_COMMAND_ENGINE_DEFAULT,
+	I2C_COMMAND_ENGINE_SW,
+	I2C_COMMAND_ENGINE_HW
+};
+
+struct i2c_command {
+	struct i2c_payload *payloads;
+	uint8_t number_of_payloads;
+
+	enum i2c_command_engine engine;
+
+	/* expressed in KHz
+	 * zero means "use default value" */
+	uint32_t speed;
+};
+
+#define DEFAULT_AUX_MAX_DATA_SIZE 16
+#define AUX_MAX_DEFER_WRITE_RETRY 20
+
+struct aux_payload {
+	/* set following flag to read/write I2C data,
+	 * reset it to read/write DPCD data */
+	bool i2c_over_aux;
+	/* set following flag to write data,
+	 * reset it to read data */
+	bool write;
+	uint32_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+struct aux_command {
+	struct aux_payload *payloads;
+	uint8_t number_of_payloads;
+
+	/* expressed in milliseconds
+	 * zero means "use default value" */
+	uint32_t defer_delay;
+
+	/* zero means "use default value" */
+	uint32_t max_defer_write_retry;
+};
+
+union aux_config {
+	struct {
+		uint32_t ALLOW_AUX_WHEN_HPD_LOW:1;
+	} bits;
+	uint32_t raw;
+};
+
+struct i2caux;
+
+struct i2caux *dal_i2caux_create(
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+bool dal_i2caux_submit_i2c_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct i2c_command *cmd);
+
+bool dal_i2caux_submit_aux_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct aux_command *cmd);
+
+void dal_i2caux_keep_engine_power_up(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	bool keep_power_up);
+
+bool dal_i2caux_start_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+bool dal_i2caux_stop_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+void dal_i2caux_configure_aux(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	union aux_config cfg);
+
+void dal_i2caux_destroy(
+	struct i2caux **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/irq_interface.h b/drivers/gpu/drm/amd/dal/include/irq_interface.h
new file mode 100644
index 000000000000..0faa48fabf95
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/irq_interface.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_INTERFACE_H__
+#define __DAL_IRQ_INTERFACE_H__
+
+#include "gpio_types.h"
+
+struct irq;
+
+enum gpio_result dal_irq_open(
+	struct irq *irq);
+
+enum gpio_result dal_irq_get_value(
+	const struct irq *irq,
+	uint32_t *value);
+
+enum dc_irq_source dal_irq_get_source(
+	const struct irq *irq);
+
+enum dc_irq_source dal_irq_get_rx_source(
+	const struct irq *irq);
+
+enum gpio_result dal_irq_setup_hpd_filter(
+	struct irq *irq,
+	struct gpio_hpd_config *config);
+
+void dal_irq_close(
+	struct irq *irq);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/irq_service_interface.h b/drivers/gpu/drm/amd/dal/include/irq_service_interface.h
new file mode 100644
index 000000000000..7ae4aebb738d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/irq_service_interface.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_SERVICE_INTERFACE_H__
+#define __DAL_IRQ_SERVICE_INTERFACE_H__
+
+#include "include/adapter_service_types.h"
+
+struct irq_service_init_data {
+	struct dc_context *ctx;
+};
+
+struct irq_service *dal_irq_service_create(
+	enum dce_version version,
+	struct irq_service_init_data *init_data);
+
+void dal_irq_service_destroy(struct irq_service **irq_service);
+
+bool dal_irq_service_set(
+	struct irq_service *irq_service,
+	enum dc_irq_source source,
+	bool enable);
+
+bool dal_irq_service_ack(
+	struct irq_service *irq_service,
+	enum dc_irq_source source);
+
+enum dc_irq_source dal_irq_service_to_irq_source(
+		struct irq_service *irq_service,
+		uint32_t src_id,
+		uint32_t ext_id);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/link_service_interface.h b/drivers/gpu/drm/amd/dal/include/link_service_interface.h
new file mode 100644
index 000000000000..2ac93119cc02
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/link_service_interface.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LINK_SERVICE_INTERFACE_H__
+#define __DAL_LINK_SERVICE_INTERFACE_H__
+
+#include "include/link_service_types.h"
+
+/* forward declaration */
+struct link_service;
+struct hw_crtc_timing;
+struct hw_path_mode;
+struct display_path;
+struct hw_path_mode_set;
+struct link_training_preference;
+enum ddc_result;
+
+struct link_service *dal_link_service_create(
+	struct link_service_init_data *init_data);
+
+void dal_link_service_destroy(
+	struct link_service **ls);
+
+enum link_service_type dal_ls_get_link_service_type(
+	struct link_service *link_service);
+
+bool dal_ls_validate_mode_timing(
+	struct link_service *ls,
+	uint32_t display_index,
+	const struct hw_crtc_timing *timing,
+	struct link_validation_flags flags);
+
+bool dal_ls_get_mst_sink_info(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct mst_sink_info *sink_info);
+
+bool dal_ls_get_gtc_sync_status(
+	struct link_service *ls);
+
+bool dal_ls_enable_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_disable_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *poath_mode);
+
+bool dal_ls_optimized_enable_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct display_path *display_path);
+
+void dal_ls_update_stream_features(
+	struct link_service *ls,
+	const struct hw_path_mode *path_mode);
+
+bool dal_ls_blank_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_unblank_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_pre_mode_change(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_post_mode_change(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_power_on_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_power_off_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+void dal_ls_retrain_link(
+	struct link_service *ls,
+	struct hw_path_mode_set *path_set);
+
+bool dal_ls_get_current_link_setting(
+	struct link_service *ls,
+	struct link_settings *link_settings);
+
+void dal_ls_connect_link(
+	struct link_service *ls,
+	const struct display_path *display_path,
+	bool initial_detection);
+
+void dal_ls_disconnect_link(
+	struct link_service *ls);
+
+bool dal_ls_is_mst_network_present(
+	struct link_service *ls);
+
+void dal_ls_invalidate_down_stream_devices(
+	struct link_service *ls);
+
+bool dal_ls_are_mst_displays_cofunctional(
+	struct link_service *ls,
+	const uint32_t *array_display_index,
+	uint32_t len);
+
+bool dal_ls_is_sink_present_at_display_index(
+	struct link_service *ls,
+	uint32_t display_index);
+
+struct ddc_service *dal_ls_obtain_mst_ddc_service(
+	struct link_service *ls,
+	uint32_t display_index);
+
+void dal_ls_release_mst_ddc_service(
+	struct link_service *ls,
+	struct ddc_service *ddc_service);
+
+void dal_ls_release_hw(
+	struct link_service *ls);
+
+bool dal_ls_associate_link(
+	struct link_service *ls,
+	uint32_t display_index,
+	uint32_t link_index,
+	bool is_internal_link);
+
+bool dal_dpsst_ls_set_overridden_trained_link_settings(
+	struct link_service *ls,
+	const struct link_settings *link_settings);
+
+void dal_dpsst_ls_set_link_training_preference(
+	struct link_service *ls,
+	const struct link_training_preference *ltp);
+
+struct link_training_preference
+	dal_dpsst_ls_get_link_training_preference(
+	struct link_service *ls);
+
+bool dal_ls_should_send_notification(
+	struct link_service *ls);
+
+uint32_t dal_ls_get_notification_display_index(
+	struct link_service *ls);
+
+enum ddc_result dal_dpsst_ls_read_dpcd_data(
+	struct link_service *ls,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t size);
+
+enum ddc_result dal_dpsst_ls_write_dpcd_data(
+	struct link_service *ls,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t size);
+
+bool dal_ls_is_link_psr_supported(struct link_service *ls);
+
+bool dal_ls_is_stream_drr_supported(struct link_service *ls);
+
+void dal_ls_set_link_psr_capabilities(
+		struct link_service *ls,
+		struct psr_caps *psr_caps);
+
+void dal_ls_get_link_psr_capabilities(
+		struct link_service *ls,
+		struct psr_caps *psr_caps);
+
+#endif /* __DAL_LINK_SERVICE_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/link_service_types.h b/drivers/gpu/drm/amd/dal/include/link_service_types.h
new file mode 100644
index 000000000000..d2e6256695fb
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/link_service_types.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LINK_SERVICE_TYPES_H__
+#define __DAL_LINK_SERVICE_TYPES_H__
+
+#include "grph_object_id.h"
+#include "dpcd_defs.h"
+#include "dal_types.h"
+#include "irq_types.h"
+
+/*struct mst_mgr_callback_object;*/
+struct ddc;
+struct irq_manager;
+
+enum {
+	MAX_CONTROLLER_NUM = 6
+};
+
+enum link_service_type {
+	LINK_SERVICE_TYPE_LEGACY = 0,
+	LINK_SERVICE_TYPE_DP_SST,
+	LINK_SERVICE_TYPE_DP_MST,
+	LINK_SERVICE_TYPE_MAX
+};
+
+struct link_validation_flags {
+	uint32_t DYNAMIC_VALIDATION:1;
+	uint32_t CANDIDATE_TIMING:1;
+	uint32_t START_OF_VALIDATION:1;
+};
+
+/* Post Cursor 2 is optional for transmitter
+ * and it applies only to the main link operating at HBR2
+ */
+enum post_cursor2 {
+	POST_CURSOR2_DISABLED = 0,	/* direct HW translation! */
+	POST_CURSOR2_LEVEL1,
+	POST_CURSOR2_LEVEL2,
+	POST_CURSOR2_LEVEL3,
+	POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3,
+};
+
+enum voltage_swing {
+	VOLTAGE_SWING_LEVEL0 = 0,	/* direct HW translation! */
+	VOLTAGE_SWING_LEVEL1,
+	VOLTAGE_SWING_LEVEL2,
+	VOLTAGE_SWING_LEVEL3,
+	VOLTAGE_SWING_MAX_LEVEL = VOLTAGE_SWING_LEVEL3
+};
+
+enum pre_emphasis {
+	PRE_EMPHASIS_DISABLED = 0,	/* direct HW translation! */
+	PRE_EMPHASIS_LEVEL1,
+	PRE_EMPHASIS_LEVEL2,
+	PRE_EMPHASIS_LEVEL3,
+	PRE_EMPHASIS_MAX_LEVEL = PRE_EMPHASIS_LEVEL3
+};
+
+enum dpcd_value_mask {
+	DPCD_VALUE_MASK_MAX_LANE_COUNT_LANE_COUNT = 0x1F,
+	DPCD_VALUE_MASK_MAX_LANE_COUNT_TPS3_SUPPORTED = 0x40,
+	DPCD_VALUE_MASK_MAX_LANE_COUNT_ENHANCED_FRAME_EN = 0x80,
+	DPCD_VALUE_MASK_MAX_DOWNSPREAD = 0x01,
+	DPCD_VALUE_MASK_LANE_ALIGN_STATUS_INTERLANE_ALIGN_DONE = 0x01
+};
+
+enum dp_power_state {
+	DP_POWER_STATE_D0 = 1,
+	DP_POWER_STATE_D3
+};
+
+enum dpcd_downstream_port_types {
+	DPCD_DOWNSTREAM_DP,
+	DPCD_DOWNSTREAM_VGA,
+	DPCD_DOWNSTREAM_DVI_HDMI,
+	/* has no EDID (TV, CV) */
+	DPCD_DOWNSTREAM_NON_DDC
+};
+
+enum edp_revision {
+	/* eDP version 1.1 or lower */
+	EDP_REVISION_11 = 0x00,
+	/* eDP version 1.2 */
+	EDP_REVISION_12 = 0x01,
+	/* eDP version 1.3 */
+	EDP_REVISION_13 = 0x02
+};
+
+enum lane_count {
+	LANE_COUNT_UNKNOWN = 0,
+	LANE_COUNT_ONE = 1,
+	LANE_COUNT_TWO = 2,
+	LANE_COUNT_FOUR = 4,
+	LANE_COUNT_EIGHT = 8,
+	LANE_COUNT_DP_MAX = LANE_COUNT_FOUR
+};
+
+/* This is actually a reference clock (27MHz) multiplier
+ * 162MBps bandwidth for 1.62GHz like rate,
+ * 270MBps for 2.70GHz,
+ * 324MBps for 3.24Ghz,
+ * 540MBps for 5.40GHz
+ */
+enum link_rate {
+	LINK_RATE_UNKNOWN = 0,
+	LINK_RATE_LOW = 0x06,
+	LINK_RATE_HIGH = 0x0A,
+	LINK_RATE_RBR2 = 0x0C,
+	LINK_RATE_HIGH2 = 0x14
+};
+
+enum {
+	LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/
+};
+
+enum link_spread {
+	LINK_SPREAD_DISABLED = 0x00,
+	/* 0.5 % downspread 30 kHz */
+	LINK_SPREAD_05_DOWNSPREAD_30KHZ = 0x10,
+	/* 0.5 % downspread 33 kHz */
+	LINK_SPREAD_05_DOWNSPREAD_33KHZ = 0x11
+};
+
+/* DPCD_ADDR_DOWNSTREAM_PORT_PRESENT register value */
+union dpcd_downstream_port {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t PRESENT:1;
+		uint8_t TYPE:2;
+		uint8_t FORMAT_CONV:1;
+		uint8_t RESERVED:4;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t RESERVED:4;
+		uint8_t FORMAT_CONV:1;
+		uint8_t TYPE:2;
+		uint8_t PRESENT:1;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+/* DPCD_ADDR_SINK_COUNT register value */
+union dpcd_sink_count {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t SINK_COUNT:6;
+		uint8_t CP_READY:1;
+		uint8_t RESERVED:1;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t RESERVED:1;
+		uint8_t CP_READY:1;
+		uint8_t SINK_COUNT:6;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+struct link_settings {
+	enum lane_count lane_count;
+	enum link_rate link_rate;
+	enum link_spread link_spread;
+};
+
+struct lane_settings {
+	enum voltage_swing VOLTAGE_SWING;
+	enum pre_emphasis PRE_EMPHASIS;
+	enum post_cursor2 POST_CURSOR2;
+};
+
+struct link_training_settings {
+	struct link_settings link_settings;
+	struct lane_settings lane_settings[LANE_COUNT_DP_MAX];
+	bool allow_invalid_msa_timing_param;
+};
+
+enum hw_dp_training_pattern {
+	HW_DP_TRAINING_PATTERN_1 = 0,
+	HW_DP_TRAINING_PATTERN_2,
+	HW_DP_TRAINING_PATTERN_3
+};
+
+/*TODO: Move this enum test harness*/
+/* Test patterns*/
+enum dp_test_pattern {
+	/* Input data is pass through Scrambler
+	 * and 8b10b Encoder straight to output*/
+	DP_TEST_PATTERN_VIDEO_MODE = 0,
+	/* phy test patterns*/
+	DP_TEST_PATTERN_D102,
+	DP_TEST_PATTERN_SYMBOL_ERROR,
+	DP_TEST_PATTERN_PRBS7,
+
+	DP_TEST_PATTERN_80BIT_CUSTOM,
+	DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE,
+
+	/* Link Training Patterns */
+	DP_TEST_PATTERN_TRAINING_PATTERN1,
+	DP_TEST_PATTERN_TRAINING_PATTERN2,
+	DP_TEST_PATTERN_TRAINING_PATTERN3,
+
+	/* link test patterns*/
+	DP_TEST_PATTERN_COLOR_SQUARES,
+	DP_TEST_PATTERN_COLOR_SQUARES_CEA,
+	DP_TEST_PATTERN_VERTICAL_BARS,
+	DP_TEST_PATTERN_HORIZONTAL_BARS,
+	DP_TEST_PATTERN_COLOR_RAMP,
+
+	/* audio test patterns*/
+	DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED,
+	DP_TEST_PATTERN_AUDIO_SAWTOOTH,
+
+	DP_TEST_PATTERN_UNSUPPORTED
+};
+
+enum dp_panel_mode {
+	/* not required */
+	DP_PANEL_MODE_DEFAULT,
+	/* standard mode for eDP */
+	DP_PANEL_MODE_EDP,
+	/* external chips specific settings */
+	DP_PANEL_MODE_SPECIAL
+};
+
+/**
+ * @brief LinkServiceInitOptions to set certain bits
+ */
+struct link_service_init_options {
+	uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1;
+};
+
+/**
+ * @brief data required to initialize LinkService
+ */
+struct link_service_init_data {
+	/* number of displays indices which the MST Mgr would manange*/
+	uint32_t num_of_displays;
+	enum link_service_type link_type;
+	/*struct mst_mgr_callback_object*topology_change_callback;*/
+	/* native aux access */
+	struct ddc_service *dpcd_access_srv;
+	/* for calling HWSS to program HW */
+	struct hw_sequencer *hwss;
+	/* the source which to register IRQ on */
+	enum dc_irq_source irq_src_hpd_rx;
+	enum dc_irq_source irq_src_dp_sink;
+	/* other init options such as SW Workarounds */
+	struct link_service_init_options init_options;
+	uint32_t connector_enum_id;
+	struct graphics_object_id connector_id;
+	struct adapter_service *adapter_service;
+	struct dc_context *ctx;
+	struct topology_mgr *tm;
+};
+
+/**
+ * @brief LinkServiceInitOptions to set certain bits
+ */
+struct LinkServiceInitOptions {
+	uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1;
+};
+
+/* DPCD_ADDR_TRAINING_LANEx_SET registers value */
+union dpcd_training_lane_set {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t VOLTAGE_SWING_SET:2;
+		uint8_t MAX_SWING_REACHED:1;
+		uint8_t PRE_EMPHASIS_SET:2;
+		uint8_t MAX_PRE_EMPHASIS_REACHED:1;
+		/* following is reserved in DP 1.1 */
+		uint8_t POST_CURSOR2_SET:2;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t POST_CURSOR2_SET:2;
+		uint8_t MAX_PRE_EMPHASIS_REACHED:1;
+		uint8_t PRE_EMPHASIS_SET:2;
+		uint8_t MAX_SWING_REACHED:1;
+		uint8_t VOLTAGE_SWING_SET:2;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+/* DPCD_ADDR_TRAINING_LANEx_SET2 registers value - since DP 1.2 */
+union dpcd_training_lanes_set2 {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t LANE0_POST_CURSOR2_SET:2;
+		uint8_t LANE0_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE0_RESERVED:1;
+		uint8_t LANE1_POST_CURSOR2_SET:2;
+		uint8_t LANE1_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE1_RESERVED:1;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t LANE1_RESERVED:1;
+		uint8_t LANE1_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE1_POST_CURSOR2_SET:2;
+		uint8_t LANE0_RESERVED:1;
+		uint8_t LANE0_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE0_POST_CURSOR2_SET:2;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+/**
+ * @brief represent the 16 byte
+ *  global unique identifier
+ */
+struct mst_guid {
+	uint8_t ids[16];
+};
+
+/**
+ * @brief represents the relative address used
+ * to identify a node in MST topology network
+ */
+struct mst_rad {
+	/* number of links. rad[0] up to
+	 * rad [linkCount - 1] are valid. */
+	uint32_t rad_link_count;
+	/* relative address. rad[0] is the
+	 * first device connected to the source.	*/
+	uint8_t rad[15];
+	/* extra 10 bytes for underscores; for e.g.:2_1_8*/
+	int8_t rad_str[25];
+};
+
+/**
+ * @brief this structure is used to report
+ * properties associated to a sink device
+ */
+struct mst_sink_info {
+	/* global unique identifier */
+	struct mst_guid guid;
+	/* relative address */
+	struct mst_rad  rad;
+	/* total bandwidth available on the DP connector */
+	uint32_t total_available_bandwidth_in_mbps;
+	/* bandwidth allocated to the sink device. */
+	uint32_t allocated_bandwidth_in_mbps;
+	/* bandwidth consumed to support for the current mode. */
+	uint32_t consumed_bandwidth_in_mbps;
+};
+
+/**
+ * @brief represent device information in MST topology
+ */
+struct mst_device_info {
+	/* global unique identifier*/
+	struct mst_guid guid;
+	/* relative address*/
+	struct mst_rad  rad;
+};
+
+/* DP MST stream allocation (payload bandwidth number) */
+struct dp_mst_stream_allocation {
+	uint8_t vcp_id;
+	/* number of slots required for the DP stream in
+	 * transport packet */
+	uint8_t slot_count;
+};
+
+/* DP MST stream allocation table */
+struct dp_mst_stream_allocation_table {
+	/* number of DP video streams */
+	int stream_count;
+	/* array of stream allocations */
+	struct dp_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM];
+};
+
+struct dp_test_event_data {
+	/*size of parameters (starting from params) in bytes*/
+	uint32_t size;
+	/*parameters block*/
+	uint32_t params[1];
+};
+
+struct psr_caps {
+	/* These parameters are from PSR capabilities reported by Sink DPCD. */
+	uint8_t psr_version;
+	uint32_t psr_rfb_setup_time;
+	bool psr_exit_link_training_req;
+
+	/* These parameters are calculated in Driver, based on display timing
+	 * and Sink capabilities.
+	 * If VBLANK region is too small and Sink takes a long time to power up
+	 * Remote Frame Buffer, it may take an extra frame to enter PSR */
+	bool psr_frame_capture_indication_req;
+	uint32_t psr_sdp_transmit_line_num_deadline;
+};
+
+#endif /*__DAL_LINK_SERVICE_TYPES_H__*/
diff --git a/drivers/gpu/drm/amd/dal/include/logger_interface.h b/drivers/gpu/drm/amd/dal/include/logger_interface.h
new file mode 100644
index 000000000000..4d945eabb07f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/logger_interface.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LOGGER_INTERFACE_H__
+#define __DAL_LOGGER_INTERFACE_H__
+
+#include "logger_types.h"
+
+struct dal_logger;
+struct dc_context;
+union logger_flags;
+
+/*
+ * TODO: This logger functionality needs to be implemented and reworked.
+ */
+
+
+/*
+ *
+ * DAL logger functionality
+ *
+ */
+
+struct dal_logger *dal_logger_create(struct dc_context *ctx);
+
+uint32_t dal_logger_destroy(struct dal_logger **logger);
+
+uint32_t dal_logger_get_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor);
+
+uint32_t dal_logger_set_mask(
+		struct dal_logger *logger,
+		enum log_major lvl_major, enum log_minor lvl_minor);
+
+uint32_t dal_logger_get_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major);
+
+void dal_logger_set_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major, uint32_t log_mask);
+
+uint32_t dal_logger_unset_mask(
+		struct dal_logger *logger,
+		enum log_major lvl_major, enum log_minor lvl_minor);
+
+bool dal_logger_should_log(
+		struct dal_logger *logger,
+		enum log_major major,
+		enum log_minor minor);
+
+uint32_t dal_logger_get_flags(
+		struct dal_logger *logger);
+
+void dal_logger_set_flags(
+		struct dal_logger *logger,
+		union logger_flags flags);
+
+void dal_logger_write(
+		struct dal_logger *logger,
+		enum log_major major,
+		enum log_minor minor,
+		const char *msg,
+		...);
+
+void dal_logger_append(
+		struct log_entry *entry,
+		const char *msg,
+		...);
+
+uint32_t dal_logger_read(
+		struct dal_logger *logger,
+		uint32_t output_buffer_size,
+		char *output_buffer,
+		uint32_t *bytes_read,
+		bool single_line);
+
+void dal_logger_open(
+		struct dal_logger *logger,
+		struct log_entry *entry,
+		enum log_major major,
+		enum log_minor minor);
+
+void dal_logger_close(struct log_entry *entry);
+
+uint32_t dal_logger_get_buffer_size(struct dal_logger *logger);
+
+uint32_t dal_logger_set_buffer_size(
+		struct dal_logger *logger,
+		uint32_t new_size);
+
+const struct log_major_info *dal_logger_enum_log_major_info(
+		struct dal_logger *logger,
+		unsigned int enum_index);
+
+const struct log_minor_info *dal_logger_enum_log_minor_info(
+		struct dal_logger *logger,
+		enum log_major major,
+		unsigned int enum_index);
+
+/* Any function which is empty or have incomplete implementation should be
+ * marked by this macro.
+ * Note that the message will be printed exactly once for every function
+ * it is used in order to avoid repeating of the same message. */
+#define DAL_LOGGER_NOT_IMPL(log_minor, fmt, ...) \
+{ \
+	static bool print_not_impl = true; \
+\
+	if (print_not_impl == true) { \
+		print_not_impl = false; \
+		dal_logger_write(ctx->logger, LOG_MAJOR_WARNING, \
+		log_minor, "DAL_NOT_IMPL: " fmt, ##__VA_ARGS__); \
+	} \
+}
+
+/******************************************************************************
+ * Convenience macros to save on typing.
+ *****************************************************************************/
+
+#define DC_ERROR(...) \
+	dal_logger_write(dc_ctx->logger, \
+		LOG_MAJOR_ERROR, LOG_MINOR_COMPONENT_DC, \
+		__VA_ARGS__);
+
+#define DC_SYNC_INFO(...) \
+	dal_logger_write(dc_ctx->logger, \
+		LOG_MAJOR_SYNC, LOG_MINOR_SYNC_TIMING, \
+		__VA_ARGS__);
+
+#endif /* __DAL_LOGGER_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/logger_types.h b/drivers/gpu/drm/amd/dal/include/logger_types.h
new file mode 100644
index 000000000000..614799907e19
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/logger_types.h
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LOGGER_TYPES_H__
+#define __DAL_LOGGER_TYPES_H__
+
+
+/*
+ * TODO: This logger functionality needs to be implemented and reworked.
+ */
+
+
+struct dal_logger;
+
+enum log_major {
+/*00*/
+	LOG_MAJOR_ERROR = 0,	/*< DAL subcomponent error MSG*/
+/*01*/  LOG_MAJOR_WARNING,	/*< DAL subcomponent warning MSG*/
+/*02*/  LOG_MAJOR_INTERFACE_TRACE,/*< DAL subcomponent interface tracing*/
+/*03*/  LOG_MAJOR_HW_TRACE,	/*< Log ASIC register read/write,
+				* ATOMBIOS exec table call and delays*/
+
+/*04*/  LOG_MAJOR_MST,		/*< related to multi-stream*/
+/*05*/  LOG_MAJOR_DCS,		/*< related to Dcs*/
+/*06*/  LOG_MAJOR_DCP,		/*< related to Dcp grph and ovl,gamam and csc*/
+/*07*/  LOG_MAJOR_BIOS,		/*< related to BiosParser*/
+/*08*/  LOG_MAJOR_REGISTER,	/*< register access*/
+/*09*/  LOG_MAJOR_INFO_PACKETS,	/*< info packets*/
+/*10*/  LOG_MAJOR_DSAT,		/*< related
+				*	to Display System Analysis Tool*/
+/*11*/  LOG_MAJOR_EC,		/*< External Components - MCIL Events/queries,
+				*	PPLib notifications/queries*/
+/*12*/  LOG_MAJOR_BWM,		/*< related to Bandwidth Manager*/
+/*13*/  LOG_MAJOR_MODE_ENUM,	/*< related to mode enumeration*/
+/*14*/  LOG_MAJOR_I2C_AUX,	/*< i2c and aux channel log*/
+/*15*/  LOG_MAJOR_LINE_BUFFER,	/*< Line Buffer object logging activity*/
+/*16*/  LOG_MAJOR_HWSS,		/*< HWSS object logging activity*/
+/*17*/  LOG_MAJOR_OPTIMIZATION,	/*< Optimization code path*/
+/*18*/  LOG_MAJOR_PERF_MEASURE,	/*< Performance measurement dumps*/
+/*19*/  LOG_MAJOR_SYNC,		/*< related to HW and SW Synchronization*/
+/*20*/  LOG_MAJOR_BACKLIGHT,	/*< related to backlight */
+/*21*/  LOG_MAJOR_INTERRUPTS,	/*< logging for all interrupts */
+
+/*22*/  LOG_MAJOR_TM,		/*< related to Topology Manager*/
+/*23*/  LOG_MAJOR_DISPLAY_SERVICE, /*< related to Display Service*/
+/*24*/	LOG_MAJOR_FEATURE_OVERRIDE,	/*< related to features*/
+/*25*/	LOG_MAJOR_DETECTION,	/*< related to detection*/
+	LOG_MAJOR_COUNT,	/*< count of the Major categories*/
+};
+
+/**
+* @brief defines minor switch for logging.  each of these define sub category
+*        of log message per LogMajor
+*/
+
+
+enum log_minor {
+
+	/* Special case for 'all' checkbox */
+	LOG_MINOR_MASK_ALL = (uint32_t)-1, /* 0xFFFFFFFF */
+/**
+* @brief defines minor category for
+*         LOG_MAJOR_ERROR,
+*         LOG_MAJOR_WARNING,
+*         LOG_MAJOR_INTERFACE_TRACE
+*
+* @note  each DAL subcomponent should have a corresponding enum
+*/
+	LOG_MINOR_COMPONENT_LINK_SERVICE = 0,
+	LOG_MINOR_COMPONENT_DAL_INTERFACE,
+	LOG_MINOR_COMPONENT_HWSS,
+	LOG_MINOR_COMPONENT_ADAPTER_SERVICE,
+	LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+	LOG_MINOR_COMPONENT_TOPOLOGY_MANAGER,
+	LOG_MINOR_COMPONENT_ENCODER,
+	LOG_MINOR_COMPONENT_I2C_AUX,
+	LOG_MINOR_COMPONENT_AUDIO,
+	LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE,
+	LOG_MINOR_COMPONENT_DMCU,
+	LOG_MINOR_COMPONENT_GPU,
+	LOG_MINOR_COMPONENT_CONTROLLER,
+	LOG_MINOR_COMPONENT_ISR,
+	LOG_MINOR_COMPONENT_BIOS,
+	LOG_MINOR_COMPONENT_DC,
+	LOG_MINOR_COMPONENT_IRQ_SERVICE,
+
+/**
+* @brief define minor category for LogMajor_HardwareTrace
+*
+* @note  defines functionality based HW programming trace
+*/
+	LOG_MINOR_HW_TRACE_MST = 0,
+	LOG_MINOR_HW_TRACE_TRAVIS,
+	LOG_MINOR_HW_TRACE_HOTPLUG,
+	LOG_MINOR_HW_TRACE_LINK_TRAINING,
+	LOG_MINOR_HW_TRACE_SET_MODE,
+	LOG_MINOR_HW_TRACE_RESUME_S3,
+	LOG_MINOR_HW_TRACE_RESUME_S4,
+	LOG_MINOR_HW_TRACE_BOOTUP,
+	LOG_MINOR_HW_TRACE_AUDIO,
+	LOG_MINOR_HW_TRACE_HPD_IRQ,
+	LOG_MINOR_HW_TRACE_INTERRUPT,
+	LOG_MINOR_HW_TRACE_MPO,
+
+/**
+* @brief defines minor category for LogMajor_Mst
+*
+* @note  define sub functionality related to MST
+*/
+	LOG_MINOR_MST_IRQ_HPD_RX = 0,
+	LOG_MINOR_MST_IRQ_TIMER,
+	LOG_MINOR_MST_NATIVE_AUX,
+	LOG_MINOR_MST_SIDEBAND_MSG,
+	LOG_MINOR_MST_MSG_TRANSACTION,
+	LOG_MINOR_MST_SIDEBAND_MSG_PARSED,
+	LOG_MINOR_MST_MSG_TRANSACTION_PARSED,
+	LOG_MINOR_MST_AUX_MSG_DPCD_ACCESS,
+	LOG_MINOR_MST_PROGRAMMING,
+	LOG_MINOR_MST_TOPOLOGY_DISCOVERY,
+	LOG_MINOR_MST_CONVERTER_CAPS,
+
+/**
+* @brief defines minor category for LogMajor_DCS
+*
+* @note  should define sub functionality related to Dcs
+*/
+	LOG_MINOR_DCS_EDID_EMULATOR = 0,
+	LOG_MINOR_DCS_DONGLE_DETECTION,
+
+/**
+* @brief defines minor category for DCP
+*
+* @note  should define sub functionality related to Dcp
+*/
+	LOG_MINOR_DCP_GAMMA_GRPH = 0,
+	LOG_MINOR_DCP_GAMMA_OVL,
+	LOG_MINOR_DCP_CSC_GRPH,
+	LOG_MINOR_DCP_CSC_OVL,
+	LOG_MINOR_DCP_SCALER,
+	LOG_MINOR_DCP_SCALER_TABLES,
+/**
+* @brief defines minor category for LogMajor_Bios
+*
+* @note define sub functionality related to BiosParser
+*/
+	LOG_MINOR_BIOS_CMD_TABLE = 0,
+/**
+* @brief defines minor category for LogMajor_Bios
+*
+* @note define sub functionality related to BiosParser
+*/
+	LOG_MINOR_REGISTER_INDEX = 0,
+/**
+* @brief defines minor category for info packets
+*
+*/
+	LOG_MINOR_INFO_PACKETS_HDMI = 0,
+
+/**
+* @brief defines minor category for LOG_MAJOR_DSAT
+*
+* @note define sub functionality related to Display System Analysis Tool
+*/
+	LOG_MINOR_DSAT_LOGGER = 0,
+	LOG_MINOR_DSAT_GET_EDID,
+	LOG_MINOR_DSAT_EDID_OVERRIDE,
+	LOG_MINOR_DSAT_SET_ADJUSTMENTS,
+	LOG_MINOR_DSAT_GET_ADJUSTMENTS,
+
+/**
+* @brief defines minor category for LOG_MAJOR_EC
+*
+* @note define sub functionality related to External components notifications
+*/
+	LOG_MINOR_EC_PPLIB_NOTIFY = 0,
+	LOG_MINOR_EC_PPLIB_QUERY,
+
+/**
+* @brief defines minor category for LOG_MAJOR_BWM
+*
+* @note define sub functionality related to Bandwidth Manager
+*/
+	LOG_MINOR_BWM_MODE_VALIDATION = 0,
+	LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS,
+
+/**
+* @brief define minor category for LogMajor_ModeEnum
+*
+* @note  defines functionality mode enumeration trace
+*/
+	LOG_MINOR_MODE_ENUM_BEST_VIEW_CANDIDATES = 0,
+	LOG_MINOR_MODE_ENUM_VIEW_SOLUTION,
+	LOG_MINOR_MODE_ENUM_TS_LIST_BUILD,
+	LOG_MINOR_MODE_ENUM_TS_LIST,
+	LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST,
+	LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST_UPDATE,
+
+/**
+* @brief defines minor category for LogMajor_I2C_AUX
+*
+* @note define sub functionality related to I2c and Aux Channel Log
+*/
+	LOG_MINOR_I2C_AUX_LOG = 0,
+	LOG_MINOR_I2C_AUX_AUX_TIMESTAMP,
+	LOG_MINOR_I2C_AUX_CFG,
+
+/**
+* @brief defines minor category for LogMajor_LineBuffer
+*
+* @note define sub functionality related to LineBuffer
+*/
+	LOG_MINOR_LINE_BUFFER_POWERGATING = 0,
+
+/**
+* @brief defines minor category for LogMajor_HWSS
+*
+* @note define sub functionality related to HWSS
+*/
+	LOG_MINOR_HWSS_TAPS_VALIDATION = 0,
+
+/**
+* @brief defines minor category for LogMajor_Optimization
+*
+* @note define sub functionality related to Optimization
+*/
+	LOG_MINOR_OPTMZ_GENERAL = 0,
+	LOG_MINOR_OPTMZ_DO_NOT_TURN_OFF_VCC_DURING_SET_MODE,
+
+/**
+* @brief defines minor category for LogMajor_PerfMeasure
+*
+* @note define sub functionality related to Performance measurement dumps
+*/
+	LOG_MINOR_PERF_MEASURE_GENERAL = 0,
+	LOG_MINOR_PERF_MEASURE_HEAP_MEMORY,
+
+/**
+* @brief defines minor category for LogMajor_Sync
+*
+* @note define sub functionality related to HW and SW Synchronization
+*/
+	LOG_MINOR_SYNC_HW_CLOCK_ADJUST = 0,
+	LOG_MINOR_SYNC_TIMING,
+
+/**
+* @brief defines minor category for LogMajor_Backlight
+*
+* @note define sub functionality related to backlight (including VariBright)
+*/
+	LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS = 0,
+	LOG_MINOR_BACKLIGHT_DMCU_DELTALUT,
+	LOG_MINOR_BACKLIGHT_DMCU_BUILD_DELTALUT,
+	LOG_MINOR_BACKLIGHT_INTERFACE,
+	LOG_MINOR_BACKLIGHT_LID,
+
+/**
+* @brief defines minor category for LOG_MAJOR_TM
+*
+* @note define sub functionality related to Topology Manager
+*/
+	LOG_MINOR_TM_INFO = 0,
+	LOG_MINOR_TM_IFACE_TRACE,
+	LOG_MINOR_TM_RESOURCES,
+	LOG_MINOR_TM_ENCODER_CTL,
+	LOG_MINOR_TM_ENG_ASN,
+	LOG_MINOR_TM_CONTROLLER_ASN,
+	LOG_MINOR_TM_PWR_GATING,
+	LOG_MINOR_TM_BUILD_DSP_PATH,
+	LOG_MINOR_TM_DISPLAY_DETECT,
+	LOG_MINOR_TM_LINK_SRV,
+	LOG_MINOR_TM_NOT_IMPLEMENTED,
+	LOG_MINOR_TM_COFUNC_PATH,
+
+/**
+* @brief defines minor category for LOG_MAJOR_DISPLAY_SERVICE
+*
+* @note define sub functionality related to Display Service
+*/
+	LOG_MINOR_DS_MODE_SETTING = 0,
+
+/**
+* @brief defines minor category for LOG_MAJOR_FEATURE_OVERRIDE
+*
+* @note define sub functionality related to features in adapter service
+*/
+	LOG_MINOR_FEATURE_OVERRIDE = 0,
+
+/**
+* @brief defines minor category for LOG_MAJOR_DETECTION
+*
+* @note define sub functionality related to detection
+*/
+	LOG_MINOR_DETECTION_EDID_PARSER = 0,
+	LOG_MINOR_DETECTION_DP_CAPS,
+};
+
+union logger_flags {
+	struct {
+		uint32_t ENABLE_CONSOLE:1; /* Print to console */
+		uint32_t ENABLE_BUFFER:1; /* Print to buffer */
+		uint32_t RESERVED:30;
+	} bits;
+	uint32_t value;
+};
+
+struct log_entry {
+
+	struct dal_logger *logger;
+	enum log_major major;
+	enum log_minor minor;
+
+	char *buf;
+	uint32_t buf_offset;
+	uint32_t max_buf_bytes;
+};
+
+/**
+* Structure for enumerating LogMajors and LogMinors
+*/
+
+#define MAX_MAJOR_NAME_LEN 32
+#define MAX_MINOR_NAME_LEN 32
+
+struct log_major_info {
+	enum log_major major;
+	char major_name[MAX_MAJOR_NAME_LEN];
+};
+
+struct log_minor_info {
+	enum log_minor minor;
+	char minor_name[MAX_MINOR_NAME_LEN];
+};
+
+#endif /* __DAL_LOGGER_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/scaler_types.h b/drivers/gpu/drm/amd/dal/include/scaler_types.h
new file mode 100644
index 000000000000..db52dbc72383
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/scaler_types.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SCALER_TYPES_H__
+#define __DAL_SCALER_TYPES_H__
+
+#include "signal_types.h"
+#include "fixed31_32.h"
+#include "dc_types.h"
+
+enum pixel_type {
+	PIXEL_TYPE_30BPP = 1,
+	PIXEL_TYPE_20BPP
+};
+
+/*overscan or window*/
+struct overscan_info {
+	uint32_t left;
+	uint32_t right;
+	uint32_t top;
+	uint32_t bottom;
+};
+
+struct mp_scaling_data {
+	struct rect viewport;
+	struct view dst_res;
+	struct overscan_info overscan;
+	struct scaling_taps taps;
+	struct scaling_ratios ratios;
+};
+
+struct scaler_validation_params {
+	uint32_t INTERLACED:1;
+	uint32_t CHROMA_SUB_SAMPLING:1;
+
+	uint32_t line_buffer_size;
+	uint32_t display_clock; /* in KHz */
+	uint32_t actual_pixel_clock; /* in KHz */
+	struct view source_view;
+	struct view dest_view;
+	enum signal_type signal_type;
+
+	struct scaling_taps taps_requested;
+	enum pixel_format pixel_format;
+	enum dc_rotation_angle rotation;
+};
+
+struct adjustment_factor {
+	int32_t adjust;	 /* Actual adjustment value * lDivider */
+	uint32_t divider;
+};
+
+struct sharpness_adjustment {
+	int32_t sharpness;
+	bool enable_sharpening;
+};
+
+enum scaling_options {
+	SCALING_BYPASS = 0,
+	SCALING_ENABLE
+};
+
+/* same as Hw register */
+enum filter_type {
+	FILTER_TYPE_V_LOW_PASS = 0x0,
+	FILTER_TYPE_V_HIGH_PASS = 0x1,
+	FILTER_TYPE_H_LUMA = 0x2,
+	FILTER_TYPE_H_CHROMA = 0x3
+};
+
+/* Validation Result enumeration */
+enum scaler_validation_code {
+	SCALER_VALIDATION_OK = 0,
+	SCALER_VALIDATION_INVALID_INPUT_PARAMETERS,
+	SCALER_VALIDATION_SCALING_RATIO_NOT_SUPPORTED,
+	SCALER_VALIDATION_SOURCE_VIEW_WIDTH_EXCEEDING_LIMIT,
+	SCALER_VALIDATION_DISPLAY_CLOCK_BELOW_PIXEL_CLOCK,
+	SCALER_VALIDATION_FAILURE_PREDEFINED_TAPS_NUMBER
+};
+
+
+#define FILTER_TYPE_MASK 0x0000000FL
+#define TWO_TAPS 2
+
+struct init_int_and_frac {
+	uint32_t integer;
+	uint32_t fraction;
+};
+
+struct scl_ratios_inits {
+	uint32_t bottom_enable;
+	uint32_t h_int_scale_ratio;
+	uint32_t v_int_scale_ratio;
+	struct init_int_and_frac h_init;
+	struct init_int_and_frac v_init;
+	struct init_int_and_frac v_init_bottom;
+};
+
+union scaler_flags {
+	uint32_t raw;
+	struct {
+		uint32_t INTERLACED:1;
+		uint32_t DOUBLE_SCAN_MODE:1;
+		/* this one is legacy flag only used in DCE80 */
+		uint32_t RGB_COLOR_SPACE:1;
+		uint32_t PIPE_LOCK_REQ:1;
+		/* 4 */
+		uint32_t WIDE_DISPLAY:1;
+		uint32_t OTHER_PIPE:1;
+		uint32_t SHOULD_PROGRAM_VIEWPORT:1;
+		uint32_t SHOULD_UNLOCK:1;
+		/* 8 */
+		uint32_t SHOULD_PROGRAM_ALPHA:1;
+		uint32_t SHOW_COLOURED_BORDER:1;
+
+		uint32_t  RESERVED:22;
+	} bits;
+};
+
+struct scaler_data {
+	struct view src_res;
+	struct view dst_res;
+	struct overscan_info overscan;
+	struct scaling_taps taps;
+	struct adjustment_factor scale_ratio_hp_factor;
+	struct adjustment_factor scale_ratio_lp_factor;
+	enum pixel_type pixel_type; /*legacy*/
+	struct sharpness_adjustment sharp_gain;
+
+	union scaler_flags flags;
+	int32_t h_sharpness;
+	int32_t v_sharpness;
+
+	struct view src_res_wide_display;
+	struct view dst_res_wide_display;
+
+	/* it is here because of the HW bug in NI (UBTS #269539)
+	causes glitches in this VBI signal. It shouldn't change after
+	initialization, kind of a const */
+	const struct hw_crtc_timing *hw_crtc_timing;
+
+	struct rect viewport;
+
+	enum pixel_format dal_pixel_format;/*plane concept*/
+	/*stereoformat TODO*/
+	/*hwtotation TODO*/
+
+	const struct scaling_ratios *ratios;
+};
+
+enum bypass_type {
+	/* 00 - 00 - Manual Centering, Manual Replication */
+	BYPASS_TYPE_MANUAL = 0,
+	/* 01 - 01 - Auto-Centering, No Replication */
+	BYPASS_TYPE_AUTO_CENTER = 1,
+	/* 02 - 10 - Auto-Centering, Auto-Replication */
+	BYPASS_TYPE_AUTO_REPLICATION = 3
+};
+
+struct replication_factor {
+	uint32_t h_manual;
+	uint32_t v_manual;
+};
+
+enum ram_filter_type {
+	FILTER_TYPE_RGB_Y_VERTICAL = 0,	/* 0 - RGB/Y Vertical filter */
+	FILTER_TYPE_CBCR_VERTICAL = 1,	/* 1 - CbCr  Vertical filter */
+	FILTER_TYPE_RGB_Y_HORIZONTAL   = 2, /* 1 - RGB/Y Horizontal filter */
+	FILTER_TYPE_CBCR_HORIZONTAL   = 3, /* 3 - CbCr  Horizontal filter */
+	FILTER_TYPE_ALPHA_VERTICAL    = 4, /* 4 - Alpha Vertical filter. */
+	FILTER_TYPE_ALPHA_HORIZONTAL  = 5, /* 5 - Alpha Horizontal filter. */
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/set_mode_types.h b/drivers/gpu/drm/amd/dal/include/set_mode_types.h
new file mode 100644
index 000000000000..97160fe7484c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/set_mode_types.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SET_MODE_TYPES_H__
+#define __DAL_SET_MODE_TYPES_H__
+
+#include "dc_types.h"
+
+
+/* GTC group number */
+enum gtc_group {
+	GTC_GROUP_DISABLED,
+	GTC_GROUP_1,
+	GTC_GROUP_2,
+	GTC_GROUP_3,
+	GTC_GROUP_4,
+	GTC_GROUP_5,
+	GTC_GROUP_6,
+	GTC_GROUP_MAX
+};
+
+/* Info frame packet status */
+enum info_frame_flag {
+	INFO_PACKET_PACKET_INVALID = 0,
+	INFO_PACKET_PACKET_VALID = 1,
+	INFO_PACKET_PACKET_RESET = 2,
+	INFO_PACKET_PACKET_UPDATE_SCAN_TYPE = 8
+};
+
+/* Info frame types */
+enum info_frame_type {
+	INFO_FRAME_GAMUT = 0x0A,
+	INFO_FRAME_VENDOR_INFO = 0x81,
+	INFO_FRAME_AVI = 0x82
+};
+
+/* Info frame versions */
+enum info_frame_version {
+	INFO_FRAME_VERSION_1 = 1,
+	INFO_FRAME_VERSION_2 = 2,
+	INFO_FRAME_VERSION_3 = 3
+};
+
+/* Info frame size */
+enum info_frame_size {
+	INFO_FRAME_SIZE_AVI = 13,
+	INFO_FRAME_SIZE_VENDOR = 25,
+	INFO_FRAME_SIZE_AUDIO = 10
+};
+
+struct hdmi_info_frame_header {
+	uint8_t info_frame_type;
+	uint8_t version;
+	uint8_t length;
+};
+
+#pragma pack(push)
+#pragma pack(1)
+
+struct info_packet_raw_data {
+	uint8_t hb0;
+	uint8_t hb1;
+	uint8_t hb2;
+	uint8_t sb[28]; /* sb0~sb27 */
+};
+
+union hdmi_info_packet {
+	struct avi_info_frame {
+		struct hdmi_info_frame_header header;
+
+		uint8_t CHECK_SUM:8;
+
+		uint8_t S0_S1:2;
+		uint8_t B0_B1:2;
+		uint8_t A0:1;
+		uint8_t Y0_Y1_Y2:3;
+
+		uint8_t R0_R3:4;
+		uint8_t M0_M1:2;
+		uint8_t C0_C1:2;
+
+		uint8_t SC0_SC1:2;
+		uint8_t Q0_Q1:2;
+		uint8_t EC0_EC2:3;
+		uint8_t ITC:1;
+
+		uint8_t VIC0_VIC7:8;
+
+		uint8_t PR0_PR3:4;
+		uint8_t CN0_CN1:2;
+		uint8_t YQ0_YQ1:2;
+
+		uint16_t bar_top;
+		uint16_t bar_bottom;
+		uint16_t bar_left;
+		uint16_t bar_right;
+
+		uint8_t reserved[14];
+	} bits;
+
+	struct info_packet_raw_data packet_raw_data;
+};
+
+struct info_packet {
+	enum info_frame_flag flags;
+	union hdmi_info_packet info_packet_hdmi;
+};
+
+struct info_frame {
+	struct info_packet avi_info_packet;
+	struct info_packet gamut_packet;
+	struct info_packet vendor_info_packet;
+	struct info_packet spd_info_packet;
+};
+
+
+
+#pragma pack(pop)
+
+#endif /* __DAL_SET_MODE_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/signal_types.h b/drivers/gpu/drm/amd/dal/include/signal_types.h
new file mode 100644
index 000000000000..a50f7ed74a33
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/signal_types.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_SIGNAL_TYPES_H__
+#define __DC_SIGNAL_TYPES_H__
+
+enum signal_type {
+	SIGNAL_TYPE_NONE		= 0L,		/* no signal */
+	SIGNAL_TYPE_DVI_SINGLE_LINK	= (1 << 0),
+	SIGNAL_TYPE_DVI_DUAL_LINK	= (1 << 1),
+	SIGNAL_TYPE_HDMI_TYPE_A		= (1 << 2),
+	SIGNAL_TYPE_LVDS		= (1 << 3),
+	SIGNAL_TYPE_RGB			= (1 << 4),
+	SIGNAL_TYPE_DISPLAY_PORT	= (1 << 5),
+	SIGNAL_TYPE_DISPLAY_PORT_MST	= (1 << 6),
+	SIGNAL_TYPE_EDP			= (1 << 7),
+	SIGNAL_TYPE_WIRELESS		= (1 << 8),	/* Wireless Display */
+	SIGNAL_TYPE_VIRTUAL		= (1 << 9),	/* Virtual Display */
+
+	SIGNAL_TYPE_COUNT		= 10,
+	SIGNAL_TYPE_ALL			= (1 << SIGNAL_TYPE_COUNT) - 1
+};
+
+/* help functions for signal types manipulation */
+bool dc_is_hdmi_signal(enum signal_type signal);
+bool dc_is_dp_sst_signal(enum signal_type signal);
+bool dc_is_dp_signal(enum signal_type signal);
+bool dc_is_dp_external_signal(enum signal_type signal);
+bool dc_is_analog_signal(enum signal_type signal);
+bool dc_is_embedded_signal(enum signal_type signal);
+bool dc_is_dvi_signal(enum signal_type signal);
+bool dc_is_dvi_single_link_signal(enum signal_type signal);
+bool dc_is_dual_link_signal(enum signal_type signal);
+bool dc_is_audio_capable_signal(enum signal_type signal);
+bool dc_is_digital_encoder_compatible_signal(enum signal_type signal);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/vector.h b/drivers/gpu/drm/amd/dal/include/vector.h
new file mode 100644
index 000000000000..8233b7c22a07
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/vector.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_VECTOR_H__
+#define __DAL_VECTOR_H__
+
+struct vector {
+	uint8_t *container;
+	uint32_t struct_size;
+	uint32_t count;
+	uint32_t capacity;
+	struct dc_context *ctx;
+};
+
+bool dal_vector_construct(
+	struct vector *vector,
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size);
+
+struct vector *dal_vector_create(
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size);
+
+/* 'initial_value' is optional. If initial_value not supplied,
+ * each "structure" in the vector will contain zeros by default. */
+struct vector *dal_vector_presized_create(
+	struct dc_context *ctx,
+	uint32_t size,
+	void *initial_value,
+	uint32_t struct_size);
+
+void dal_vector_destruct(
+	struct vector *vector);
+
+void dal_vector_destroy(
+	struct vector **vector);
+
+uint32_t dal_vector_get_count(
+	const struct vector *vector);
+
+/* dal_vector_insert_at
+ * reallocate container if necessary
+ * then shell items at right and insert
+ * return if the container modified
+ * do not check that index belongs to container
+ * since the function is private and index is going to be calculated
+ * either with by function or as get_count+1 */
+bool dal_vector_insert_at(
+	struct vector *vector,
+	const void *what,
+	uint32_t position);
+
+bool dal_vector_append(
+	struct vector *vector,
+	const void *item);
+
+/* operator[] */
+void *dal_vector_at_index(
+	const struct vector *vector,
+	uint32_t index);
+
+void dal_vector_set_at_index(
+	const struct vector *vector,
+	const void *what,
+	uint32_t index);
+
+/* create a clone (copy) of a vector */
+struct vector *dal_vector_clone(
+	const struct vector *vector_other);
+
+/* dal_vector_remove_at_index
+ * Shifts elements on the right from remove position to the left,
+ * removing an element at position by overwrite means*/
+bool dal_vector_remove_at_index(
+	struct vector *vector,
+	uint32_t index);
+
+uint32_t dal_vector_capacity(const struct vector *vector);
+
+bool dal_vector_reserve(struct vector *vector, uint32_t capacity);
+
+void dal_vector_clear(struct vector *vector);
+
+/***************************************************************************
+ * Macro definitions of TYPE-SAFE versions of vector set/get functions.
+ ***************************************************************************/
+
+#define DAL_VECTOR_INSERT_AT(vector_type, type_t) \
+	static bool vector_type##_vector_insert_at( \
+		struct vector *vector, \
+		type_t what, \
+		uint32_t position) \
+{ \
+	return dal_vector_insert_at(vector, what, position); \
+}
+
+#define DAL_VECTOR_APPEND(vector_type, type_t) \
+	static bool vector_type##_vector_append( \
+		struct vector *vector, \
+		type_t item) \
+{ \
+	return dal_vector_append(vector, item); \
+}
+
+/* Note: "type_t" is the ONLY token accepted by "checkpatch.pl" and by
+ * "checkcommit" as *return type*.
+ * For uniformity reasons "type_t" is used for all type-safe macro
+ * definitions here. */
+#define DAL_VECTOR_AT_INDEX(vector_type, type_t) \
+	static type_t vector_type##_vector_at_index( \
+		const struct vector *vector, \
+		uint32_t index) \
+{ \
+	return dal_vector_at_index(vector, index); \
+}
+
+#define DAL_VECTOR_SET_AT_INDEX(vector_type, type_t) \
+	static void vector_type##_vector_set_at_index( \
+		const struct vector *vector, \
+		type_t what, \
+		uint32_t index) \
+{ \
+	dal_vector_set_at_index(vector, what, index); \
+}
+
+#endif /* __DAL_VECTOR_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/video_csc_types.h b/drivers/gpu/drm/amd/dal/include/video_csc_types.h
new file mode 100644
index 000000000000..c229f5a7a325
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/video_csc_types.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_VIDEO_CSC_TYPES_H__
+#define __DAL_VIDEO_CSC_TYPES_H__
+
+#include "video_gamma_types.h"
+
+enum ovl_alpha_blending_mode {
+	OVL_ALPHA_PER_PIXEL_GRPH_ALPHA_MODE = 0,
+	OVL_ALPHA_PER_PIXEL_OVL_ALPHA_MODE
+};
+
+enum ovl_color_space {
+	OVL_COLOR_SPACE_UNKNOWN = 0,
+	OVL_COLOR_SPACE_RGB,
+	OVL_COLOR_SPACE_YUV601,
+	OVL_COLOR_SPACE_YUV709
+};
+
+enum ovl_surface_format {
+	OVL_SURFACE_FORMAT_UNKNOWN = 0,
+	OVL_SURFACE_FORMAT_YUY2,
+	OVL_SURFACE_FORMAT_UYVY,
+	OVL_SURFACE_FORMAT_RGB565,
+	OVL_SURFACE_FORMAT_RGB555,
+	OVL_SURFACE_FORMAT_RGB32,
+	OVL_SURFACE_FORMAT_YUV444,
+	OVL_SURFACE_FORMAT_RGB32_2101010
+};
+
+struct ovl_color_adjust_option {
+	uint32_t ALLOW_OVL_RGB_ADJUST:1;
+	uint32_t ALLOW_OVL_TEMPERATURE:1;
+	uint32_t FULL_RANGE:1; /* 0 for limited range it'is default for YUV */
+	uint32_t OVL_MATRIX:1;
+	uint32_t RESERVED:28;
+};
+
+struct overlay_adjust_item {
+	int32_t adjust; /* InInteger */
+	int32_t adjust_divider;
+};
+
+enum overlay_csc_adjust_type {
+	OVERLAY_CSC_ADJUST_TYPE_BYPASS = 0,
+	OVERLAY_CSC_ADJUST_TYPE_HW, /* without adjustments */
+	OVERLAY_CSC_ADJUST_TYPE_SW  /* use adjustments */
+};
+
+enum overlay_gamut_adjust_type {
+	OVERLAY_GAMUT_ADJUST_TYPE_BYPASS = 0,
+	OVERLAY_GAMUT_ADJUST_TYPE_SW /* use adjustments */
+};
+
+#define TEMPERATURE_MATRIX_SIZE 9
+#define MAXTRIX_SIZE TEMPERATURE_MAXTRIX_SIZE
+#define MAXTRIX_SIZE_WITH_OFFSET 12
+
+/* overlay adjustment input */
+union ovl_csc_flag {
+	uint32_t u_all;
+	struct {
+		uint32_t CONFIG_IS_CHANGED:1;
+		uint32_t RESERVED:31;
+	} bits;
+};
+
+struct ovl_csc_adjustment {
+	enum ovl_color_space ovl_cs;
+	struct ovl_color_adjust_option ovl_option;
+	enum dc_color_depth display_color_depth;
+	uint32_t lb_color_depth;
+	enum pixel_format desktop_surface_pixel_format;
+	enum ovl_surface_format ovl_sf;
+	/* API adjustment */
+	struct overlay_adjust_item overlay_brightness;
+	struct overlay_adjust_item overlay_gamma;
+	struct overlay_adjust_item overlay_contrast;
+	struct overlay_adjust_item overlay_saturation;
+	struct overlay_adjust_item overlay_hue; /* unit in degree from API. */
+	int32_t f_temperature[TEMPERATURE_MATRIX_SIZE];
+	uint32_t temperature_divider;
+	/* OEM/Application matrix related. */
+	int32_t matrix[MAXTRIX_SIZE_WITH_OFFSET];
+	uint32_t matrix_divider;
+
+	/* DCE50 parameters */
+	struct regamma_lut regamma;
+	enum overlay_gamma_adjust adjust_gamma_type;
+	enum overlay_csc_adjust_type adjust_csc_type;
+	enum overlay_gamut_adjust_type adjust_gamut_type;
+	union ovl_csc_flag flag;
+
+};
+
+enum ovl_csc_adjust_item {
+	OVERLAY_BRIGHTNESS = 0,
+	OVERLAY_GAMMA,
+	OVERLAY_CONTRAST,
+	OVERLAY_SATURATION,
+	OVERLAY_HUE,
+	OVERLAY_ALPHA,
+	OVERLAY_ALPHA_PER_PIX,
+	OVERLAY_COLOR_TEMPERATURE
+};
+
+struct input_csc_matrix {
+	enum color_space color_space;
+	uint16_t regval[12];
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/video_gamma_types.h b/drivers/gpu/drm/amd/dal/include/video_gamma_types.h
new file mode 100644
index 000000000000..6f9cd3fda21d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/video_gamma_types.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_VIDEO_GAMMA_TYPES_H__
+#define __DAL_VIDEO_GAMMA_TYPES_H__
+
+#include "set_mode_types.h"
+#include "gamma_types.h"
+
+enum overlay_gamma_adjust {
+	OVERLAY_GAMMA_ADJUST_BYPASS,
+	OVERLAY_GAMMA_ADJUST_HW, /* without adjustments */
+	OVERLAY_GAMMA_ADJUST_SW /* use adjustments */
+
+};
+
+union video_gamma_flag {
+	struct {
+		uint32_t CONFIG_IS_CHANGED:1;
+		uint32_t RESERVED:31;
+	} bits;
+	uint32_t u_all;
+};
+
+struct overlay_gamma_parameters {
+	union video_gamma_flag flag;
+	int32_t ovl_gamma_cont;
+	enum overlay_gamma_adjust adjust_type;
+	enum pixel_format desktop_surface;
+	struct regamma_lut regamma;
+
+	/* here we grow with parameters if necessary */
+};
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 02/29] drm/amd/dal: Add DAL Basic Types and Logger
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
  2016-02-11 17:19 ` [PATCH 01/29] drm/amd/dal: Add dal headers Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 03/29] drm/amd/dal: Fixed point arithmetic Harry Wentland
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Laying the groundwork for the AMD DAL display driver.
This patch includes the basic services and defines basic
types required by the display driver, such as:
- ASIC register access
- VBIOS access
- Vector and flat_set data structures
- Display signal types
- ASIC versions and IDs
- HW IDs
- Logging functionality

This patch adds Kconfig options to enable the DAL
display driver.
- DRM_AMD_DAL
- DRM_AMD_DAL_VBIOS_PRESENT
- DRM_AMD_DAL_DCE11_0
- DRM_AMD_DAL_DCE10_0
- DEBUG_KERNEL_DAL

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/Kconfig                    |  48 ++
 drivers/gpu/drm/amd/dal/Makefile                   |  21 +
 drivers/gpu/drm/amd/dal/dc/basics/Makefile         |  10 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.c     | 224 +++++
 drivers/gpu/drm/amd/dal/dc/basics/conversion.h     |  49 ++
 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c | 134 +++
 drivers/gpu/drm/amd/dal/dc/basics/logger.c         | 954 +++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/basics/logger.h         |  64 ++
 .../gpu/drm/amd/dal/dc/basics/register_logger.c    | 197 +++++
 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c   | 116 +++
 drivers/gpu/drm/amd/dal/dc/basics/vector.c         | 309 +++++++
 11 files changed, 2126 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/Kconfig
 create mode 100644 drivers/gpu/drm/amd/dal/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c

diff --git a/drivers/gpu/drm/amd/dal/Kconfig b/drivers/gpu/drm/amd/dal/Kconfig
new file mode 100644
index 000000000000..2289c0b10dae
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/Kconfig
@@ -0,0 +1,48 @@
+menu "Display Engine Configuration"
+	depends on DRM && (DRM_AMDSOC || DRM_AMDGPU)
+
+config DRM_AMD_DAL
+        bool "AMD DAL - Enable new display engine
+        help
+          Choose this option if you want to use the new display engine
+          support for AMD SOC.
+
+          Will be deprecated when the DAL component becomes stable and
+          AMDSOC will fully switch to it.
+
+config DRM_AMD_DAL_VBIOS_PRESENT
+        bool "Video Bios available on board"
+        depends on DRM_AMD_DAL
+        help
+         This option is needed to allow a full range of feature
+	 support when working on
+	 x86 platforms and there is a VBIOS
+	 present in the system
+
+config DRM_AMD_DAL_DCE11_0
+        bool "Carrizo family"
+        depends on DRM_AMD_DAL
+        help
+         Choose this option
+	 if you want to have
+	 CZ family
+	 for display engine
+
+config DRM_AMD_DAL_DCE10_0
+        bool "VI family"
+        depends on DRM_AMD_DAL
+        help
+         Choose this option
+	 if you want to have
+	 VI family for display
+	 engine.
+
+config DEBUG_KERNEL_DAL
+        bool "Enable kgdb break in DAL"
+        depends on DRM_AMD_DAL
+        help
+         Choose this option
+         if you want to hit
+         kdgb_break in assert.
+
+endmenu
diff --git a/drivers/gpu/drm/amd/dal/Makefile b/drivers/gpu/drm/amd/dal/Makefile
new file mode 100644
index 000000000000..25ae4646c4d3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the DAL (Display Abstract Layer), which is a  sub-component
+# of the AMDGPU drm driver.
+# It provides the HW control for display related functionalities.
+
+AMDDALPATH = $(RELATIVE_AMD_DAL_PATH)
+
+subdir-ccflags-y += -Werror
+
+subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include
+
+subdir-ccflags-y += -I$(FULL_AMD_DAL_PATH)/dc/inc/
+
+#TODO: remove when Timing Sync feature is complete
+subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
+
+DAL_LIBS = amdgpu_dm dc
+
+AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/,$(DAL_LIBS)))
+
+include $(AMD_DAL)
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/Makefile b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
new file mode 100644
index 000000000000..6f382812fae3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the 'utils' sub-component of DAL.
+# It provides the general basic services required by other DAL
+# subcomponents.
+
+BASICS = conversion.o grph_object_id.o logger.o register_logger.o signal_types.o vector.o
+
+AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS))
+
+AMD_DAL_FILES += $(AMD_DAL_BASICS)
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.c b/drivers/gpu/drm/amd/dal/dc/basics/conversion.c
new file mode 100644
index 000000000000..2f1f3d4ff96b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/conversion.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#include "dm_services.h"
+
+#define DIVIDER 10000
+
+/* S2D13 value in [-3.00...0.9999] */
+#define S2D13_MIN (-3 * DIVIDER)
+#define S2D13_MAX (3 * DIVIDER)
+
+uint16_t fixed_point_to_int_frac(
+	struct fixed31_32 arg,
+	uint8_t integer_bits,
+	uint8_t fractional_bits)
+{
+	int32_t numerator;
+	int32_t divisor = 1 << fractional_bits;
+
+	uint16_t result;
+
+	uint16_t d = (uint16_t)dal_fixed31_32_floor(
+		dal_fixed31_32_abs(
+			arg));
+
+	if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
+		numerator = (uint16_t)dal_fixed31_32_floor(
+			dal_fixed31_32_mul_int(
+				arg,
+				divisor));
+	else {
+		numerator = dal_fixed31_32_floor(
+			dal_fixed31_32_sub(
+				dal_fixed31_32_from_int(
+					1LL << integer_bits),
+				dal_fixed31_32_recip(
+					dal_fixed31_32_from_int(
+						divisor))));
+	}
+
+	if (numerator >= 0)
+		result = (uint16_t)numerator;
+	else
+		result = (uint16_t)(
+		(1 << (integer_bits + fractional_bits + 1)) + numerator);
+
+	if ((result != 0) && dal_fixed31_32_lt(
+		arg, dal_fixed31_32_zero))
+		result |= 1 << (integer_bits + fractional_bits);
+
+	return result;
+}
+/**
+* convert_float_matrix
+* This converts a double into HW register spec defined format S2D13.
+* @param :
+* @return None
+*/
+void convert_float_matrix(
+	uint16_t *matrix,
+	struct fixed31_32 *flt,
+	uint32_t buffer_size)
+{
+	const struct fixed31_32 min_2_13 =
+		dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER);
+	const struct fixed31_32 max_2_13 =
+		dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER);
+	uint32_t i;
+
+	for (i = 0; i < buffer_size; ++i) {
+		uint32_t reg_value =
+				fixed_point_to_int_frac(
+					dal_fixed31_32_clamp(
+						flt[i],
+						min_2_13,
+						max_2_13),
+						2,
+						13);
+
+		matrix[i] = (uint16_t)reg_value;
+	}
+}
+
+static void calculate_adjustments_common(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix)
+{
+	const struct fixed31_32 sin_hue =
+		dal_fixed31_32_sin(adjustments->hue);
+	const struct fixed31_32 cos_hue =
+		dal_fixed31_32_cos(adjustments->hue);
+
+	const struct fixed31_32 multiplier =
+		dal_fixed31_32_mul(
+			adjustments->contrast,
+			adjustments->saturation);
+
+	matrix[0] = dal_fixed31_32_mul(
+		ideal_matrix[0],
+		adjustments->contrast);
+
+	matrix[1] = dal_fixed31_32_mul(
+		ideal_matrix[1],
+		adjustments->contrast);
+
+	matrix[2] = dal_fixed31_32_mul(
+		ideal_matrix[2],
+		adjustments->contrast);
+
+	matrix[4] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(
+				ideal_matrix[8],
+				sin_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[4],
+				cos_hue)));
+
+	matrix[5] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(
+				ideal_matrix[9],
+				sin_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[5],
+				cos_hue)));
+
+	matrix[6] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(
+				ideal_matrix[10],
+				sin_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[6],
+				cos_hue)));
+
+	matrix[7] = ideal_matrix[7];
+
+	matrix[8] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				ideal_matrix[8],
+				cos_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[4],
+				sin_hue)));
+
+	matrix[9] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				ideal_matrix[9],
+				cos_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[5],
+				sin_hue)));
+
+	matrix[10] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				ideal_matrix[10],
+				cos_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[6],
+				sin_hue)));
+
+	matrix[11] = ideal_matrix[11];
+}
+
+void calculate_adjustments(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix)
+{
+	calculate_adjustments_common(ideal_matrix, adjustments, matrix);
+
+	matrix[3] = dal_fixed31_32_add(
+		ideal_matrix[3],
+		dal_fixed31_32_mul(
+			adjustments->brightness,
+			dal_fixed31_32_from_fraction(86, 100)));
+}
+
+void calculate_adjustments_y_only(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix)
+{
+	calculate_adjustments_common(ideal_matrix, adjustments, matrix);
+
+	matrix[3] = dal_fixed31_32_add(
+		ideal_matrix[3],
+		adjustments->brightness);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.h b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h
new file mode 100644
index 000000000000..24ff47352688
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_CONVERSION_H__
+#define __DAL_CONVERSION_H__
+
+uint16_t fixed_point_to_int_frac(
+	struct fixed31_32 arg,
+	uint8_t integer_bits,
+	uint8_t fractional_bits);
+
+void convert_float_matrix(
+	uint16_t *matrix,
+	struct fixed31_32 *flt,
+	uint32_t buffer_size);
+
+void calculate_adjustments(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix);
+
+void calculate_adjustments_y_only(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
new file mode 100644
index 000000000000..9c80847d03a9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/grph_object_id.h"
+
+bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
+{
+	bool rc = true;
+
+	switch (id.type) {
+	case OBJECT_TYPE_UNKNOWN:
+		rc = false;
+		break;
+	case OBJECT_TYPE_GPU:
+	case OBJECT_TYPE_ENGINE:
+		/* do NOT check for id.id == 0 */
+		if (id.enum_id == ENUM_ID_UNKNOWN)
+			rc = false;
+		break;
+	default:
+		if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
+			rc = false;
+		break;
+	}
+
+	return rc;
+}
+
+bool dal_graphics_object_id_is_equal(
+	struct graphics_object_id id1,
+	struct graphics_object_id id2)
+{
+	if (false == dal_graphics_object_id_is_valid(id1)) {
+		dm_output_to_console(
+		"%s: Warning: comparing invalid object 'id1'!\n", __func__);
+		return false;
+	}
+
+	if (false == dal_graphics_object_id_is_valid(id2)) {
+		dm_output_to_console(
+		"%s: Warning: comparing invalid object 'id2'!\n", __func__);
+		return false;
+	}
+
+	if (id1.id == id2.id && id1.enum_id == id2.enum_id
+		&& id1.type == id2.type)
+		return true;
+
+	return false;
+}
+
+/* Based on internal data members memory layout */
+uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id)
+{
+	uint32_t object_id = 0;
+
+	object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc);
+	return object_id;
+}
+
+/*
+ * ******* get specific ID - internal safe cast into specific type *******
+ */
+
+enum controller_id dal_graphics_object_id_get_controller_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_CONTROLLER)
+		return id.id;
+	return CONTROLLER_ID_UNDEFINED;
+}
+
+enum clock_source_id dal_graphics_object_id_get_clock_source_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_CLOCK_SOURCE)
+		return id.id;
+	return CLOCK_SOURCE_ID_UNDEFINED;
+}
+
+enum encoder_id dal_graphics_object_id_get_encoder_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_ENCODER)
+		return id.id;
+	return ENCODER_ID_UNKNOWN;
+}
+
+enum connector_id dal_graphics_object_id_get_connector_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_CONNECTOR)
+		return id.id;
+	return CONNECTOR_ID_UNKNOWN;
+}
+
+enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_AUDIO)
+		return id.id;
+	return AUDIO_ID_UNKNOWN;
+}
+
+enum engine_id dal_graphics_object_id_get_engine_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_ENGINE)
+		return id.id;
+	return ENGINE_ID_UNKNOWN;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.c b/drivers/gpu/drm/amd/dal/dc/basics/logger.c
new file mode 100644
index 000000000000..e7938ec9bb7c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.c
@@ -0,0 +1,954 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include <stdarg.h>
+#include "dm_services.h"
+#include "include/dal_types.h"
+#include "include/logger_interface.h"
+#include "logger.h"
+
+/* TODO: for now - empty, use DRM defines from dal services.
+		Need to define appropriate levels of prints, and implement
+		this component
+void dal_log(const char *format, ...)
+{
+}
+*/
+
+/* ----------- Logging Major/Minor names ------------ */
+
+#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
+
+static const struct log_minor_info component_minor_info_tbl[] = {
+	{LOG_MINOR_COMPONENT_LINK_SERVICE, "LS"},
+	{LOG_MINOR_COMPONENT_DAL_INTERFACE, "DalIf"},
+	{LOG_MINOR_COMPONENT_HWSS, "HWSS"},
+	{LOG_MINOR_COMPONENT_ADAPTER_SERVICE, "AS"},
+	{LOG_MINOR_COMPONENT_DISPLAY_SERVICE, "DS"},
+	{LOG_MINOR_COMPONENT_TOPOLOGY_MANAGER, "TM"},
+	{LOG_MINOR_COMPONENT_ENCODER, "Encoder"},
+	{LOG_MINOR_COMPONENT_I2C_AUX, "I2cAux"},
+	{LOG_MINOR_COMPONENT_AUDIO, "Audio"},
+	{LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE, "Dcs"},
+	{LOG_MINOR_COMPONENT_DMCU, "Dmcu"},
+	{LOG_MINOR_COMPONENT_GPU, "GPU"},
+	{LOG_MINOR_COMPONENT_CONTROLLER, "Cntrlr"},
+	{LOG_MINOR_COMPONENT_ISR, "ISR"},
+	{LOG_MINOR_COMPONENT_BIOS, "BIOS"},
+	{LOG_MINOR_COMPONENT_DC, "DC"},
+	{LOG_MINOR_COMPONENT_IRQ_SERVICE, "IRQ SERVICE"},
+
+};
+
+static const struct log_minor_info hw_trace_minor_info_tbl[] = {
+	{LOG_MINOR_HW_TRACE_MST, "Mst" },
+	{LOG_MINOR_HW_TRACE_TRAVIS, "Travis" },
+	{LOG_MINOR_HW_TRACE_HOTPLUG, "Hotplug" },
+	{LOG_MINOR_HW_TRACE_LINK_TRAINING, "LinkTraining" },
+	{LOG_MINOR_HW_TRACE_SET_MODE, "SetMode" },
+	{LOG_MINOR_HW_TRACE_RESUME_S3, "ResumeS3" },
+	{LOG_MINOR_HW_TRACE_RESUME_S4, "ResumeS4" },
+	{LOG_MINOR_HW_TRACE_BOOTUP, "BootUp" },
+	{LOG_MINOR_HW_TRACE_AUDIO, "Audio"},
+	{LOG_MINOR_HW_TRACE_HPD_IRQ, "HpdIrq" },
+	{LOG_MINOR_HW_TRACE_INTERRUPT, "Interrupt" },
+	{LOG_MINOR_HW_TRACE_MPO, "Planes" },
+};
+
+static const struct log_minor_info mst_minor_info_tbl[] = {
+	{LOG_MINOR_MST_IRQ_HPD_RX, "IrqHpdRx"},
+	{LOG_MINOR_MST_IRQ_TIMER, "IrqTimer"},
+	{LOG_MINOR_MST_NATIVE_AUX, "NativeAux"},
+	{LOG_MINOR_MST_SIDEBAND_MSG, "SB"},
+	{LOG_MINOR_MST_MSG_TRANSACTION, "MT"},
+	{LOG_MINOR_MST_SIDEBAND_MSG_PARSED, "SB Parsed"},
+	{LOG_MINOR_MST_MSG_TRANSACTION_PARSED, "MT Parsed"},
+	{LOG_MINOR_MST_AUX_MSG_DPCD_ACCESS, "AuxMsgDpcdAccess"},
+	{LOG_MINOR_MST_PROGRAMMING, "Programming"},
+	{LOG_MINOR_MST_TOPOLOGY_DISCOVERY, "TopologyDiscovery"},
+	{LOG_MINOR_MST_CONVERTER_CAPS, "ConverterCaps"},
+};
+
+static const struct log_minor_info dcs_minor_info_tbl[] = {
+	{LOG_MINOR_DCS_EDID_EMULATOR, "EdidEmul"},
+	{LOG_MINOR_DCS_DONGLE_DETECTION, "DongleDetect"},
+};
+
+static const struct log_minor_info dcp_minor_info_tbl[] = {
+	{ LOG_MINOR_DCP_GAMMA_GRPH, "GammaGrph"},
+	{ LOG_MINOR_DCP_GAMMA_OVL, "GammaOvl"},
+	{ LOG_MINOR_DCP_CSC_GRPH, "CscGrph"},
+	{ LOG_MINOR_DCP_CSC_OVL, "CscOvl"},
+	{ LOG_MINOR_DCP_SCALER, "Scaler"},
+	{ LOG_MINOR_DCP_SCALER_TABLES, "ScalerTables"},
+};
+
+static const struct log_minor_info bios_minor_info_tbl[] = {
+	{LOG_MINOR_BIOS_CMD_TABLE, "CmdTbl"},
+};
+
+static const struct log_minor_info reg_minor_info_tbl[] = {
+	{LOG_MINOR_REGISTER_INDEX, "Index"},
+};
+
+static const struct log_minor_info info_packet_minor_info_tbl[] = {
+	{LOG_MINOR_INFO_PACKETS_HDMI, "Hdmi"},
+};
+
+
+static const struct log_minor_info dsat_minor_info_tbl[] = {
+	{LOG_MINOR_DSAT_LOGGER, "Logger"},
+	{LOG_MINOR_DSAT_EDID_OVERRIDE, "EDID_Override"},
+};
+
+static const struct log_minor_info ec_minor_info_tbl[] = {
+	{LOG_MINOR_EC_PPLIB_NOTIFY, "PPLib_Notify" }, /* PPLib notifies DAL */
+	{LOG_MINOR_EC_PPLIB_QUERY, "PPLib_Query" } /* DAL requested info from
+							PPLib */
+};
+
+static const struct log_minor_info bwm_minor_info_tbl[] = {
+	{LOG_MINOR_BWM_MODE_VALIDATION, "ModeValidation"},
+	{LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS, "Req_Bandw_Calcs"}
+};
+
+static const struct log_minor_info mode_enum_minor_info_tbl[] = {
+	{LOG_MINOR_MODE_ENUM_BEST_VIEW_CANDIDATES, "BestviewCandidates"},
+	{LOG_MINOR_MODE_ENUM_VIEW_SOLUTION, "ViewSolution"},
+	{LOG_MINOR_MODE_ENUM_TS_LIST_BUILD, "TsListBuild"},
+	{LOG_MINOR_MODE_ENUM_TS_LIST, "TsList"},
+	{LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST, "MasterViewList"},
+	{LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST_UPDATE, "MasterViewListUpdate"},
+};
+
+static const struct log_minor_info i2caux_minor_info_tbl[] = {
+	{LOG_MINOR_I2C_AUX_LOG, "Log"},
+	{LOG_MINOR_I2C_AUX_AUX_TIMESTAMP, "Timestamp"},
+	{LOG_MINOR_I2C_AUX_CFG, "Config"}
+};
+
+static const struct log_minor_info line_buffer_minor_info_tbl[] = {
+	{LOG_MINOR_LINE_BUFFER_POWERGATING, "PowerGating"}
+};
+
+static const struct log_minor_info hwss_minor_info_tbl[] = {
+	{LOG_MINOR_HWSS_TAPS_VALIDATION, "HWSS Taps"}
+};
+
+static const struct log_minor_info optimization_minor_info_tbl[] = {
+	{LOG_MINOR_OPTMZ_GENERAL, "General Optimizations"},
+	{LOG_MINOR_OPTMZ_DO_NOT_TURN_OFF_VCC_DURING_SET_MODE,
+		"Skip Vcc Off During Set Mode"}
+};
+
+static const struct log_minor_info perf_measure_minor_info_tbl[] = {
+	{LOG_MINOR_PERF_MEASURE_GENERAL, "General Performance Measurement"},
+	{LOG_MINOR_PERF_MEASURE_HEAP_MEMORY, "Heap Memory Management"}
+};
+
+static const struct log_minor_info sync_minor_info_tbl[] = {
+	{LOG_MINOR_SYNC_HW_CLOCK_ADJUST, "Pixel Rate Tune-up"},
+	{LOG_MINOR_SYNC_TIMING, "Timing"}
+};
+
+static const struct log_minor_info backlight_minor_info_tbl[] = {
+	{LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS, "Caps"},
+	{LOG_MINOR_BACKLIGHT_DMCU_DELTALUT, "DMCU Delta LUT"},
+	{LOG_MINOR_BACKLIGHT_DMCU_BUILD_DELTALUT, "Build DMCU Delta LUT"},
+	{LOG_MINOR_BACKLIGHT_INTERFACE, "Interface"},
+	{LOG_MINOR_BACKLIGHT_LID, "Lid Status"}
+};
+
+
+static const struct log_minor_info override_feature_minor_info_tbl[] = {
+	{LOG_MINOR_FEATURE_OVERRIDE, "overriden feature"},
+};
+
+static const struct log_minor_info detection_minor_info_tbl[] = {
+	{LOG_MINOR_DETECTION_EDID_PARSER, "EDID Parser"},
+	{LOG_MINOR_DETECTION_DP_CAPS, "DP caps"},
+};
+
+static const struct log_minor_info tm_minor_info_tbl[] = {
+	{LOG_MINOR_TM_INFO, "INFO"},
+	{LOG_MINOR_TM_IFACE_TRACE, "IFACE_TRACE"},
+	{LOG_MINOR_TM_RESOURCES, "RESOURCES"},
+	{LOG_MINOR_TM_ENCODER_CTL, "ENCODER_CTL"},
+	{LOG_MINOR_TM_ENG_ASN, "ENG_ASN"},
+	{LOG_MINOR_TM_CONTROLLER_ASN, "CONTROLLER_ASN"},
+	{LOG_MINOR_TM_PWR_GATING, "PWR_GATING"},
+	{LOG_MINOR_TM_BUILD_DSP_PATH, "BUILD_PATH"},
+	{LOG_MINOR_TM_DISPLAY_DETECT, "DISPLAY_DETECT"},
+	{LOG_MINOR_TM_LINK_SRV,	"LINK_SRV"},
+	{LOG_MINOR_TM_NOT_IMPLEMENTED, "NOT_IMPL"},
+	{LOG_MINOR_TM_COFUNC_PATH, "COFUNC_PATH"}
+};
+
+static const struct log_minor_info ds_minor_info_tbl[] = {
+	{LOG_MINOR_DS_MODE_SETTING, "Mode_Setting"},
+};
+
+
+struct log_major_mask_info {
+	struct log_major_info major_info;
+	uint32_t default_mask;
+	const struct log_minor_info *minor_tbl;
+	uint32_t tbl_element_cnt;
+};
+
+/* A mask for each Major.
+ * Use a mask or zero. */
+#define LG_ERR_MSK 0xffffffff
+#define LG_WRN_MSK 0xffffffff
+#define LG_TM_MSK (1 << LOG_MINOR_TM_INFO)
+#define LG_FO_MSK (1 << LOG_MINOR_FEATURE_OVERRIDE)
+#define LG_EC_MSK ((1 << LOG_MINOR_EC_PPLIB_NOTIFY) | \
+			(1 << LOG_MINOR_EC_PPLIB_QUERY))
+#define LG_DSAT_MSK (1 << LOG_MINOR_DSAT_EDID_OVERRIDE)
+#define LG_DT_MSK (1 << LOG_MINOR_DETECTION_EDID_PARSER)
+
+/* IFT - InterFaceTrace */
+#define LG_IFT_MSK (1 << LOG_MINOR_COMPONENT_DC)
+
+
+#define LG_HW_TR_AUD_MSK (1 << LOG_MINOR_HW_TRACE_AUDIO)
+#define LG_HW_TR_INTERRUPT_MSK (1 << LOG_MINOR_HW_TRACE_INTERRUPT) | \
+		(1 << LOG_MINOR_HW_TRACE_HPD_IRQ)
+#define LG_HW_TR_PLANES_MSK (1 << LOG_MINOR_HW_TRACE_MPO)
+#define LG_ALL_MSK 0xffffffff
+#define LG_DCP_MSK ~(1 << LOG_MINOR_DCP_SCALER)
+
+#define LG_SYNC_MSK (1 << LOG_MINOR_SYNC_TIMING)
+
+#define LG_BWM_MSK (1 << LOG_MINOR_BWM_MODE_VALIDATION)
+
+static const struct log_major_mask_info log_major_mask_info_tbl[] = {
+	/* LogMajor                  major name       default     MinorTble                    tblElementCnt */
+	{{LOG_MAJOR_ERROR,           "Error"       }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_WARNING,         "Warning"     }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_INTERFACE_TRACE, "IfTrace"     }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_HW_TRACE,        "HwTrace"     }, (LG_ALL_MSK &
+			~((1 << LOG_MINOR_HW_TRACE_LINK_TRAINING) |
+			(1 << LOG_MINOR_HW_TRACE_AUDIO))),
+								hw_trace_minor_info_tbl,     NUM_ELEMENTS(hw_trace_minor_info_tbl)},
+	{{LOG_MAJOR_MST,             "MST"         }, LG_ALL_MSK, mst_minor_info_tbl,          NUM_ELEMENTS(mst_minor_info_tbl)},
+	{{LOG_MAJOR_DCS,             "DCS"         }, LG_ALL_MSK, dcs_minor_info_tbl,          NUM_ELEMENTS(dcs_minor_info_tbl)},
+	{{LOG_MAJOR_DCP,             "DCP"         }, LG_DCP_MSK, dcp_minor_info_tbl,          NUM_ELEMENTS(dcp_minor_info_tbl)},
+	{{LOG_MAJOR_BIOS,            "Bios"        }, LG_ALL_MSK, bios_minor_info_tbl,         NUM_ELEMENTS(bios_minor_info_tbl)},
+	{{LOG_MAJOR_REGISTER,        "Register"    }, LG_ALL_MSK, reg_minor_info_tbl,          NUM_ELEMENTS(reg_minor_info_tbl)},
+	{{LOG_MAJOR_INFO_PACKETS,    "InfoPacket"  }, LG_ALL_MSK, info_packet_minor_info_tbl,  NUM_ELEMENTS(info_packet_minor_info_tbl)},
+	{{LOG_MAJOR_DSAT,            "DSAT"        }, LG_ALL_MSK, dsat_minor_info_tbl,         NUM_ELEMENTS(dsat_minor_info_tbl)},
+	{{LOG_MAJOR_EC,              "EC"          }, LG_ALL_MSK, ec_minor_info_tbl,           NUM_ELEMENTS(ec_minor_info_tbl)},
+	{{LOG_MAJOR_BWM,             "BWM"         }, LG_BWM_MSK, bwm_minor_info_tbl,          NUM_ELEMENTS(bwm_minor_info_tbl)},
+	{{LOG_MAJOR_MODE_ENUM,       "ModeEnum"    }, LG_ALL_MSK, mode_enum_minor_info_tbl,    NUM_ELEMENTS(mode_enum_minor_info_tbl)},
+	{{LOG_MAJOR_I2C_AUX,         "I2cAux"      }, LG_ALL_MSK, i2caux_minor_info_tbl,       NUM_ELEMENTS(i2caux_minor_info_tbl)},
+	{{LOG_MAJOR_LINE_BUFFER,     "LineBuffer"  }, LG_ALL_MSK, line_buffer_minor_info_tbl,  NUM_ELEMENTS(line_buffer_minor_info_tbl)},
+	{{LOG_MAJOR_HWSS,            "HWSS"        }, LG_ALL_MSK, hwss_minor_info_tbl,         NUM_ELEMENTS(hwss_minor_info_tbl)},
+	{{LOG_MAJOR_OPTIMIZATION,    "Optimization"}, LG_ALL_MSK, optimization_minor_info_tbl, NUM_ELEMENTS(optimization_minor_info_tbl)},
+	{{LOG_MAJOR_PERF_MEASURE,    "PerfMeasure" }, LG_ALL_MSK, perf_measure_minor_info_tbl, NUM_ELEMENTS(perf_measure_minor_info_tbl)},
+	{{LOG_MAJOR_SYNC,            "Sync"        }, LG_SYNC_MSK,sync_minor_info_tbl,         NUM_ELEMENTS(sync_minor_info_tbl)},
+	{{LOG_MAJOR_BACKLIGHT,       "Backlight"   }, LG_ALL_MSK, backlight_minor_info_tbl,    NUM_ELEMENTS(backlight_minor_info_tbl)},
+	{{LOG_MAJOR_INTERRUPTS,      "Interrupts"  }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_TM,              "TM"          }, 0,          tm_minor_info_tbl,           NUM_ELEMENTS(tm_minor_info_tbl)},
+	{{LOG_MAJOR_DISPLAY_SERVICE, "DS"          }, LG_ALL_MSK, ds_minor_info_tbl,           NUM_ELEMENTS(ds_minor_info_tbl)},
+	{{LOG_MAJOR_FEATURE_OVERRIDE, "FeatureOverride" }, LG_ALL_MSK, override_feature_minor_info_tbl, NUM_ELEMENTS(override_feature_minor_info_tbl)},
+	{{LOG_MAJOR_DETECTION,       "Detection"   }, LG_ALL_MSK,  detection_minor_info_tbl,    NUM_ELEMENTS(detection_minor_info_tbl)},
+};
+
+/* ----------- Object init and destruction ----------- */
+static bool construct(struct dc_context *ctx, struct dal_logger *logger)
+{
+	uint32_t i;
+	/* malloc buffer and init offsets */
+
+	logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE;
+	logger->log_buffer = (char *)dm_alloc(ctx,
+		logger->log_buffer_size *
+		sizeof(char));
+
+	if (!logger->log_buffer)
+		return false;
+
+	/* todo: Fill buffer with \0 if not done by dal_alloc */
+
+	/* Initialize both offsets to start of buffer (empty) */
+	logger->buffer_read_offset = 0;
+	logger->buffer_write_offset = 0;
+
+	logger->write_wrap_count = 0;
+	logger->read_wrap_count = 0;
+	logger->open_count = 0;
+
+	logger->flags.bits.ENABLE_CONSOLE = 1;
+	logger->flags.bits.ENABLE_BUFFER = 0;
+
+	logger->ctx = ctx;
+
+	/* malloc and init minor mask array */
+	logger->log_enable_mask_minors =
+			(uint32_t *)dm_alloc(
+				ctx,
+				NUM_ELEMENTS(log_major_mask_info_tbl)
+				* sizeof(uint32_t));
+	if (!logger->log_enable_mask_minors)
+		return false;
+
+
+	/* Set default values for mask */
+	for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) {
+
+		uint32_t dflt_mask = log_major_mask_info_tbl[i].default_mask;
+
+		logger->log_enable_mask_minors[i] = dflt_mask;
+	}
+
+	return true;
+}
+
+static void destruct(struct dal_logger *logger)
+{
+	if (logger->log_buffer) {
+		dm_free(logger->ctx, logger->log_buffer);
+		logger->log_buffer = NULL;
+	}
+
+	if (logger->log_enable_mask_minors) {
+		dm_free(logger->ctx, logger->log_enable_mask_minors);
+		logger->log_enable_mask_minors = NULL;
+	}
+}
+
+struct dal_logger *dal_logger_create(struct dc_context *ctx)
+{
+	/* malloc struct */
+	struct dal_logger *logger = dm_alloc(ctx, sizeof(struct dal_logger));
+
+	if (!logger)
+		return NULL;
+	if (!construct(ctx, logger)) {
+		dm_free(ctx, logger);
+		return NULL;
+	}
+
+	return logger;
+}
+
+uint32_t dal_logger_destroy(struct dal_logger **logger)
+{
+	if (logger == NULL || *logger == NULL)
+		return 1;
+	destruct(*logger);
+	dm_free((*logger)->ctx, *logger);
+	*logger = NULL;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void lock(struct dal_logger *logger)
+{
+	/* Todo: lock mutex? */
+}
+
+static void unlock(struct dal_logger *logger)
+{
+	/* Todo: unlock mutex */
+}
+
+bool dal_logger_should_log(
+	struct dal_logger *logger,
+	enum log_major major,
+	enum log_minor minor)
+{
+	if (major < LOG_MAJOR_COUNT) {
+
+		uint32_t minor_mask = logger->log_enable_mask_minors[major];
+
+		if ((minor_mask & (1 << minor)) != 0)
+			return true;
+	}
+
+	return false;
+}
+
+static void log_to_debug_console(struct log_entry *entry)
+{
+	struct dal_logger *logger = entry->logger;
+
+	if (logger->flags.bits.ENABLE_CONSOLE == 0)
+		return;
+
+	if (entry->buf_offset) {
+		switch (entry->major) {
+		case LOG_MAJOR_ERROR:
+			dm_error("%s", entry->buf);
+			break;
+		default:
+			dm_output_to_console("%s", entry->buf);
+			break;
+		}
+	}
+}
+
+/* Print everything unread existing in log_buffer to debug console*/
+static void flush_to_debug_console(struct dal_logger *logger)
+{
+	int i = logger->buffer_read_offset;
+	char *string_start = &logger->log_buffer[i];
+
+	dm_output_to_console(
+		"---------------- FLUSHING LOG BUFFER ----------------\n");
+	while (i < logger->buffer_write_offset)	{
+
+		if (logger->log_buffer[i] == '\0') {
+			dm_output_to_console("%s", string_start);
+			string_start = (char *)logger->log_buffer + i + 1;
+		}
+		i++;
+	}
+	dm_output_to_console(
+		"-------------- END FLUSHING LOG BUFFER --------------\n\n");
+}
+
+static void log_to_internal_buffer(struct log_entry *entry)
+{
+
+	uint32_t size = entry->buf_offset;
+	struct dal_logger *logger = entry->logger;
+
+	if (logger->flags.bits.ENABLE_BUFFER == 0)
+		return;
+
+	if (logger->log_buffer == NULL)
+		return;
+
+	if (size > 0 && size < logger->log_buffer_size) {
+
+		int total_free_space = 0;
+		int space_before_wrap = 0;
+
+		if (logger->buffer_write_offset > logger->buffer_read_offset) {
+			total_free_space = logger->log_buffer_size -
+					logger->buffer_write_offset +
+					logger->buffer_read_offset;
+			space_before_wrap = logger->log_buffer_size -
+					logger->buffer_write_offset;
+		} else if (logger->buffer_write_offset <
+				logger->buffer_read_offset) {
+			total_free_space = logger->log_buffer_size -
+					logger->buffer_read_offset +
+					logger->buffer_write_offset;
+			space_before_wrap = total_free_space;
+		} else if (logger->write_wrap_count !=
+				logger->read_wrap_count) {
+			/* Buffer is completely full already */
+			total_free_space = 0;
+			space_before_wrap = 0;
+		} else {
+			/* Buffer is empty, start writing at beginning */
+			total_free_space = logger->log_buffer_size;
+			space_before_wrap = logger->log_buffer_size;
+			logger->buffer_write_offset = 0;
+			logger->buffer_read_offset = 0;
+		}
+
+
+
+
+		if (space_before_wrap > size) {
+			/* No wrap around, copy 'size' bytes
+			 * from 'entry->buf' to 'log_buffer'
+			 */
+			dm_memmove(logger->log_buffer +
+					logger->buffer_write_offset,
+					entry->buf, size);
+			logger->buffer_write_offset += size;
+
+		} else if (total_free_space > size) {
+			/* We have enough room without flushing,
+			 * but need to wrap around */
+
+			int space_after_wrap = total_free_space -
+					space_before_wrap;
+
+			dm_memmove(logger->log_buffer +
+					logger->buffer_write_offset,
+					entry->buf, space_before_wrap);
+			dm_memmove(logger->log_buffer, entry->buf +
+					space_before_wrap, space_after_wrap);
+
+			logger->buffer_write_offset = space_after_wrap;
+			logger->write_wrap_count++;
+
+		} else {
+			/* Not enough room remaining, we should flush
+			 * existing logs */
+
+			/* Flush existing unread logs to console */
+			flush_to_debug_console(logger);
+
+			/* Start writing to beginning of buffer */
+			dm_memmove(logger->log_buffer, entry->buf, size);
+			logger->buffer_write_offset = size;
+			logger->buffer_read_offset = 0;
+		}
+
+	}
+
+	unlock(logger);
+}
+
+
+static void log_timestamp(struct log_entry *entry)
+{
+	dal_logger_append(entry, "00:00:00 ");
+}
+
+static void log_major_minor(struct log_entry *entry)
+{
+	uint32_t i;
+	enum log_major major = entry->major;
+	enum log_minor minor = entry->minor;
+
+	for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) {
+
+		const struct log_major_mask_info *maj_mask_info =
+				&log_major_mask_info_tbl[i];
+
+		if (maj_mask_info->major_info.major == major) {
+
+			dal_logger_append(entry, "[%s_",
+					maj_mask_info->major_info.major_name);
+
+			if (maj_mask_info->minor_tbl != NULL) {
+				uint32_t j;
+
+				for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) {
+
+					const struct log_minor_info *min_info = &maj_mask_info->minor_tbl[j];
+
+					if (min_info->minor == minor)
+						dal_logger_append(entry, "%s]\t", min_info->minor_name);
+				}
+			}
+
+			break;
+		}
+	}
+}
+
+static void log_heading(struct log_entry *entry,
+			enum log_major major,
+			enum log_minor minor)
+{
+	log_timestamp(entry);
+	log_major_minor(entry);
+}
+
+
+static void append_entry(
+		struct log_entry *entry,
+		char *buffer,
+		uint32_t buf_size)
+{
+	if (!entry->buf ||
+		entry->buf_offset + buf_size > entry->max_buf_bytes
+	) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	/* Todo: check if off by 1 byte due to \0 anywhere */
+	dm_memmove(entry->buf + entry->buf_offset, buffer, buf_size);
+	entry->buf_offset += buf_size;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Warning: Be careful that 'msg' is null terminated and the total size is
+ * less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0'
+ */
+void dal_logger_write(
+	struct dal_logger *logger,
+	enum log_major major,
+	enum log_minor minor,
+	const char *msg,
+	...)
+{
+
+	if (logger && dal_logger_should_log(logger, major, minor)) {
+
+		uint32_t size;
+		va_list args;
+		char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE];
+		struct log_entry entry;
+
+		va_start(args, msg);
+		dal_logger_open(logger, &entry, major, minor);
+
+
+		size = dm_log_to_buffer(
+			buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args);
+
+		if (size > 0 && size <
+				DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) {
+
+			if (buffer[size] == '\0')
+				size++; /* Add one for null terminator */
+
+			/* Concatenate onto end of entry buffer */
+			append_entry(&entry, buffer, size);
+		} else {
+			append_entry(&entry,
+				"LOG_ERROR, line too long or null\n", 35);
+		}
+
+		dal_logger_close(&entry);
+		va_end(args);
+
+	}
+}
+
+
+/* Same as dal_logger_write, except without open() and close(), which must
+ * be done separately.
+ */
+void dal_logger_append(
+	struct log_entry *entry,
+	const char *msg,
+	...)
+{
+	struct dal_logger *logger;
+
+	if (!entry) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	logger = entry->logger;
+
+	if (logger && logger->open_count > 0 &&
+		dal_logger_should_log(logger, entry->major, entry->minor)) {
+
+		uint32_t size;
+		va_list args;
+		char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE];
+
+		va_start(args, msg);
+
+		size = dm_log_to_buffer(
+			buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args);
+
+		if (size < DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) {
+			append_entry(entry, buffer, size);
+		} else {
+			append_entry(entry, "LOG_ERROR, line too long\n", 27);
+		}
+
+		va_end(args);
+	}
+}
+
+
+uint32_t dal_logger_read(
+	struct dal_logger *logger, /* <[in] */
+	uint32_t output_buffer_size, /* <[in] */
+	char *output_buffer, /* >[out] */
+	uint32_t *bytes_read, /* >[out] */
+	bool single_line)
+{
+	uint32_t bytes_remaining = 0;
+	uint32_t bytes_read_count = 0;
+	bool keep_reading = true;
+
+	if (!logger || output_buffer == NULL || output_buffer_size == 0) {
+		BREAK_TO_DEBUGGER();
+		*bytes_read = 0;
+		return 0;
+	}
+
+	lock(logger);
+
+	/* Read until null terminator (if single_line==true,
+	 *  max buffer size, or until we've read everything new
+	 */
+
+	do {
+		char cur;
+
+		/* Stop when we've read everything */
+		if (logger->buffer_read_offset ==
+			logger->buffer_write_offset) {
+
+			break;
+		}
+
+		cur = logger->log_buffer[logger->buffer_read_offset];
+		logger->buffer_read_offset++;
+
+		/* Wrap read pointer if at end */
+		if (logger->buffer_read_offset == logger->log_buffer_size) {
+
+			logger->buffer_read_offset = 0;
+			logger->read_wrap_count++;
+		}
+
+		/* Don't send null terminators to buffer */
+		if (cur != '\0') {
+			output_buffer[bytes_read_count] = cur;
+			bytes_read_count++;
+		} else if (single_line) {
+			keep_reading = false;
+		}
+
+	} while (bytes_read_count <= output_buffer_size && keep_reading);
+
+	/* We assume that reading can never be ahead of writing */
+	if (logger->write_wrap_count > logger->read_wrap_count) {
+		bytes_remaining = logger->log_buffer_size -
+			logger->buffer_read_offset +
+			logger->buffer_write_offset;
+	} else {
+		bytes_remaining = logger->buffer_write_offset -
+				logger->buffer_read_offset;
+	}
+
+	/* reset write/read wrap count to 0 if we've read everything */
+	if (bytes_remaining == 0) {
+
+		logger->write_wrap_count = 0;
+		logger->read_wrap_count = 0;
+	}
+
+	*bytes_read = bytes_read_count;
+	unlock(logger);
+
+	return bytes_remaining;
+}
+
+void dal_logger_open(
+		struct dal_logger *logger,
+		struct log_entry *entry, /* out */
+		enum log_major major,
+		enum log_minor minor)
+{
+	if (!entry) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	entry->major = LOG_MAJOR_COUNT;
+	entry->minor = 0;
+	entry->logger = logger;
+
+	entry->buf = dm_alloc(
+		logger->ctx,
+		DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char));
+
+	entry->buf_offset = 0;
+	entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char);
+
+	logger->open_count++;
+	entry->major = major;
+	entry->minor = minor;
+
+	log_heading(entry, major, minor);
+}
+
+void dal_logger_close(struct log_entry *entry)
+{
+	struct dal_logger *logger = entry->logger;
+
+
+	if (logger && logger->open_count > 0) {
+		logger->open_count--;
+	} else {
+		BREAK_TO_DEBUGGER();
+		goto cleanup;
+	}
+
+	/* --Flush log_entry buffer-- */
+	/* print to kernel console */
+	log_to_debug_console(entry);
+	/* log internally for dsat */
+	log_to_internal_buffer(entry);
+
+	/* TODO: Write end heading */
+
+cleanup:
+	if (entry->buf) {
+		dm_free(entry->logger->ctx, entry->buf);
+		entry->buf = NULL;
+		entry->buf_offset = 0;
+		entry->max_buf_bytes = 0;
+	}
+}
+
+uint32_t dal_logger_get_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor)
+{
+	uint32_t log_mask = 0;
+
+	if (logger && lvl_major < LOG_MAJOR_COUNT)
+		log_mask = logger->log_enable_mask_minors[lvl_major];
+
+	log_mask &= 1 << lvl_minor;
+	return log_mask;
+}
+
+uint32_t dal_logger_set_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor)
+{
+
+	if (logger && lvl_major < LOG_MAJOR_COUNT) {
+		if (lvl_minor == LOG_MINOR_MASK_ALL) {
+			logger->log_enable_mask_minors[lvl_major] = 0xFFFFFFFF;
+		} else {
+			logger->log_enable_mask_minors[lvl_major] |=
+				(1 << lvl_minor);
+		}
+		return 0;
+	}
+	return 1;
+}
+
+uint32_t dal_logger_get_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major)
+{
+	uint32_t log_mask = 0;
+
+	if (logger && lvl_major < LOG_MAJOR_COUNT)
+		log_mask = logger->log_enable_mask_minors[lvl_major];
+
+	return log_mask;
+}
+
+void dal_logger_set_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major, uint32_t log_mask)
+{
+	if (logger && lvl_major < LOG_MAJOR_COUNT)
+		logger->log_enable_mask_minors[lvl_major] = log_mask;
+}
+
+uint32_t dal_logger_unset_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor)
+{
+
+	if (lvl_major < LOG_MAJOR_COUNT) {
+		if (lvl_minor == LOG_MINOR_MASK_ALL) {
+			logger->log_enable_mask_minors[lvl_major] = 0;
+		} else {
+			logger->log_enable_mask_minors[lvl_major] &=
+				~(1 << lvl_minor);
+		}
+		return 0;
+	}
+	return 1;
+}
+
+uint32_t dal_logger_get_flags(
+		struct dal_logger *logger)
+{
+
+	return logger->flags.value;
+}
+
+void dal_logger_set_flags(
+		struct dal_logger *logger,
+		union logger_flags flags)
+{
+
+	logger->flags = flags;
+}
+
+
+uint32_t dal_logger_get_buffer_size(struct dal_logger *logger)
+{
+	return DAL_LOGGER_BUFFER_MAX_SIZE;
+}
+
+uint32_t dal_logger_set_buffer_size(
+		struct dal_logger *logger,
+		uint32_t new_size)
+{
+	/* ToDo: implement dynamic size */
+
+	/* return new size */
+	return DAL_LOGGER_BUFFER_MAX_SIZE;
+}
+
+
+const struct log_major_info *dal_logger_enum_log_major_info(
+		struct dal_logger *logger,
+		unsigned int enum_index)
+{
+	const struct log_major_info *major_info;
+
+	if (enum_index >= NUM_ELEMENTS(log_major_mask_info_tbl))
+		return NULL;
+
+	major_info = &log_major_mask_info_tbl[enum_index].major_info;
+	return major_info;
+}
+
+const struct log_minor_info *dal_logger_enum_log_minor_info(
+		struct dal_logger *logger,
+		enum log_major major,
+		unsigned int enum_index)
+{
+	const struct log_minor_info *minor_info = NULL;
+	uint32_t i;
+
+	for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) {
+
+		const struct log_major_mask_info *maj_mask_info =
+				&log_major_mask_info_tbl[i];
+
+		if (maj_mask_info->major_info.major == major) {
+
+			if (maj_mask_info->minor_tbl != NULL) {
+				uint32_t j;
+
+				for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) {
+
+					minor_info = &maj_mask_info->minor_tbl[j];
+
+					if (minor_info->minor == enum_index)
+						return minor_info;
+				}
+			}
+
+			break;
+		}
+	}
+	return NULL;
+
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.h b/drivers/gpu/drm/amd/dal/dc/basics/logger.h
new file mode 100644
index 000000000000..fba5ec3264b6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LOGGER_H__
+#define __DAL_LOGGER_H__
+
+/* Structure for keeping track of offsets, buffer, etc */
+
+#define DAL_LOGGER_BUFFER_MAX_SIZE 2048
+#define DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE 256
+
+
+#include "include/logger_types.h"
+
+struct dal_logger {
+
+	/* How far into the circular buffer has been read by dsat
+	 * Read offset should never cross write offset. Write \0's to
+	 * read data just to be sure?
+	 */
+	uint32_t buffer_read_offset;
+
+	/* How far into the circular buffer we have written
+	 * Write offset should never cross read offset
+	 */
+	uint32_t buffer_write_offset;
+
+	uint32_t write_wrap_count;
+	uint32_t read_wrap_count;
+
+	uint32_t open_count;
+
+	char *log_buffer;	/* Pointer to malloc'ed buffer */
+	uint32_t log_buffer_size; /* Size of circular buffer */
+
+	uint32_t *log_enable_mask_minors; /*array of masks for major elements*/
+
+	union logger_flags flags;
+	struct dc_context *ctx;
+};
+
+#endif /* __DAL_LOGGER_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
new file mode 100644
index 000000000000..6d32b1bdf35c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/dal_types.h"
+#include "include/logger_interface.h"
+#include "logger.h"
+
+/******************************************************************************
+ * Register Logger.
+ * A facility to create register R/W logs.
+ * Currently used for DAL Test.
+ *****************************************************************************/
+
+/******************************************************************************
+ * Private structures
+ *****************************************************************************/
+struct dal_reg_dump_stack_location {
+	const char *current_caller_func;
+	long current_pid;
+	long current_tgid;
+	uint32_t rw_count;/* register access counter for current function. */
+};
+
+/* This the maximum number of nested calls to the 'reg_dump' facility. */
+#define DAL_REG_DUMP_STACK_MAX_SIZE 32
+
+struct dal_reg_dump_stack {
+	int32_t stack_pointer;
+	struct dal_reg_dump_stack_location
+		stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE];
+	uint32_t total_rw_count; /* Total count for *all* functions. */
+};
+
+static struct dal_reg_dump_stack reg_dump_stack = {0};
+
+/******************************************************************************
+ * Private functions
+ *****************************************************************************/
+
+/* Check if current process is the one which requested register dump.
+ * The reason for the check:
+ * mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter().
+ * Which runs all the time when at least one display is connected.
+ * (Triggered by drm_mode_page_flip_ioctl()). */
+static bool is_reg_dump_process(void)
+{
+	uint32_t i;
+
+	/* walk the list of our processes */
+	for (i = 0; i < reg_dump_stack.stack_pointer; i++) {
+		struct dal_reg_dump_stack_location *stack_location
+					= &reg_dump_stack.stack_locations[i];
+
+		if (stack_location->current_pid == dm_get_pid()
+			&& stack_location->current_tgid == dm_get_tgid())
+			return true;
+	}
+
+	return false;
+}
+
+static bool dal_reg_dump_stack_is_empty(void)
+{
+	if (reg_dump_stack.stack_pointer <= 0)
+		return true;
+	else
+		return false;
+}
+
+static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void)
+{
+	struct dal_reg_dump_stack_location *current_location = NULL;
+
+	if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) {
+		/* stack is full */
+		dm_output_to_console("[REG_DUMP]: %s: stack is full!\n",
+				__func__);
+	} else {
+		current_location =
+		&reg_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
+		++reg_dump_stack.stack_pointer;
+	}
+
+	return current_location;
+}
+
+static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void)
+{
+	struct dal_reg_dump_stack_location *current_location = NULL;
+
+	if (dal_reg_dump_stack_is_empty()) {
+		/* stack is empty */
+		dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n",
+				__func__);
+	} else {
+		--reg_dump_stack.stack_pointer;
+		current_location =
+		&reg_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
+	}
+
+	return current_location;
+}
+
+/******************************************************************************
+ * Public functions
+ *****************************************************************************/
+
+void dal_reg_logger_push(const char *caller_func)
+{
+	struct dal_reg_dump_stack_location *free_stack_location;
+
+	free_stack_location = dal_reg_dump_stack_push();
+
+	if (NULL == free_stack_location)
+		return;
+
+	dm_memset(free_stack_location, 0, sizeof(*free_stack_location));
+
+	free_stack_location->current_caller_func = caller_func;
+	free_stack_location->current_pid = dm_get_pid();
+	free_stack_location->current_tgid = dm_get_tgid();
+
+	dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n",
+		caller_func,
+		free_stack_location->current_pid,
+		free_stack_location->current_tgid);
+}
+
+void dal_reg_logger_pop(void)
+{
+	struct dal_reg_dump_stack_location *top_stack_location;
+
+	top_stack_location = dal_reg_dump_stack_pop();
+
+	if (NULL == top_stack_location) {
+		dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n",
+				__func__);
+		return;
+	}
+
+	dm_output_to_console(
+	"[REG_DUMP]:%s - end."\
+	" Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n",
+			top_stack_location->current_caller_func,
+			reg_dump_stack.total_rw_count,
+			top_stack_location->rw_count,
+			dm_get_pid(),
+			dm_get_tgid());
+
+	dm_memset(top_stack_location, 0, sizeof(*top_stack_location));
+}
+
+void dal_reg_logger_rw_count_increment(void)
+{
+	++reg_dump_stack.total_rw_count;
+
+	++reg_dump_stack.stack_locations
+		[reg_dump_stack.stack_pointer - 1].rw_count;
+}
+
+bool dal_reg_logger_should_dump_register(void)
+{
+	if (true == dal_reg_dump_stack_is_empty())
+		return false;
+
+	if (false == is_reg_dump_process())
+		return false;
+
+	return true;
+}
+
+/******************************************************************************
+ * End of File.
+ *****************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
new file mode 100644
index 000000000000..44447e07803a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/signal_types.h"
+
+bool dc_is_hdmi_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_HDMI_TYPE_A);
+}
+
+bool dc_is_dp_sst_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_EDP);
+}
+
+bool dc_is_dp_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_EDP ||
+		signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
+}
+
+bool dc_is_dp_external_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
+}
+
+bool dc_is_analog_signal(enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_RGB:
+		return true;
+	break;
+	default:
+		return false;
+	}
+}
+
+bool dc_is_embedded_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS);
+}
+
+bool dc_is_dvi_signal(enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		return true;
+	break;
+	default:
+		return false;
+	}
+}
+
+bool dc_is_dvi_single_link_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK);
+}
+
+bool dc_is_dual_link_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DVI_DUAL_LINK);
+}
+
+bool dc_is_audio_capable_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
+		dc_is_hdmi_signal(signal) ||
+		signal == SIGNAL_TYPE_WIRELESS);
+}
+
+/*
+ * @brief
+ * Returns whether the signal is compatible
+ * with other digital encoder signal types.
+ * This is true for DVI, LVDS, and HDMI signal types.
+ */
+bool dc_is_digital_encoder_compatible_signal(enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_LVDS:
+		return true;
+	default:
+		return false;
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/vector.c b/drivers/gpu/drm/amd/dal/dc/basics/vector.c
new file mode 100644
index 000000000000..32ca6b13a3bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/vector.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/vector.h"
+
+bool dal_vector_construct(
+	struct vector *vector,
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size)
+{
+	vector->container = NULL;
+
+	if (!struct_size || !capacity) {
+		/* Container must be non-zero size*/
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	vector->container = dm_alloc(ctx, struct_size * capacity);
+	if (vector->container == NULL)
+		return false;
+	vector->capacity = capacity;
+	vector->struct_size = struct_size;
+	vector->count = 0;
+	vector->ctx = ctx;
+	return true;
+}
+
+bool dal_vector_presized_costruct(
+	struct vector *vector,
+	struct dc_context *ctx,
+	uint32_t count,
+	void *initial_value,
+	uint32_t struct_size)
+{
+	uint32_t i;
+
+	vector->container = NULL;
+
+	if (!struct_size || !count) {
+		/* Container must be non-zero size*/
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	vector->container = dm_alloc(ctx, struct_size * count);
+
+	if (vector->container == NULL)
+		return false;
+
+	/* If caller didn't supply initial value then the default
+	 * of all zeros is expected, which is exactly what dal_alloc()
+	 * initialises the memory to. */
+	if (NULL != initial_value) {
+		for (i = 0; i < count; ++i)
+			dm_memmove(
+				vector->container + i * struct_size,
+				initial_value,
+				struct_size);
+	}
+
+	vector->capacity = count;
+	vector->struct_size = struct_size;
+	vector->count = count;
+	return true;
+}
+
+struct vector *dal_vector_presized_create(
+	struct dc_context *ctx,
+	uint32_t size,
+	void *initial_value,
+	uint32_t struct_size)
+{
+	struct vector *vector = dm_alloc(ctx, sizeof(struct vector));
+
+	if (vector == NULL)
+		return NULL;
+
+	if (dal_vector_presized_costruct(
+		vector, ctx, size, initial_value, struct_size))
+		return vector;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, vector);
+	return NULL;
+}
+
+struct vector *dal_vector_create(
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size)
+{
+	struct vector *vector = dm_alloc(ctx, sizeof(struct vector));
+
+	if (vector == NULL)
+		return NULL;
+
+	if (dal_vector_construct(vector, ctx, capacity, struct_size))
+		return vector;
+
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, vector);
+	return NULL;
+}
+
+void dal_vector_destruct(
+	struct vector *vector)
+{
+	if (vector->container != NULL)
+		dm_free(vector->ctx, vector->container);
+	vector->count = 0;
+	vector->capacity = 0;
+}
+
+void dal_vector_destroy(
+	struct vector **vector)
+{
+	if (vector == NULL || *vector == NULL)
+		return;
+	dal_vector_destruct(*vector);
+	dm_free((*vector)->ctx, *vector);
+	*vector = NULL;
+}
+
+uint32_t dal_vector_get_count(
+	const struct vector *vector)
+{
+	return vector->count;
+}
+
+void *dal_vector_at_index(
+	const struct vector *vector,
+	uint32_t index)
+{
+	if (vector->container == NULL || index >= vector->count)
+		return NULL;
+	return vector->container + (index * vector->struct_size);
+}
+
+bool dal_vector_remove_at_index(
+	struct vector *vector,
+	uint32_t index)
+{
+	if (index >= vector->count)
+		return false;
+
+	if (index != vector->count - 1)
+		dm_memmove(
+			vector->container + (index * vector->struct_size),
+			vector->container + ((index + 1) * vector->struct_size),
+			(vector->count - index - 1) * vector->struct_size);
+	vector->count -= 1;
+
+	return true;
+}
+
+void dal_vector_set_at_index(
+	const struct vector *vector,
+	const void *what,
+	uint32_t index)
+{
+	void *where = dal_vector_at_index(vector, index);
+
+	if (!where) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+	dm_memmove(
+		where,
+		what,
+		vector->struct_size);
+}
+
+static inline uint32_t calc_increased_capacity(
+	uint32_t old_capacity)
+{
+	return old_capacity * 2;
+}
+
+bool dal_vector_insert_at(
+	struct vector *vector,
+	const void *what,
+	uint32_t position)
+{
+	uint8_t *insert_address;
+
+	if (vector->count == vector->capacity) {
+		if (!dal_vector_reserve(
+			vector,
+			calc_increased_capacity(vector->capacity)))
+			return false;
+	}
+
+	insert_address = vector->container + (vector->struct_size * position);
+
+	if (vector->count && position < vector->count)
+		dm_memmove(
+			insert_address + vector->struct_size,
+			insert_address,
+			vector->struct_size * (vector->count - position));
+
+	dm_memmove(
+		insert_address,
+		what,
+		vector->struct_size);
+
+	vector->count++;
+
+	return true;
+}
+
+bool dal_vector_append(
+	struct vector *vector,
+	const void *item)
+{
+	return dal_vector_insert_at(vector, item, vector->count);
+}
+
+struct vector *dal_vector_clone(
+	const struct vector *vector)
+{
+	struct vector *vec_cloned;
+	uint32_t count;
+
+	/* create new vector */
+	count = dal_vector_get_count(vector);
+
+	if (count == 0)
+		/* when count is 0 we still want to create clone of the vector
+		 */
+		vec_cloned = dal_vector_create(
+			vector->ctx,
+			vector->capacity,
+			vector->struct_size);
+	else
+		/* Call "presized create" version, independently of how the
+		 * original vector was created.
+		 * The owner of original vector must know how to treat the new
+		 * vector - as "presized" or as "regular".
+		 * But from vector point of view it doesn't matter. */
+		vec_cloned = dal_vector_presized_create(vector->ctx, count,
+			NULL,/* no initial value */
+			vector->struct_size);
+
+	if (NULL == vec_cloned) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	/* copy vector's data */
+	dm_memmove(vec_cloned->container, vector->container,
+			vec_cloned->struct_size * vec_cloned->capacity);
+
+	return vec_cloned;
+}
+
+uint32_t dal_vector_capacity(const struct vector *vector)
+{
+	return vector->capacity;
+}
+
+bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
+{
+	void *new_container;
+
+	if (capacity <= vector->capacity)
+		return true;
+
+	new_container = dm_realloc(vector->ctx, vector->container,
+		capacity * vector->struct_size);
+
+	if (new_container) {
+		vector->container = new_container;
+		vector->capacity = capacity;
+		return true;
+	}
+
+	return false;
+}
+
+void dal_vector_clear(struct vector *vector)
+{
+	vector->count = 0;
+}
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 03/29] drm/amd/dal: Fixed point arithmetic
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
  2016-02-11 17:19 ` [PATCH 01/29] drm/amd/dal: Add dal headers Harry Wentland
  2016-02-11 17:19 ` [PATCH 02/29] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 04/29] drm/amd/dal: Asic Capabilities Harry Wentland
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Arithmetic operations on real numbers represented
as fixed-point numbers.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/basics/Makefile     |   2 +-
 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c | 692 +++++++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c | 223 ++++++++
 3 files changed, 916 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c

diff --git a/drivers/gpu/drm/amd/dal/dc/basics/Makefile b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
index 6f382812fae3..93e23714e411 100644
--- a/drivers/gpu/drm/amd/dal/dc/basics/Makefile
+++ b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
@@ -3,7 +3,7 @@
 # It provides the general basic services required by other DAL
 # subcomponents.
 
-BASICS = conversion.o grph_object_id.o logger.o register_logger.o signal_types.o vector.o
+BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o logger.o register_logger.o signal_types.o vector.o
 
 AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS))
 
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
new file mode 100644
index 000000000000..9f93b3b20634
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
@@ -0,0 +1,692 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/fixed31_32.h"
+
+static inline uint64_t abs_i64(
+	int64_t arg)
+{
+	if (arg > 0)
+		return (uint64_t)arg;
+	else
+		return (uint64_t)(-arg);
+}
+
+/*
+ * @brief
+ * result = dividend / divisor
+ * *remainder = dividend % divisor
+ */
+static inline uint64_t complete_integer_division_u64(
+	uint64_t dividend,
+	uint64_t divisor,
+	uint64_t *remainder)
+{
+	uint64_t result;
+
+	ASSERT(divisor);
+
+	result = div64_u64_rem(dividend, divisor, remainder);
+
+	return result;
+}
+
+#define BITS_PER_FRACTIONAL_PART \
+	32
+
+#define FRACTIONAL_PART_MASK \
+	((1ULL << BITS_PER_FRACTIONAL_PART) - 1)
+
+#define GET_INTEGER_PART(x) \
+	((x) >> BITS_PER_FRACTIONAL_PART)
+
+#define GET_FRACTIONAL_PART(x) \
+	(FRACTIONAL_PART_MASK & (x))
+
+struct fixed31_32 dal_fixed31_32_from_fraction(
+	int64_t numerator,
+	int64_t denominator)
+{
+	struct fixed31_32 res;
+
+	bool arg1_negative = numerator < 0;
+	bool arg2_negative = denominator < 0;
+
+	uint64_t arg1_value = arg1_negative ? -numerator : numerator;
+	uint64_t arg2_value = arg2_negative ? -denominator : denominator;
+
+	uint64_t remainder;
+
+	/* determine integer part */
+
+	uint64_t res_value = complete_integer_division_u64(
+		arg1_value, arg2_value, &remainder);
+
+	ASSERT(res_value <= LONG_MAX);
+
+	/* determine fractional part */
+	{
+		uint32_t i = BITS_PER_FRACTIONAL_PART;
+
+		do {
+			remainder <<= 1;
+
+			res_value <<= 1;
+
+			if (remainder >= arg2_value) {
+				res_value |= 1;
+				remainder -= arg2_value;
+			}
+		} while (--i != 0);
+	}
+
+	/* round up LSB */
+	{
+		uint64_t summand = (remainder << 1) >= arg2_value;
+
+		ASSERT(res_value <= LLONG_MAX - summand);
+
+		res_value += summand;
+	}
+
+	res.value = (int64_t)res_value;
+
+	if (arg1_negative ^ arg2_negative)
+		res.value = -res.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_from_int(
+	int64_t arg)
+{
+	struct fixed31_32 res;
+
+	ASSERT((LONG_MIN <= arg) && (arg <= LONG_MAX));
+
+	res.value = arg << BITS_PER_FRACTIONAL_PART;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_neg(
+	struct fixed31_32 arg)
+{
+	struct fixed31_32 res;
+
+	res.value = -arg.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_abs(
+	struct fixed31_32 arg)
+{
+	if (arg.value < 0)
+		return dal_fixed31_32_neg(arg);
+	else
+		return arg;
+}
+
+bool dal_fixed31_32_lt(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return arg1.value < arg2.value;
+}
+
+bool dal_fixed31_32_le(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return arg1.value <= arg2.value;
+}
+
+bool dal_fixed31_32_eq(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return arg1.value == arg2.value;
+}
+
+struct fixed31_32 dal_fixed31_32_min(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	if (arg1.value <= arg2.value)
+		return arg1;
+	else
+		return arg2;
+}
+
+struct fixed31_32 dal_fixed31_32_max(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	if (arg1.value <= arg2.value)
+		return arg2;
+	else
+		return arg1;
+}
+
+struct fixed31_32 dal_fixed31_32_clamp(
+	struct fixed31_32 arg,
+	struct fixed31_32 min_value,
+	struct fixed31_32 max_value)
+{
+	if (dal_fixed31_32_le(arg, min_value))
+		return min_value;
+	else if (dal_fixed31_32_le(max_value, arg))
+		return max_value;
+	else
+		return arg;
+}
+
+struct fixed31_32 dal_fixed31_32_shl(
+	struct fixed31_32 arg,
+	uint8_t shift)
+{
+	struct fixed31_32 res;
+
+	ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) ||
+		((arg.value < 0) && (arg.value >= LLONG_MIN >> shift)));
+
+	res.value = arg.value << shift;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_shr(
+	struct fixed31_32 arg,
+	uint8_t shift)
+{
+	struct fixed31_32 res;
+
+	ASSERT(shift < 64);
+
+	res.value = arg.value >> shift;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_add(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	struct fixed31_32 res;
+
+	ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) ||
+		((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value)));
+
+	res.value = arg1.value + arg2.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_sub_int(
+	struct fixed31_32 arg1,
+	int32_t arg2)
+{
+	return dal_fixed31_32_sub(
+		arg1,
+		dal_fixed31_32_from_int(arg2));
+}
+
+struct fixed31_32 dal_fixed31_32_sub(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	struct fixed31_32 res;
+
+	ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) ||
+		((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value)));
+
+	res.value = arg1.value - arg2.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_mul_int(
+	struct fixed31_32 arg1,
+	int32_t arg2)
+{
+	return dal_fixed31_32_mul(
+		arg1,
+		dal_fixed31_32_from_int(arg2));
+}
+
+struct fixed31_32 dal_fixed31_32_mul(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	struct fixed31_32 res;
+
+	bool arg1_negative = arg1.value < 0;
+	bool arg2_negative = arg2.value < 0;
+
+	uint64_t arg1_value = arg1_negative ? -arg1.value : arg1.value;
+	uint64_t arg2_value = arg2_negative ? -arg2.value : arg2.value;
+
+	uint64_t arg1_int = GET_INTEGER_PART(arg1_value);
+	uint64_t arg2_int = GET_INTEGER_PART(arg2_value);
+
+	uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
+	uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
+
+	uint64_t tmp;
+
+	res.value = arg1_int * arg2_int;
+
+	ASSERT(res.value <= LONG_MAX);
+
+	res.value <<= BITS_PER_FRACTIONAL_PART;
+
+	tmp = arg1_int * arg2_fra;
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	tmp = arg2_int * arg1_fra;
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	tmp = arg1_fra * arg2_fra;
+
+	tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
+		(tmp >= (uint64_t)dal_fixed31_32_half.value);
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	if (arg1_negative ^ arg2_negative)
+		res.value = -res.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_sqr(
+	struct fixed31_32 arg)
+{
+	struct fixed31_32 res;
+
+	uint64_t arg_value = abs_i64(arg.value);
+
+	uint64_t arg_int = GET_INTEGER_PART(arg_value);
+
+	uint64_t arg_fra = GET_FRACTIONAL_PART(arg_value);
+
+	uint64_t tmp;
+
+	res.value = arg_int * arg_int;
+
+	ASSERT(res.value <= LONG_MAX);
+
+	res.value <<= BITS_PER_FRACTIONAL_PART;
+
+	tmp = arg_int * arg_fra;
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	tmp = arg_fra * arg_fra;
+
+	tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
+		(tmp >= (uint64_t)dal_fixed31_32_half.value);
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_div_int(
+	struct fixed31_32 arg1,
+	int64_t arg2)
+{
+	return dal_fixed31_32_from_fraction(
+		arg1.value,
+		dal_fixed31_32_from_int(arg2).value);
+}
+
+struct fixed31_32 dal_fixed31_32_div(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return dal_fixed31_32_from_fraction(
+		arg1.value,
+		arg2.value);
+}
+
+struct fixed31_32 dal_fixed31_32_recip(
+	struct fixed31_32 arg)
+{
+	/*
+	 * @note
+	 * Good idea to use Newton's method
+	 */
+
+	ASSERT(arg.value);
+
+	return dal_fixed31_32_from_fraction(
+		dal_fixed31_32_one.value,
+		arg.value);
+}
+
+struct fixed31_32 dal_fixed31_32_sinc(
+	struct fixed31_32 arg)
+{
+	struct fixed31_32 square;
+
+	struct fixed31_32 res = dal_fixed31_32_one;
+
+	int32_t n = 27;
+
+	struct fixed31_32 arg_norm = arg;
+
+	if (dal_fixed31_32_le(
+		dal_fixed31_32_two_pi,
+		dal_fixed31_32_abs(arg))) {
+		arg_norm = dal_fixed31_32_sub(
+			arg_norm,
+			dal_fixed31_32_mul_int(
+				dal_fixed31_32_two_pi,
+				(int32_t)div64_s64(
+					arg_norm.value,
+					dal_fixed31_32_two_pi.value)));
+	}
+
+	square = dal_fixed31_32_sqr(arg_norm);
+
+	do {
+		res = dal_fixed31_32_sub(
+			dal_fixed31_32_one,
+			dal_fixed31_32_div_int(
+				dal_fixed31_32_mul(
+					square,
+					res),
+				n * (n - 1)));
+
+		n -= 2;
+	} while (n > 2);
+
+	if (arg.value != arg_norm.value)
+		res = dal_fixed31_32_div(
+			dal_fixed31_32_mul(res, arg_norm),
+			arg);
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_sin(
+	struct fixed31_32 arg)
+{
+	return dal_fixed31_32_mul(
+		arg,
+		dal_fixed31_32_sinc(arg));
+}
+
+struct fixed31_32 dal_fixed31_32_cos(
+	struct fixed31_32 arg)
+{
+	/* TODO implement argument normalization */
+
+	const struct fixed31_32 square = dal_fixed31_32_sqr(arg);
+
+	struct fixed31_32 res = dal_fixed31_32_one;
+
+	int32_t n = 26;
+
+	do {
+		res = dal_fixed31_32_sub(
+			dal_fixed31_32_one,
+			dal_fixed31_32_div_int(
+				dal_fixed31_32_mul(
+					square,
+					res),
+				n * (n - 1)));
+
+		n -= 2;
+	} while (n != 0);
+
+	return res;
+}
+
+/*
+ * @brief
+ * result = exp(arg),
+ * where abs(arg) < 1
+ *
+ * Calculated as Taylor series.
+ */
+static struct fixed31_32 fixed31_32_exp_from_taylor_series(
+	struct fixed31_32 arg)
+{
+	uint32_t n = 9;
+
+	struct fixed31_32 res = dal_fixed31_32_from_fraction(
+		n + 2,
+		n + 1);
+	/* TODO find correct res */
+
+	ASSERT(dal_fixed31_32_lt(arg, dal_fixed31_32_one));
+
+	do
+		res = dal_fixed31_32_add(
+			dal_fixed31_32_one,
+			dal_fixed31_32_div_int(
+				dal_fixed31_32_mul(
+					arg,
+					res),
+				n));
+	while (--n != 1);
+
+	return dal_fixed31_32_add(
+		dal_fixed31_32_one,
+		dal_fixed31_32_mul(
+			arg,
+			res));
+}
+
+struct fixed31_32 dal_fixed31_32_exp(
+	struct fixed31_32 arg)
+{
+	/*
+	 * @brief
+	 * Main equation is:
+	 * exp(x) = exp(r + m * ln(2)) = (1 << m) * exp(r),
+	 * where m = round(x / ln(2)), r = x - m * ln(2)
+	 */
+
+	if (dal_fixed31_32_le(
+		dal_fixed31_32_ln2_div_2,
+		dal_fixed31_32_abs(arg))) {
+		int32_t m = dal_fixed31_32_round(
+			dal_fixed31_32_div(
+				arg,
+				dal_fixed31_32_ln2));
+
+		struct fixed31_32 r = dal_fixed31_32_sub(
+			arg,
+			dal_fixed31_32_mul_int(
+				dal_fixed31_32_ln2,
+				m));
+
+		ASSERT(m != 0);
+
+		ASSERT(dal_fixed31_32_lt(
+			dal_fixed31_32_abs(r),
+			dal_fixed31_32_one));
+
+		if (m > 0)
+			return dal_fixed31_32_shl(
+				fixed31_32_exp_from_taylor_series(r),
+				(uint8_t)m);
+		else
+			return dal_fixed31_32_div_int(
+				fixed31_32_exp_from_taylor_series(r),
+				1LL << -m);
+	} else if (arg.value != 0)
+		return fixed31_32_exp_from_taylor_series(arg);
+	else
+		return dal_fixed31_32_one;
+}
+
+struct fixed31_32 dal_fixed31_32_log(
+	struct fixed31_32 arg)
+{
+	struct fixed31_32 res = dal_fixed31_32_neg(dal_fixed31_32_one);
+	/* TODO improve 1st estimation */
+
+	struct fixed31_32 error;
+
+	ASSERT(arg.value > 0);
+	/* TODO if arg is negative, return NaN */
+	/* TODO if arg is zero, return -INF */
+
+	do {
+		struct fixed31_32 res1 = dal_fixed31_32_add(
+			dal_fixed31_32_sub(
+				res,
+				dal_fixed31_32_one),
+			dal_fixed31_32_div(
+				arg,
+				dal_fixed31_32_exp(res)));
+
+		error = dal_fixed31_32_sub(
+			res,
+			res1);
+
+		res = res1;
+		/* TODO determine max_allowed_error based on quality of exp() */
+	} while (abs_i64(error.value) > 100ULL);
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_pow(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return dal_fixed31_32_exp(
+		dal_fixed31_32_mul(
+			dal_fixed31_32_log(arg1),
+			arg2));
+}
+
+int32_t dal_fixed31_32_floor(
+	struct fixed31_32 arg)
+{
+	uint64_t arg_value = abs_i64(arg.value);
+
+	if (arg.value >= 0)
+		return (int32_t)GET_INTEGER_PART(arg_value);
+	else
+		return -(int32_t)GET_INTEGER_PART(arg_value);
+}
+
+int32_t dal_fixed31_32_round(
+	struct fixed31_32 arg)
+{
+	uint64_t arg_value = abs_i64(arg.value);
+
+	const int64_t summand = dal_fixed31_32_half.value;
+
+	ASSERT(LLONG_MAX - (int64_t)arg_value >= summand);
+
+	arg_value += summand;
+
+	if (arg.value >= 0)
+		return (int32_t)GET_INTEGER_PART(arg_value);
+	else
+		return -(int32_t)GET_INTEGER_PART(arg_value);
+}
+
+int32_t dal_fixed31_32_ceil(
+	struct fixed31_32 arg)
+{
+	uint64_t arg_value = abs_i64(arg.value);
+
+	const int64_t summand = dal_fixed31_32_one.value -
+		dal_fixed31_32_epsilon.value;
+
+	ASSERT(LLONG_MAX - (int64_t)arg_value >= summand);
+
+	arg_value += summand;
+
+	if (arg.value >= 0)
+		return (int32_t)GET_INTEGER_PART(arg_value);
+	else
+		return -(int32_t)GET_INTEGER_PART(arg_value);
+}
+
+/* this function is a generic helper to translate fixed point value to
+ * specified integer format that will consist of integer_bits integer part and
+ * fractional_bits fractional part. For example it is used in
+ * dal_fixed31_32_u2d19 to receive 2 bits integer part and 19 bits fractional
+ * part in 32 bits. It is used in hw programming (scaler)
+ */
+
+static inline uint32_t ux_dy(
+	int64_t value,
+	uint32_t integer_bits,
+	uint32_t fractional_bits)
+{
+	/* 1. create mask of integer part */
+	uint32_t result =
+		(1 << integer_bits) - 1;
+	/* 2. mask out fractional part */
+	uint32_t fractional_part = FRACTIONAL_PART_MASK & value;
+	/* 3. shrink fixed point integer part to be of integer_bits width*/
+	result &= GET_INTEGER_PART(value);
+	/* 4. make space for fractional part to be filled in after integer */
+	result <<= fractional_bits;
+	/* 5. shrink fixed point fractional part to of fractional_bits width*/
+	fractional_part >>= BITS_PER_FRACTIONAL_PART - fractional_bits;
+	/* 6. merge the result */
+	return result | fractional_part;
+}
+
+uint32_t dal_fixed31_32_u2d19(
+	struct fixed31_32 arg)
+{
+	return ux_dy(arg.value, 2, 19);
+}
+
+uint32_t dal_fixed31_32_u0d19(
+	struct fixed31_32 arg)
+{
+	return ux_dy(arg.value, 0, 19);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c b/drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c
new file mode 100644
index 000000000000..74e6d756295e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/fixed32_32.h"
+
+static uint64_t u64_div(uint64_t n, uint64_t d)
+{
+	uint32_t i = 0;
+	uint64_t r;
+	uint64_t q = div64_u64_rem(n, d, &r);
+
+	for (i = 0; i < 32; ++i) {
+		uint64_t sbit = q & (1ULL<<63);
+
+		r <<= 1;
+		r |= sbit ? 1 : 0;
+		q <<= 1;
+		if (r >= d) {
+			r -= d;
+			q |= 1;
+		}
+	}
+
+	if (2*r >= d)
+		q += 1;
+	return q;
+}
+
+struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d)
+{
+	struct fixed32_32 fx;
+
+	fx.value = u64_div((uint64_t)n << 32, (uint64_t)d << 32);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_from_int(uint32_t value)
+{
+	struct fixed32_32 fx;
+
+	fx.value = (uint64_t)value<<32;
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_add(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	struct fixed32_32 fx = {lhs.value + rhs.value};
+
+	ASSERT(fx.value >= rhs.value);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_add_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	struct fixed32_32 fx = {lhs.value + ((uint64_t)rhs << 32)};
+
+	ASSERT(fx.value >= (uint64_t)rhs << 32);
+	return fx;
+
+}
+struct fixed32_32 dal_fixed32_32_sub(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	struct fixed32_32 fx;
+
+	ASSERT(lhs.value >= rhs.value);
+	fx.value = lhs.value - rhs.value;
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_sub_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	struct fixed32_32 fx;
+
+	ASSERT(lhs.value >= ((uint64_t)rhs<<32));
+	fx.value = lhs.value - ((uint64_t)rhs<<32);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_mul(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	struct fixed32_32 fx;
+	uint64_t lhs_int = lhs.value>>32;
+	uint64_t lhs_frac = (uint32_t)lhs.value;
+	uint64_t rhs_int = rhs.value>>32;
+	uint64_t rhs_frac = (uint32_t)rhs.value;
+	uint64_t ahbh = lhs_int * rhs_int;
+	uint64_t ahbl = lhs_int * rhs_frac;
+	uint64_t albh = lhs_frac * rhs_int;
+	uint64_t albl = lhs_frac * rhs_frac;
+
+	ASSERT((ahbh>>32) == 0);
+
+	fx.value = (ahbh<<32) + ahbl + albh + (albl>>32);
+	return fx;
+
+}
+
+struct fixed32_32 dal_fixed32_32_mul_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	struct fixed32_32 fx;
+	uint64_t lhsi = (lhs.value>>32) * (uint64_t)rhs;
+	uint64_t lhsf;
+
+	ASSERT((lhsi>>32) == 0);
+	lhsf = ((uint32_t)lhs.value) * (uint64_t)rhs;
+	ASSERT((lhsi<<32) + lhsf >= lhsf);
+	fx.value = (lhsi<<32) + lhsf;
+	return fx;
+}
+
+
+
+struct fixed32_32 dal_fixed32_32_div(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	struct fixed32_32 fx;
+
+	fx.value = u64_div(lhs.value, rhs.value);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_div_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	struct fixed32_32 fx;
+
+	fx.value = u64_div(lhs.value, (uint64_t)rhs << 32);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_min(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	return (lhs.value < rhs.value) ? lhs : rhs;
+}
+
+struct fixed32_32 dal_fixed32_32_max(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	return (lhs.value > rhs.value) ? lhs : rhs;
+}
+
+bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs)
+{
+	return lhs.value > rhs.value;
+}
+bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	return lhs.value > ((uint64_t)rhs<<32);
+}
+
+bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs)
+{
+	return lhs.value < rhs.value;
+}
+
+bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs)
+{
+	return lhs.value <= rhs.value;
+}
+
+bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	return lhs.value < ((uint64_t)rhs<<32);
+}
+
+bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	return lhs.value <= ((uint64_t)rhs<<32);
+}
+
+uint32_t dal_fixed32_32_ceil(struct fixed32_32 v)
+{
+	ASSERT((uint32_t)v.value ? (v.value >> 32) + 1 >= 1 : true);
+	return (v.value>>32) + ((uint32_t)v.value ? 1 : 0);
+}
+
+uint32_t dal_fixed32_32_floor(struct fixed32_32 v)
+{
+	return v.value>>32;
+}
+
+uint32_t dal_fixed32_32_round(struct fixed32_32 v)
+{
+	ASSERT(v.value + (1ULL<<31) >= (1ULL<<31));
+	return (v.value + (1ULL<<31))>>32;
+}
+
+bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs)
+{
+	return lhs.value == rhs.value;
+}
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 04/29] drm/amd/dal: Asic Capabilities
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (2 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 03/29] drm/amd/dal: Fixed point arithmetic Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 05/29] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
                   ` (28 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Add a generic way to manage display HW capabilities
for different ASICs and implement it for Carrizo.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/dal/dc/asic_capability/Makefile    |  35 ++++
 .../amd/dal/dc/asic_capability/asic_capability.c   | 190 +++++++++++++++++++++
 .../dc/asic_capability/carrizo_asic_capability.c   | 147 ++++++++++++++++
 .../dc/asic_capability/carrizo_asic_capability.h   |  36 ++++
 .../dal/dc/asic_capability/tonga_asic_capability.c | 146 ++++++++++++++++
 .../dal/dc/asic_capability/tonga_asic_capability.h |  36 ++++
 6 files changed, 590 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h

diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile b/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
new file mode 100644
index 000000000000..8491b38ae726
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
@@ -0,0 +1,35 @@
+#
+# Makefile for the 'asic_capability' sub-component of DAL.
+#
+
+ASIC_CAPABILITY = asic_capability.o
+
+AMD_DAL_ASIC_CAPABILITY = \
+	$(addprefix $(AMDDALPATH)/dc/asic_capability/,$(ASIC_CAPABILITY))
+
+AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY)
+
+###############################################################################
+# DCE 10x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE10_0
+ASIC_CAPABILITY_DCE10 = tonga_asic_capability.o
+
+AMD_DAL_ASIC_CAPABILITY_DCE10 = \
+	$(addprefix $(AMDDALPATH)/dc/asic_capability/,$(ASIC_CAPABILITY_DCE10))
+
+AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY_DCE10)
+endif
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+ASIC_CAPABILITY_DCE11 = carrizo_asic_capability.o
+
+AMD_DAL_ASIC_CAPABILITY_DCE11 = \
+	$(addprefix $(AMDDALPATH)/dc/asic_capability/,$(ASIC_CAPABILITY_DCE11))
+
+AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY_DCE11)
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
new file mode 100644
index 000000000000..7a905f532040
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "include/asic_capability_interface.h"
+#include "include/asic_capability_types.h"
+#include "include/dal_types.h"
+#include "include/dal_asic_id.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "tonga_asic_capability.h"
+#endif
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "carrizo_asic_capability.h"
+#endif
+
+/*
+ * Initializes asic_capability instance.
+ */
+static bool construct(
+	struct asic_capability *cap,
+	struct hw_asic_id *init,
+	struct dc_context *ctx)
+{
+	bool asic_supported = false;
+
+	cap->ctx = ctx;
+	dm_memset(cap->data, 0, sizeof(cap->data));
+
+	/* ASIC data */
+	cap->data[ASIC_DATA_VRAM_TYPE] = init->vram_type;
+	cap->data[ASIC_DATA_VRAM_BITWIDTH] = init->vram_width;
+	cap->data[ASIC_DATA_FEATURE_FLAGS] = init->feature_flags;
+	cap->runtime_flags = init->runtime_flags;
+	cap->data[ASIC_DATA_REVISION_ID] = init->hw_internal_rev;
+	cap->data[ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE] = 10;
+	cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY] = 4;
+	cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 1;
+	cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES] = 0;
+	cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ] = 25;
+
+	/* ASIC basic capability */
+	cap->caps.UNDERSCAN_FOR_HDMI_ONLY = true;
+	cap->caps.SUPPORT_CEA861E_FINAL = true;
+	cap->caps.MIRABILIS_SUPPORTED = false;
+	cap->caps.MIRABILIS_ENABLED_BY_DEFAULT = false;
+	cap->caps.WIRELESS_LIMIT_TO_720P = false;
+	cap->caps.WIRELESS_FULL_TIMING_ADJUSTMENT = false;
+	cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+	cap->caps.WIRELESS_COMPRESSED_AUDIO = false;
+	cap->caps.VCE_SUPPORTED = false;
+	cap->caps.HPD_CHECK_FOR_EDID = false;
+	cap->caps.NO_VCC_OFF_HPD_POLLING = false;
+	cap->caps.NEED_MC_TUNING = false;
+	cap->caps.SUPPORT_8BPP = true;
+
+	/* ASIC stereo 3D capability */
+	cap->stereo_3d_caps.SUPPORTED = true;
+
+	switch (init->chip_family) {
+	case FAMILY_CI:
+		break;
+
+	case FAMILY_KV:
+		if (ASIC_REV_IS_KALINDI(init->hw_internal_rev) ||
+			ASIC_REV_IS_BHAVANI(init->hw_internal_rev)) {
+		} else {
+		}
+		break;
+
+	case FAMILY_CZ:
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+		carrizo_asic_capability_create(cap, init);
+		asic_supported = true;
+#endif
+		break;
+ 	case FAMILY_VI:
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+		if (ASIC_REV_IS_TONGA_P(init->hw_internal_rev) ||
+				ASIC_REV_IS_FIJI_P(init->hw_internal_rev)) {
+			tonga_asic_capability_create(cap, init);
+			asic_supported = true;
+			break;
+		}
+#endif
+		break;
+	default:
+		/* unsupported "chip_family" */
+		break;
+	}
+
+	if (false == asic_supported) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_MASK_ALL,
+			"%s: ASIC not supported!\n", __func__);
+	}
+
+	return asic_supported;
+}
+
+static void destruct(
+	struct asic_capability *cap)
+{
+	/* nothing to do (yet?) */
+}
+
+/*
+ * dal_asic_capability_create
+ *
+ * Creates asic capability based on DCE version.
+ */
+struct asic_capability *dal_asic_capability_create(
+	struct hw_asic_id *init,
+	struct dc_context *ctx)
+{
+	struct asic_capability *cap;
+
+	if (!init) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	cap = dm_alloc(ctx, sizeof(struct asic_capability));
+
+	if (!cap) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (construct(cap, init, ctx))
+		return cap;
+
+	BREAK_TO_DEBUGGER();
+
+	dm_free(ctx, cap);
+
+	return NULL;
+}
+
+/*
+ * dal_asic_capability_destroy
+ *
+ * Destroy allocated memory.
+ */
+void dal_asic_capability_destroy(
+	struct asic_capability **cap)
+{
+	if (!cap) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if (!*cap) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct(*cap);
+
+	dm_free((*cap)->ctx, *cap);
+
+	*cap = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
new file mode 100644
index 000000000000..4aa8c305b08c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/asic_capability_interface.h"
+#include "include/asic_capability_types.h"
+
+#include "carrizo_asic_capability.h"
+
+#include "atom.h"
+#include "dce/dce_11_0_d.h"
+#include "smu/smu_8_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dal_asic_id.h"
+
+#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074
+
+/*
+ * carrizo_asic_capability_create
+ *
+ * Create and initiate Carrizo capability.
+ */
+void carrizo_asic_capability_create(struct asic_capability *cap,
+	struct hw_asic_id *init)
+{
+	uint32_t e_fuse_setting;
+	/* ASIC data */
+	cap->data[ASIC_DATA_CONTROLLERS_NUM] = 3;
+	cap->data[ASIC_DATA_DIGFE_NUM] = 3;
+	cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 3;
+	cap->data[ASIC_DATA_LINEBUFFER_NUM] = 3;
+	cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR] = 4;
+	cap->data[ASIC_DATA_DCE_VERSION] = 0x110; /* DCE 11 */
+	cap->data[ASIC_DATA_LINEBUFFER_SIZE] = 1712 * 144;
+	cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY] = 45;
+	cap->data[ASIC_DATA_CLOCKSOURCES_NUM] = 2;
+	cap->data[ASIC_DATA_MC_LATENCY] = 5000;
+	cap->data[ASIC_DATA_STUTTERMODE] = 0x200A;
+	cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY] = 2;
+	cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS] = 2;
+	cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER] = 2;
+	cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ] = 100;
+	cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES] = 1;
+	cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 3;
+
+	/* ASIC basic capability */
+	cap->caps.IS_FUSION = true;
+	cap->caps.DP_MST_SUPPORTED = true;
+	cap->caps.PANEL_SELF_REFRESH_SUPPORTED = true;
+	cap->caps.MIRABILIS_SUPPORTED = true;
+	cap->caps.NO_VCC_OFF_HPD_POLLING = true;
+	cap->caps.VCE_SUPPORTED = true;
+	cap->caps.HPD_CHECK_FOR_EDID = true;
+	cap->caps.DFSBYPASS_DYNAMIC_SUPPORT = true;
+	cap->caps.SUPPORT_8BPP = false;
+
+	/* ASIC stereo 3d capability */
+	cap->stereo_3d_caps.DISPLAY_BASED_ON_WS = true;
+	cap->stereo_3d_caps.HDMI_FRAME_PACK = true;
+	cap->stereo_3d_caps.INTERLACE_FRAME_PACK = true;
+	cap->stereo_3d_caps.DISPLAYPORT_FRAME_PACK = true;
+	cap->stereo_3d_caps.DISPLAYPORT_FRAME_ALT = true;
+	cap->stereo_3d_caps.INTERLEAVE = true;
+
+	e_fuse_setting = dm_read_index_reg(cap->ctx,CGS_IND_REG__SMC, ixVCE_HARVEST_FUSE_MACRO__ADDRESS);
+
+	/* Bits [28:27]*/
+	switch ((e_fuse_setting >> 27) & 0x3) {
+	case 0:
+		/*both VCE engine are working*/
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = false;
+		/*TODO:
+		cap->caps.wirelessLowVCEPerformance = false;
+		m_AsicCaps.vceInstance0Enabled = true;
+		m_AsicCaps.vceInstance1Enabled = true;*/
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 1:
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+		/*TODO:
+		m_AsicCaps.wirelessLowVCEPerformance = false;
+		m_AsicCaps.vceInstance1Enabled = true;*/
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 2:
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+		/*TODO:
+		m_AsicCaps.wirelessLowVCEPerformance = false;
+		m_AsicCaps.vceInstance0Enabled = true;*/
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 3:
+		/* VCE_DISABLE = 0x3  - both VCE
+		 * instances are in harvesting,
+		 * no VCE supported any more.
+		 */
+		cap->caps.VCE_SUPPORTED = false;
+		break;
+
+	default:
+		break;
+	}
+
+	if (ASIC_REV_IS_STONEY(init->hw_internal_rev))
+	{
+		/* Stoney is the same DCE11, but only two pipes, three  digs.
+		 * and HW added 64bit back for non SG */
+		cap->data[ASIC_DATA_CONTROLLERS_NUM] = 2;
+		cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 2;
+		cap->data[ASIC_DATA_LINEBUFFER_NUM] = 2;
+		/*3 DP MST per connector, limited by number of pipe and number
+		 * of Dig.*/
+		cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR] = 2;
+
+	}
+
+
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
new file mode 100644
index 000000000000..d1e9b8337d5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_CARRIZO_ASIC_CAPABILITY_H__
+#define __DAL_CARRIZO_ASIC_CAPABILITY_H__
+
+/* Forward declaration */
+struct asic_capability;
+
+/* Create and initialize Carrizo data */
+void carrizo_asic_capability_create(struct asic_capability *cap,
+	struct hw_asic_id *init);
+
+#endif /* __DAL_CARRIZO_ASIC_CAPABILITY_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
new file mode 100644
index 000000000000..af669c81085b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/asic_capability_interface.h"
+#include "include/asic_capability_types.h"
+
+#include "tonga_asic_capability.h"
+
+#include "atom.h"
+#include "dce/dce_10_0_d.h"
+#include "smu/smu_8_0_d.h"
+#include "dce/dce_10_0_sh_mask.h"
+#include "dal_asic_id.h"
+
+#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS     0xC0014074
+
+/*
+ * carrizo_asic_capability_create
+ *
+ * Create and initiate Carrizo capability.
+ */
+void tonga_asic_capability_create(struct asic_capability *cap,
+	struct hw_asic_id *init)
+{
+	uint32_t e_fuse_setting;
+	/* ASIC data */
+	cap->data[ASIC_DATA_CONTROLLERS_NUM] = 6;
+	cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 6;
+	cap->data[ASIC_DATA_DIGFE_NUM] = 6;
+	cap->data[ASIC_DATA_LINEBUFFER_NUM] = 6;
+
+	cap->data[ASIC_DATA_LINEBUFFER_SIZE] = 1712 * 144;
+	cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY] = 70;
+	cap->data[ASIC_DATA_CLOCKSOURCES_NUM] = 3;
+	cap->data[ASIC_DATA_MC_LATENCY] = 5000;
+	cap->data[ASIC_DATA_STUTTERMODE] = 0x2002;
+	cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR] = 4;
+	cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY] = 2;
+	cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 3;
+	cap->data[ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN] = 300000;
+
+	cap->data[ASIC_DATA_DCE_VERSION] = 0x100; /* DCE 11 */
+
+	cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS] = 2;
+	cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER] = 4;
+	cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ] = 40;
+	cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES] = 1;
+
+
+	/* ASIC basic capability */
+	cap->caps.IS_FUSION = true;
+	cap->caps.DP_MST_SUPPORTED = true;
+	cap->caps.PANEL_SELF_REFRESH_SUPPORTED = true;
+	cap->caps.MIRABILIS_SUPPORTED = true;
+	cap->caps.NO_VCC_OFF_HPD_POLLING = true;
+	cap->caps.VCE_SUPPORTED = true;
+	cap->caps.HPD_CHECK_FOR_EDID = true;
+	cap->caps.DFSBYPASS_DYNAMIC_SUPPORT = true;
+	cap->caps.SUPPORT_8BPP = false;
+
+	/* ASIC stereo 3d capability */
+	cap->stereo_3d_caps.DISPLAY_BASED_ON_WS = true;
+	cap->stereo_3d_caps.HDMI_FRAME_PACK = true;
+	cap->stereo_3d_caps.INTERLACE_FRAME_PACK = true;
+	cap->stereo_3d_caps.DISPLAYPORT_FRAME_PACK = true;
+	cap->stereo_3d_caps.DISPLAYPORT_FRAME_ALT = true;
+	cap->stereo_3d_caps.INTERLEAVE = true;
+
+	e_fuse_setting = dm_read_index_reg(cap->ctx, CGS_IND_REG__SMC, ixVCE_HARVEST_FUSE_MACRO__ADDRESS);
+
+	/* Bits [28:27]*/
+	switch ((e_fuse_setting >> 27) & 0x3) {
+	case 0:
+		/* both VCE engine are working*/
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = false;
+		/*
+		 * TODO:
+		 * cap->caps.wirelessLowVCEPerformance = false;
+		 * m_AsicCaps.vceInstance0Enabled = true;
+		 * m_AsicCaps.vceInstance1Enabled = true;
+		 */
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 1:
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+		/*
+		 * TODO:
+		 * m_AsicCaps.wirelessLowVCEPerformance = false;
+		 * m_AsicCaps.vceInstance1Enabled = true;
+		 */
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 2:
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+		/*
+		 * TODO:
+		 * m_AsicCaps.wirelessLowVCEPerformance = false;
+		 * m_AsicCaps.vceInstance0Enabled = true;
+		 */
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 3:
+		/*
+		 * VCE_DISABLE = 0x3  - both VCE
+		 * instances are in harvesting,
+		 * no VCE supported any more.
+		 */
+		cap->caps.VCE_SUPPORTED = false;
+		break;
+
+	default:
+		break;
+	}
+
+
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h b/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h
new file mode 100644
index 000000000000..29d9760e6c94
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef TONGA_ASIC_CAPABILITY_H_
+#define TONGA_ASIC_CAPABILITY_H_
+
+/* Forward declaration */
+struct asic_capability;
+
+/* Create and initialize Carrizo data */
+void tonga_asic_capability_create(struct asic_capability *cap,
+	struct hw_asic_id *init);
+
+#endif /* TONGA_ASIC_CAPABILITY_H_ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 05/29] drm/amd/dal: GPIO (General Purpose IO)
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (3 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 04/29] drm/amd/dal: Asic Capabilities Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 06/29] drm/amd/dal: Adapter Service Harry Wentland
                   ` (27 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Manages all DCE GPIO pins. The pins are represented as generic IO
handles as well as handles dedicated for certain functions, such as
DDC, HPD, and DVO.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/gpio/Makefile           |  32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c | 882 +++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h |  46 ++
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c |  81 ++
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h |  32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c | 366 +++++++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h |  47 ++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.c   | 400 ++++++++++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.h   |  34 +
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c              | 290 +++++++
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h              |  45 ++
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c  |  97 +++
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h  |  34 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.c  |  65 ++
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.h  |  32 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c  | 101 +++
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h  |  35 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.c    |  41 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.h    |  34 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h             |  48 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c        | 279 +++++++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c     | 386 +++++++++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h     |  57 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c           | 104 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h           |  60 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c       |  93 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h       |  71 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c          | 407 ++++++++++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h          | 129 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c      |  92 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h      |  47 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c      |  85 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h      |  79 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c           |  87 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h           |  45 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c     |  77 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h     |  50 ++
 drivers/gpu/drm/amd/dal/dc/gpio/irq.c              | 180 +++++
 drivers/gpu/drm/amd/dal/dc/gpio/irq.h              |  42 +
 39 files changed, 5112 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.h

diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/Makefile b/drivers/gpu/drm/amd/dal/dc/gpio/Makefile
new file mode 100644
index 000000000000..2507bb564946
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/Makefile
@@ -0,0 +1,32 @@
+#
+# Makefile for the 'gpio' sub-component of DAL.
+# It provides the control and status of HW GPIO pins.
+
+GPIO = ddc.o gpio_base.o gpio_service.o hw_ddc.o hw_factory.o \
+       hw_gpio.o hw_gpio_pad.o hw_gpio_pin.o hw_hpd.o hw_translate.o irq.o
+
+AMD_DAL_GPIO = $(addprefix $(AMDDALPATH)/dc/gpio/,$(GPIO))
+
+AMD_DAL_FILES += $(AMD_DAL_GPIO)
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+GPIO_DCE110 = hw_translate_dce110.o hw_factory_dce110.o hw_hpd_dce110.o \
+	hw_ddc_dce110.o
+
+AMD_DAL_GPIO_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpio/dce110/,$(GPIO_DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_GPIO_DCE110)
+endif
+
+###############################################################################
+# Diagnostics on FPGA
+###############################################################################
+GPIO_DIAG_FPGA = hw_translate_diag.o hw_factory_diag.o hw_hpd_diag.o hw_ddc_diag.o
+
+AMD_DAL_GPIO_DIAG_FPGA = $(addprefix $(AMDDALPATH)/dc/gpio/diagnostics/,$(GPIO_DIAG_FPGA))
+
+AMD_DAL_FILES += $(AMD_DAL_GPIO_DIAG_FPGA)
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
new file mode 100644
index 000000000000..8ff899c5ad12
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
@@ -0,0 +1,882 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+
+/*
+ * Header of this unit
+ */
+#include "hw_ddc_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#define ADDR_DDC_SETUP pin->addr.dc_i2c_ddc_setup
+/*
+ * This unit
+ */
+static void destruct(
+	struct hw_ddc_dce110 *pin)
+{
+	dal_hw_ddc_destruct(&pin->base);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_ddc_dce110 *pin = DDC_DCE110_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+struct hw_ddc_dce110_init {
+	struct hw_gpio_pin_reg hw_gpio_data_reg;
+	struct hw_ddc_mask hw_ddc_mask;
+	struct hw_ddc_dce110_addr hw_ddc_dce110_addr;
+};
+
+static const struct hw_ddc_dce110_init
+	hw_ddc_dce110_init_data[GPIO_DDC_LINE_COUNT] = {
+	/* GPIO_DDC_LINE_DDC1 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC1_MASK,
+				DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_A,
+				DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_EN,
+				DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_Y,
+				DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV_MASK,
+			DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK,
+			DC_GPIO_DDC1_MASK__AUX1_POL_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC1_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC2 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC2_MASK,
+				DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_A,
+				DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_EN,
+				DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_Y,
+				DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV_MASK,
+			DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK,
+			DC_GPIO_DDC2_MASK__AUX2_POL_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC2_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC3 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC3_MASK,
+				DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_A,
+				DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_EN,
+				DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_Y,
+				DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV_MASK,
+			DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK,
+			DC_GPIO_DDC3_MASK__AUX3_POL_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC3_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC4 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC4_MASK,
+				DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_A,
+				DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_EN,
+				DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_Y,
+				DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV_MASK,
+			DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK,
+			DC_GPIO_DDC4_MASK__AUX4_POL_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC4_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC5 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC5_MASK,
+				DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_A,
+				DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_EN,
+				DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_Y,
+				DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV_MASK,
+			DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK,
+			DC_GPIO_DDC5_MASK__AUX5_POL_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC5_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC6 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC6_MASK,
+				DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_A,
+				DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_EN,
+				DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_Y,
+				DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV_MASK,
+			DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK,
+			DC_GPIO_DDC6_MASK__AUX6_POL_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC6_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC_VGA */
+	{
+		{
+			{
+				mmDC_GPIO_DDCVGA_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_A,
+				DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_EN,
+				DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_Y,
+				DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV_MASK,
+			DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK,
+			DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDCVGA_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_I2CPAD */
+	{
+		{
+			{
+				mmDC_GPIO_I2CPAD_MASK,
+				DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_A,
+				DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_EN,
+				DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_Y,
+				DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_PD_DIS_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_RECV_MASK,
+			0,
+			0,
+			0
+		},
+		{
+			0
+		}
+	}
+};
+
+static const struct hw_ddc_dce110_init
+	hw_ddc_dce110_init_clock[GPIO_DDC_LINE_COUNT] = {
+	/* GPIO_DDC_LINE_DDC1 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC1_MASK,
+				DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_A,
+				DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_EN,
+				DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_Y,
+				DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV_MASK,
+			DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK,
+			DC_GPIO_DDC1_MASK__AUX1_POL_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC1_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC2 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC2_MASK,
+				DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_A,
+				DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_EN,
+				DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_Y,
+				DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV_MASK,
+			DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK,
+			DC_GPIO_DDC2_MASK__AUX2_POL_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC2_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC3 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC3_MASK,
+				DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_A,
+				DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_EN,
+				DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_Y,
+				DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV_MASK,
+			DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK,
+			DC_GPIO_DDC3_MASK__AUX3_POL_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC3_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC4 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC4_MASK,
+				DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_A,
+				DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_EN,
+				DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_Y,
+				DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV_MASK,
+			DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK,
+			DC_GPIO_DDC4_MASK__AUX4_POL_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC4_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC5 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC5_MASK,
+				DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_A,
+				DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_EN,
+				DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_Y,
+				DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV_MASK,
+			DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK,
+			DC_GPIO_DDC5_MASK__AUX5_POL_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC5_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC6 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC6_MASK,
+				DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_A,
+				DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_EN,
+				DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_Y,
+				DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV_MASK,
+			DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK,
+			DC_GPIO_DDC6_MASK__AUX6_POL_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC6_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC_VGA */
+	{
+		{
+			{
+				mmDC_GPIO_DDCVGA_MASK,
+				DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_A,
+				DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_EN,
+				DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_Y,
+				DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV_MASK,
+			DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK,
+			DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDCVGA_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_I2CPAD */
+	{
+		{
+			{
+				mmDC_GPIO_I2CPAD_MASK,
+				DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_A,
+				DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_EN,
+				DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_Y,
+				DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_PD_DIS_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_RECV_MASK,
+			0,
+			0,
+			0
+		},
+		{
+			0
+		}
+	}
+};
+
+static void setup_i2c_polling(
+	struct dc_context *ctx,
+	const uint32_t addr,
+	bool enable_detect,
+	bool detect_mode)
+{
+	uint32_t value;
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		enable_detect,
+		DC_I2C_DDC1_SETUP,
+		DC_I2C_DDC1_ENABLE);
+
+	set_reg_field_value(
+		value,
+		enable_detect,
+		DC_I2C_DDC1_SETUP,
+		DC_I2C_DDC1_EDID_DETECT_ENABLE);
+
+	if (enable_detect)
+		set_reg_field_value(
+			value,
+			detect_mode,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_EDID_DETECT_MODE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static enum gpio_result set_config(
+	struct hw_gpio_pin *ptr,
+	const struct gpio_config_data *config_data)
+{
+	struct hw_ddc_dce110 *pin = DDC_DCE110_FROM_BASE(ptr);
+	struct hw_gpio *hw_gpio = NULL;
+	uint32_t addr;
+	uint32_t regval;
+	uint32_t ddc_data_pd_en = 0;
+	uint32_t ddc_clk_pd_en = 0;
+	uint32_t aux_pad_mode = 0;
+
+	hw_gpio = &pin->base.base;
+
+	if (hw_gpio == NULL) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	/* switch dual mode GPIO to I2C/AUX mode */
+
+	addr = hw_gpio->pin_reg.DC_GPIO_DATA_MASK.addr;
+
+	regval = dm_read_reg(ptr->ctx, addr);
+
+	ddc_data_pd_en = get_reg_field_value(
+			regval,
+			DC_GPIO_DDC1_MASK,
+			DC_GPIO_DDC1DATA_PD_EN);
+
+	ddc_clk_pd_en = get_reg_field_value(
+			regval,
+			DC_GPIO_DDC1_MASK,
+			DC_GPIO_DDC1CLK_PD_EN);
+
+	aux_pad_mode = get_reg_field_value(
+			regval,
+			DC_GPIO_DDC1_MASK,
+			AUX_PAD1_MODE);
+
+	switch (config_data->config.ddc.type) {
+	case GPIO_DDC_CONFIG_TYPE_MODE_I2C:
+		/* On plug-in, there is a transient level on the pad
+		 * which must be discharged through the internal pull-down.
+		 * Enable internal pull-down, 2.5msec discharge time
+		 * is required for detection of AUX mode */
+		if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) {
+			if (!ddc_data_pd_en || !ddc_clk_pd_en) {
+				set_reg_field_value(
+					regval,
+					1,
+					DC_GPIO_DDC1_MASK,
+					DC_GPIO_DDC1DATA_PD_EN);
+
+				set_reg_field_value(
+					regval,
+					1,
+					DC_GPIO_DDC1_MASK,
+					DC_GPIO_DDC1CLK_PD_EN);
+
+				dm_write_reg(ptr->ctx, addr, regval);
+
+				if (config_data->type ==
+					GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
+					/* should not affect normal I2C R/W */
+					/* [anaumov] in DAL2, there was
+					 * dc_service_delay_in_microseconds(2500); */
+					dm_sleep_in_milliseconds(ptr->ctx, 3);
+			}
+		} else {
+			uint32_t reg2 = regval;
+			uint32_t sda_pd_dis = 0;
+			uint32_t scl_pd_dis = 0;
+
+			sda_pd_dis = get_reg_field_value(
+					reg2,
+					DC_GPIO_I2CPAD_MASK,
+					DC_GPIO_SDA_PD_DIS);
+
+			scl_pd_dis = get_reg_field_value(
+					reg2,
+					DC_GPIO_I2CPAD_MASK,
+					DC_GPIO_SCL_PD_DIS);
+
+			if (sda_pd_dis) {
+				sda_pd_dis = 0;
+
+				dm_write_reg(ptr->ctx, addr, reg2);
+
+				if (config_data->type ==
+					GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
+					/* should not affect normal I2C R/W */
+					/* [anaumov] in DAL2, there was
+					 * dc_service_delay_in_microseconds(2500); */
+					dm_sleep_in_milliseconds(ptr->ctx, 3);
+			}
+
+			if (!scl_pd_dis) {
+				scl_pd_dis = 1;
+
+				dm_write_reg(ptr->ctx, addr, reg2);
+
+				if (config_data->type ==
+					GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
+					/* should not affect normal I2C R/W */
+					/* [anaumov] in DAL2, there was
+					 * dc_service_delay_in_microseconds(2500); */
+					dm_sleep_in_milliseconds(ptr->ctx, 3);
+			}
+		}
+
+		if (aux_pad_mode) {
+			/* let pins to get de-asserted
+			 * before setting pad to I2C mode */
+			if (config_data->config.ddc.data_en_bit_present ||
+				config_data->config.ddc.clock_en_bit_present)
+				/* [anaumov] in DAL2, there was
+				 * dc_service_delay_in_microseconds(2000); */
+				dm_sleep_in_milliseconds(ptr->ctx, 2);
+
+			/* set the I2C pad mode */
+			/* read the register again,
+			 * some bits may have been changed */
+			regval = dm_read_reg(ptr->ctx, addr);
+
+			set_reg_field_value(
+				regval,
+				0,
+				DC_GPIO_DDC1_MASK,
+				AUX_PAD1_MODE);
+
+			dm_write_reg(ptr->ctx, addr, regval);
+		}
+
+		return GPIO_RESULT_OK;
+	case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
+		/* set the AUX pad mode */
+		if (!aux_pad_mode) {
+			set_reg_field_value(
+				regval,
+				1,
+				DC_GPIO_DDC1_MASK,
+				AUX_PAD1_MODE);
+
+			dm_write_reg(ptr->ctx, addr, regval);
+		}
+
+		return GPIO_RESULT_OK;
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
+		if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
+			(hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+			setup_i2c_polling(
+				ptr->ctx, ADDR_DDC_SETUP, 1, 0);
+			return GPIO_RESULT_OK;
+		}
+	break;
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
+		if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
+			(hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+			setup_i2c_polling(
+				ptr->ctx, ADDR_DDC_SETUP, 1, 1);
+			return GPIO_RESULT_OK;
+		}
+	break;
+	case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
+		if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
+			(hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+			setup_i2c_polling(
+				ptr->ctx, ADDR_DDC_SETUP, 0, 0);
+			return GPIO_RESULT_OK;
+		}
+	break;
+	}
+
+	BREAK_TO_DEBUGGER();
+
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = dal_hw_ddc_open,
+	.get_value = dal_hw_gpio_get_value,
+	.set_value = dal_hw_gpio_set_value,
+	.set_config = set_config,
+	.change_mode = dal_hw_gpio_change_mode,
+	.close = dal_hw_gpio_close,
+};
+
+
+static bool construct(
+	struct hw_ddc_dce110 *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	const struct hw_ddc_dce110_init *init;
+
+	if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (!dal_hw_ddc_construct(&pin->base, id, en, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	pin->base.base.base.funcs = &funcs;
+
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+		init = hw_ddc_dce110_init_data + en;
+
+		pin->base.base.pin_reg = init->hw_gpio_data_reg;
+		pin->base.mask = init->hw_ddc_mask;
+		pin->addr = init->hw_ddc_dce110_addr;
+
+		return true;
+	case GPIO_ID_DDC_CLOCK:
+		init = hw_ddc_dce110_init_clock + en;
+
+		pin->base.base.pin_reg = init->hw_gpio_data_reg;
+		pin->base.mask = init->hw_ddc_mask;
+		pin->addr = init->hw_ddc_dce110_addr;
+
+		return true;
+	default:
+		ASSERT_CRITICAL(false);
+	}
+
+	return false;
+}
+
+struct hw_gpio_pin *dal_hw_ddc_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_ddc_dce110 *pin = dm_alloc(ctx, sizeof(struct hw_ddc_dce110));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
new file mode 100644
index 000000000000..683036984f6f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_DDC_DCE110_H__
+#define __DAL_HW_DDC_DCE110_H__
+
+struct hw_ddc_dce110_addr {
+	uint32_t dc_i2c_ddc_setup;
+};
+
+struct hw_ddc_dce110 {
+	struct hw_ddc base;
+	struct hw_ddc_dce110_addr addr;
+};
+
+#define DDC_DCE110_FROM_BASE(ddc_base) \
+	container_of((HW_DDC_FROM_BASE(ddc_base)), struct hw_ddc_dce110, base)
+
+struct hw_gpio_pin *dal_hw_ddc_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
new file mode 100644
index 000000000000..bdeb60173d0e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_factory.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+#include "../hw_hpd.h"
+
+#include "hw_factory_dce110.h"
+
+#include "hw_hpd_dce110.h"
+#include "hw_ddc_dce110.h"
+
+/* fucntion table */
+static const struct hw_factory_funcs funcs = {
+	.create_ddc_data = dal_hw_ddc_dce110_create,
+	.create_ddc_clock = dal_hw_ddc_dce110_create,
+	.create_generic = NULL,
+	.create_hpd = dal_hw_hpd_dce110_create,
+	.create_gpio_pad = NULL,
+	.create_sync = NULL,
+	.create_gsl = NULL,
+};
+
+/*
+ * dal_hw_factory_dce110_init
+ *
+ * @brief
+ * Initialize HW factory function pointers and pin info
+ *
+ * @param
+ * struct hw_factory *factory - [out] struct of function pointers
+ */
+void dal_hw_factory_dce110_init(struct hw_factory *factory)
+{
+	/*TODO check ASIC CAPs*/
+	factory->number_of_pins[GPIO_ID_DDC_DATA] = 8;
+	factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8;
+	factory->number_of_pins[GPIO_ID_GENERIC] = 7;
+	factory->number_of_pins[GPIO_ID_HPD] = 6;
+	factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31;
+	factory->number_of_pins[GPIO_ID_VIP_PAD] = 0;
+	factory->number_of_pins[GPIO_ID_SYNC] = 2;
+	factory->number_of_pins[GPIO_ID_GSL] = 4;
+
+	factory->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
new file mode 100644
index 000000000000..ecf06ed0d587
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_DCE110_H__
+#define __DAL_HW_FACTORY_DCE110_H__
+
+/* Initialize HW factory function pointers and pin info */
+void dal_hw_factory_dce110_init(struct hw_factory *factory);
+
+#endif /* __DAL_HW_FACTORY_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
new file mode 100644
index 000000000000..a90115cdd55d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_hpd.h"
+
+/*
+ * Header of this unit
+ */
+#include "hw_hpd_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+/*
+ * This unit
+ */
+
+static void destruct(
+	struct hw_hpd_dce110 *pin)
+{
+	dal_hw_hpd_destruct(&pin->base);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+struct hw_gpio_generic_dce110_init {
+	struct hw_gpio_pin_reg hw_gpio_data_reg;
+	struct hw_hpd_dce110_addr addr;
+};
+
+static const struct hw_gpio_generic_dce110_init
+	hw_gpio_generic_dce110_init[GPIO_HPD_COUNT] = {
+	/* GPIO_HPD_1 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y_MASK
+			}
+		},
+		{
+			mmHPD0_DC_HPD_INT_STATUS,
+			mmHPD0_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_2 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y_MASK
+			}
+		},
+		{
+			mmHPD1_DC_HPD_INT_STATUS,
+			mmHPD1_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_3 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y_MASK
+			}
+		},
+		{
+			mmHPD2_DC_HPD_INT_STATUS,
+			mmHPD2_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_4 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y_MASK
+			}
+		},
+		{
+			mmHPD3_DC_HPD_INT_STATUS,
+			mmHPD3_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_5 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y_MASK
+			}
+		},
+		{
+			mmHPD4_DC_HPD_INT_STATUS,
+			mmHPD4_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_6 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y_MASK
+			}
+		},
+		{
+			mmHPD5_DC_HPD_INT_STATUS,
+			mmHPD5_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	}
+};
+
+static enum gpio_result get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(ptr);
+
+	/* in Interrupt mode we ask for SENSE bit */
+
+	if (ptr->mode == GPIO_MODE_INTERRUPT) {
+		uint32_t regval;
+		uint32_t hpd_delayed = 0;
+		uint32_t hpd_sense = 0;
+
+		regval = dm_read_reg(
+				ptr->ctx,
+				pin->addr.DC_HPD_INT_STATUS);
+
+		hpd_delayed = get_reg_field_value(
+				regval,
+				DC_HPD_INT_STATUS,
+				DC_HPD_SENSE_DELAYED);
+
+		hpd_sense = get_reg_field_value(
+				regval,
+				DC_HPD_INT_STATUS,
+				DC_HPD_SENSE);
+
+		*value = hpd_delayed;
+		return GPIO_RESULT_OK;
+	}
+
+	/* in any other modes, operate as normal GPIO */
+
+	return dal_hw_gpio_get_value(ptr, value);
+}
+
+static enum gpio_result set_config(
+	struct hw_gpio_pin *ptr,
+	const struct gpio_config_data *config_data)
+{
+	struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(ptr);
+
+	if (!config_data)
+		return GPIO_RESULT_INVALID_DATA;
+
+	{
+		uint32_t value;
+
+		value = dm_read_reg(
+			ptr->ctx,
+			pin->addr.DC_HPD_TOGGLE_FILT_CNTL);
+
+		set_reg_field_value(
+			value,
+			config_data->config.hpd.delay_on_connect / 10,
+			DC_HPD_TOGGLE_FILT_CNTL,
+			DC_HPD_CONNECT_INT_DELAY);
+
+		set_reg_field_value(
+			value,
+			config_data->config.hpd.delay_on_disconnect / 10,
+			DC_HPD_TOGGLE_FILT_CNTL,
+			DC_HPD_DISCONNECT_INT_DELAY);
+
+		dm_write_reg(
+			ptr->ctx,
+			pin->addr.DC_HPD_TOGGLE_FILT_CNTL,
+			value);
+
+	}
+
+	return GPIO_RESULT_OK;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = dal_hw_gpio_open,
+	.get_value = get_value,
+	.set_value = dal_hw_gpio_set_value,
+	.set_config = set_config,
+	.change_mode = dal_hw_gpio_change_mode,
+	.close = dal_hw_gpio_close,
+};
+
+static bool construct(
+	struct hw_hpd_dce110 *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	const struct hw_gpio_generic_dce110_init *init;
+
+	if (id != GPIO_ID_HPD) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (!dal_hw_hpd_construct(&pin->base, id, en, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	pin->base.base.base.funcs = &funcs;
+
+	init = hw_gpio_generic_dce110_init + en;
+
+	pin->base.base.pin_reg = init->hw_gpio_data_reg;
+
+	pin->addr = init->addr;
+
+	return true;
+}
+
+struct hw_gpio_pin *dal_hw_hpd_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_hpd_dce110 *pin = dm_alloc(ctx, sizeof(struct hw_hpd_dce110));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
new file mode 100644
index 000000000000..d032f4b9c91e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_HPD_DCE110_H__
+#define __DAL_HW_HPD_DCE110_H__
+
+struct hw_hpd_dce110_addr {
+	uint32_t DC_HPD_INT_STATUS;
+	uint32_t DC_HPD_TOGGLE_FILT_CNTL;
+};
+
+struct hw_hpd_dce110 {
+	struct hw_hpd base;
+	struct hw_hpd_dce110_addr addr;
+};
+
+#define HPD_DCE110_FROM_BASE(hpd_base) \
+	container_of((HW_HPD_FROM_BASE(hpd_base)), struct hw_hpd_dce110, base)
+
+struct hw_gpio_pin *dal_hw_hpd_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif /*__DAL_HW_HPD_DCE110_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
new file mode 100644
index 000000000000..b058f4d22708
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_translate.h"
+
+/*
+ * Header of this unit
+ */
+#include "hw_translate_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#include "../hw_gpio_pin.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+static bool offset_to_id(
+	uint32_t offset,
+	uint32_t mask,
+	enum gpio_id *id,
+	uint32_t *en)
+{
+	switch (offset) {
+	/* GENERIC */
+	case mmDC_GPIO_GENERIC_A:
+		*id = GPIO_ID_GENERIC;
+		switch (mask) {
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK:
+			*en = GPIO_GENERIC_A;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK:
+			*en = GPIO_GENERIC_B;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK:
+			*en = GPIO_GENERIC_C;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK:
+			*en = GPIO_GENERIC_D;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK:
+			*en = GPIO_GENERIC_E;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK:
+			*en = GPIO_GENERIC_F;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK:
+			*en = GPIO_GENERIC_G;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* HPD */
+	case mmDC_GPIO_HPD_A:
+		*id = GPIO_ID_HPD;
+		switch (mask) {
+		case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK:
+			*en = GPIO_HPD_1;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK:
+			*en = GPIO_HPD_2;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK:
+			*en = GPIO_HPD_3;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK:
+			*en = GPIO_HPD_4;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK:
+			*en = GPIO_HPD_5;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK:
+			*en = GPIO_HPD_6;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* SYNCA */
+	case mmDC_GPIO_SYNCA_A:
+		*id = GPIO_ID_SYNC;
+		switch (mask) {
+		case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK:
+			*en = GPIO_SYNC_HSYNC_A;
+			return true;
+		case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK:
+			*en = GPIO_SYNC_VSYNC_A;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* mmDC_GPIO_GENLK_MASK */
+	case mmDC_GPIO_GENLK_A:
+		*id = GPIO_ID_GSL;
+		switch (mask) {
+		case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK:
+			*en = GPIO_GSL_GENLOCK_CLOCK;
+			return true;
+		case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK:
+			*en = GPIO_GSL_GENLOCK_VSYNC;
+			return true;
+		case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK:
+			*en = GPIO_GSL_SWAPLOCK_A;
+			return true;
+		case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK:
+			*en = GPIO_GSL_SWAPLOCK_B;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* DDC */
+	/* we don't care about the GPIO_ID for DDC
+	 * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK
+	 * directly in the create method */
+	case mmDC_GPIO_DDC1_A:
+		*en = GPIO_DDC_LINE_DDC1;
+		return true;
+	case mmDC_GPIO_DDC2_A:
+		*en = GPIO_DDC_LINE_DDC2;
+		return true;
+	case mmDC_GPIO_DDC3_A:
+		*en = GPIO_DDC_LINE_DDC3;
+		return true;
+	case mmDC_GPIO_DDC4_A:
+		*en = GPIO_DDC_LINE_DDC4;
+		return true;
+	case mmDC_GPIO_DDC5_A:
+		*en = GPIO_DDC_LINE_DDC5;
+		return true;
+	case mmDC_GPIO_DDC6_A:
+		*en = GPIO_DDC_LINE_DDC6;
+		return true;
+	case mmDC_GPIO_DDCVGA_A:
+		*en = GPIO_DDC_LINE_DDC_VGA;
+		return true;
+	/* GPIO_I2CPAD */
+	case mmDC_GPIO_I2CPAD_A:
+		*en = GPIO_DDC_LINE_I2C_PAD;
+		return true;
+	/* Not implemented */
+	case mmDC_GPIO_PWRSEQ_A:
+	case mmDC_GPIO_PAD_STRENGTH_1:
+	case mmDC_GPIO_PAD_STRENGTH_2:
+	case mmDC_GPIO_DEBUG:
+		return false;
+	/* UNEXPECTED */
+	default:
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+}
+
+static bool id_to_offset(
+	enum gpio_id id,
+	uint32_t en,
+	struct gpio_pin_info *info)
+{
+	bool result = true;
+
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+		info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK;
+		switch (en) {
+		case GPIO_DDC_LINE_DDC1:
+			info->offset = mmDC_GPIO_DDC1_A;
+		break;
+		case GPIO_DDC_LINE_DDC2:
+			info->offset = mmDC_GPIO_DDC2_A;
+		break;
+		case GPIO_DDC_LINE_DDC3:
+			info->offset = mmDC_GPIO_DDC3_A;
+		break;
+		case GPIO_DDC_LINE_DDC4:
+			info->offset = mmDC_GPIO_DDC4_A;
+		break;
+		case GPIO_DDC_LINE_DDC5:
+			info->offset = mmDC_GPIO_DDC5_A;
+		break;
+		case GPIO_DDC_LINE_DDC6:
+			info->offset = mmDC_GPIO_DDC6_A;
+		break;
+		case GPIO_DDC_LINE_DDC_VGA:
+			info->offset = mmDC_GPIO_DDCVGA_A;
+		break;
+		case GPIO_DDC_LINE_I2C_PAD:
+			info->offset = mmDC_GPIO_I2CPAD_A;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_DDC_CLOCK:
+		info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK;
+		switch (en) {
+		case GPIO_DDC_LINE_DDC1:
+			info->offset = mmDC_GPIO_DDC1_A;
+		break;
+		case GPIO_DDC_LINE_DDC2:
+			info->offset = mmDC_GPIO_DDC2_A;
+		break;
+		case GPIO_DDC_LINE_DDC3:
+			info->offset = mmDC_GPIO_DDC3_A;
+		break;
+		case GPIO_DDC_LINE_DDC4:
+			info->offset = mmDC_GPIO_DDC4_A;
+		break;
+		case GPIO_DDC_LINE_DDC5:
+			info->offset = mmDC_GPIO_DDC5_A;
+		break;
+		case GPIO_DDC_LINE_DDC6:
+			info->offset = mmDC_GPIO_DDC6_A;
+		break;
+		case GPIO_DDC_LINE_DDC_VGA:
+			info->offset = mmDC_GPIO_DDCVGA_A;
+		break;
+		case GPIO_DDC_LINE_I2C_PAD:
+			info->offset = mmDC_GPIO_I2CPAD_A;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_GENERIC:
+		info->offset = mmDC_GPIO_GENERIC_A;
+		switch (en) {
+		case GPIO_GENERIC_A:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK;
+		break;
+		case GPIO_GENERIC_B:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK;
+		break;
+		case GPIO_GENERIC_C:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK;
+		break;
+		case GPIO_GENERIC_D:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK;
+		break;
+		case GPIO_GENERIC_E:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK;
+		break;
+		case GPIO_GENERIC_F:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK;
+		break;
+		case GPIO_GENERIC_G:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_HPD:
+		info->offset = mmDC_GPIO_HPD_A;
+		switch (en) {
+		case GPIO_HPD_1:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK;
+		break;
+		case GPIO_HPD_2:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK;
+		break;
+		case GPIO_HPD_3:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK;
+		break;
+		case GPIO_HPD_4:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK;
+		break;
+		case GPIO_HPD_5:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK;
+		break;
+		case GPIO_HPD_6:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_SYNC:
+		switch (en) {
+		case GPIO_SYNC_HSYNC_A:
+			info->offset = mmDC_GPIO_SYNCA_A;
+			info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK;
+		break;
+		case GPIO_SYNC_VSYNC_A:
+			info->offset = mmDC_GPIO_SYNCA_A;
+			info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK;
+		break;
+		case GPIO_SYNC_HSYNC_B:
+		case GPIO_SYNC_VSYNC_B:
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_GSL:
+		switch (en) {
+		case GPIO_GSL_GENLOCK_CLOCK:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK;
+		break;
+		case GPIO_GSL_GENLOCK_VSYNC:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask =
+				DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK;
+		break;
+		case GPIO_GSL_SWAPLOCK_A:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK;
+		break;
+		case GPIO_GSL_SWAPLOCK_B:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_VIP_PAD:
+	default:
+		ASSERT_CRITICAL(false);
+		result = false;
+	}
+
+	if (result) {
+		info->offset_y = info->offset + 2;
+		info->offset_en = info->offset + 1;
+		info->offset_mask = info->offset - 1;
+
+		info->mask_y = info->mask;
+		info->mask_en = info->mask;
+		info->mask_mask = info->mask;
+	}
+
+	return result;
+}
+
+/* function table */
+static const struct hw_translate_funcs funcs = {
+	.offset_to_id = offset_to_id,
+	.id_to_offset = id_to_offset,
+};
+
+/*
+ * dal_hw_translate_dce110_init
+ *
+ * @brief
+ * Initialize Hw translate function pointers.
+ *
+ * @param
+ * struct hw_translate *tr - [out] struct of function pointers
+ *
+ */
+void dal_hw_translate_dce110_init(struct hw_translate *tr)
+{
+	tr->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
new file mode 100644
index 000000000000..4d16e09853c8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_DCE110_H__
+#define __DAL_HW_TRANSLATE_DCE110_H__
+
+struct hw_translate;
+
+/* Initialize Hw translate function pointers */
+void dal_hw_translate_dce110_init(struct hw_translate *tr);
+
+#endif /* __DAL_HW_TRANSLATE_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
new file mode 100644
index 000000000000..c3d8cdb44756
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+
+#include "include/gpio_interface.h"
+#include "include/ddc_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_gpio_pin.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+#include "gpio_service.h"
+#include "gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "ddc.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+enum gpio_result dal_ddc_open(
+	struct ddc *ddc,
+	enum gpio_mode mode,
+	enum gpio_ddc_config_type config_type)
+{
+	enum gpio_result result;
+
+	struct gpio_ddc_open_options data_options;
+	struct gpio_ddc_open_options clock_options;
+	struct gpio_config_data config_data;
+
+	result = dal_gpio_open_ex(ddc->pin_data, mode, &data_options);
+
+	if (result != GPIO_RESULT_OK) {
+		BREAK_TO_DEBUGGER();
+		return result;
+	}
+
+	result = dal_gpio_open_ex(ddc->pin_clock, mode, &clock_options);
+
+	if (result != GPIO_RESULT_OK) {
+		BREAK_TO_DEBUGGER();
+		goto failure;
+	}
+
+	/* DDC clock and data pins should belong
+	 * to the same DDC block id,
+	 * we use the data pin to set the pad mode. */
+
+	if (mode == GPIO_MODE_INPUT)
+		/* this is from detect_sink_type,
+		 * we need extra delay there */
+		config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
+	else
+		config_data.type = GPIO_CONFIG_TYPE_DDC;
+
+	config_data.config.ddc.type = config_type;
+	config_data.config.ddc.data_en_bit_present =
+		data_options.en_bit_present;
+	config_data.config.ddc.clock_en_bit_present =
+		clock_options.en_bit_present;
+
+	result = dal_gpio_set_config(ddc->pin_data, &config_data);
+
+	if (result == GPIO_RESULT_OK)
+		return result;
+
+	BREAK_TO_DEBUGGER();
+
+	dal_gpio_close(ddc->pin_clock);
+
+failure:
+	dal_gpio_close(ddc->pin_data);
+
+	return result;
+}
+
+enum gpio_result dal_ddc_get_clock(
+	const struct ddc *ddc,
+	uint32_t *value)
+{
+	return dal_gpio_get_value(ddc->pin_clock, value);
+}
+
+enum gpio_result dal_ddc_set_clock(
+	const struct ddc *ddc,
+	uint32_t value)
+{
+	return dal_gpio_set_value(ddc->pin_clock, value);
+}
+
+enum gpio_result dal_ddc_get_data(
+	const struct ddc *ddc,
+	uint32_t *value)
+{
+	return dal_gpio_get_value(ddc->pin_data, value);
+}
+
+enum gpio_result dal_ddc_set_data(
+	const struct ddc *ddc,
+	uint32_t value)
+{
+	return dal_gpio_set_value(ddc->pin_data, value);
+}
+
+enum gpio_result dal_ddc_change_mode(
+	struct ddc *ddc,
+	enum gpio_mode mode)
+{
+	enum gpio_result result;
+
+	enum gpio_mode original_mode =
+		dal_gpio_get_mode(ddc->pin_data);
+
+	result = dal_gpio_change_mode(ddc->pin_data, mode);
+
+	/* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
+	 * in case of failures;
+	 * set_mode() is so that, in case of failure,
+	 * we must explicitly set original mode */
+
+	if (result != GPIO_RESULT_OK)
+		goto failure;
+
+	result = dal_gpio_change_mode(ddc->pin_clock, mode);
+
+	if (result == GPIO_RESULT_OK)
+		return result;
+
+	dal_gpio_change_mode(ddc->pin_clock, original_mode);
+
+failure:
+	dal_gpio_change_mode(ddc->pin_data, original_mode);
+
+	return result;
+}
+
+bool dal_ddc_is_hw_supported(
+	const struct ddc *ddc)
+{
+	return ddc->hw_info.hw_supported;
+}
+
+enum gpio_ddc_line dal_ddc_get_line(
+	const struct ddc *ddc)
+{
+	return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
+}
+
+bool dal_ddc_check_line_aborted(
+	const struct ddc *self)
+{
+	/* No arbitration with VBIOS is performed since DCE 6.0 */
+
+	return false;
+}
+
+enum gpio_result dal_ddc_set_config(
+	struct ddc *ddc,
+	enum gpio_ddc_config_type config_type)
+{
+	struct gpio_config_data config_data;
+
+	config_data.type = GPIO_CONFIG_TYPE_DDC;
+
+	config_data.config.ddc.type = config_type;
+	config_data.config.ddc.data_en_bit_present = false;
+	config_data.config.ddc.clock_en_bit_present = false;
+
+	return dal_gpio_set_config(ddc->pin_data, &config_data);
+}
+
+void dal_ddc_close(
+	struct ddc *ddc)
+{
+	dal_gpio_close(ddc->pin_clock);
+	dal_gpio_close(ddc->pin_data);
+}
+
+/*
+ * @brief
+ * Creation and destruction
+ */
+
+struct ddc *dal_gpio_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info)
+{
+	enum gpio_id id;
+	uint32_t en;
+	struct ddc *ddc;
+
+	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
+		return NULL;
+
+	ddc = dm_alloc(service->ctx, sizeof(struct ddc));
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	ddc->pin_data = dal_gpio_service_create_gpio_ex(
+		service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+
+	if (!ddc->pin_data) {
+		BREAK_TO_DEBUGGER();
+		goto failure_1;
+	}
+
+	ddc->pin_clock = dal_gpio_service_create_gpio_ex(
+		service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+
+	if (!ddc->pin_clock) {
+		BREAK_TO_DEBUGGER();
+		goto failure_2;
+	}
+
+	ddc->hw_info = *info;
+
+	ddc->ctx = service->ctx;
+
+	return ddc;
+
+failure_2:
+	dal_gpio_service_destroy_gpio(&ddc->pin_data);
+
+failure_1:
+	dm_free(service->ctx, ddc);
+
+	return NULL;
+}
+
+static void destruct(struct ddc *ddc)
+{
+	dal_ddc_close(ddc);
+	dal_gpio_service_destroy_gpio(&ddc->pin_data);
+	dal_gpio_service_destroy_gpio(&ddc->pin_clock);
+
+}
+
+void dal_gpio_destroy_ddc(
+	struct ddc **ddc)
+{
+	if (!ddc || !*ddc) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct(*ddc);
+	dm_free((*ddc)->ctx, *ddc);
+
+	*ddc = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
new file mode 100644
index 000000000000..2631571f09c0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DDC_H__
+#define __DAL_DDC_H__
+
+struct ddc {
+	struct gpio *pin_data;
+	struct gpio *pin_clock;
+	struct gpio_ddc_hw_info hw_info;
+	struct dc_context *ctx;
+};
+
+struct ddc *dal_gpio_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info);
+
+void dal_gpio_destroy_ddc(
+	struct ddc **ddc);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
new file mode 100644
index 000000000000..1dd31d86031c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+
+/*
+ * This unit
+ */
+static void destruct(
+	struct hw_ddc *pin)
+{
+	dal_hw_ddc_destruct(pin);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_ddc *pin = HW_DDC_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = NULL,
+	.get_value = NULL,
+	.set_value = NULL,
+	.set_config = NULL,
+	.change_mode = NULL,
+	.close = NULL,
+};
+
+static bool construct(
+	struct hw_ddc *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	pin->base.base.funcs = &funcs;
+	return true;
+}
+
+struct hw_gpio_pin *dal_hw_ddc_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_ddc *pin = dm_alloc(ctx, sizeof(struct hw_ddc));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
new file mode 100644
index 000000000000..7515aaf33ee3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_DDC_DIAG_FPGA_H__
+#define __DAL_HW_DDC_DIAG_FPGA_H__
+
+struct hw_gpio_pin *dal_hw_ddc_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
new file mode 100644
index 000000000000..0690b4266002
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_factory.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+#include "../hw_hpd.h"
+
+/* function table */
+static const struct hw_factory_funcs funcs = {
+	.create_ddc_data = NULL,
+	.create_ddc_clock = NULL,
+	.create_generic = NULL,
+	.create_hpd = NULL,
+	.create_gpio_pad = NULL,
+	.create_sync = NULL,
+	.create_gsl = NULL,
+};
+
+void dal_hw_factory_diag_fpga_init(struct hw_factory *factory)
+{
+	factory->number_of_pins[GPIO_ID_DDC_DATA] = 8;
+	factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8;
+	factory->number_of_pins[GPIO_ID_GENERIC] = 7;
+	factory->number_of_pins[GPIO_ID_HPD] = 6;
+	factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31;
+	factory->number_of_pins[GPIO_ID_VIP_PAD] = 0;
+	factory->number_of_pins[GPIO_ID_SYNC] = 2;
+	factory->number_of_pins[GPIO_ID_GSL] = 4;
+	factory->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
new file mode 100644
index 000000000000..8a74f6adb8ee
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_DIAG_FPGA_H__
+#define __DAL_HW_FACTORY_DIAG_FPGA_H__
+
+/* Initialize HW factory function pointers and pin info */
+void dal_hw_factory_diag_fpga_init(struct hw_factory *factory);
+
+#endif /* __DAL_HW_FACTORY_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
new file mode 100644
index 000000000000..019e810ec31e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_hpd.h"
+
+
+static void destruct(
+	struct hw_hpd *pin)
+{
+	dal_hw_hpd_destruct(pin);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_hpd *pin = HW_HPD_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = NULL,
+	.get_value = NULL,
+	.set_value = NULL,
+	.set_config = NULL,
+	.change_mode = NULL,
+	.close = NULL,
+};
+
+static bool construct(
+	struct hw_hpd *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_hpd_construct(pin, id, en, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	pin->base.base.funcs = &funcs;
+
+	return true;
+}
+
+struct hw_gpio_pin *dal_hw_hpd_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_hpd *pin = dm_alloc(ctx, sizeof(struct hw_hpd));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
new file mode 100644
index 000000000000..bfa2c24a987a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_HPD_DIAG_FPGA_H__
+#define __DAL_HW_HPD_DIAG_FPGA_H__
+
+
+struct hw_gpio_pin *dal_hw_hpd_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif /*__DAL_HW_HPD_DIAG_FPGA_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
new file mode 100644
index 000000000000..177330ab157c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+
+#include "../hw_translate.h"
+
+
+/* function table */
+static const struct hw_translate_funcs funcs = {
+	.offset_to_id = NULL,
+	.id_to_offset = NULL,
+};
+
+void dal_hw_translate_diag_fpga_init(struct hw_translate *tr)
+{
+	tr->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
new file mode 100644
index 000000000000..4f053241fe96
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_DIAG_FPGA_H__
+#define __DAL_HW_TRANSLATE_DIAG_FPGA_H__
+
+struct hw_translate;
+
+/* Initialize Hw translate function pointers */
+void dal_hw_translate_diag_fpga_init(struct hw_translate *tr);
+
+#endif /* __DAL_HW_TRANSLATE_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h b/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
new file mode 100644
index 000000000000..7fcbb6972895
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_H__
+#define __DAL_GPIO_H__
+
+struct gpio {
+	struct gpio_service *service;
+	struct hw_gpio_pin *pin;
+	enum gpio_id id;
+	uint32_t en;
+	enum gpio_mode mode;
+	/* when GPIO comes from VBIOS, it has defined output state */
+	enum gpio_pin_output_state output_state;
+};
+
+struct gpio *dal_gpio_create(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state);
+
+void dal_gpio_destroy(
+	struct gpio **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
new file mode 100644
index 000000000000..7e16d631e671
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+
+#include "include/gpio_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_gpio_pin.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+#include "gpio_service.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "gpio.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Public API
+ */
+
+enum gpio_result dal_gpio_open(
+	struct gpio *gpio,
+	enum gpio_mode mode)
+{
+	return dal_gpio_open_ex(gpio, mode, NULL);
+}
+
+enum gpio_result dal_gpio_open_ex(
+	struct gpio *gpio,
+	enum gpio_mode mode,
+	void *options)
+{
+	if (gpio->pin) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_ALREADY_OPENED;
+	}
+
+	gpio->mode = mode;
+
+	return dal_gpio_service_open(
+		gpio->service, gpio->id, gpio->en, mode, options, &gpio->pin);
+}
+
+enum gpio_result dal_gpio_get_value(
+	const struct gpio *gpio,
+	uint32_t *value)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->get_value(gpio->pin, value);
+}
+
+enum gpio_result dal_gpio_set_value(
+	const struct gpio *gpio,
+	uint32_t value)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->set_value(gpio->pin, value);
+}
+
+enum gpio_mode dal_gpio_get_mode(
+	const struct gpio *gpio)
+{
+	return gpio->mode;
+}
+
+enum gpio_result dal_gpio_change_mode(
+	struct gpio *gpio,
+	enum gpio_mode mode)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->change_mode(gpio->pin, mode);
+}
+
+enum gpio_id dal_gpio_get_id(
+	const struct gpio *gpio)
+{
+	return gpio->id;
+}
+
+uint32_t dal_gpio_get_enum(
+	const struct gpio *gpio)
+{
+	return gpio->en;
+}
+
+enum gpio_result dal_gpio_set_config(
+	struct gpio *gpio,
+	const struct gpio_config_data *config_data)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->set_config(gpio->pin, config_data);
+}
+
+enum gpio_result dal_gpio_get_pin_info(
+	const struct gpio *gpio,
+	struct gpio_pin_info *pin_info)
+{
+	return gpio->service->translate.funcs->id_to_offset(
+		gpio->id, gpio->en, pin_info) ?
+		GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA;
+}
+
+enum sync_source dal_gpio_get_sync_source(
+	const struct gpio *gpio)
+{
+	switch (gpio->id) {
+	case GPIO_ID_GENERIC:
+		switch (gpio->en) {
+		case GPIO_GENERIC_A:
+			return SYNC_SOURCE_IO_GENERIC_A;
+		case GPIO_GENERIC_B:
+			return SYNC_SOURCE_IO_GENERIC_B;
+		case GPIO_GENERIC_C:
+			return SYNC_SOURCE_IO_GENERIC_C;
+		case GPIO_GENERIC_D:
+			return SYNC_SOURCE_IO_GENERIC_D;
+		case GPIO_GENERIC_E:
+			return SYNC_SOURCE_IO_GENERIC_E;
+		case GPIO_GENERIC_F:
+			return SYNC_SOURCE_IO_GENERIC_F;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	case GPIO_ID_SYNC:
+		switch (gpio->en) {
+		case GPIO_SYNC_HSYNC_A:
+			return SYNC_SOURCE_IO_HSYNC_A;
+		case GPIO_SYNC_VSYNC_A:
+			return SYNC_SOURCE_IO_VSYNC_A;
+		case GPIO_SYNC_HSYNC_B:
+			return SYNC_SOURCE_IO_HSYNC_B;
+		case GPIO_SYNC_VSYNC_B:
+			return SYNC_SOURCE_IO_VSYNC_B;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	case GPIO_ID_HPD:
+		switch (gpio->en) {
+		case GPIO_HPD_1:
+			return SYNC_SOURCE_IO_HPD1;
+		case GPIO_HPD_2:
+			return SYNC_SOURCE_IO_HPD2;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	case GPIO_ID_GSL:
+		switch (gpio->en) {
+		case GPIO_GSL_GENLOCK_CLOCK:
+			return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK;
+		case GPIO_GSL_GENLOCK_VSYNC:
+			return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC;
+		case GPIO_GSL_SWAPLOCK_A:
+			return SYNC_SOURCE_GSL_IO_SWAPLOCK_A;
+		case GPIO_GSL_SWAPLOCK_B:
+			return SYNC_SOURCE_GSL_IO_SWAPLOCK_B;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	default:
+		return SYNC_SOURCE_NONE;
+	}
+}
+
+enum gpio_pin_output_state dal_gpio_get_output_state(
+	const struct gpio *gpio)
+{
+	return gpio->output_state;
+}
+
+void dal_gpio_close(
+	struct gpio *gpio)
+{
+	if (!gpio)
+		return;
+
+	dal_gpio_service_close(gpio->service, &gpio->pin);
+
+	gpio->mode = GPIO_MODE_UNKNOWN;
+}
+
+/*
+ * @brief
+ * Creation and destruction
+ */
+
+struct gpio *dal_gpio_create(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state)
+{
+	struct gpio *gpio = dm_alloc(service->ctx, sizeof(struct gpio));
+
+	if (!gpio) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	gpio->service = service;
+	gpio->pin = NULL;
+	gpio->id = id;
+	gpio->en = en;
+	gpio->mode = GPIO_MODE_UNKNOWN;
+	gpio->output_state = output_state;
+
+	return gpio;
+}
+
+void dal_gpio_destroy(
+	struct gpio **gpio)
+{
+	if (!gpio || !*gpio) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	dal_gpio_close(*gpio);
+
+	dm_free((*gpio)->service->ctx, *gpio);
+
+	*gpio = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
new file mode 100644
index 000000000000..6837898b3bfe
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_interface.h"
+#include "include/ddc_interface.h"
+#include "include/irq_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "gpio_service.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "hw_gpio_pin.h"
+#include "gpio.h"
+#include "ddc.h"
+#include "irq.h"
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Public API.
+ */
+
+struct gpio_service *dal_gpio_service_create(
+	enum dce_version dce_version_major,
+	enum dce_version dce_version_minor,
+	struct dc_context *ctx)
+{
+	struct gpio_service *service;
+
+	uint32_t index_of_id;
+
+	service = dm_alloc(ctx, sizeof(struct gpio_service));
+
+	if (!service) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (!dal_hw_translate_init(&service->translate, dce_version_major,
+			dce_version_minor)) {
+		BREAK_TO_DEBUGGER();
+		goto failure_1;
+	}
+
+	if (!dal_hw_factory_init(&service->factory, dce_version_major,
+			dce_version_minor)) {
+		BREAK_TO_DEBUGGER();
+		goto failure_1;
+	}
+
+	/* allocate and initialize business storage */
+	{
+		const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+		index_of_id = 0;
+		service->ctx = ctx;
+
+		do {
+			uint32_t number_of_bits =
+				service->factory.number_of_pins[index_of_id];
+
+			uint32_t number_of_uints =
+				(number_of_bits + bits_per_uint - 1) /
+				bits_per_uint;
+
+			uint32_t *slot;
+
+			if (number_of_bits) {
+				uint32_t index_of_uint = 0;
+
+				slot = dm_alloc(
+					ctx,
+					number_of_uints * sizeof(uint32_t));
+
+				if (!slot) {
+					BREAK_TO_DEBUGGER();
+					goto failure_2;
+				}
+
+				do {
+					slot[index_of_uint] = 0;
+
+					++index_of_uint;
+				} while (index_of_uint < number_of_uints);
+			} else
+				slot = NULL;
+
+			service->busyness[index_of_id] = slot;
+
+			++index_of_id;
+		} while (index_of_id < GPIO_ID_COUNT);
+	}
+
+	return service;
+
+failure_2:
+	while (index_of_id) {
+		uint32_t *slot;
+
+		--index_of_id;
+
+		slot = service->busyness[index_of_id];
+
+		if (slot)
+			dm_free(ctx, slot);
+	};
+
+failure_1:
+	dm_free(ctx, service);
+
+	return NULL;
+}
+
+struct gpio *dal_gpio_service_create_gpio(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	enum gpio_pin_output_state output_state)
+{
+	enum gpio_id id;
+	uint32_t en;
+
+	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	return dal_gpio_create(service, id, en, output_state);
+}
+
+struct gpio *dal_gpio_service_create_gpio_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state)
+{
+	return dal_gpio_create(service, id, en, output_state);
+}
+
+void dal_gpio_service_destroy_gpio(
+	struct gpio **gpio)
+{
+	dal_gpio_destroy(gpio);
+}
+
+struct ddc *dal_gpio_service_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info)
+{
+	return dal_gpio_create_ddc(service, offset, mask, info);
+}
+
+void dal_gpio_service_destroy_ddc(
+	struct ddc **ddc)
+{
+	dal_gpio_destroy_ddc(ddc);
+}
+
+struct irq *dal_gpio_service_create_irq(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask)
+{
+	enum gpio_id id;
+	uint32_t en;
+
+	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	return dal_gpio_create_irq(service, id, en);
+}
+
+struct irq *dal_gpio_service_create_irq_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	return dal_gpio_create_irq(service, id, en);
+}
+
+void dal_gpio_service_destroy_irq(
+	struct irq **irq)
+{
+	dal_gpio_destroy_irq(irq);
+}
+
+void dal_gpio_service_destroy(
+	struct gpio_service **ptr)
+{
+	if (!ptr || !*ptr) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	/* free business storage */
+	{
+		uint32_t index_of_id = 0;
+
+		do {
+			uint32_t *slot = (*ptr)->busyness[index_of_id];
+
+			if (slot)
+				dm_free((*ptr)->ctx, slot);
+
+			++index_of_id;
+		} while (index_of_id < GPIO_ID_COUNT);
+	}
+
+	dm_free((*ptr)->ctx, *ptr);
+
+	*ptr = NULL;
+}
+
+/*
+ * @brief
+ * Private API.
+ */
+
+static bool is_pin_busy(
+	const struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+	const uint32_t *slot = service->busyness[id] + (en / bits_per_uint);
+
+	return 0 != (*slot & (1 << (en % bits_per_uint)));
+}
+
+static void set_pin_busy(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+	service->busyness[id][en / bits_per_uint] |=
+		(1 << (en % bits_per_uint));
+}
+
+static void set_pin_free(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+	service->busyness[id][en / bits_per_uint] &=
+		~(1 << (en % bits_per_uint));
+}
+
+enum gpio_result dal_gpio_service_open(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_mode mode,
+	void *options,
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_gpio_pin *pin;
+
+	if (!service->busyness[id]) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_OPEN_FAILED;
+	}
+
+	if (is_pin_busy(service, id, en)) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_DEVICE_BUSY;
+	}
+
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+		pin = service->factory.funcs->create_ddc_data(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_DDC_CLOCK:
+		pin = service->factory.funcs->create_ddc_clock(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_GENERIC:
+		pin = service->factory.funcs->create_generic(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_HPD:
+		pin = service->factory.funcs->create_hpd(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_GPIO_PAD:
+		pin = service->factory.funcs->create_gpio_pad(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_SYNC:
+		pin = service->factory.funcs->create_sync(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_GSL:
+		pin = service->factory.funcs->create_gsl(
+			service->ctx, id, en);
+	break;
+	default:
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+
+	if (!pin->funcs->open(pin, mode, options)) {
+		ASSERT_CRITICAL(false);
+		dal_gpio_service_close(service, &pin);
+		return GPIO_RESULT_OPEN_FAILED;
+	}
+
+	set_pin_busy(service, id, en);
+	*ptr = pin;
+	return GPIO_RESULT_OK;
+}
+
+void dal_gpio_service_close(
+	struct gpio_service *service,
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_gpio_pin *pin;
+
+	if (!ptr) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	pin = *ptr;
+
+	if (pin) {
+		set_pin_free(service, pin->id, pin->en);
+
+		pin->funcs->close(pin);
+
+		pin->funcs->destroy(ptr);
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
new file mode 100644
index 000000000000..a17c4386668d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_SERVICE_H__
+#define __DAL_GPIO_SERVICE_H__
+
+struct hw_translate;
+struct hw_factory;
+
+struct gpio_service {
+	struct dc_context *ctx;
+	struct hw_translate translate;
+	struct hw_factory factory;
+	/*
+	 * @brief
+	 * Business storage.
+	 * For each member of 'enum gpio_id',
+	 * store array of bits (packed into uint32_t slots),
+	 * index individual bit by 'en' value */
+	uint32_t *busyness[GPIO_ID_COUNT];
+};
+
+enum gpio_result dal_gpio_service_open(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_mode mode,
+	void *options,
+	struct hw_gpio_pin **ptr);
+
+void dal_gpio_service_close(
+	struct gpio_service *service,
+	struct hw_gpio_pin **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
new file mode 100644
index 000000000000..41e46a7dc001
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+#include "hw_gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_ddc.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define FROM_HW_GPIO(ptr) \
+	container_of((ptr), struct hw_ddc, base)
+
+#define FROM_HW_GPIO_PIN(ptr) \
+	FROM_HW_GPIO(container_of((ptr), struct hw_gpio, base))
+
+bool dal_hw_ddc_open(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode,
+	void *options)
+{
+	struct hw_ddc *pin = FROM_HW_GPIO_PIN(ptr);
+
+	uint32_t en;
+
+	if (!options) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	/* get the EN bit before overwriting it */
+
+	dal_hw_gpio_get_reg_value(
+		ptr->ctx,
+		&pin->base.pin_reg.DC_GPIO_DATA_EN,
+		&en);
+
+	((struct gpio_ddc_open_options *)options)->en_bit_present = (en != 0);
+
+	return dal_hw_gpio_open(ptr, mode, options);
+}
+
+bool dal_hw_ddc_construct(
+	struct hw_ddc *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_gpio_construct(&pin->base, id, en, ctx))
+		return false;
+
+	pin->mask.DC_GPIO_DDC_MASK_MASK = 0;
+	pin->mask.DC_GPIO_DDC_PD_EN_MASK = 0;
+	pin->mask.DC_GPIO_DDC_RECV_MASK = 0;
+	pin->mask.AUX_PAD_MODE_MASK = 0;
+	pin->mask.AUX_POL_MASK = 0;
+	pin->mask.DC_GPIO_DDCCLK_STR_MASK = 0;
+
+	return true;
+}
+
+void dal_hw_ddc_destruct(
+	struct hw_ddc *pin)
+{
+	dal_hw_gpio_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
new file mode 100644
index 000000000000..a3a727c58b83
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_DDC_H__
+#define __DAL_HW_DDC_H__
+
+struct hw_ddc_mask {
+	uint32_t DC_GPIO_DDC_MASK_MASK;
+	uint32_t DC_GPIO_DDC_PD_EN_MASK;
+	uint32_t DC_GPIO_DDC_RECV_MASK;
+	uint32_t AUX_PAD_MODE_MASK;
+	uint32_t AUX_POL_MASK;
+	uint32_t DC_GPIO_DDCCLK_STR_MASK;
+};
+
+struct hw_ddc {
+	struct hw_gpio base;
+	struct hw_ddc_mask mask;
+};
+
+#define HW_DDC_FROM_BASE(hw_gpio) \
+	container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_ddc, base)
+
+bool dal_hw_ddc_construct(
+	struct hw_ddc *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_ddc_destruct(
+	struct hw_ddc *pin);
+
+bool dal_hw_ddc_open(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode,
+	void *options);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
new file mode 100644
index 000000000000..e0f6ecfaf4a7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_factory.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/hw_factory_dce110.h"
+#endif
+
+#include "diagnostics/hw_factory_diag.h"
+
+/*
+ * This unit
+ */
+
+bool dal_hw_factory_init(
+	struct hw_factory *factory,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment)
+{
+	if (IS_FPGA_MAXIMUS_DC(dce_environment)) {
+		dal_hw_factory_diag_fpga_init(factory);
+		return true;
+	}
+
+	switch (dce_version) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		dal_hw_factory_dce110_init(factory);
+		return true;
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		dal_hw_factory_dce110_init(factory);
+		return true;
+#endif
+	default:
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+}
+
+void dal_hw_factory_destroy(
+	struct dc_context *ctx,
+	struct hw_factory **factory)
+{
+	if (!factory || !*factory) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	dm_free(ctx, *factory);
+
+	*factory = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
new file mode 100644
index 000000000000..1fa8b6d85f35
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_H__
+#define __DAL_HW_FACTORY_H__
+
+struct hw_gpio_pin;
+
+struct hw_factory {
+	uint32_t number_of_pins[GPIO_ID_COUNT];
+
+	const struct hw_factory_funcs {
+		struct hw_gpio_pin *(*create_ddc_data)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_ddc_clock)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_generic)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_hpd)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_gpio_pad)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_sync)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_gsl)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+	} *funcs;
+};
+
+bool dal_hw_factory_init(
+	struct hw_factory *factory,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
new file mode 100644
index 000000000000..2a2262c7b107
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_gpio.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+enum gpio_result dal_hw_gpio_get_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t *value)
+{
+	*value = dm_read_reg(ctx, reg->addr);
+
+	*value &= reg->mask;
+
+	return GPIO_RESULT_OK;
+}
+
+enum gpio_result dal_hw_gpio_set_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t value)
+{
+	uint32_t prev_value;
+
+	if ((value & reg->mask) != value) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_INVALID_DATA;
+	}
+
+	prev_value = dm_read_reg(ctx, reg->addr);
+
+	prev_value &= ~reg->mask;
+	prev_value |= (value & reg->mask);
+
+	dm_write_reg(ctx, reg->addr, prev_value);
+
+	return GPIO_RESULT_OK;
+}
+
+uint32_t dal_hw_gpio_get_shift_from_mask(
+	uint32_t mask)
+{
+	uint32_t result = 0;
+
+	if (!mask)
+		return 32;
+
+	do {
+		if ((1 << result) & mask)
+			break;
+
+		++result;
+	} while (result < 32);
+
+	return result;
+}
+
+#define FROM_HW_GPIO_PIN(ptr) \
+	container_of((ptr), struct hw_gpio, base)
+
+static void store_registers(
+	struct hw_gpio *pin)
+{
+	dal_hw_gpio_get_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		&pin->store.mask);
+	dal_hw_gpio_get_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_A,
+		&pin->store.a);
+	dal_hw_gpio_get_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		&pin->store.en);
+
+	if (pin->mux_supported)
+		dal_hw_gpio_get_reg_value(
+			pin->base.ctx,
+			&pin->mux_reg.GPIO_MUX_CONTROL,
+			&pin->store.mux);
+}
+
+static void restore_registers(
+	struct hw_gpio *pin)
+{
+	dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->store.mask);
+	dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_A,
+		pin->store.a);
+	dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		pin->store.en);
+
+	if (pin->mux_supported)
+		dal_hw_gpio_set_reg_value(
+			pin->base.ctx,
+			&pin->mux_reg.GPIO_MUX_CONTROL,
+			pin->store.mux);
+}
+
+bool dal_hw_gpio_open(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode,
+	void *options)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	store_registers(pin);
+
+	ptr->opened = (pin->funcs->config_mode(pin, mode) == GPIO_RESULT_OK);
+
+	return ptr->opened;
+}
+
+enum gpio_result dal_hw_gpio_get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	const struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	enum gpio_result result;
+
+	switch (ptr->mode) {
+	case GPIO_MODE_INPUT:
+	case GPIO_MODE_OUTPUT:
+	case GPIO_MODE_HARDWARE:
+	case GPIO_MODE_FAST_OUTPUT:
+		result = dal_hw_gpio_get_reg_value(
+			ptr->ctx,
+			&pin->pin_reg.DC_GPIO_DATA_Y,
+			value);
+		/* Clients does not know that the value
+		 * comes from register and is shifted. */
+		if (result == GPIO_RESULT_OK)
+			*value >>= dal_hw_gpio_get_shift_from_mask(
+				pin->pin_reg.DC_GPIO_DATA_Y.mask);
+	break;
+	default:
+		result = GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+
+	return result;
+}
+
+enum gpio_result dal_hw_gpio_set_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	/* This is the public interface
+	 * where the input comes from client, not shifted yet
+	 * (because client does not know the shifts). */
+
+	switch (ptr->mode) {
+	case GPIO_MODE_OUTPUT:
+		return dal_hw_gpio_set_reg_value(
+			ptr->ctx,
+			&pin->pin_reg.DC_GPIO_DATA_A,
+			value << dal_hw_gpio_get_shift_from_mask(
+				pin->pin_reg.DC_GPIO_DATA_A.mask));
+	case GPIO_MODE_FAST_OUTPUT:
+		/* We use (EN) to faster switch (used in DDC GPIO).
+		 * So (A) is grounded, output is driven by (EN = 0)
+		 * to pull the line down (output == 0) and (EN=1)
+		 * then output is tri-state */
+		return dal_hw_gpio_set_reg_value(
+			ptr->ctx,
+			&pin->pin_reg.DC_GPIO_DATA_EN,
+			pin->pin_reg.DC_GPIO_DATA_EN.mask &
+			~(value << dal_hw_gpio_get_shift_from_mask(
+				pin->pin_reg.DC_GPIO_DATA_EN.mask)));
+	default:
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+enum gpio_result dal_hw_gpio_change_mode(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	return pin->funcs->config_mode(pin, mode);
+}
+
+void dal_hw_gpio_close(
+	struct hw_gpio_pin *ptr)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	restore_registers(pin);
+
+	ptr->mode = GPIO_MODE_UNKNOWN;
+	ptr->opened = false;
+}
+
+static enum gpio_result config_mode_input(
+	struct hw_gpio *pin)
+{
+	enum gpio_result result;
+
+	/* turn off output enable, act as input pin;
+	 * program the pin as GPIO, mask out signal driven by HW */
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		0);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->pin_reg.DC_GPIO_DATA_MASK.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+static enum gpio_result config_mode_output(
+	struct hw_gpio *pin)
+{
+	enum gpio_result result;
+
+	/* turn on output enable, act as output pin;
+	 * program the pin as GPIO, mask out signal driven by HW */
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		pin->pin_reg.DC_GPIO_DATA_EN.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->pin_reg.DC_GPIO_DATA_MASK.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+static enum gpio_result config_mode_fast_output(
+	struct hw_gpio *pin)
+{
+	enum gpio_result result;
+
+	/* grounding the A register then use the EN register bit
+	 * will have faster effect on the rise time */
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_A, 0);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->pin_reg.DC_GPIO_DATA_MASK.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+static enum gpio_result config_mode_hardware(
+	struct hw_gpio *pin)
+{
+	/* program the pin as tri-state, pin is driven by HW */
+
+	enum gpio_result result =
+		dal_hw_gpio_set_reg_value(
+			pin->base.ctx,
+			&pin->pin_reg.DC_GPIO_DATA_MASK,
+			0);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+enum gpio_result dal_hw_gpio_config_mode(
+	struct hw_gpio *pin,
+	enum gpio_mode mode)
+{
+	pin->base.mode = mode;
+
+	switch (mode) {
+	case GPIO_MODE_INPUT:
+		return config_mode_input(pin);
+	case GPIO_MODE_OUTPUT:
+		return config_mode_output(pin);
+	case GPIO_MODE_FAST_OUTPUT:
+		return config_mode_fast_output(pin);
+	case GPIO_MODE_HARDWARE:
+		return config_mode_hardware(pin);
+	default:
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+const struct hw_gpio_funcs func = {
+	.config_mode = dal_hw_gpio_config_mode,
+};
+
+bool dal_hw_gpio_construct(
+	struct hw_gpio *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	struct hw_gpio_pin *base = &pin->base;
+
+	if (!dal_hw_gpio_pin_construct(base, id, en, ctx))
+		return false;
+
+	pin->funcs = &func;
+
+	pin->pin_reg.DC_GPIO_DATA_MASK.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_MASK.mask = 0;
+	pin->pin_reg.DC_GPIO_DATA_A.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_A.mask = 0;
+	pin->pin_reg.DC_GPIO_DATA_EN.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_EN.mask = 0;
+	pin->pin_reg.DC_GPIO_DATA_Y.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_Y.mask = 0;
+	pin->mux_reg.GPIO_MUX_CONTROL.addr = 0;
+	pin->mux_reg.GPIO_MUX_CONTROL.mask = 0;
+	pin->mux_reg.GPIO_MUX_STEREO_SEL.addr = 0;
+	pin->mux_reg.GPIO_MUX_STEREO_SEL.mask = 0;
+
+	pin->store.mask = 0;
+	pin->store.a = 0;
+	pin->store.en = 0;
+	pin->store.mux = 0;
+
+	pin->mux_supported = false;
+
+	return true;
+}
+
+void dal_hw_gpio_destruct(
+	struct hw_gpio *pin)
+{
+	dal_hw_gpio_pin_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
new file mode 100644
index 000000000000..44eb86e1cc32
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_GPIO_H__
+#define __DAL_HW_GPIO_H__
+
+struct addr_mask {
+	uint32_t addr;
+	uint32_t mask;
+};
+
+enum gpio_result dal_hw_gpio_get_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t *value);
+
+enum gpio_result dal_hw_gpio_set_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t value);
+
+uint32_t dal_hw_gpio_get_shift_from_mask(
+	uint32_t mask);
+
+struct hw_gpio;
+
+struct hw_gpio_funcs {
+	enum gpio_result (*config_mode)(
+		struct hw_gpio *pin,
+		enum gpio_mode mode);
+};
+
+/* Register indices are represented by member variables
+ * and are to be filled in by constructors of derived classes.
+ * These members permit the use of common code
+ * for programming registers, where the sequence is the same
+ * but register sets are different.
+ * Some GPIOs have HW mux which allows to choose
+ * what is the source of the signal in HW mode */
+
+struct hw_gpio_pin_reg {
+	struct addr_mask DC_GPIO_DATA_MASK;
+	struct addr_mask DC_GPIO_DATA_A;
+	struct addr_mask DC_GPIO_DATA_EN;
+	struct addr_mask DC_GPIO_DATA_Y;
+};
+
+struct hw_gpio_mux_reg {
+	struct addr_mask GPIO_MUX_CONTROL;
+	struct addr_mask GPIO_MUX_STEREO_SEL;
+};
+
+struct hw_gpio {
+	struct hw_gpio_pin base;
+	const struct hw_gpio_funcs *funcs;
+	struct hw_gpio_pin_reg pin_reg;
+	struct hw_gpio_mux_reg mux_reg;
+
+	/* variables to save register value */
+	struct {
+		uint32_t mask;
+		uint32_t a;
+		uint32_t en;
+		uint32_t mux;
+	} store;
+
+	/* GPIO MUX support */
+	bool mux_supported;
+};
+
+#define HW_GPIO_FROM_BASE(hw_gpio_pin) \
+	container_of((hw_gpio_pin), struct hw_gpio, base)
+
+bool dal_hw_gpio_construct(
+	struct hw_gpio *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+bool dal_hw_gpio_open(
+	struct hw_gpio_pin *pin,
+	enum gpio_mode mode,
+	void *options);
+
+enum gpio_result dal_hw_gpio_get_value(
+	const struct hw_gpio_pin *pin,
+	uint32_t *value);
+
+enum gpio_result dal_hw_gpio_config_mode(
+	struct hw_gpio *pin,
+	enum gpio_mode mode);
+
+void dal_hw_gpio_destruct(
+	struct hw_gpio *pin);
+
+enum gpio_result dal_hw_gpio_set_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value);
+
+enum gpio_result dal_hw_gpio_change_mode(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode);
+
+void dal_hw_gpio_close(
+	struct hw_gpio_pin *ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
new file mode 100644
index 000000000000..2392f2ce353b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+#include "hw_gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_gpio_pad.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define FROM_HW_GPIO(ptr) \
+	container_of((ptr), struct hw_gpio_pad, base)
+
+#define FROM_HW_GPIO_PIN(ptr) \
+	FROM_HW_GPIO(container_of((ptr), struct hw_gpio, base))
+
+enum gpio_result dal_hw_gpio_pad_get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	const struct hw_gpio_pad *pin = FROM_HW_GPIO_PIN(ptr);
+
+	if (ptr->mode == GPIO_MODE_INTERRUPT)
+		/* in Interrupt mode, ask for interrupt status bit */
+		return dal_hw_gpio_get_reg_value(
+			ptr->ctx,
+			&pin->gpiopad_int_status,
+			value);
+	else
+		/* for any mode other than Interrupt,
+		 * gpio_pad operates as normal GPIO */
+		return dal_hw_gpio_get_value(ptr, value);
+}
+
+bool dal_hw_gpio_pad_construct(
+	struct hw_gpio_pad *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_gpio_construct(&pin->base, id, en, ctx))
+		return false;
+
+	pin->gpiopad_int_status.addr = 0;
+	pin->gpiopad_int_status.mask = 0;
+
+	return true;
+}
+
+void dal_hw_gpio_pad_destruct(
+	struct hw_gpio_pad *pin)
+{
+	dal_hw_gpio_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
new file mode 100644
index 000000000000..34b470a11464
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_GPIO_PAD_H__
+#define __DAL_HW_GPIO_PAD_H__
+
+struct hw_gpio_pad {
+	struct hw_gpio base;
+	struct addr_mask gpiopad_int_status;
+};
+
+bool dal_hw_gpio_pad_construct(
+	struct hw_gpio_pad *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_gpio_pad_destruct(
+	struct hw_gpio_pad *pin);
+
+enum gpio_result dal_hw_gpio_pad_get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
new file mode 100644
index 000000000000..411ad89645e0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_gpio_pin.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+enum gpio_result dal_hw_gpio_pin_set_config(
+	struct hw_gpio_pin *pin,
+	const struct gpio_config_data *config_data)
+{
+	/* Attention!
+	 * You must override this method in derived class */
+
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+enum gpio_result dal_hw_gpio_pin_change_mode(
+	struct hw_gpio_pin *pin,
+	enum gpio_mode mode)
+{
+	/* Attention!
+	 * You must override this method in derived class */
+
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+bool dal_hw_gpio_pin_construct(
+	struct hw_gpio_pin *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	pin->ctx = ctx;
+	pin->id = id;
+	pin->en = en;
+	pin->mode = GPIO_MODE_UNKNOWN;
+	pin->opened = false;
+
+	return true;
+}
+
+void dal_hw_gpio_pin_destruct(
+	struct hw_gpio_pin *pin)
+{
+	ASSERT(!pin->opened);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
new file mode 100644
index 000000000000..d1f2f2712fe2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_GPIO_PIN_H__
+#define __DAL_HW_GPIO_PIN_H__
+
+struct hw_gpio_pin;
+
+struct hw_gpio_pin_funcs {
+	void (*destroy)(
+		struct hw_gpio_pin **ptr);
+	bool (*open)(
+		struct hw_gpio_pin *pin,
+		enum gpio_mode mode,
+		void *options);
+	enum gpio_result (*get_value)(
+		const struct hw_gpio_pin *pin,
+		uint32_t *value);
+	enum gpio_result (*set_value)(
+		const struct hw_gpio_pin *pin,
+		uint32_t value);
+	enum gpio_result (*set_config)(
+		struct hw_gpio_pin *pin,
+		const struct gpio_config_data *config_data);
+	enum gpio_result (*change_mode)(
+		struct hw_gpio_pin *pin,
+		enum gpio_mode mode);
+	void (*close)(
+		struct hw_gpio_pin *pin);
+};
+
+struct hw_gpio_pin {
+	const struct hw_gpio_pin_funcs *funcs;
+	enum gpio_id id;
+	uint32_t en;
+	enum gpio_mode mode;
+	bool opened;
+	struct dc_context *ctx;
+};
+
+bool dal_hw_gpio_pin_construct(
+	struct hw_gpio_pin *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_gpio_pin_destruct(
+	struct hw_gpio_pin *pin);
+
+enum gpio_result dal_hw_gpio_pin_change_mode(
+	struct hw_gpio_pin *pin,
+	enum gpio_mode mode);
+
+enum gpio_result dal_hw_gpio_pin_set_config(
+	struct hw_gpio_pin *pin,
+	const struct gpio_config_data *config_data);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
new file mode 100644
index 000000000000..f072fd551b4a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+#include "hw_gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_hpd.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+static enum gpio_result config_mode(
+	struct hw_gpio *pin,
+	enum gpio_mode mode)
+{
+	if (mode == GPIO_MODE_INTERRUPT) {
+		/* Interrupt mode supported only by HPD (IrqGpio) pins. */
+		pin->base.mode = mode;
+
+		return dal_hw_gpio_set_reg_value(
+			pin->base.ctx,
+			&pin->pin_reg.DC_GPIO_DATA_MASK,
+			0);
+	} else
+		/* For any mode other than Interrupt,
+		 * act as normal GPIO. */
+		return dal_hw_gpio_config_mode(pin, mode);
+}
+
+const struct hw_gpio_funcs hw_hpd_func = {
+	.config_mode = config_mode,
+};
+
+bool dal_hw_hpd_construct(
+	struct hw_hpd *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_gpio_construct(&pin->base, id, en, ctx))
+		return false;
+	pin->base.funcs = &hw_hpd_func;
+	return true;
+}
+
+void dal_hw_hpd_destruct(
+	struct hw_hpd *pin)
+{
+	dal_hw_gpio_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
new file mode 100644
index 000000000000..3fb82df88802
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_HPD_H__
+#define __DAL_HW_HPD_H__
+
+struct hw_hpd {
+	struct hw_gpio base;
+};
+
+#define HW_HPD_FROM_BASE(hw_gpio) \
+	container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_hpd, base)
+
+bool dal_hw_hpd_construct(
+	struct hw_hpd *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_hpd_destruct(
+	struct hw_hpd *pin);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
new file mode 100644
index 000000000000..215322e9d7e9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_translate.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/hw_translate_dce110.h"
+#endif
+
+#include "diagnostics/hw_translate_diag.h"
+
+/*
+ * This unit
+ */
+
+bool dal_hw_translate_init(
+	struct hw_translate *translate,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment)
+{
+	if (IS_FPGA_MAXIMUS_DC(dce_environment)) {
+		dal_hw_translate_diag_fpga_init(translate);
+		return true;
+	}
+
+	switch (dce_version) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+#endif
+	case DCE_VERSION_11_0:
+		dal_hw_translate_dce110_init(translate);
+		return true;
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
new file mode 100644
index 000000000000..3a7d89ca1605
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_H__
+#define __DAL_HW_TRANSLATE_H__
+
+struct hw_translate_funcs {
+	bool (*offset_to_id)(
+		uint32_t offset,
+		uint32_t mask,
+		enum gpio_id *id,
+		uint32_t *en);
+	bool (*id_to_offset)(
+		enum gpio_id id,
+		uint32_t en,
+		struct gpio_pin_info *info);
+};
+
+struct hw_translate {
+	const struct hw_translate_funcs *funcs;
+};
+
+bool dal_hw_translate_init(
+	struct hw_translate *translate,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/irq.c b/drivers/gpu/drm/amd/dal/dc/gpio/irq.c
new file mode 100644
index 000000000000..debc2ea48ca1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/irq.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_interface.h"
+#include "include/irq_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_gpio_pin.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+#include "gpio_service.h"
+#include "gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "irq.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+enum gpio_result dal_irq_open(
+	struct irq *irq)
+{
+	return dal_gpio_open(irq->pin, GPIO_MODE_INTERRUPT);
+}
+
+enum gpio_result dal_irq_get_value(
+	const struct irq *irq,
+	uint32_t *value)
+{
+	return dal_gpio_get_value(irq->pin, value);
+}
+
+enum dc_irq_source dal_irq_get_source(
+	const struct irq *irq)
+{
+	enum gpio_id id = dal_gpio_get_id(irq->pin);
+
+	switch (id) {
+	case GPIO_ID_HPD:
+		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
+			dal_gpio_get_enum(irq->pin));
+	case GPIO_ID_GPIO_PAD:
+		return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
+			dal_gpio_get_enum(irq->pin));
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+enum dc_irq_source dal_irq_get_rx_source(
+	const struct irq *irq)
+{
+	enum gpio_id id = dal_gpio_get_id(irq->pin);
+
+	switch (id) {
+	case GPIO_ID_HPD:
+		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
+			dal_gpio_get_enum(irq->pin));
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+enum gpio_result dal_irq_setup_hpd_filter(
+	struct irq *irq,
+	struct gpio_hpd_config *config)
+{
+	struct gpio_config_data config_data;
+
+	if (!config)
+		return GPIO_RESULT_INVALID_DATA;
+
+	config_data.type = GPIO_CONFIG_TYPE_HPD;
+	config_data.config.hpd = *config;
+
+	return dal_gpio_set_config(irq->pin, &config_data);
+}
+
+void dal_irq_close(
+	struct irq *irq)
+{
+	dal_gpio_close(irq->pin);
+}
+
+/*
+ * @brief
+ * Creation and destruction
+ */
+
+struct irq *dal_gpio_create_irq(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct irq *irq;
+
+	switch (id) {
+	case GPIO_ID_HPD:
+	case GPIO_ID_GPIO_PAD:
+	break;
+	default:
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	irq = dm_alloc(service->ctx, sizeof(struct irq));
+
+	if (!irq) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	irq->pin = dal_gpio_service_create_gpio_ex(
+		service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+	irq->ctx = service->ctx;
+
+	if (irq->pin)
+		return irq;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(service->ctx, irq);
+
+	return NULL;
+}
+
+static void destruct(struct irq *irq)
+{
+	dal_irq_close(irq);
+	dal_gpio_service_destroy_gpio(&irq->pin);
+
+}
+
+void dal_gpio_destroy_irq(
+	struct irq **irq)
+{
+	if (!irq || !*irq) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	destruct(*irq);
+	dm_free((*irq)->ctx, *irq);
+
+	*irq = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/irq.h b/drivers/gpu/drm/amd/dal/dc/gpio/irq.h
new file mode 100644
index 000000000000..b69375cd8dc2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/irq.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_H__
+#define __DAL_IRQ_H__
+
+struct irq {
+	struct gpio *pin;
+	struct dc_context *ctx;
+};
+
+struct irq *dal_gpio_create_irq(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en);
+
+void dal_gpio_destroy_irq(
+	struct irq **ptr);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 06/29] drm/amd/dal: Adapter Service
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (4 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 05/29] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-12  0:26   ` Dave Airlie
  2016-02-11 17:19 ` [PATCH 07/29] drm/amd/dal: BIOS Parser Harry Wentland
                   ` (26 subsequent siblings)
  32 siblings, 1 reply; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Provides information about ASIC features and capabilities. Also provides
access to ASIC resources such as VBIOS, GPIO and I2cAux Manager

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/adapter/Makefile        |   24 +
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.c   | 2089 ++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.h   |   71 +
 .../adapter/dce110/hw_ctx_adapter_service_dce110.c |  304 +++
 .../adapter/dce110/hw_ctx_adapter_service_dce110.h |   40 +
 .../diagnostics/hw_ctx_adapter_service_diag.c      |  133 ++
 .../diagnostics/hw_ctx_adapter_service_diag.h      |   33 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.c    |  164 ++
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.h    |   86 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.c  |  208 ++
 .../drm/amd/dal/dc/adapter/wireless_data_source.h  |   80 +
 11 files changed, 3232 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h

diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/Makefile b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile
new file mode 100644
index 000000000000..2c6ca7a513bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile for the 'adapter' sub-component of DAL.
+# It provides the control and status of HW adapter.
+
+ADAPTER = adapter_service.o hw_ctx_adapter_service.o wireless_data_source.o
+
+AMD_DAL_ADAPTER = $(addprefix $(AMDDALPATH)/dc/adapter/,$(ADAPTER))
+
+AMD_DAL_FILES += $(AMD_DAL_ADAPTER)
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+AMD_DAL_FILES += $(AMDDALPATH)/dc/adapter/dce110/hw_ctx_adapter_service_dce110.o
+endif
+
+###############################################################################
+# FPGA Diagnositcs
+###############################################################################
+
+AMD_DAL_FILES += $(AMDDALPATH)/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.o
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
new file mode 100644
index 000000000000..dd2f931fe9a1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
@@ -0,0 +1,2089 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dc_bios_types.h"
+
+#include "include/adapter_service_interface.h"
+#include "include/i2caux_interface.h"
+#include "include/asic_capability_types.h"
+#include "include/gpio_service_interface.h"
+#include "include/asic_capability_interface.h"
+#include "include/logger_interface.h"
+
+#include "adapter_service.h"
+
+#include "hw_ctx_adapter_service.h"
+#include "wireless_data_source.h"
+
+#include "atom.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/hw_ctx_adapter_service_dce110.h"
+#endif
+
+#include "diagnostics/hw_ctx_adapter_service_diag.h"
+
+/*
+ * Adapter service feature entry table.
+ *
+ * This is an array of features that is used to generate feature set. Each
+ * entry consists three element:
+ *
+ * Feature name, default value, and if this feature is a boolean type. A
+ * feature can only be a boolean or int type.
+ *
+ * Example 1: a boolean type feature
+ * FEATURE_ENABLE_HW_EDID_POLLING, false, true
+ *
+ * First element is feature name: EATURE_ENABLE_HW_EDID_POLLING, it has a
+ * default value 0, and it is a boolean feature.
+ *
+ * Example 2: an int type feature
+ * FEATURE_DCP_PROGRAMMING_WA, 0x1FF7, false
+ *
+ * In this case, the default value is 0x1FF7 and not a boolean type, which
+ * makes it an int type.
+ */
+
+static struct feature_source_entry feature_entry_table[] = {
+	/* Feature name | default value | is boolean type */
+	{FEATURE_ENABLE_HW_EDID_POLLING, false, true},
+	{FEATURE_DP_SINK_DETECT_POLL_DATA_PIN, false, true},
+	{FEATURE_UNDERFLOW_INTERRUPT, false, true},
+	{FEATURE_ALLOW_WATERMARK_ADJUSTMENT, false, true},
+	{FEATURE_LIGHT_SLEEP, false, true},
+	{FEATURE_DCP_DITHER_FRAME_RANDOM_ENABLE, false, true},
+	{FEATURE_DCP_DITHER_RGB_RANDOM_ENABLE, false, true},
+	{FEATURE_DCP_DITHER_HIGH_PASS_RANDOM_ENABLE, false, true},
+	{FEATURE_LINE_BUFFER_ENHANCED_PIXEL_DEPTH, false, true},
+	{FEATURE_MAXIMIZE_URGENCY_WATERMARKS, false, true},
+	{FEATURE_MAXIMIZE_STUTTER_MARKS, false, true},
+	{FEATURE_MAXIMIZE_NBP_MARKS, false, true},
+	/*
+	 * We meet HW I2C issue when test S3 resume on KB.
+	 * An EPR is created for debug the issue.
+	 * Make Test has already been implemented
+	 * with HW I2C. The work load for revert back to SW I2C in make test
+	 * is big. Below is workaround for this issue.
+	 * Driver uses SW I2C.
+	 * Make Test uses HW I2C.
+	 */
+	{FEATURE_RESTORE_USAGE_I2C_SW_ENGINE, false, true},
+	{FEATURE_USE_MAX_DISPLAY_CLK, false, true},
+	{FEATURE_ALLOW_EDP_RESOURCE_SHARING, false, true},
+	{FEATURE_SUPPORT_DP_YUV, false, true},
+	{FEATURE_SUPPORT_DP_Y_ONLY, false, true},
+	{FEATURE_DISABLE_DP_GTC_SYNC, true, true},
+	{FEATURE_MODIFY_TIMINGS_FOR_WIRELESS, false, true},
+	{FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE, 0, false},
+	{FEATURE_DCP_DITHER_MODE, 0, false},
+	{FEATURE_DCP_PROGRAMMING_WA, 0, false},
+	{FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, false, true},
+	{FEATURE_ENABLE_DFS_BYPASS, false, true},
+	{FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT, false, true},
+	{FEATURE_MAX_COFUNC_NON_DP_DISPLAYS, 2, false},
+	{FEATURE_WIRELESS_LIMIT_720P, false, true},
+	{FEATURE_MODIFY_TIMINGS_FOR_WIRELESS, false, true},
+	{FEATURE_SUPPORTED_HDMI_CONNECTION_NUM, 0, false},
+	{FEATURE_DETECT_REQUIRE_HPD_HIGH, false, true},
+	{FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, false, true},
+	{FEATURE_LB_HIGH_RESOLUTION, false, true},
+	{FEATURE_MAX_CONTROLLER_NUM, 0, false},
+	{FEATURE_DRR_SUPPORT, AS_DRR_SUPPORT_ENABLED, false},
+	{FEATURE_STUTTER_MODE, 15, false},
+	{FEATURE_DP_DISPLAY_FORCE_SS_ENABLE, false, true},
+	{FEATURE_REPORT_CE_MODE_ONLY, false, true},
+	{FEATURE_ALLOW_OPTIMIZED_MODE_AS_DEFAULT, false, true},
+	{FEATURE_DDC_READ_FORCE_REPEATED_START, false, true},
+	{FEATURE_FORCE_TIMING_RESYNC, false, true},
+	{FEATURE_TMDS_DISABLE_DITHERING, false, true},
+	{FEATURE_HDMI_DISABLE_DITHERING, false, true},
+	{FEATURE_DP_DISABLE_DITHERING, false, true},
+	{FEATURE_EMBEDDED_DISABLE_DITHERING, true, true},
+	{FEATURE_ALLOW_SELF_REFRESH, false, true},
+	{FEATURE_ALLOW_DYNAMIC_PIXEL_ENCODING_CHANGE, false, true},
+	{FEATURE_ALLOW_HSYNC_VSYNC_ADJUSTMENT, false, true},
+	{FEATURE_FORCE_PSR, false, true},
+	{FEATURE_PSR_SETUP_TIME_TEST, 0, false},
+	{FEATURE_POWER_GATING_PIPE_IN_TILE, true, true},
+	{FEATURE_POWER_GATING_LB_PORTION, true, true},
+	{FEATURE_PREFER_3D_TIMING, false, true},
+	{FEATURE_VARI_BRIGHT_ENABLE, true, true},
+	{FEATURE_PSR_ENABLE, false, true},
+	{FEATURE_WIRELESS_ENABLE_COMPRESSED_AUDIO, false, true},
+	{FEATURE_WIRELESS_INCLUDE_UNVERIFIED_TIMINGS, true, true},
+	{FEATURE_EDID_STRESS_READ, false, true},
+	{FEATURE_DP_FRAME_PACK_STEREO3D, false, true},
+	{FEATURE_DISPLAY_PREFERRED_VIEW, 0, false},
+	{FEATURE_ALLOW_HDMI_WITHOUT_AUDIO, false, true},
+	{FEATURE_ABM_2_0, false, true},
+	{FEATURE_SUPPORT_MIRABILIS, false, true},
+	{FEATURE_OPTIMIZATION, 0xFFFF, false},
+	{FEATURE_PERF_MEASURE, 0, false},
+	{FEATURE_MIN_BACKLIGHT_LEVEL, 0, false},
+	{FEATURE_MAX_BACKLIGHT_LEVEL, 255, false},
+	{FEATURE_LOAD_DMCU_FIRMWARE, true, true},
+	{FEATURE_DISABLE_AZ_CLOCK_GATING, false, true},
+	{FEATURE_ENABLE_GPU_SCALING, false, true},
+	{FEATURE_DONGLE_SINK_COUNT_CHECK, true, true},
+	{FEATURE_INSTANT_UP_SCALE_DOWN_SCALE, false, true},
+	{FEATURE_TILED_DISPLAY, false, true},
+	{FEATURE_PREFERRED_ABM_CONFIG_SET, 0, false},
+	{FEATURE_CHANGE_SW_I2C_SPEED, 50, false},
+	{FEATURE_CHANGE_HW_I2C_SPEED, 50, false},
+	{FEATURE_CHANGE_I2C_SPEED_CONTROL, false, true},
+	{FEATURE_DEFAULT_PSR_LEVEL, 0, false},
+	{FEATURE_MAX_CLOCK_SOURCE_NUM, 0, false},
+	{FEATURE_REPORT_SINGLE_SELECTED_TIMING, false, true},
+	{FEATURE_ALLOW_HDMI_HIGH_CLK_DP_DONGLE, true, true},
+	{FEATURE_SUPPORT_EXTERNAL_PANEL_DRR, false, true},
+	{FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE, 0, false},
+	{FEATURE_ABM_CONFIG, 0, false},
+	{FEATURE_WIRELESS_ENABLE, false, true},
+	{FEATURE_ALLOW_DIRECT_MEMORY_ACCESS_TRIG, false, true},
+	{FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS, 0, false},
+	{FEATURE_USE_PPLIB, true, true},
+	{FEATURE_DISABLE_LPT_SUPPORT, false, true},
+	{FEATURE_DUMMY_FBC_BACKEND, false, true},
+	{FEATURE_DPMS_AUDIO_ENDPOINT_CONTROL, true, true},
+	{FEATURE_DISABLE_FBC_COMP_CLK_GATE, false, true},
+	{FEATURE_PIXEL_PERFECT_OUTPUT, false, true},
+	{FEATURE_8BPP_SUPPORTED, false, true}
+};
+
+
+/* Stores entire ASIC features by sets */
+uint32_t adapter_feature_set[FEATURE_MAXIMUM/32];
+
+enum {
+	LEGACY_MAX_NUM_OF_CONTROLLERS = 2,
+	DEFAULT_NUM_COFUNC_NON_DP_DISPLAYS = 2
+};
+
+/*
+ * get_feature_entries_num
+ *
+ * Get number of feature entries
+ */
+static inline uint32_t get_feature_entries_num(void)
+{
+	return ARRAY_SIZE(feature_entry_table);
+}
+
+static void get_platform_info_methods(
+		struct adapter_service *as)
+{
+	struct platform_info_params params;
+	uint32_t mask = 0;
+
+	params.data = &mask;
+	params.method = PM_GET_AVAILABLE_METHODS;
+
+	if (dm_get_platform_info(as->ctx, &params))
+		as->platform_methods_mask = mask;
+
+
+}
+
+static void initialize_backlight_caps(
+		struct adapter_service *as)
+{
+	struct firmware_info fw_info;
+	struct embedded_panel_info panel_info;
+	struct platform_info_ext_brightness_caps caps;
+	struct platform_info_params params;
+	bool custom_curve_present = false;
+	bool custom_min_max_present = false;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (!(PM_GET_EXTENDED_BRIGHNESS_CAPS & as->platform_methods_mask)) {
+			dal_logger_write(as->ctx->logger,
+					LOG_MAJOR_BACKLIGHT,
+					LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS,
+					"This method is not supported\n");
+			return;
+	}
+
+	if (dcb->funcs->get_firmware_info(dcb, &fw_info) != BP_RESULT_OK ||
+		dcb->funcs->get_embedded_panel_info(dcb, &panel_info) != BP_RESULT_OK)
+		return;
+
+	params.data = &caps;
+	params.method = PM_GET_EXTENDED_BRIGHNESS_CAPS;
+
+	if (dm_get_platform_info(as->ctx, &params)) {
+		as->ac_level_percentage = caps.basic_caps.ac_level_percentage;
+		as->dc_level_percentage = caps.basic_caps.dc_level_percentage;
+		custom_curve_present = (caps.data_points_num > 0);
+		custom_min_max_present = true;
+	} else
+		return;
+	/* Choose minimum backlight level base on priority:
+	 * extended caps,VBIOS,default */
+	if (custom_min_max_present)
+		as->backlight_8bit_lut[0] = caps.min_input_signal;
+
+	else if (fw_info.min_allowed_bl_level > 0)
+		as->backlight_8bit_lut[0] = fw_info.min_allowed_bl_level;
+
+	else
+		as->backlight_8bit_lut[0] = DEFAULT_MIN_BACKLIGHT;
+
+	/* Choose maximum backlight level base on priority:
+	 * extended caps,default */
+	if (custom_min_max_present)
+		as->backlight_8bit_lut[100] = caps.max_input_signal;
+
+	else
+		as->backlight_8bit_lut[100] = DEFAULT_MAX_BACKLIGHT;
+
+	if (as->backlight_8bit_lut[100] > ABSOLUTE_BACKLIGHT_MAX)
+		as->backlight_8bit_lut[100] = ABSOLUTE_BACKLIGHT_MAX;
+
+	if (as->backlight_8bit_lut[0] > as->backlight_8bit_lut[100])
+		as->backlight_8bit_lut[0] = as->backlight_8bit_lut[100];
+
+	if (custom_curve_present) {
+		uint16_t index = 1;
+		uint16_t i;
+		uint16_t num_of_data_points = (caps.data_points_num <= 99 ?
+				caps.data_points_num : 99);
+		/* Filling translation table from data points -
+		 * between every two provided data points we
+		 * lineary interpolate missing values
+		 */
+		for (i = 0 ; i < num_of_data_points; i++) {
+			uint16_t luminance = caps.data_points[i].luminance;
+			uint16_t signal_level =
+					caps.data_points[i].signal_level;
+
+			if (signal_level < as->backlight_8bit_lut[0])
+				signal_level = as->backlight_8bit_lut[0];
+
+			if (signal_level > as->backlight_8bit_lut[100])
+				signal_level = as->backlight_8bit_lut[100];
+
+			/* Lineary interpolate missing values */
+			if (index < luminance) {
+				uint16_t base_value =
+						as->backlight_8bit_lut[index-1];
+				uint16_t delta_signal =
+						signal_level - base_value;
+				uint16_t delta_luma = luminance - index + 1;
+				uint16_t step = delta_signal;
+
+				for (; index < luminance ; index++) {
+					as->backlight_8bit_lut[index] =
+							base_value +
+							(step / delta_luma);
+					step += delta_signal;
+				}
+			}
+			/* Now [index == luminance], so we can add
+			 * data point to the translation table */
+			as->backlight_8bit_lut[index++] = signal_level;
+		}
+		/* Complete the final segment of interpolation -
+		 * between last datapoint and maximum value */
+		if (index < 100) {
+			uint16_t base_value = as->backlight_8bit_lut[index-1];
+			uint16_t delta_signal =
+					as->backlight_8bit_lut[100]-base_value;
+			uint16_t delta_luma = 100 - index + 1;
+			uint16_t step = delta_signal;
+
+			for (; index < 100 ; index++) {
+				as->backlight_8bit_lut[index] = base_value +
+						(step / delta_luma);
+				step += delta_signal;
+			}
+		}
+	}
+	/* build backlight translation table based on default curve */
+	else {
+		/* Default backlight curve can be defined by
+		 * polinomial F(x) = A(x*x) + Bx + C.
+		 * Backlight curve should always  satisfy
+		 * F(0) = min, F(100) = max, so polinomial coefficients are:
+		 * A is 0.0255 - B/100 - min/10000 -
+		 * (255-max)/10000 = (max - min)/10000 - B/100
+		 * B is adjustable factor to modify the curve.
+		 * Bigger B results in less concave curve.
+		 * B range is [0..(max-min)/100]
+		 * C is backlight minimum
+		 */
+		uint16_t delta = as->backlight_8bit_lut[100] -
+				as->backlight_8bit_lut[0];
+		uint16_t coeffc = as->backlight_8bit_lut[0];
+		uint16_t coeffb = (BACKLIGHT_CURVE_COEFFB < delta ?
+				BACKLIGHT_CURVE_COEFFB : delta);
+		uint16_t coeffa = delta - coeffb;
+		uint16_t i;
+		uint32_t temp;
+
+		for (i = 1; i < 100 ; i++) {
+			temp = (coeffa * i * i) / BACKLIGHT_CURVE_COEFFA_FACTOR;
+			as->backlight_8bit_lut[i] = temp + (coeffb * i) /
+					BACKLIGHT_CURVE_COEFFB_FACTOR + coeffc;
+		}
+	}
+	as->backlight_caps_initialized = true;
+}
+
+static void log_overriden_features(
+	struct adapter_service *as,
+	const char *feature_name,
+	enum adapter_feature_id id,
+	bool bool_feature,
+	uint32_t value)
+{
+	if (bool_feature)
+		dal_logger_write(as->ctx->logger,
+			LOG_MAJOR_FEATURE_OVERRIDE,
+			LOG_MINOR_FEATURE_OVERRIDE,
+			"Overridden %s is %s now\n",
+			feature_name,
+			(value == 0) ? "disabled" : "enabled");
+	else
+		dal_logger_write(as->ctx->logger,
+			LOG_MAJOR_FEATURE_OVERRIDE,
+			LOG_MINOR_FEATURE_OVERRIDE,
+			"Overridden %s new value: %d\n",
+			feature_name,
+			value);
+}
+
+/*************************************
+ * Local static functions definition *
+ *************************************/
+
+#define check_bool_feature(feature) \
+case FEATURE_ ## feature: \
+	if (param->bool_param_enable_mask & \
+		(1 << DAL_PARAM_ ## feature)) { \
+		*data = param->bool_param_values & \
+		(1 << DAL_PARAM_ ## feature); \
+		ret = true; \
+		feature_name = "FEATURE_" #feature; \
+	} \
+	break
+
+#define check_int_feature(feature) \
+case FEATURE_ ## feature: \
+	if (param->int_param_values[DAL_PARAM_ ## feature] != \
+		DAL_PARAM_INVALID_INT) { \
+		*data = param->int_param_values[DAL_PARAM_ ## feature];\
+		ret = true;\
+		bool_feature = false;\
+		feature_name = "FEATURE_" #feature;\
+	} \
+	break
+
+/*
+ * override_default_parameters
+ *
+ * Override features (from runtime parameter)
+ * corresponding to Adapter Service Feature ID
+ */
+static bool override_default_parameters(
+	struct adapter_service *as,
+	const struct dal_override_parameters *param,
+	const uint32_t idx,
+	uint32_t *data)
+{
+	bool ret = false;
+	bool bool_feature = true;
+	char *feature_name;
+
+	if (idx >= get_feature_entries_num()) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	switch (feature_entry_table[idx].feature_id) {
+	check_int_feature(MAX_COFUNC_NON_DP_DISPLAYS);
+	check_int_feature(DRR_SUPPORT);
+	check_bool_feature(LIGHT_SLEEP);
+	check_bool_feature(MAXIMIZE_STUTTER_MARKS);
+	check_bool_feature(MAXIMIZE_URGENCY_WATERMARKS);
+	check_bool_feature(USE_MAX_DISPLAY_CLK);
+	check_bool_feature(ENABLE_DFS_BYPASS);
+	check_bool_feature(POWER_GATING_PIPE_IN_TILE);
+	check_bool_feature(POWER_GATING_LB_PORTION);
+	check_bool_feature(PSR_ENABLE);
+	check_bool_feature(VARI_BRIGHT_ENABLE);
+	check_bool_feature(USE_PPLIB);
+	check_bool_feature(DISABLE_LPT_SUPPORT);
+	check_bool_feature(DUMMY_FBC_BACKEND);
+	check_bool_feature(ENABLE_GPU_SCALING);
+	default:
+		return false;
+	}
+	if (ret)
+		log_overriden_features(
+			as,
+			feature_name,
+			feature_entry_table[idx].feature_id,
+			bool_feature,
+			*data);
+
+	return ret;
+}
+
+/*
+ * get_feature_value_from_data_sources
+ *
+ * For a given feature, determine its value from ASIC cap and wireless
+ * data source.
+ * idx : index of feature_entry_table for the feature id.
+ */
+static bool get_feature_value_from_data_sources(
+		const struct adapter_service *as,
+		const uint32_t idx,
+		uint32_t *data)
+{
+	if (idx >= get_feature_entries_num()) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	switch (feature_entry_table[idx].feature_id) {
+	case FEATURE_MAX_COFUNC_NON_DP_DISPLAYS:
+		*data = as->asic_cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS];
+		break;
+
+	case FEATURE_WIRELESS_LIMIT_720P:
+		*data = as->asic_cap->caps.WIRELESS_LIMIT_TO_720P;
+		break;
+
+	case FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT:
+		*data = as->asic_cap->caps.WIRELESS_FULL_TIMING_ADJUSTMENT;
+		break;
+
+	case FEATURE_MODIFY_TIMINGS_FOR_WIRELESS:
+		*data = as->asic_cap->caps.WIRELESS_TIMING_ADJUSTMENT;
+		break;
+
+	case FEATURE_SUPPORTED_HDMI_CONNECTION_NUM:
+		*data =
+		as->asic_cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM];
+		break;
+
+	case FEATURE_DETECT_REQUIRE_HPD_HIGH:
+		*data = as->asic_cap->caps.HPD_CHECK_FOR_EDID;
+		break;
+
+	case FEATURE_NO_HPD_LOW_POLLING_VCC_OFF:
+		*data = as->asic_cap->caps.NO_VCC_OFF_HPD_POLLING;
+		break;
+
+	case FEATURE_STUTTER_MODE:
+		*data = as->asic_cap->data[ASIC_DATA_STUTTERMODE];
+		break;
+
+	case FEATURE_WIRELESS_ENABLE:
+		*data = as->wireless_data.wireless_enable;
+		break;
+
+	case FEATURE_8BPP_SUPPORTED:
+		*data = as->asic_cap->caps.SUPPORT_8BPP;
+		break;
+
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+/* get_bool_value
+ *
+ * Get the boolean value of a given feature
+ */
+static bool get_bool_value(
+	const uint32_t set,
+	const uint32_t idx)
+{
+	if (idx >= 32) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	return ((set & (1 << idx)) != 0);
+}
+
+/*
+ * get_hpd_info
+ *
+ * Get HPD information from BIOS
+ */
+static bool get_hpd_info(struct adapter_service *as,
+	struct graphics_object_id id,
+	struct graphics_object_hpd_info *info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return BP_RESULT_OK == dcb->funcs->get_hpd_info(dcb, id, info);
+}
+
+/*
+ * lookup_feature_entry
+ *
+ * Find the entry index of a given feature in feature table
+ */
+static uint32_t lookup_feature_entry(
+	enum adapter_feature_id feature_id)
+{
+	uint32_t entries_num = get_feature_entries_num();
+	uint32_t i = 0;
+
+	while (i != entries_num) {
+		if (feature_entry_table[i].feature_id == feature_id)
+			break;
+
+		++i;
+	}
+
+	return i;
+}
+
+/*
+ * set_bool_value
+ *
+ * Set the boolean value of a given feature
+ */
+static void set_bool_value(
+	uint32_t *set,
+	const uint32_t idx,
+	bool value)
+{
+	if (idx >= 32) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	if (value)
+		*set |= (1 << idx);
+	else
+		*set &= ~(1 << idx);
+}
+
+/*
+ * generate_feature_set
+ *
+ * Generate the internal feature set from multiple data sources
+ */
+static bool generate_feature_set(
+		struct adapter_service *as,
+		const struct dal_override_parameters *param)
+{
+	uint32_t i = 0;
+	uint32_t value = 0;
+	uint32_t set_idx = 0;
+	uint32_t internal_idx = 0;
+	uint32_t entry_num = 0;
+	const struct feature_source_entry *entry = NULL;
+
+	dm_memset(adapter_feature_set, 0, sizeof(adapter_feature_set));
+	entry_num = get_feature_entries_num();
+
+
+	while (i != entry_num) {
+		entry = &feature_entry_table[i];
+
+		if (entry->feature_id <= FEATURE_UNKNOWN ||
+				entry->feature_id >= FEATURE_MAXIMUM) {
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+
+		set_idx = (uint32_t)((entry->feature_id - 1) / 32);
+		internal_idx = (uint32_t)((entry->feature_id - 1) % 32);
+
+		/* TODO: wireless, runtime parameter, vbios */
+		if (!override_default_parameters(as, param, i, &value)) {
+			if (!get_feature_value_from_data_sources(
+					as, i, &value)) {
+				/*
+				 * Can't find feature values from
+				 * above data sources
+				 * Assign default value
+				 */
+				value = entry->default_value;
+			}
+		}
+
+		if (entry->is_boolean_type)
+			set_bool_value(&adapter_feature_set[set_idx],
+					internal_idx,
+					value != 0);
+		else
+			adapter_feature_set[set_idx] = value;
+
+		i++;
+	}
+
+	return true;
+}
+
+
+/*
+ * create_hw_ctx
+ *
+ * Create HW context for adapter service. This is DCE specific.
+ */
+static struct hw_ctx_adapter_service *create_hw_ctx(
+	enum dce_version dce_version,
+	enum dce_environment dce_environment,
+	struct dc_context *ctx)
+{
+	if (IS_FPGA_MAXIMUS_DC(dce_environment))
+		return dal_adapter_service_create_hw_ctx_diag(ctx);
+
+	switch (dce_version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dal_adapter_service_create_hw_ctx_dce110(ctx);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dal_adapter_service_create_hw_ctx_dce110(ctx);
+#endif
+	default:
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+}
+
+/*
+ * adapter_service_destruct
+ *
+ * Release memory of objects in adapter service
+ */
+static void adapter_service_destruct(
+	struct adapter_service *as)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	dal_adapter_service_destroy_hw_ctx(&as->hw_ctx);
+	dal_i2caux_destroy(&as->i2caux);
+	dal_gpio_service_destroy(&as->gpio_service);
+	dal_asic_capability_destroy(&as->asic_cap);
+
+	dcb->funcs->destroy_integrated_info(dcb, &as->integrated_info);
+
+	if (as->dcb_internal) {
+		/* We are responsible only for destruction of Internal BIOS.
+		 * The External one will be destroyed by its creator. */
+		dal_bios_parser_destroy(&as->dcb_internal);
+	}
+}
+
+/*
+ * adapter_service_construct
+ *
+ * Construct the derived type of adapter service
+ */
+static bool adapter_service_construct(
+	struct adapter_service *as,
+	struct as_init_data *init_data)
+{
+	struct dc_bios *dcb;
+	enum dce_version dce_version;
+
+	if (!init_data)
+		return false;
+
+	/* Create ASIC capability */
+	as->ctx = init_data->ctx;
+	as->asic_cap = dal_asic_capability_create(
+			&init_data->hw_init_data, as->ctx);
+
+	if (!as->asic_cap) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	if (dal_adapter_service_get_dce_version(as) == DCE_VERSION_11_0) {
+		uint32_t i;
+
+		for (i = 0; i < ARRAY_SIZE(feature_entry_table); i++) {
+			enum adapter_feature_id id =
+				feature_entry_table[i].feature_id;
+			if (id == FEATURE_MAXIMIZE_URGENCY_WATERMARKS ||
+				id == FEATURE_MAXIMIZE_STUTTER_MARKS ||
+				id == FEATURE_MAXIMIZE_NBP_MARKS)
+				feature_entry_table[i].default_value = true;
+		}
+	}
+#endif
+
+	/* Generate feature set table */
+	if (!generate_feature_set(as, init_data->display_param)) {
+		ASSERT_CRITICAL(false);
+		goto failed_to_generate_features;
+	}
+
+	as->dce_environment = init_data->dce_environment;
+
+	if (init_data->vbios_override)
+		as->dcb_override = init_data->vbios_override;
+	else {
+		/* Create BIOS parser */
+		init_data->bp_init_data.ctx = init_data->ctx;
+
+		as->dcb_internal = dal_bios_parser_create(
+				&init_data->bp_init_data, as);
+
+		if (!as->dcb_internal) {
+			ASSERT_CRITICAL(false);
+			goto failed_to_create_bios_parser;
+		}
+	}
+
+	dcb = dal_adapter_service_get_bios_parser(as);
+
+	dce_version = dal_adapter_service_get_dce_version(as);
+
+	/* Create GPIO service */
+	as->gpio_service = dal_gpio_service_create(
+			dce_version,
+			as->dce_environment,
+			as->ctx);
+
+	if (!as->gpio_service) {
+		ASSERT_CRITICAL(false);
+		goto failed_to_create_gpio_service;
+	}
+
+	/* Create I2C AUX */
+	as->i2caux = dal_i2caux_create(as, as->ctx);
+
+	if (!as->i2caux) {
+		ASSERT_CRITICAL(false);
+		goto failed_to_create_i2caux;
+	}
+
+	/* Create Adapter Service HW Context*/
+	as->hw_ctx = create_hw_ctx(
+			dce_version,
+			as->dce_environment,
+			as->ctx);
+
+	if (!as->hw_ctx) {
+		ASSERT_CRITICAL(false);
+		goto failed_to_create_hw_ctx;
+	}
+
+	/* Avoid wireless encoder creation in upstream branch. */
+
+	/* Integrated info is not provided on discrete ASIC. NULL is allowed */
+	as->integrated_info = dcb->funcs->create_integrated_info(dcb);
+
+	dcb->funcs->post_init(dcb);
+
+	/* Generate backlight translation table and initializes
+			  other brightness properties */
+	as->backlight_caps_initialized = false;
+
+	get_platform_info_methods(as);
+
+	initialize_backlight_caps(as);
+
+	return true;
+
+failed_to_generate_features:
+	dal_adapter_service_destroy_hw_ctx(&as->hw_ctx);
+
+failed_to_create_hw_ctx:
+	dal_i2caux_destroy(&as->i2caux);
+
+failed_to_create_i2caux:
+	dal_gpio_service_destroy(&as->gpio_service);
+
+failed_to_create_gpio_service:
+	if (as->dcb_internal)
+		dal_bios_parser_destroy(&as->dcb_internal);
+
+failed_to_create_bios_parser:
+	dal_asic_capability_destroy(&as->asic_cap);
+
+	return false;
+}
+
+/*
+ * Global function definition
+ */
+
+/*
+ * dal_adapter_service_create
+ *
+ * Create adapter service
+ */
+struct adapter_service *dal_adapter_service_create(
+	struct as_init_data *init_data)
+{
+	struct adapter_service *as;
+
+	as = dm_alloc(init_data->ctx, sizeof(struct adapter_service));
+
+	if (!as) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (adapter_service_construct(as, init_data))
+		return as;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(init_data->ctx, as);
+
+	return NULL;
+}
+
+/*
+ * dal_adapter_service_destroy
+ *
+ * Destroy adapter service and objects it contains
+ */
+void dal_adapter_service_destroy(
+	struct adapter_service **as)
+{
+	if (!as) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	if (!*as) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	adapter_service_destruct(*as);
+
+	dm_free((*as)->ctx, *as);
+
+	*as = NULL;
+}
+
+/*
+ * dal_adapter_service_get_dce_version
+ *
+ * Get the DCE version of current ASIC
+ */
+enum dce_version dal_adapter_service_get_dce_version(
+	const struct adapter_service *as)
+{
+	uint32_t version = as->asic_cap->data[ASIC_DATA_DCE_VERSION];
+
+	switch (version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case 0x100:
+		return DCE_VERSION_10_0;
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case 0x110:
+		return DCE_VERSION_11_0;
+#endif
+	default:
+		ASSERT_CRITICAL(false);
+		return DCE_VERSION_UNKNOWN;
+	}
+}
+
+enum dce_environment dal_adapter_service_get_dce_environment(
+	const struct adapter_service *as)
+{
+	return as->dce_environment;
+}
+
+
+/*
+ * dal_adapter_service_get_controllers_num
+ *
+ * Get number of controllers
+ */
+uint8_t dal_adapter_service_get_controllers_num(
+	struct adapter_service *as)
+{
+	uint32_t result = as->asic_cap->data[ASIC_DATA_CONTROLLERS_NUM];
+
+	/* Check the "max num of controllers" feature,
+	 * use it for debugging purposes only */
+	/* TODO implement
+	 * dal_adapter_service_get_feature_value(as, ) */
+
+	return result;
+}
+
+/** Get total number of connectors.
+ *
+ * \param as	Adapter Service
+ *
+ * \return Total number of connectors. It is up-to-the caller to decide
+ *	if the number is valid.
+ */
+uint8_t dal_adapter_service_get_connectors_num(
+	struct adapter_service *as)
+{
+	uint8_t vbios_connectors_num = 0;
+	uint8_t wireless_connectors_num = 0;
+	struct dc_bios *dcb;
+
+	dcb = dal_adapter_service_get_bios_parser(as);
+
+	vbios_connectors_num = dcb->funcs->get_connectors_number(dcb);
+
+	wireless_connectors_num = wireless_get_connectors_num(as);
+
+	return vbios_connectors_num + wireless_connectors_num;
+}
+
+static bool is_wireless_object(struct graphics_object_id id)
+{
+	if ((id.type == OBJECT_TYPE_ENCODER &&
+		id.id == ENCODER_ID_INTERNAL_WIRELESS) ||
+		(id.type == OBJECT_TYPE_CONNECTOR && id.id ==
+			CONNECTOR_ID_WIRELESS) ||
+		(id.type == OBJECT_TYPE_CONNECTOR && id.id ==
+			CONNECTOR_ID_MIRACAST))
+		return true;
+	return false;
+}
+
+/**
+ * Get the number of source objects of an object
+ *
+ * \param [in] as: Adapter Service
+ *
+ * \param [in] id: The graphics object id
+ *
+ * \return
+ *     The number of the source objects of an object
+ */
+uint32_t dal_adapter_service_get_src_num(
+	struct adapter_service *as, struct graphics_object_id id)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (is_wireless_object(id))
+		return wireless_get_srcs_num(as, id);
+	else
+		return dcb->funcs->get_src_number(dcb, id);
+}
+
+/**
+ * Get the source objects of an object
+ *
+ * \param [in] id      The graphics object id
+ * \param [in] index   Enumerating index which starts at 0
+ *
+ * \return If enumerating successfully, return the VALID source object id,
+ *	otherwise, returns "zeroed out" object id.
+ *	Client should call dal_graphics_object_id_is_valid() to check
+ *	weather the id is valid.
+ */
+struct graphics_object_id dal_adapter_service_get_src_obj(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	uint32_t index)
+{
+	struct graphics_object_id src_object_id;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (is_wireless_object(id))
+		src_object_id = wireless_get_src_obj_id(as, id, index);
+	else {
+		if (BP_RESULT_OK != dcb->funcs->get_src_obj(dcb, id, index,
+				&src_object_id)) {
+			src_object_id =
+				dal_graphics_object_id_init(
+					0,
+					ENUM_ID_UNKNOWN,
+					OBJECT_TYPE_UNKNOWN);
+		}
+	}
+
+	return src_object_id;
+}
+
+/** Get connector object id associated with a connector index.
+ *
+ * \param as	Adapter Service
+ *
+ * \param connector_index Index of connector between zero and total number
+ *	returned by dal_adapter_service_get_connectors_num()
+ *
+ * \return graphics object id corresponding to the connector_index.
+ */
+struct graphics_object_id dal_adapter_service_get_connector_obj_id(
+		struct adapter_service *as,
+		uint8_t connector_index)
+{
+	struct dc_bios *dcb;
+	uint8_t bios_connectors_num;
+
+	dcb = dal_adapter_service_get_bios_parser(as);
+
+	bios_connectors_num = dcb->funcs->get_connectors_number(dcb);
+
+	if (connector_index >= bios_connectors_num)
+		return wireless_get_connector_id(as, connector_index);
+	else
+		return dcb->funcs->get_connector_id(dcb, connector_index);
+}
+
+bool dal_adapter_service_get_device_tag(
+		struct adapter_service *as,
+		struct graphics_object_id connector_object_id,
+		uint32_t device_tag_index,
+		struct connector_device_tag_info *info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (BP_RESULT_OK == dcb->funcs->get_device_tag(dcb,
+			connector_object_id, device_tag_index, info))
+		return true;
+	else
+		return false;
+}
+
+/* Check if DeviceId is supported by ATOM_OBJECT_HEADER support info */
+bool dal_adapter_service_is_device_id_supported(struct adapter_service *as,
+		struct device_id id)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return dcb->funcs->is_device_id_supported(dcb, id);
+}
+
+bool dal_adapter_service_is_meet_underscan_req(struct adapter_service *as)
+{
+	struct firmware_info fw_info;
+	enum bp_result bp_result = dal_adapter_service_get_firmware_info(
+		as, &fw_info);
+	uint32_t disp_clk_limit =
+		as->asic_cap->data[ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN];
+	if (BP_RESULT_OK == bp_result) {
+		dal_logger_write(as->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ADAPTER_SERVICE,
+			"Read firmware is NULL");
+		return false;
+	}
+	if (fw_info.default_display_engine_pll_frequency < disp_clk_limit)
+		return false;
+	return true;
+}
+
+bool dal_adapter_service_underscan_for_hdmi_only(struct adapter_service *as)
+{
+	return as->asic_cap->caps.UNDERSCAN_FOR_HDMI_ONLY;
+}
+/*
+ * dal_adapter_service_get_clock_sources_num
+ *
+ * Get number of clock sources
+ */
+uint8_t dal_adapter_service_get_clock_sources_num(
+	struct adapter_service *as)
+{
+	struct firmware_info fw_info;
+	uint32_t max_clk_src = 0;
+	uint32_t num = as->asic_cap->data[ASIC_DATA_CLOCKSOURCES_NUM];
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	/*
+	 * Check is system supports the use of the External clock source
+	 * as a clock source for DP
+	 */
+	enum bp_result bp_result = dcb->funcs->get_firmware_info(dcb, &fw_info);
+
+	if (BP_RESULT_OK == bp_result &&
+			fw_info.external_clock_source_frequency_for_dp != 0)
+		++num;
+
+	/*
+	 * Add clock source for wireless if supported
+	 */
+	num += (uint32_t)wireless_get_clocks_num(as);
+
+	/* Check the "max number of clock sources" feature */
+	if (dal_adapter_service_get_feature_value(
+			FEATURE_MAX_CLOCK_SOURCE_NUM,
+			&max_clk_src,
+			sizeof(uint32_t)))
+		if ((max_clk_src != 0) && (max_clk_src < num))
+			num = max_clk_src;
+
+	return num;
+}
+
+/*
+ * dal_adapter_service_get_func_controllers_num
+ *
+ * Get number of controllers
+ */
+uint8_t dal_adapter_service_get_func_controllers_num(
+	struct adapter_service *as)
+{
+	uint32_t result =
+		as->asic_cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM];
+
+	/* Check the "max num of controllers" feature,
+	 * use it for debugging purposes only */
+
+	/* Limit number of controllers by OS */
+
+	struct asic_feature_flags flags;
+
+	flags.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS];
+
+	if (flags.bits.LEGACY_CLIENT &&
+		(result > LEGACY_MAX_NUM_OF_CONTROLLERS))
+		result = LEGACY_MAX_NUM_OF_CONTROLLERS;
+
+	return result;
+}
+
+/*
+ * dal_adapter_service_is_feature_supported
+ *
+ * Return if a given feature is supported by the ASIC. The feature has to be
+ * a boolean type.
+ */
+bool dal_adapter_service_is_feature_supported(
+	enum adapter_feature_id feature_id)
+{
+	bool data = 0;
+
+	dal_adapter_service_get_feature_value(feature_id, &data, sizeof(bool));
+
+	return data;
+}
+
+/**
+ * Reports maximum number of confunctional non-DP displays.
+ * Value can be overriden if FEATURE_REPORT_SINGLE_SELECTED_TIMING feature is
+ * enabled.
+ *
+ * \return
+ *     Maximum number of confunctional non-DP displays
+ */
+uint32_t dal_adapter_service_get_max_cofunc_non_dp_displays(void)
+{
+	uint32_t non_dp_displays = DEFAULT_NUM_COFUNC_NON_DP_DISPLAYS;
+
+	if (true == dal_adapter_service_get_feature_value(
+			FEATURE_MAX_COFUNC_NON_DP_DISPLAYS,
+			&non_dp_displays,
+			sizeof(non_dp_displays))) {
+		/* the cached value exist */
+		/* TODO: add more logic as per-DAL2 */
+	}
+
+	return non_dp_displays;
+}
+
+uint32_t dal_adapter_service_get_single_selected_timing_signals(void)
+{
+	uint32_t signals_bitmap = 0;
+
+	if (dal_adapter_service_is_feature_supported(
+			FEATURE_REPORT_SINGLE_SELECTED_TIMING)) {
+		/* the cached value exist */
+		/* TODO: add more logic as per-DAL2 */
+		signals_bitmap = 0;
+	}
+
+	return signals_bitmap;
+}
+
+/*
+ * dal_adapter_service_get_i2c_info
+ *
+ * Get I2C information from BIOS
+ */
+bool dal_adapter_service_get_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	struct graphics_object_i2c_info *i2c_info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (!i2c_info) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	return BP_RESULT_OK == dcb->funcs->get_i2c_info(dcb, id, i2c_info);
+}
+
+/*
+ * dal_adapter_service_obtain_ddc
+ *
+ * Obtain DDC
+ */
+struct ddc *dal_adapter_service_obtain_ddc(
+	struct adapter_service *as,
+	struct graphics_object_id id)
+{
+	struct graphics_object_i2c_info i2c_info;
+	struct gpio_ddc_hw_info hw_info;
+
+
+	if (!dal_adapter_service_get_i2c_info(as, id, &i2c_info))
+		return NULL;
+
+	hw_info.ddc_channel = i2c_info.i2c_line;
+	hw_info.hw_supported = i2c_info.i2c_hw_assist;
+
+	return dal_gpio_service_create_ddc(
+		as->gpio_service,
+		i2c_info.gpio_info.clk_a_register_index,
+		1 << i2c_info.gpio_info.clk_a_shift,
+		&hw_info);
+}
+
+/*
+ * dal_adapter_service_release_ddc
+ *
+ * Release DDC
+ */
+void dal_adapter_service_release_ddc(
+	struct adapter_service *as,
+	struct ddc *ddc)
+{
+	dal_gpio_service_destroy_ddc(&ddc);
+}
+
+/*
+ * dal_adapter_service_obtain_hpd_irq
+ *
+ * Obtain HPD interrupt request
+ */
+struct irq *dal_adapter_service_obtain_hpd_irq(
+	struct adapter_service *as,
+	struct graphics_object_id id)
+{
+	enum bp_result bp_result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+	struct graphics_object_hpd_info hpd_info;
+	struct gpio_pin_info pin_info;
+
+	if (!get_hpd_info(as, id, &hpd_info))
+		return NULL;
+
+	bp_result = dcb->funcs->get_gpio_pin_info(dcb,
+		hpd_info.hpd_int_gpio_uid, &pin_info);
+
+	if (bp_result != BP_RESULT_OK) {
+		ASSERT(bp_result == BP_RESULT_NORECORD);
+		return NULL;
+	}
+
+	return dal_gpio_service_create_irq(
+		as->gpio_service,
+		pin_info.offset,
+		pin_info.mask);
+}
+
+/*
+ * dal_adapter_service_release_irq
+ *
+ * Release interrupt request
+ */
+void dal_adapter_service_release_irq(
+	struct adapter_service *as,
+	struct irq *irq)
+{
+	dal_gpio_service_destroy_irq(&irq);
+}
+
+/*
+ * dal_adapter_service_get_ss_info_num
+ *
+ * Get number of spread spectrum entries from BIOS
+ */
+uint32_t dal_adapter_service_get_ss_info_num(
+	struct adapter_service *as,
+	enum as_signal_type signal)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return dcb->funcs->get_ss_entry_number(dcb, signal);
+}
+
+/*
+ * dal_adapter_service_get_ss_info
+ *
+ * Get spread spectrum info from BIOS
+ */
+bool dal_adapter_service_get_ss_info(
+	struct adapter_service *as,
+	enum as_signal_type signal,
+	uint32_t idx,
+	struct spread_spectrum_info *info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	enum bp_result bp_result = dcb->funcs->get_spread_spectrum_info(dcb,
+			signal, idx, info);
+
+	return BP_RESULT_OK == bp_result;
+}
+
+/*
+ * dal_adapter_service_get_integrated_info
+ *
+ * Get integrated information on BIOS
+ */
+bool dal_adapter_service_get_integrated_info(
+	struct adapter_service *as,
+	struct integrated_info *info)
+{
+	if (info == NULL || as->integrated_info == NULL)
+		return false;
+
+	dm_memmove(info, as->integrated_info, sizeof(struct integrated_info));
+
+	return true;
+}
+
+/*
+ * dal_adapter_service_is_dfs_bypass_enabled
+ *
+ * Check if DFS bypass is enabled
+ */
+bool dal_adapter_service_is_dfs_bypass_enabled(
+	struct adapter_service *as)
+{
+	if (as->integrated_info == NULL)
+		return false;
+	if ((as->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) &&
+		dal_adapter_service_is_feature_supported(
+			FEATURE_ENABLE_DFS_BYPASS))
+		return true;
+	else
+		return false;
+}
+
+/*
+ * dal_adapter_service_get_sw_i2c_speed
+ *
+ * Get SW I2C speed
+ */
+uint32_t dal_adapter_service_get_sw_i2c_speed(
+	struct adapter_service *as)
+{
+	/* TODO: only from ASIC caps. Feature key is not implemented*/
+	return as->asic_cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ];
+}
+
+/*
+ * dal_adapter_service_get_hw_i2c_speed
+ *
+ * Get HW I2C speed
+ */
+uint32_t dal_adapter_service_get_hw_i2c_speed(
+	struct adapter_service *as)
+{
+	/* TODO: only from ASIC caps. Feature key is not implemented*/
+	return as->asic_cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ];
+}
+
+/*
+ * dal_adapter_service_get_mc_latency
+ *
+ * Get memory controller latency
+ */
+uint32_t dal_adapter_service_get_mc_latency(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_MC_LATENCY];
+}
+
+/*
+ * dal_adapter_service_get_asic_vram_bit_width
+ *
+ * Get the video RAM bit width set on the ASIC
+ */
+uint32_t dal_adapter_service_get_asic_vram_bit_width(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_VRAM_BITWIDTH];
+}
+
+/*
+ * dal_adapter_service_get_asic_bugs
+ *
+ * Get the bug flags set on this ASIC
+ */
+struct asic_bugs dal_adapter_service_get_asic_bugs(
+	struct adapter_service *as)
+{
+	return as->asic_cap->bugs;
+}
+
+
+struct dal_asic_runtime_flags dal_adapter_service_get_asic_runtime_flags(
+		struct adapter_service *as)
+{
+	return as->asic_cap->runtime_flags;
+}
+
+/*
+ * dal_adapter_service_get_line_buffer_size
+ *
+ * Get line buffer size
+ */
+uint32_t dal_adapter_service_get_line_buffer_size(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_LINEBUFFER_SIZE];
+}
+
+/*
+ * dal_adapter_service_get_bandwidth_tuning_params
+ *
+ * Get parameters for bandwidth tuning
+ */
+bool dal_adapter_service_get_bandwidth_tuning_params(
+	struct adapter_service *as,
+	union bandwidth_tuning_params *params)
+{
+	/* TODO: add implementation */
+	/* note: data comes from runtime parameters */
+	return false;
+}
+
+/*
+ * dal_adapter_service_get_feature_flags
+ *
+ * Get a copy of ASIC feature flags
+ */
+struct asic_feature_flags dal_adapter_service_get_feature_flags(
+	struct adapter_service *as)
+{
+	struct asic_feature_flags result = { { 0 } };
+
+	if (!as) {
+		ASSERT_CRITICAL(false);
+		return result;
+	}
+
+	result.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS];
+
+	return result;
+}
+
+/*
+ * dal_adapter_service_get_dram_bandwidth_efficiency
+ *
+ * Get efficiency of DRAM
+ */
+uint32_t dal_adapter_service_get_dram_bandwidth_efficiency(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY];
+}
+
+/*
+ * dal_adapter_service_obtain_gpio
+ *
+ * Obtain GPIO
+ */
+struct gpio *dal_adapter_service_obtain_gpio(
+	struct adapter_service *as,
+	enum gpio_id id,
+	uint32_t en)
+{
+	return dal_gpio_service_create_gpio_ex(
+		as->gpio_service, id, en,
+		GPIO_PIN_OUTPUT_STATE_DEFAULT);
+}
+
+/*
+ * dal_adapter_service_obtain_stereo_gpio
+ *
+ * Obtain GPIO for stereo3D
+ */
+struct gpio *dal_adapter_service_obtain_stereo_gpio(
+	struct adapter_service *as)
+{
+	const bool have_param_stereo_gpio = false;
+
+	struct asic_feature_flags result;
+
+	result.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS];
+
+	/* Case 1 : Workstation stereo */
+	if (result.bits.WORKSTATION_STEREO) {
+		/* "active low" <--> "default 3d right eye polarity" = false */
+		return dal_gpio_service_create_gpio_ex(as->gpio_service,
+				GPIO_ID_GENERIC, GPIO_GENERIC_A,
+				GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW);
+	/* Case 2 : runtime parameter override for sideband stereo */
+	} else if (have_param_stereo_gpio) {
+		/* TODO implement */
+		return NULL;
+		/* Case 3 : VBIOS gives us GPIO for sideband stereo */
+	} else {
+		const struct graphics_object_id id =
+				dal_graphics_object_id_init(GENERIC_ID_STEREO,
+						ENUM_ID_1, OBJECT_TYPE_GENERIC);
+
+		struct bp_gpio_cntl_info cntl_info;
+		struct gpio_pin_info pin_info;
+		struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+		/* Get GPIO record for this object.
+		 * Stereo GPIO record should have exactly one entry
+		 * where active state defines stereosync polarity */
+		if (1 != dcb->funcs->get_gpio_record(
+						dcb, id, &cntl_info,
+						1)) {
+			return NULL;
+		} else if (BP_RESULT_OK
+				!= dcb->funcs->get_gpio_pin_info(
+						dcb, cntl_info.id,
+						&pin_info)) {
+			/*ASSERT_CRITICAL(false);*/
+			return NULL;
+		} else {
+			return dal_gpio_service_create_gpio_ex(as->gpio_service,
+					pin_info.offset, pin_info.mask,
+					cntl_info.state);
+		}
+	}
+}
+
+/*
+ * dal_adapter_service_release_gpio
+ *
+ * Release GPIO
+ */
+void dal_adapter_service_release_gpio(
+	struct adapter_service *as,
+	struct gpio *gpio)
+{
+	dal_gpio_service_destroy_gpio(&gpio);
+}
+
+/*
+ * dal_adapter_service_get_firmware_info
+ *
+ * Get firmware information from BIOS
+ */
+bool dal_adapter_service_get_firmware_info(
+	struct adapter_service *as,
+	struct firmware_info *info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return dcb->funcs->get_firmware_info(dcb, info) == BP_RESULT_OK;
+}
+
+/*
+ * dal_adapter_service_get_audio_support
+ *
+ * Get information on audio support
+ */
+union audio_support dal_adapter_service_get_audio_support(
+	struct adapter_service *as)
+{
+	return dal_adapter_service_hw_ctx_get_audio_support(as->hw_ctx);
+}
+
+/*
+ * dal_adapter_service_get_stream_engines_num
+ *
+ * Get number of stream engines
+ */
+uint8_t dal_adapter_service_get_stream_engines_num(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_DIGFE_NUM];
+}
+
+/*
+ * dal_adapter_service_get_feature_value
+ *
+ * Get the cached value of a given feature. This value can be a boolean, int,
+ * or characters.
+ */
+bool dal_adapter_service_get_feature_value(
+	const enum adapter_feature_id feature_id,
+	void *data,
+	uint32_t size)
+{
+	uint32_t entry_idx = 0;
+	uint32_t set_idx = 0;
+	uint32_t set_internal_idx = 0;
+
+	if (feature_id >= FEATURE_MAXIMUM || feature_id <= FEATURE_UNKNOWN) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (data == NULL) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	entry_idx = lookup_feature_entry(feature_id);
+	set_idx = (uint32_t)((feature_id - 1)/32);
+	set_internal_idx = (uint32_t)((feature_id - 1) % 32);
+
+	if (entry_idx >= get_feature_entries_num()) {
+		/* Cannot find this entry */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (feature_entry_table[entry_idx].is_boolean_type) {
+		if (size != sizeof(bool)) {
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+
+		*(bool *)data = get_bool_value(adapter_feature_set[set_idx],
+				set_internal_idx);
+	} else {
+		if (size != sizeof(uint32_t)) {
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+
+		*(uint32_t *)data = adapter_feature_set[set_idx];
+	}
+
+	return true;
+}
+
+/*
+ * dal_adapter_service_get_memory_type_multiplier
+ *
+ * Get multiplier for the memory type
+ */
+uint32_t dal_adapter_service_get_memory_type_multiplier(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER];
+}
+
+/*
+ * dal_adapter_service_get_bios_parser
+ *
+ * Get BIOS parser handler
+ */
+struct dc_bios *dal_adapter_service_get_bios_parser(
+	struct adapter_service *as)
+{
+	return as->dcb_override ? as->dcb_override : as->dcb_internal;
+}
+
+/*
+ * dal_adapter_service_get_i2caux
+ *
+ * Get i2c aux handler
+ */
+struct i2caux *dal_adapter_service_get_i2caux(
+	struct adapter_service *as)
+{
+	return as->i2caux;
+}
+
+bool dal_adapter_service_initialize_hw_data(
+	struct adapter_service *as)
+{
+	return as->hw_ctx->funcs->power_up(as->hw_ctx);
+}
+
+struct graphics_object_id dal_adapter_service_enum_fake_path_resource(
+	struct adapter_service *as,
+	uint32_t index)
+{
+	return as->hw_ctx->funcs->enum_fake_path_resource(as->hw_ctx, index);
+}
+
+struct graphics_object_id dal_adapter_service_enum_stereo_sync_object(
+	struct adapter_service *as,
+	uint32_t index)
+{
+	return as->hw_ctx->funcs->enum_stereo_sync_object(as->hw_ctx, index);
+}
+
+struct graphics_object_id dal_adapter_service_enum_sync_output_object(
+	struct adapter_service *as,
+	uint32_t index)
+{
+	return as->hw_ctx->funcs->enum_sync_output_object(as->hw_ctx, index);
+}
+
+struct graphics_object_id dal_adapter_service_enum_audio_object(
+	struct adapter_service *as,
+	uint32_t index)
+{
+	return as->hw_ctx->funcs->enum_audio_object(as->hw_ctx, index);
+}
+
+
+void dal_adapter_service_update_audio_connectivity(
+	struct adapter_service *as,
+	uint32_t number_of_audio_capable_display_path)
+{
+	as->hw_ctx->funcs->update_audio_connectivity(
+		as->hw_ctx,
+		number_of_audio_capable_display_path,
+		dal_adapter_service_get_controllers_num(as));
+}
+
+bool dal_adapter_service_has_embedded_display_connector(
+	struct adapter_service *as)
+{
+	uint8_t index;
+	uint8_t num_connectors = dal_adapter_service_get_connectors_num(as);
+
+	if (num_connectors == 0 || num_connectors > ENUM_ID_COUNT)
+		return false;
+
+	for (index = 0; index < num_connectors; index++) {
+		struct graphics_object_id obj_id =
+			dal_adapter_service_get_connector_obj_id(as, index);
+		enum connector_id connector_id =
+			dal_graphics_object_id_get_connector_id(obj_id);
+
+		if ((connector_id == CONNECTOR_ID_LVDS) ||
+				(connector_id == CONNECTOR_ID_EDP))
+			return true;
+	}
+
+	return false;
+}
+
+bool dal_adapter_service_get_embedded_panel_info(
+	struct adapter_service *as,
+	struct embedded_panel_info *info)
+{
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (info == NULL)
+		/*TODO: add DALASSERT_MSG here*/
+		return false;
+
+	result = dcb->funcs->get_embedded_panel_info(dcb, info);
+
+	return result == BP_RESULT_OK;
+}
+
+bool dal_adapter_service_enum_embedded_panel_patch_mode(
+	struct adapter_service *as,
+	uint32_t index,
+	struct embedded_panel_patch_mode *mode)
+{
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (mode == NULL)
+		/*TODO: add DALASSERT_MSG here*/
+		return false;
+
+	result = dcb->funcs->enum_embedded_panel_patch_mode(dcb, index, mode);
+
+	return result == BP_RESULT_OK;
+}
+
+bool dal_adapter_service_get_faked_edid_len(
+	struct adapter_service *as,
+	uint32_t *len)
+{
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	result = dcb->funcs->get_faked_edid_len(dcb, len);
+
+	return result == BP_RESULT_OK;
+}
+
+bool dal_adapter_service_get_faked_edid_buf(
+	struct adapter_service *as,
+	uint8_t *buf,
+	uint32_t len)
+{
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	result = dcb->funcs->get_faked_edid_buf(dcb, buf, len);
+
+	return result == BP_RESULT_OK;
+
+}
+
+/*
+ * dal_adapter_service_is_fusion
+ *
+ * Is this Fusion ASIC
+ */
+bool dal_adapter_service_is_fusion(struct adapter_service *as)
+{
+	return as->asic_cap->caps.IS_FUSION;
+}
+
+/*
+ * dal_adapter_service_is_dfsbyass_dynamic
+ *
+ *
+ **/
+bool dal_adapter_service_is_dfsbyass_dynamic(struct adapter_service *as)
+{
+	return as->asic_cap->caps.DFSBYPASS_DYNAMIC_SUPPORT;
+}
+
+/*
+ * dal_adapter_service_should_optimize
+ *
+ * @brief Reports whether driver settings allow requested optimization
+ *
+ * @param
+ * as: adapter service handler
+ * feature: for which optimization is validated
+ *
+ * @return
+ * true if requested feature can be optimized
+ */
+bool dal_adapter_service_should_optimize(
+		struct adapter_service *as, enum optimization_feature feature)
+{
+	uint32_t supported_optimization = 0;
+	struct dal_asic_runtime_flags flags;
+
+	if (!dal_adapter_service_get_feature_value(FEATURE_OPTIMIZATION,
+			&supported_optimization, sizeof(uint32_t)))
+		return false;
+
+	/* Retrieve ASIC runtime flags */
+	flags = dal_adapter_service_get_asic_runtime_flags(as);
+
+	/* Check runtime flags against different optimization features */
+	switch (feature) {
+	case OF_SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY:
+		if (!flags.flags.bits.OPTIMIZED_DISPLAY_PROGRAMMING_ON_BOOT)
+			return false;
+		break;
+
+	case OF_SKIP_RESET_OF_ALL_HW_ON_S3RESUME:
+		if (as->integrated_info == NULL ||
+				!flags.flags.bits.SKIP_POWER_DOWN_ON_RESUME)
+			return false;
+		break;
+	case OF_SKIP_POWER_DOWN_INACTIVE_ENCODER:
+		if (!dal_adapter_service_get_asic_runtime_flags(as).flags.bits.
+			SKIP_POWER_DOWN_ON_RESUME)
+			return false;
+		break;
+	default:
+		break;
+	}
+
+	return (supported_optimization & feature) != 0;
+}
+
+/*
+ * dal_adapter_service_is_in_accelerated_mode
+ *
+ * @brief Determine if driver is in accelerated mode
+ *
+ * @param
+ * as: Adapter Service handler
+ *
+ * @out
+ * True if driver is in accelerated mode, false otherwise.
+ */
+bool dal_adapter_service_is_in_accelerated_mode(struct adapter_service *as)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return dcb->funcs->is_accelerated_mode(dcb);
+}
+
+struct ddc *dal_adapter_service_obtain_ddc_from_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_i2c_info *info)
+{
+	struct gpio_ddc_hw_info hw_info = {
+		info->i2c_hw_assist,
+		info->i2c_line };
+	return dal_gpio_service_create_ddc(as->gpio_service,
+		info->gpio_info.clk_a_register_index,
+		(1 << info->gpio_info.clk_a_shift), &hw_info);
+}
+
+struct bdf_info dal_adapter_service_get_adapter_info(struct adapter_service *as)
+{
+	return as->bdf_info;
+}
+
+/*
+ * dal_adapter_service_should_psr_skip_wait_for_pll_lock
+ *
+ * @brief Determine if this ASIC needs to wait on PLL lock bit
+ *
+ * @param
+ * as: Adapter Service handle
+ *
+ * @out
+ * True if ASIC does not need to wait for PLL lock bit, i.e. skip the wait.
+ */
+bool dal_adapter_service_should_psr_skip_wait_for_pll_lock(
+	struct adapter_service *as)
+{
+	return as->asic_cap->caps.SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT;
+}
+
+bool dal_adapter_service_is_lid_open(struct adapter_service *as)
+{
+	bool is_lid_open = false;
+	struct platform_info_params params;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	params.data = &is_lid_open;
+	params.method = PM_GET_LID_STATE;
+
+	if ((PM_GET_LID_STATE & as->platform_methods_mask) &&
+		dm_get_platform_info(as->ctx, &params))
+		return is_lid_open;
+
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	return dcb->funcs->is_lid_open(dcb);
+#else
+	return false;
+#endif
+}
+
+bool dal_adapter_service_get_panel_backlight_default_levels(
+	struct adapter_service *as,
+	struct panel_backlight_levels *levels)
+{
+	if (!as->backlight_caps_initialized)
+		return false;
+
+	levels->ac_level_percentage = as->ac_level_percentage;
+	levels->dc_level_percentage = as->dc_level_percentage;
+	return true;
+}
+
+bool dal_adapter_service_get_panel_backlight_boundaries(
+	struct adapter_service *as,
+	struct panel_backlight_boundaries *boundaries)
+{
+	if (!as->backlight_caps_initialized)
+		return false;
+	if (boundaries != NULL) {
+		boundaries->min_signal_level = as->backlight_8bit_lut[0];
+		boundaries->max_signal_level =
+			as->backlight_8bit_lut[SIZEOF_BACKLIGHT_LUT - 1];
+		return true;
+	}
+	return false;
+}
+
+
+uint32_t dal_adapter_service_get_view_port_pixel_granularity(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY];
+}
+
+/**
+ * Get number of paths per DP 1.2 connector from the runtime parameter if it
+ * exists.
+ * A check to see if MST is supported for the generation of ASIC is done
+ *
+ * \return
+ *    Number of paths per DP 1.2 connector is exists in runtime parameters
+ *    or ASIC cap
+ */
+uint32_t dal_adapter_service_get_num_of_path_per_dp_mst_connector(
+		struct adapter_service *as)
+{
+	if (as->asic_cap->caps.DP_MST_SUPPORTED == 0) {
+		/* ASIC doesn't support DP MST at all */
+		return 0;
+	}
+
+	return as->asic_cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR];
+}
+
+uint32_t dal_adapter_service_get_num_of_underlays(
+		struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES];
+}
+
+bool dal_adapter_service_get_encoder_cap_info(
+		struct adapter_service *as,
+		struct graphics_object_id id,
+		struct graphics_object_encoder_cap_info *info)
+{
+	struct bp_encoder_cap_info bp_cap_info = {0};
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (NULL == info) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	/*
+	 * Retrieve Encoder Capability Information from VBIOS and store the
+	 * call result (success or fail)
+	 * Info from VBIOS about HBR2 has two fields:
+	 *
+	 * - dpHbr2Cap: indicates supported/not supported by HW Encoder
+	 * - dpHbr2En : indicates DP spec compliant/not compliant
+	 */
+	result = dcb->funcs->get_encoder_cap_info(dcb, id, &bp_cap_info);
+
+	/* Set dp_hbr2_validated flag (it's equal to Enable) */
+	info->dp_hbr2_validated = bp_cap_info.DP_HBR2_EN;
+
+	if (result == BP_RESULT_OK) {
+		info->dp_hbr2_cap = bp_cap_info.DP_HBR2_CAP;
+		return true;
+	}
+
+	return false;
+}
+
+bool dal_adapter_service_is_mc_tuning_req(struct adapter_service *as)
+{
+	return as->asic_cap->caps.NEED_MC_TUNING ? true : false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
new file mode 100644
index 000000000000..60464e89cc5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ADAPTER_SERVICE_H__
+#define __DAL_ADAPTER_SERVICE_H__
+
+/* Include */
+#include "dc_bios_types.h"
+#include "include/adapter_service_interface.h"
+#include "wireless_data_source.h"
+
+/*
+ * Forward declaration
+ */
+struct gpio_service;
+struct asic_cap;
+
+
+/* Adapter service */
+struct adapter_service {
+	struct dc_context *ctx;
+	struct asic_capability *asic_cap;
+	struct dc_bios *dcb_internal;/* created by DC */
+	struct dc_bios *dcb_override;/* supplied by creator of DC */
+	enum dce_environment dce_environment;
+	struct gpio_service *gpio_service;
+	struct i2caux *i2caux;
+	struct wireless_data wireless_data;
+	struct hw_ctx_adapter_service *hw_ctx;
+	struct integrated_info *integrated_info;
+	struct bdf_info bdf_info;
+	uint32_t platform_methods_mask;
+	uint32_t ac_level_percentage;
+	uint32_t dc_level_percentage;
+	uint32_t backlight_caps_initialized;
+	uint32_t backlight_8bit_lut[SIZEOF_BACKLIGHT_LUT];
+};
+
+/* Type of feature with its runtime parameter and default value */
+struct feature_source_entry {
+	enum adapter_feature_id feature_id;
+	uint32_t default_value;
+	bool is_boolean_type;
+};
+
+/* Stores entire ASIC features by sets */
+extern uint32_t adapter_feature_set[];
+
+#endif /* __DAL_ADAPTER_SERVICE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
new file mode 100644
index 000000000000..f10bee6f2b83
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "../hw_ctx_adapter_service.h"
+
+#include "hw_ctx_adapter_service_dce110.h"
+
+#include "include/logger_interface.h"
+#include "include/grph_object_id.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#ifndef mmCC_DC_HDMI_STRAPS
+#define mmCC_DC_HDMI_STRAPS 0x4819
+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40
+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6
+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700
+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8
+#endif
+
+static const struct graphics_object_id invalid_go = {
+	0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN, 0
+};
+
+/* Macro */
+#define AUDIO_STRAPS_HDMI_ENABLE 0x2
+
+#define FROM_HW_CTX(ptr) \
+	container_of((ptr), struct hw_ctx_adapter_service_dce110, base)
+
+static const uint32_t audio_index_reg_offset[] = {
+	/*CZ has 3 DIGs but 4 audio endpoints*/
+	mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX,
+	mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX,
+	mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX,
+	mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX
+};
+
+static const uint32_t audio_data_reg_offset[] = {
+	mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA,
+	mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA,
+	mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA,
+	mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA,
+};
+
+enum {
+	MAX_NUMBER_OF_AUDIO_PINS = 4
+};
+
+static void destruct(
+	struct hw_ctx_adapter_service_dce110 *hw_ctx)
+{
+	/* There is nothing to destruct at the moment */
+	dal_adapter_service_destruct_hw_ctx(&hw_ctx->base);
+}
+
+static void destroy(
+	struct hw_ctx_adapter_service *ptr)
+{
+	struct hw_ctx_adapter_service_dce110 *hw_ctx =
+		FROM_HW_CTX(ptr);
+
+	destruct(hw_ctx);
+
+	dm_free(ptr->ctx, hw_ctx);
+}
+
+/*
+ * enum_audio_object
+ *
+ * @brief enumerate audio object
+ *
+ * @param
+ * const struct hw_ctx_adapter_service *hw_ctx - [in] provides num of endpoints
+ * uint32_t index - [in] audio index
+ *
+ * @return
+ * grphic object id
+ */
+static struct graphics_object_id enum_audio_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	uint32_t number_of_connected_audio_endpoints =
+		FROM_HW_CTX(hw_ctx)->number_of_connected_audio_endpoints;
+
+	if (index >= number_of_connected_audio_endpoints ||
+			number_of_connected_audio_endpoints == 0)
+		return invalid_go;
+	else
+		return dal_graphics_object_id_init(
+			AUDIO_ID_INTERNAL_AZALIA,
+			(enum object_enum_id)(index + 1),
+			OBJECT_TYPE_AUDIO);
+}
+
+static uint32_t get_number_of_connected_audio_endpoints_multistream(
+		struct dc_context *ctx)
+{
+	uint32_t num_connected_audio_endpoints = 0;
+	uint32_t i;
+	uint32_t default_config =
+	ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT;
+
+	/* find the total number of streams available via the
+	 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
+	 * registers (one for each pin) starting from pin 1
+	 * up to the max number of audio pins.
+	 * We stop on the first pin where
+	 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
+	 */
+	for (i = 0; i < MAX_NUMBER_OF_AUDIO_PINS; i++) {
+		uint32_t value = 0;
+
+		set_reg_field_value(value,
+			default_config,
+			AZALIA_F0_CODEC_ENDPOINT_INDEX,
+			AZALIA_ENDPOINT_REG_INDEX);
+
+		dm_write_reg(ctx, audio_index_reg_offset[i], value);
+
+		value = 0;
+		value = dm_read_reg(ctx, audio_data_reg_offset[i]);
+
+		/* 1 means not supported*/
+		if (get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT,
+		PORT_CONNECTIVITY) == 1)
+			break;
+
+		num_connected_audio_endpoints++;
+	}
+
+	return num_connected_audio_endpoints;
+
+}
+
+/*
+ * get_number_of_connected_audio_endpoints
+ */
+static uint32_t get_number_of_connected_audio_endpoints(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	uint32_t addr = mmCC_DC_HDMI_STRAPS;
+	uint32_t value = 0;
+	uint32_t field = 0;
+
+	if (hw_ctx->cached_audio_straps == AUDIO_STRAPS_NOT_ALLOWED)
+		/* audio straps indicate no audio supported */
+		return 0;
+
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	field = get_reg_field_value(
+			value, CC_DC_HDMI_STRAPS, AUDIO_STREAM_NUMBER);
+	if (field == 1)
+		/* multi streams not supported */
+		return 1;
+	else if (field == 0)
+		/* multi streams supported */
+		return get_number_of_connected_audio_endpoints_multistream(
+				hw_ctx->ctx);
+
+	/* unexpected value */
+	ASSERT_CRITICAL(false);
+	return field;
+}
+
+
+/*
+ * power_up
+ *
+ * @brief
+ * Determine and cache audio support from register.
+ *
+ * @param
+ * struct hw_ctx_adapter_service *hw_ctx - [in] adapter service hw context
+ *
+ * @return
+ * true if succeed, false otherwise
+ */
+static bool power_up(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	struct hw_ctx_adapter_service_dce110 *hw_ctx_dce11 =
+			FROM_HW_CTX(hw_ctx);
+	/* Allow DP audio all the time
+	 * without additional pinstrap check on Fusion */
+
+
+	{
+		uint32_t value = 0;
+		uint32_t field = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, mmCC_DC_HDMI_STRAPS);
+		field = get_reg_field_value(
+				value, CC_DC_HDMI_STRAPS, HDMI_DISABLE);
+
+		if (field == 0) {
+			hw_ctx->cached_audio_straps = AUDIO_STRAPS_DP_HDMI_AUDIO;
+		} else {
+			value = dm_read_reg(
+					hw_ctx->ctx, mmDC_PINSTRAPS);
+			field = get_reg_field_value(
+						value,
+						DC_PINSTRAPS,
+						DC_PINSTRAPS_AUDIO);
+
+			if (field & AUDIO_STRAPS_HDMI_ENABLE)
+				hw_ctx->cached_audio_straps =
+					AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE;
+			else
+				hw_ctx->cached_audio_straps =
+						AUDIO_STRAPS_DP_AUDIO_ALLOWED;
+		}
+
+	}
+
+	/* get the number of connected audio endpoints */
+	hw_ctx_dce11->number_of_connected_audio_endpoints =
+		get_number_of_connected_audio_endpoints(hw_ctx);
+
+	return true;
+}
+
+static void update_audio_connectivity(
+	struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t number_of_audio_capable_display_path,
+	uint32_t number_of_controllers)
+{
+	/* this one should be empty on DCE110 */
+}
+
+static const struct hw_ctx_adapter_service_funcs funcs = {
+	.destroy = destroy,
+	.power_up = power_up,
+	.enum_fake_path_resource = NULL,
+	.enum_stereo_sync_object = NULL,
+	.enum_sync_output_object = NULL,
+	.enum_audio_object = enum_audio_object,
+	.update_audio_connectivity = update_audio_connectivity
+};
+
+static bool construct(
+	struct hw_ctx_adapter_service_dce110 *hw_ctx,
+	struct dc_context *ctx)
+{
+	if (!dal_adapter_service_construct_hw_ctx(&hw_ctx->base, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	hw_ctx->base.funcs = &funcs;
+	hw_ctx->number_of_connected_audio_endpoints = 0;
+
+	return true;
+}
+
+struct hw_ctx_adapter_service *
+	dal_adapter_service_create_hw_ctx_dce110(
+			struct dc_context *ctx)
+{
+	struct hw_ctx_adapter_service_dce110 *hw_ctx =
+			dm_alloc(ctx, sizeof(struct hw_ctx_adapter_service_dce110));
+
+	if (!hw_ctx) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(hw_ctx, ctx))
+		return &hw_ctx->base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, hw_ctx);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
new file mode 100644
index 000000000000..092b67173dc4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__
+#define __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__
+
+struct hw_ctx_adapter_service_dce110 {
+	struct hw_ctx_adapter_service base;
+	uint32_t number_of_connected_audio_endpoints;
+};
+
+struct hw_ctx_adapter_service *
+	dal_adapter_service_create_hw_ctx_dce110(
+			struct dc_context *ctx);
+
+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__ */
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
new file mode 100644
index 000000000000..4f5f0403af84
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/* FPGA Diagnostics version of AS HW CTX. */
+
+#include "dm_services.h"
+
+#include "../hw_ctx_adapter_service.h"
+
+#include "hw_ctx_adapter_service_diag.h"
+
+#include "include/logger_interface.h"
+#include "include/grph_object_id.h"
+
+static const struct graphics_object_id invalid_go = {
+	0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN
+};
+
+static void destroy(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+}
+
+static bool power_up(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	return true;
+}
+
+static struct graphics_object_id enum_fake_path_resource(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_stereo_sync_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_sync_output_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_audio_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static void update_audio_connectivity(
+	struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t number_of_audio_capable_display_path,
+	uint32_t number_of_controllers)
+{
+}
+
+static const struct hw_ctx_adapter_service_funcs funcs = {
+	destroy,
+	power_up,
+	enum_fake_path_resource,
+	enum_stereo_sync_object,
+	enum_sync_output_object,
+	enum_audio_object,
+	update_audio_connectivity
+};
+
+static bool construct(
+	struct hw_ctx_adapter_service *hw_ctx,
+	struct dc_context *ctx)
+
+{
+	if (!dal_adapter_service_construct_hw_ctx(hw_ctx, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	hw_ctx->funcs = &funcs;
+
+	return true;
+}
+
+struct hw_ctx_adapter_service *dal_adapter_service_create_hw_ctx_diag(
+	struct dc_context *ctx)
+{
+	struct hw_ctx_adapter_service *hw_ctx = dm_alloc(ctx,
+			sizeof(*hw_ctx));
+
+	if (!hw_ctx) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(hw_ctx, ctx))
+		return hw_ctx;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, hw_ctx);
+
+	return NULL;
+}
+
+/*****************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
new file mode 100644
index 000000000000..39ae7524506c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_ADAPTER_SERVICE_DIAG_H__
+#define __DAL_HW_CTX_ADAPTER_SERVICE_DIAG_H__
+
+
+struct hw_ctx_adapter_service *dal_adapter_service_create_hw_ctx_diag(
+		struct dc_context *ctx);
+
+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_DIAG_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
new file mode 100644
index 000000000000..12eabe0c3f89
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/adapter_service_types.h"
+#include "include/grph_object_id.h"
+#include "hw_ctx_adapter_service.h"
+
+static const struct graphics_object_id invalid_go = {
+	0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN
+};
+
+static void destroy(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	/* Attention!
+	 * You must override impl method in derived class */
+	BREAK_TO_DEBUGGER();
+}
+
+static bool power_up(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	/* Attention!
+	 * You must override impl method in derived class */
+	BREAK_TO_DEBUGGER();
+
+	return false;
+}
+
+static struct graphics_object_id enum_fake_path_resource(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_stereo_sync_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_sync_output_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_audio_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	/* by default, we only allow one audio */
+
+	if (index > 0)
+		return invalid_go;
+	else if (hw_ctx->cached_audio_straps == AUDIO_STRAPS_NOT_ALLOWED)
+		return invalid_go;
+	else
+		return dal_graphics_object_id_init(
+			AUDIO_ID_INTERNAL_AZALIA,
+			ENUM_ID_1,
+			OBJECT_TYPE_AUDIO);
+}
+
+static void update_audio_connectivity(
+	struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t number_of_audio_capable_display_path,
+	uint32_t number_of_controllers)
+{
+	/* Attention!
+	 * You must override impl method in derived class */
+	BREAK_TO_DEBUGGER();
+}
+
+static const struct hw_ctx_adapter_service_funcs funcs = {
+	destroy,
+	power_up,
+	enum_fake_path_resource,
+	enum_stereo_sync_object,
+	enum_sync_output_object,
+	enum_audio_object,
+	update_audio_connectivity
+};
+
+bool dal_adapter_service_construct_hw_ctx(
+	struct hw_ctx_adapter_service *hw_ctx,
+	struct dc_context *ctx)
+{
+
+	hw_ctx->ctx = ctx;
+	hw_ctx->funcs = &funcs;
+	hw_ctx->cached_audio_straps = AUDIO_STRAPS_NOT_ALLOWED;
+
+	return true;
+}
+
+union audio_support dal_adapter_service_hw_ctx_get_audio_support(
+	const struct hw_ctx_adapter_service *hw_ctx)
+{
+	union audio_support result;
+
+	result.raw = 0;
+
+	switch (hw_ctx->cached_audio_straps) {
+	case AUDIO_STRAPS_DP_HDMI_AUDIO:
+		result.bits.HDMI_AUDIO_NATIVE = true;
+		/* do not break ! */
+	case AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE:
+		result.bits.HDMI_AUDIO_ON_DONGLE = true;
+		/* do not break ! */
+	case AUDIO_STRAPS_DP_AUDIO_ALLOWED:
+		result.bits.DP_AUDIO = true;
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+void dal_adapter_service_destruct_hw_ctx(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	/* There is nothing to destruct at the moment */
+}
+
+void dal_adapter_service_destroy_hw_ctx(
+	struct hw_ctx_adapter_service **ptr)
+{
+	if (!ptr || !*ptr) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*ptr)->funcs->destroy(*ptr);
+
+	*ptr = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
new file mode 100644
index 000000000000..f98c2d428b2a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_ADAPTER_SERVICE_H__
+#define __DAL_HW_CTX_ADAPTER_SERVICE_H__
+
+enum audio_straps {
+	AUDIO_STRAPS_NOT_ALLOWED = 0,
+	AUDIO_STRAPS_DP_AUDIO_ALLOWED,
+	AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE,
+	AUDIO_STRAPS_DP_HDMI_AUDIO
+};
+
+struct hw_ctx_adapter_service;
+
+struct hw_ctx_adapter_service_funcs {
+	void (*destroy)(
+		struct hw_ctx_adapter_service *hw_ctx);
+	/* Initializes relevant HW registers
+	 * and caches relevant data from HW registers */
+	bool (*power_up)(
+		struct hw_ctx_adapter_service *hw_ctx);
+	/* Enumerate fake path resources */
+	struct graphics_object_id (*enum_fake_path_resource)(
+		const struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t index);
+	/* Enumerate stereo sync objects */
+	struct graphics_object_id (*enum_stereo_sync_object)(
+		const struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t index);
+	/* Enumerate (H/V) sync output objects */
+	struct graphics_object_id (*enum_sync_output_object)(
+		const struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t index);
+	/* Enumerate audio objects */
+	struct graphics_object_id (*enum_audio_object)(
+		const struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t index);
+	void (*update_audio_connectivity)(
+		struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t number_of_audio_capable_display_path,
+		uint32_t number_of_controllers);
+};
+
+struct hw_ctx_adapter_service {
+	struct dc_context *ctx;
+	const struct hw_ctx_adapter_service_funcs *funcs;
+	enum audio_straps cached_audio_straps;
+};
+
+bool dal_adapter_service_construct_hw_ctx(
+	struct hw_ctx_adapter_service *hw_ctx,
+	struct dc_context *ctx);
+
+union audio_support dal_adapter_service_hw_ctx_get_audio_support(
+	const struct hw_ctx_adapter_service *hw_ctx);
+
+void dal_adapter_service_destruct_hw_ctx(
+	struct hw_ctx_adapter_service *hw_ctx);
+
+void dal_adapter_service_destroy_hw_ctx(
+	struct hw_ctx_adapter_service **ptr);
+
+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
new file mode 100644
index 000000000000..0b1151ec5a2c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#include "dm_services.h"
+#include "adapter_service.h"
+#include "wireless_data_source.h"
+
+#include "atom.h"
+
+/*construct wireless data*/
+bool wireless_data_init(struct wireless_data *data,
+		struct dc_bios *dcb,
+		struct wireless_init_data *init_data)
+{
+	struct firmware_info info;
+
+	if (data == NULL || dcb == NULL || init_data == NULL) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	data->miracast_connector_enable = false;
+	data->wireless_disp_path_enable = false;
+	data->wireless_enable = false;
+
+	/* Wireless it not supported if VCE is not supported */
+	if (!init_data->vce_supported)
+		return true;
+
+	if (init_data->miracast_target_required)
+		data->miracast_connector_enable = true;
+
+	/*
+	 * If override is in place for platform support, we will both
+	 * enable wireless display as a feature (i.e. CCC aspect) and
+	 * enable the wireless display path without any further checks.
+	 */
+	if (init_data->platform_override) {
+		data->wireless_enable = true;
+		data->wireless_disp_path_enable = true;
+	} else {
+		/*
+		 * Check if SBIOS sets remote display enable, exposed
+		 * through VBIOS. This is only valid for APU, not dGPU
+		 */
+		dcb->funcs->get_firmware_info(dcb, &info);
+
+		if ((REMOTE_DISPLAY_ENABLE == info.remote_display_config) &&
+				init_data->fusion) {
+			data->wireless_enable = true;
+			data->wireless_disp_path_enable = true;
+		}
+	}
+
+	/*
+	 * If remote display path override is enabled, we enable just the
+	 * remote display path. This is mainly used for testing purposes
+	 */
+	if (init_data->remote_disp_path_override)
+		data->wireless_disp_path_enable = true;
+
+	return true;
+}
+
+uint8_t wireless_get_clocks_num(
+	struct adapter_service *as)
+{
+	if (as->wireless_data.wireless_enable ||
+		as->wireless_data.wireless_disp_path_enable)
+		return 1;
+	else
+		return 0;
+}
+
+static uint8_t wireless_get_encoders_num(
+	struct adapter_service *as)
+{
+	if (as->wireless_data.wireless_enable ||
+		as->wireless_data.wireless_disp_path_enable)
+		return 1;
+	else
+		return 0;
+}
+
+uint8_t wireless_get_connectors_num(
+	struct adapter_service *as)
+{
+	uint8_t wireless_connectors_num = 0;
+
+	if (as->wireless_data.wireless_enable &&
+		as->wireless_data.miracast_connector_enable)
+		wireless_connectors_num++;
+
+	if (as->wireless_data.wireless_disp_path_enable)
+		wireless_connectors_num++;
+
+	return wireless_connectors_num;
+}
+
+struct graphics_object_id wireless_get_connector_id(
+	struct adapter_service *as,
+	uint8_t index)
+{
+	struct graphics_object_id unknown_object_id =
+			dal_graphics_object_id_init(
+				0,
+				ENUM_ID_UNKNOWN,
+				OBJECT_TYPE_UNKNOWN);
+
+	if (!as->wireless_data.wireless_enable &&
+		!as->wireless_data.wireless_disp_path_enable)
+		return unknown_object_id;
+
+	else if (!as->wireless_data.miracast_connector_enable)
+		return dal_graphics_object_id_init(
+			CONNECTOR_ID_WIRELESS,
+			ENUM_ID_1,
+			OBJECT_TYPE_CONNECTOR);
+
+	switch (index) {
+	case 0:
+		return dal_graphics_object_id_init(
+			CONNECTOR_ID_WIRELESS,
+			ENUM_ID_1,
+			OBJECT_TYPE_CONNECTOR);
+		break;
+	case 1:
+		return dal_graphics_object_id_init(
+			CONNECTOR_ID_MIRACAST,
+			ENUM_ID_1,
+			OBJECT_TYPE_CONNECTOR);
+		break;
+	default:
+		return unknown_object_id;
+	}
+}
+
+uint8_t wireless_get_srcs_num(
+	struct adapter_service *as,
+	struct graphics_object_id id)
+{
+	switch (id.type) {
+	case OBJECT_TYPE_CONNECTOR:
+		return wireless_get_encoders_num(as);
+	case OBJECT_TYPE_ENCODER:
+		return 1;
+
+	default:
+		ASSERT_CRITICAL(false);
+		break;
+	}
+
+	return 0;
+}
+
+struct graphics_object_id wireless_get_src_obj_id(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	uint8_t index)
+{
+	if (index < wireless_get_srcs_num(as, id)) {
+		switch (id.type) {
+		case OBJECT_TYPE_CONNECTOR:
+			return dal_graphics_object_id_init(
+					ENCODER_ID_INTERNAL_WIRELESS,
+					ENUM_ID_1,
+					OBJECT_TYPE_ENCODER);
+			break;
+		case OBJECT_TYPE_ENCODER:
+			return dal_graphics_object_id_init(
+					0,
+					ENUM_ID_1,
+					OBJECT_TYPE_GPU);
+			break;
+		default:
+			ASSERT_CRITICAL(false);
+			break;
+		}
+	}
+
+	return dal_graphics_object_id_init(
+			0,
+			ENUM_ID_UNKNOWN,
+			OBJECT_TYPE_UNKNOWN);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
new file mode 100644
index 000000000000..b64089e3960e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_WIRELESS_DATA_SOURCE_H__
+#define __DAL_WIRELESS_DATA_SOURCE_H__
+
+/* Include */
+#include "include/grph_object_id.h"
+
+/*
+ * Forward declaration
+ */
+struct adapter_service;
+struct dc_bios;
+
+/* Wireless data init structure */
+struct wireless_init_data {
+	bool fusion; /* Fusion flag */
+	bool platform_override; /* Override for platform BIOS option */
+	bool remote_disp_path_override; /* Override enabling wireless path */
+	bool vce_supported; /* Existence of VCE block on this DCE */
+	bool miracast_target_required; /* OS requires Miracast target */
+};
+
+/* Wireless data */
+struct wireless_data {
+	bool wireless_enable;
+	bool wireless_disp_path_enable;
+	bool miracast_connector_enable;
+};
+
+
+/*construct wireless data*/
+bool wireless_data_init(
+	struct wireless_data *data,
+	struct dc_bios *dcb,
+	struct wireless_init_data *init_data);
+
+uint8_t wireless_get_clocks_num(
+	struct adapter_service *as);
+
+uint8_t wireless_get_connectors_num(
+	struct adapter_service *as);
+
+struct graphics_object_id wireless_get_connector_id(
+	struct adapter_service *as,
+	uint8_t connector_index);
+
+uint8_t wireless_get_srcs_num(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+struct graphics_object_id wireless_get_src_obj_id(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	uint8_t index);
+
+#endif /* __DAL_WIRELESS_DATA_SOURCE_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 07/29] drm/amd/dal: BIOS Parser
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (5 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 06/29] drm/amd/dal: Adapter Service Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 08/29] drm/amd/dal: I2C Aux Manager Harry Wentland
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Wrapper to access Video BIOS command and data tables

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/bios/Makefile           |   26 +
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c      | 5029 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h      |   84 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c   |  198 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h   |  108 +
 drivers/gpu/drm/amd/dal/dc/bios/command_table.c    | 2730 +++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/command_table.h    |  117 +
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.c |  285 ++
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.h |   90 +
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.c |  484 ++
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.h |   34 +
 .../dc/bios/dce110/command_table_helper_dce110.c   |  366 ++
 .../dc/bios/dce110/command_table_helper_dce110.h   |   34 +
 13 files changed, 9585 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h

diff --git a/drivers/gpu/drm/amd/dal/dc/bios/Makefile b/drivers/gpu/drm/amd/dal/dc/bios/Makefile
new file mode 100644
index 000000000000..ddfe457e3a8b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for the 'bios' sub-component of DAL.
+# It provides the parsing and executing controls for atom bios image.
+
+BIOS = bios_parser.o bios_parser_helper.o command_table.o command_table_helper.o
+
+AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS))
+
+AMD_DAL_FILES += $(AMD_DAL_BIOS)
+
+ifndef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+AMD_DAL_FILES := $(filter-out $(AMDDALPATH)/dc/bios/bios_parser_helper.o,$(AMD_DAL_FILES))
+endif
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+
+ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce110/bios_parser_helper_dce110.o
+endif
+
+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
new file mode 100644
index 000000000000..4ce5f9fcf907
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
@@ -0,0 +1,5029 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "dc_bios_types.h"
+#include "include/adapter_service_interface.h"
+#include "include/grph_object_ctrl_defs.h"
+#include "include/bios_parser_interface.h"
+#include "include/i2caux_interface.h"
+#include "include/logger_interface.h"
+
+#include "command_table.h"
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+#include "bios_parser_helper.h"
+#endif
+#include "command_table_helper.h"
+#include "bios_parser.h"
+#include "bios_parser_interface.h"
+
+#define THREE_PERCENT_OF_10000 300
+
+#define LAST_RECORD_TYPE 0xff
+
+/* GUID to validate external display connection info table (aka OPM module) */
+static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = {
+	0x91, 0x6E, 0x57, 0x09,
+	0x3F, 0x6D, 0xD2, 0x11,
+	0x39, 0x8E, 0x00, 0xA0,
+	0xC9, 0x69, 0x72, 0x3B};
+
+#define GET_IMAGE(type, offset) ((type *) get_image(bp, offset, sizeof(type)))
+#define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
+
+static uint8_t *get_image(struct bios_parser *bp, uint32_t offset,
+	uint32_t size);
+static uint32_t get_record_size(uint8_t *record);
+static uint32_t get_edid_size(const ATOM_FAKE_EDID_PATCH_RECORD *edid);
+static enum object_type object_type_from_bios_object_id(
+	uint32_t bios_object_id);
+static struct graphics_object_id object_id_from_bios_object_id(
+	uint32_t bios_object_id);
+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id);
+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id);
+static enum connector_id connector_id_from_bios_object_id(
+	uint32_t bios_object_id);
+static uint32_t id_from_bios_object_id(enum object_type type,
+	uint32_t bios_object_id);
+static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id);
+static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id);
+static void get_atom_data_table_revision(
+	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
+	struct atom_data_revision *tbl_revision);
+static uint32_t get_dst_number_from_object(struct bios_parser *bp,
+	ATOM_OBJECT *object);
+static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
+	uint16_t **id_list);
+static uint32_t get_dest_obj_list(struct bios_parser *bp,
+	ATOM_OBJECT *object, uint16_t **id_list);
+static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
+	struct graphics_object_id id);
+static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
+	ATOM_I2C_RECORD *record,
+	struct graphics_object_i2c_info *info);
+static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+	ATOM_OBJECT *object);
+static struct device_id device_type_from_device_id(uint16_t device_id);
+static uint32_t signal_to_ss_id(enum as_signal_type signal);
+static uint32_t get_support_mask_for_device_id(struct device_id device_id);
+static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object);
+static void process_ext_display_connection_info(struct bios_parser *bp);
+
+
+#define BIOS_IMAGE_SIZE_OFFSET 2
+#define BIOS_IMAGE_SIZE_UNIT 512
+
+/*****************************************************************************/
+static bool bios_parser_construct(
+	struct bios_parser *bp,
+	struct bp_init_data *init,
+	struct adapter_service *as);
+
+static uint8_t bios_parser_get_connectors_number(
+	struct dc_bios *dcb);
+
+static enum bp_result bios_parser_get_embedded_panel_info(
+	struct dc_bios *dcb,
+	struct embedded_panel_info *info);
+
+/*****************************************************************************/
+
+struct dc_bios *dal_bios_parser_create(
+	struct bp_init_data *init, struct adapter_service *as)
+{
+	struct bios_parser *bp = NULL;
+
+	bp = dm_alloc(init->ctx, sizeof(struct bios_parser));
+	if (!bp)
+		return NULL;
+
+	if (bios_parser_construct(bp, init, as))
+		return &bp->base;
+
+	dm_free(init->ctx, bp);
+	BREAK_TO_DEBUGGER();
+	return NULL;
+}
+
+static void destruct(struct bios_parser *bp)
+{
+	if (bp->bios_local_image)
+		dm_free(bp->ctx, bp->bios_local_image);
+}
+
+void dal_bios_parser_destroy(struct dc_bios **dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(*dcb);
+
+	if (!bp) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct(bp);
+
+	dm_free((bp)->ctx, bp);
+	*dcb = NULL;
+}
+
+static void bios_parser_power_down(struct dc_bios *dcb)
+{
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	dal_bios_parser_set_scratch_lcd_scale(bp, bp->lcd_scale);
+#endif
+}
+
+static void bios_parser_power_up(struct dc_bios *dcb)
+{
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (bp->lcd_scale == LCD_SCALE_UNKNOWN)
+		bp->lcd_scale = dal_bios_parser_get_scratch_lcd_scale(bp);
+#endif
+}
+
+static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
+{
+	ATOM_OBJECT_TABLE *table;
+
+	uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
+
+	table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset);
+
+	if (!table)
+		return 0;
+	else
+		return table->ucNumberOfObjects;
+}
+
+static uint8_t bios_parser_get_encoders_number(struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	return get_number_of_objects(bp,
+		le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset));
+}
+
+static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	return get_number_of_objects(bp,
+		le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));
+}
+
+static uint32_t bios_parser_get_oem_ddc_lines_number(struct dc_bios *dcb)
+{
+	uint32_t number = 0;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (DATA_TABLES(OemInfo) != 0) {
+		ATOM_OEM_INFO *info;
+
+		info = GET_IMAGE(ATOM_OEM_INFO,
+			DATA_TABLES(OemInfo));
+
+		if (le16_to_cpu(info->sHeader.usStructureSize)
+			> sizeof(ATOM_COMMON_TABLE_HEADER)) {
+
+			number = (le16_to_cpu(info->sHeader.usStructureSize)
+				- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_I2C_ID_CONFIG_ACCESS);
+
+		}
+	}
+
+	return number;
+}
+
+static struct graphics_object_id bios_parser_get_encoder_id(
+	struct dc_bios *dcb,
+	uint32_t i)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct graphics_object_id object_id = dal_graphics_object_id_init(
+		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
+
+	uint32_t encoder_table_offset = bp->object_info_tbl_offset
+		+ le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
+
+	ATOM_OBJECT_TABLE *tbl =
+		GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
+
+	if (tbl && tbl->ucNumberOfObjects > i) {
+		const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID);
+
+		object_id = object_id_from_bios_object_id(id);
+	}
+
+	return object_id;
+}
+
+static struct graphics_object_id bios_parser_get_connector_id(
+	struct dc_bios *dcb,
+	uint8_t i)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct graphics_object_id object_id = dal_graphics_object_id_init(
+		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
+
+	uint32_t connector_table_offset = bp->object_info_tbl_offset
+		+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+
+	ATOM_OBJECT_TABLE *tbl =
+		GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset);
+
+	if (tbl && tbl->ucNumberOfObjects > i) {
+		const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID);
+
+		object_id = object_id_from_bios_object_id(id);
+	}
+
+	return object_id;
+}
+
+static uint32_t bios_parser_get_src_number(struct dc_bios *dcb,
+	struct graphics_object_id id)
+{
+	uint32_t offset;
+	uint8_t *number;
+	ATOM_OBJECT *object;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	object = get_bios_object(bp, id);
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+			+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	return *number;
+}
+
+static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb,
+	struct graphics_object_id id)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object = get_bios_object(bp, id);
+
+	return get_dst_number_from_object(bp, object);
+}
+
+static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
+	struct graphics_object_id object_id, uint32_t index,
+	struct graphics_object_id *src_object_id)
+{
+	uint32_t number;
+	uint16_t *id;
+	ATOM_OBJECT *object;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!src_object_id)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, object_id);
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return BP_RESULT_BADINPUT;
+	}
+
+	number = get_src_obj_list(bp, object, &id);
+
+	if (number <= index)
+		return BP_RESULT_BADINPUT;
+
+	*src_object_id = object_id_from_bios_object_id(id[index]);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb,
+	struct graphics_object_id object_id, uint32_t index,
+	struct graphics_object_id *dest_object_id)
+{
+	uint32_t number;
+	uint16_t *id;
+	ATOM_OBJECT *object;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!dest_object_id)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, object_id);
+
+	number = get_dest_obj_list(bp, object, &id);
+
+	if (number <= index)
+		return BP_RESULT_BADINPUT;
+
+	*dest_object_id = object_id_from_bios_object_id(id[index]);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_oem_ddc_info(struct dc_bios *dcb,
+	uint32_t index,
+	struct graphics_object_i2c_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (DATA_TABLES(OemInfo) != 0) {
+		ATOM_OEM_INFO *tbl;
+
+		tbl = GET_IMAGE(ATOM_OEM_INFO, DATA_TABLES(OemInfo));
+
+		if (le16_to_cpu(tbl->sHeader.usStructureSize)
+			> sizeof(ATOM_COMMON_TABLE_HEADER)) {
+			ATOM_I2C_RECORD record;
+			ATOM_I2C_ID_CONFIG_ACCESS *config;
+
+			dm_memset(&record, 0, sizeof(record));
+
+			config = &tbl->sucI2cId + index - 1;
+
+			record.sucI2cId.bfHW_Capable =
+				config->sbfAccess.bfHW_Capable;
+			record.sucI2cId.bfI2C_LineMux =
+				config->sbfAccess.bfI2C_LineMux;
+			record.sucI2cId.bfHW_EngineID =
+				config->sbfAccess.bfHW_EngineID;
+
+			return get_gpio_i2c_info(bp, &record, info);
+		}
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct graphics_object_i2c_info *info)
+{
+	uint32_t offset;
+	ATOM_OBJECT *object;
+	ATOM_COMMON_RECORD_HEADER *header;
+	ATOM_I2C_RECORD *record;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, id);
+
+	if (!object)
+		return BP_RESULT_BADINPUT;
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return BP_RESULT_BADBIOSTABLE;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+			!header->ucRecordSize)
+			break;
+
+		if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
+			&& sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {
+			/* get the I2C info */
+			record = (ATOM_I2C_RECORD *) header;
+
+			if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)
+				return BP_RESULT_OK;
+		}
+
+		offset += header->ucRecordSize;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result get_voltage_ddc_info_v1(uint8_t *i2c_line,
+	ATOM_COMMON_TABLE_HEADER *header,
+	uint8_t *address)
+{
+	enum bp_result result = BP_RESULT_NORECORD;
+	ATOM_VOLTAGE_OBJECT_INFO *info =
+		(ATOM_VOLTAGE_OBJECT_INFO *) address;
+
+	uint8_t *voltage_current_object = (uint8_t *) &info->asVoltageObj[0];
+
+	while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
+		ATOM_VOLTAGE_OBJECT *object =
+			(ATOM_VOLTAGE_OBJECT *) voltage_current_object;
+
+		if ((object->ucVoltageType == SET_VOLTAGE_INIT_MODE) &&
+			(object->ucVoltageType &
+				VOLTAGE_CONTROLLED_BY_I2C_MASK)) {
+
+			*i2c_line = object->asControl.ucVoltageControlI2cLine
+					^ 0x90;
+			result = BP_RESULT_OK;
+			break;
+		}
+
+		voltage_current_object += object->ucSize;
+	}
+	return result;
+}
+
+static enum bp_result get_voltage_ddc_info_v3(uint8_t *i2c_line,
+	uint32_t index,
+	ATOM_COMMON_TABLE_HEADER *header,
+	uint8_t *address)
+{
+	enum bp_result result = BP_RESULT_NORECORD;
+	ATOM_VOLTAGE_OBJECT_INFO_V3_1 *info =
+		(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *) address;
+
+	uint8_t *voltage_current_object =
+		(uint8_t *) (&(info->asVoltageObj[0]));
+
+	while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
+		ATOM_I2C_VOLTAGE_OBJECT_V3 *object =
+			(ATOM_I2C_VOLTAGE_OBJECT_V3 *) voltage_current_object;
+
+		if (object->sHeader.ucVoltageMode ==
+			ATOM_INIT_VOLTAGE_REGULATOR) {
+			if (object->sHeader.ucVoltageType == index) {
+				*i2c_line = object->ucVoltageControlI2cLine
+						^ 0x90;
+				result = BP_RESULT_OK;
+				break;
+			}
+		}
+
+		voltage_current_object += le16_to_cpu(object->sHeader.usSize);
+	}
+	return result;
+}
+
+static enum bp_result bios_parser_get_thermal_ddc_info(
+	struct dc_bios *dcb,
+	uint32_t i2c_channel_id,
+	struct graphics_object_i2c_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_I2C_ID_CONFIG_ACCESS *config;
+	ATOM_I2C_RECORD record;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	config = (ATOM_I2C_ID_CONFIG_ACCESS *) &i2c_channel_id;
+
+	record.sucI2cId.bfHW_Capable = config->sbfAccess.bfHW_Capable;
+	record.sucI2cId.bfI2C_LineMux = config->sbfAccess.bfI2C_LineMux;
+	record.sucI2cId.bfHW_EngineID = config->sbfAccess.bfHW_EngineID;
+
+	return get_gpio_i2c_info(bp, &record, info);
+}
+
+static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb,
+	uint32_t index,
+	struct graphics_object_i2c_info *info)
+{
+	uint8_t i2c_line = 0;
+	enum bp_result result = BP_RESULT_NORECORD;
+	uint8_t *voltage_info_address;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision = {0};
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!DATA_TABLES(VoltageObjectInfo))
+		return result;
+
+	voltage_info_address = get_image(bp,
+		DATA_TABLES(VoltageObjectInfo),
+		sizeof(ATOM_COMMON_TABLE_HEADER));
+
+	header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address;
+
+	get_atom_data_table_revision(header, &revision);
+
+	switch (revision.major) {
+	case 1:
+	case 2:
+		result = get_voltage_ddc_info_v1(&i2c_line, header,
+			voltage_info_address);
+		break;
+	case 3:
+		if (revision.minor != 1)
+			break;
+		result = get_voltage_ddc_info_v3(&i2c_line, index, header,
+			voltage_info_address);
+		break;
+	}
+
+	if (result == BP_RESULT_OK)
+		result = bios_parser_get_thermal_ddc_info(dcb,
+			i2c_line, info);
+
+
+	return result;
+}
+
+enum bp_result bios_parser_get_ddc_info_for_i2c_line(struct bios_parser *bp,
+	uint8_t i2c_line, struct graphics_object_i2c_info *info)
+{
+	uint32_t offset;
+	ATOM_OBJECT *object;
+	ATOM_OBJECT_TABLE *table;
+	uint32_t i;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+
+	offset += bp->object_info_tbl_offset;
+
+	table = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
+
+	if (!table)
+		return BP_RESULT_BADBIOSTABLE;
+
+	for (i = 0; i < table->ucNumberOfObjects; i++) {
+		object = &table->asObjects[i];
+
+		if (!object) {
+			BREAK_TO_DEBUGGER(); /* Invalid object id */
+			return BP_RESULT_BADINPUT;
+		}
+
+		offset = le16_to_cpu(object->usRecordOffset)
+				+ bp->object_info_tbl_offset;
+
+		for (;;) {
+			ATOM_COMMON_RECORD_HEADER *header =
+				GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+			if (!header)
+				return BP_RESULT_BADBIOSTABLE;
+
+			offset += header->ucRecordSize;
+
+			if (LAST_RECORD_TYPE == header->ucRecordType ||
+				!header->ucRecordSize)
+				break;
+
+			if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
+				&& sizeof(ATOM_I2C_RECORD) <=
+				header->ucRecordSize) {
+				ATOM_I2C_RECORD *record =
+					(ATOM_I2C_RECORD *) header;
+
+				if (i2c_line != record->sucI2cId.bfI2C_LineMux)
+					continue;
+
+				/* get the I2C info */
+				if (get_gpio_i2c_info(bp, record, info) ==
+					BP_RESULT_OK)
+					return BP_RESULT_OK;
+			}
+		}
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct graphics_object_hpd_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object;
+	ATOM_HPD_INT_RECORD *record = NULL;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, id);
+
+	if (!object)
+		return BP_RESULT_BADINPUT;
+
+	record = get_hpd_record(bp, object);
+
+	if (record != NULL) {
+		info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;
+		info->hpd_active = record->ucPlugged_PinState;
+		return BP_RESULT_OK;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static uint32_t bios_parser_get_gpio_record(
+	struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct bp_gpio_cntl_info *gpio_record,
+	uint32_t record_size)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_COMMON_RECORD_HEADER *header = NULL;
+	ATOM_OBJECT_GPIO_CNTL_RECORD *record = NULL;
+	ATOM_OBJECT *object = get_bios_object(bp, id);
+	uint32_t offset;
+	uint32_t pins_number;
+	uint32_t i;
+
+	if (!object)
+		return 0;
+
+	/* Initialise offset */
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		/* Get record header */
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+		if (!header || header->ucRecordType == LAST_RECORD_TYPE ||
+			!header->ucRecordSize)
+			break;
+
+		/* If this is gpio control record - stop. We found the record */
+		if (header->ucRecordType == ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE
+			&& header->ucRecordSize
+				>= sizeof(ATOM_OBJECT_GPIO_CNTL_RECORD)) {
+			record = (ATOM_OBJECT_GPIO_CNTL_RECORD *) header;
+			break;
+		}
+
+		/* Advance to next record */
+		offset += header->ucRecordSize;
+	}
+
+	/* If we did not find a record - return */
+	if (!record)
+		return 0;
+
+	/* Extract gpio IDs from bios record (make sure we do not exceed passed
+	 *  array size) */
+	pins_number = (record->ucNumberOfPins < record_size ?
+			record->ucNumberOfPins : record_size);
+	for (i = 0; i < pins_number; i++) {
+		uint8_t output_state = ((record->asGpio[i].ucGPIO_PinState
+			& GPIO_PIN_OUTPUT_STATE_MASK)
+			>> GPIO_PIN_OUTPUT_STATE_SHIFT);
+		gpio_record[i].id = record->asGpio[i].ucGPIOID;
+
+		switch (output_state) {
+		case GPIO_PIN_STATE_ACTIVE_LOW:
+			gpio_record[i].state =
+				GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW;
+			break;
+
+		case GPIO_PIN_STATE_ACTIVE_HIGH:
+			gpio_record[i].state =
+				GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH;
+			break;
+
+		default:
+			BREAK_TO_DEBUGGER(); /* Invalid Pin Output State */
+			break;
+		}
+	}
+
+	return pins_number;
+}
+
+enum bp_result bios_parser_get_device_tag_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object,
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)
+{
+	ATOM_COMMON_RECORD_HEADER *header;
+	uint32_t offset;
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return BP_RESULT_BADBIOSTABLE;
+
+		offset += header->ucRecordSize;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+			!header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=
+			header->ucRecordType)
+			continue;
+
+		if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)
+			continue;
+
+		*record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;
+		return BP_RESULT_OK;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_get_device_tag(
+	struct dc_bios *dcb,
+	struct graphics_object_id connector_object_id,
+	uint32_t device_tag_index,
+	struct connector_device_tag_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object;
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;
+	ATOM_CONNECTOR_DEVICE_TAG *device_tag;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	/* getBiosObject will return MXM object */
+	object = get_bios_object(bp, connector_object_id);
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return BP_RESULT_BADINPUT;
+	}
+
+	if (bios_parser_get_device_tag_record(bp, object, &record)
+		!= BP_RESULT_OK)
+		return BP_RESULT_NORECORD;
+
+	if (device_tag_index >= record->ucNumberOfDevice)
+		return BP_RESULT_NORECORD;
+
+	device_tag = &record->asDeviceTag[device_tag_index];
+
+	info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);
+	info->dev_id =
+		device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_firmware_info_v1_4(
+	struct bios_parser *bp,
+	struct firmware_info *info);
+static enum bp_result get_firmware_info_v2_1(
+	struct bios_parser *bp,
+	struct firmware_info *info);
+static enum bp_result get_firmware_info_v2_2(
+	struct bios_parser *bp,
+	struct firmware_info *info);
+
+static enum bp_result bios_parser_get_firmware_info(
+	struct dc_bios *dcb,
+	struct firmware_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision;
+
+	if (info && DATA_TABLES(FirmwareInfo)) {
+		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+			DATA_TABLES(FirmwareInfo));
+		get_atom_data_table_revision(header, &revision);
+		switch (revision.major) {
+		case 1:
+			switch (revision.minor) {
+			case 4:
+				result = get_firmware_info_v1_4(bp, info);
+				break;
+			default:
+				break;
+			}
+			break;
+
+		case 2:
+			switch (revision.minor) {
+			case 1:
+				result = get_firmware_info_v2_1(bp, info);
+				break;
+			case 2:
+				result = get_firmware_info_v2_2(bp, info);
+				break;
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	return result;
+}
+
+static enum bp_result get_firmware_info_v1_4(
+	struct bios_parser *bp,
+	struct firmware_info *info)
+{
+	ATOM_FIRMWARE_INFO_V1_4 *firmware_info =
+		GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,
+			DATA_TABLES(FirmwareInfo));
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!firmware_info)
+		return BP_RESULT_BADBIOSTABLE;
+
+	dm_memset(info, 0, sizeof(*info));
+
+	/* Pixel clock pll information. We need to convert from 10KHz units into
+	 * KHz units */
+	info->pll_info.crystal_frequency =
+		le16_to_cpu(firmware_info->usReferenceClock) * 10;
+	info->pll_info.min_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
+	info->pll_info.max_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
+	info->pll_info.min_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
+	info->pll_info.max_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
+
+	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
+		/* Since there is no information on the SS, report conservative
+		 * value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
+
+	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
+		/* Since there is no information on the SS,report conservative
+		 * value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_ss_info_v3_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info);
+
+static enum bp_result get_firmware_info_v2_1(
+	struct bios_parser *bp,
+	struct firmware_info *info)
+{
+	ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =
+		GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));
+	struct spread_spectrum_info internalSS;
+	uint32_t index;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!firmwareInfo)
+		return BP_RESULT_BADBIOSTABLE;
+
+	dm_memset(info, 0, sizeof(*info));
+
+	/* Pixel clock pll information. We need to convert from 10KHz units into
+	 * KHz units */
+	info->pll_info.crystal_frequency =
+		le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;
+	info->pll_info.min_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;
+	info->pll_info.max_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;
+	info->pll_info.min_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;
+	info->pll_info.max_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;
+	info->default_display_engine_pll_frequency =
+		le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;
+	info->external_clock_source_frequency_for_dp =
+		le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;
+	info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;
+
+	/* There should be only one entry in the SS info table for Memory Clock
+	 */
+	index = 0;
+	if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
+		/* Since there is no information for external SS, report
+		 *  conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+		ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {
+		if (internalSS.spread_spectrum_percentage) {
+			info->feature.memory_clk_ss_percentage =
+				internalSS.spread_spectrum_percentage;
+			if (internalSS.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.memory_clk_ss_percentage;
+				info->feature.memory_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	/* There should be only one entry in the SS info table for Engine Clock
+	 */
+	index = 1;
+	if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
+		/* Since there is no information for external SS, report
+		 * conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+		ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {
+		if (internalSS.spread_spectrum_percentage) {
+			info->feature.engine_clk_ss_percentage =
+				internalSS.spread_spectrum_percentage;
+			if (internalSS.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.engine_clk_ss_percentage;
+				info->feature.engine_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_firmware_info_v2_2(
+	struct bios_parser *bp,
+	struct firmware_info *info)
+{
+	ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
+	struct spread_spectrum_info internal_ss;
+	uint32_t index;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,
+		DATA_TABLES(FirmwareInfo));
+
+	if (!firmware_info)
+		return BP_RESULT_BADBIOSTABLE;
+
+	dm_memset(info, 0, sizeof(*info));
+
+	/* Pixel clock pll information. We need to convert from 10KHz units into
+	 * KHz units */
+	info->pll_info.crystal_frequency =
+		le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;
+	info->pll_info.min_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
+	info->pll_info.max_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
+	info->pll_info.min_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
+	info->pll_info.max_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
+	info->default_display_engine_pll_frequency =
+		le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;
+	info->external_clock_source_frequency_for_dp =
+		le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;
+
+	/* There should be only one entry in the SS info table for Memory Clock
+	 */
+	index = 0;
+	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
+		/* Since there is no information for external SS, report
+		 *  conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+			ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {
+		if (internal_ss.spread_spectrum_percentage) {
+			info->feature.memory_clk_ss_percentage =
+					internal_ss.spread_spectrum_percentage;
+			if (internal_ss.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.memory_clk_ss_percentage;
+				info->feature.memory_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	/* There should be only one entry in the SS info table for Engine Clock
+	 */
+	index = 1;
+	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
+		/* Since there is no information for external SS, report
+		 * conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+			ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {
+		if (internal_ss.spread_spectrum_percentage) {
+			info->feature.engine_clk_ss_percentage =
+					internal_ss.spread_spectrum_percentage;
+			if (internal_ss.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.engine_clk_ss_percentage;
+				info->feature.engine_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	/* Remote Display */
+	info->remote_display_config = firmware_info->ucRemoteDisplayConfig;
+
+	/* Is allowed minimum BL level */
+	info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;
+	/* Used starting from CI */
+	info->smu_gpu_pll_output_freq =
+			(uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_ss_info_v3_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info)
+{
+	ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;
+	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
+	uint32_t table_size;
+	uint32_t i;
+	uint32_t table_index = 0;
+
+	if (!ss_info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return BP_RESULT_UNSUPPORTED;
+
+	ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
+		DATA_TABLES(ASIC_InternalSS_Info));
+	table_size =
+		(le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
+				- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
+				&ss_table_header_include->asSpreadSpectrum[0];
+
+	dm_memset(ss_info, 0, sizeof(struct spread_spectrum_info));
+
+	for (i = 0; i < table_size; i++) {
+		if (tbl[i].ucClockIndication != (uint8_t) id)
+			continue;
+
+		if (table_index != index) {
+			table_index++;
+			continue;
+		}
+		/* VBIOS introduced new defines for Version 3, same values as
+		 *  before, so now use these new ones for Version 3.
+		 * Shouldn't affect field VBIOS's V3 as define values are still
+		 *  same.
+		 * #define SS_MODE_V3_CENTRE_SPREAD_MASK                0x01
+		 * #define SS_MODE_V3_EXTERNAL_SS_MASK                  0x02
+
+		 * Old VBIOS defines:
+		 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001
+		 * #define ATOM_EXTERNAL_SS_MASK                  0x00000002
+		 */
+
+		if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode)
+			ss_info->type.EXTERNAL = true;
+
+		if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode)
+			ss_info->type.CENTER_MODE = true;
+
+		/* Older VBIOS (in field) always provides SS percentage in 0.01%
+		 * units set Divider to 100 */
+		ss_info->spread_percentage_divider = 100;
+
+		/* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */
+		if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK
+				& tbl[i].ucSpreadSpectrumMode)
+			ss_info->spread_percentage_divider = 1000;
+
+		ss_info->type.STEP_AND_DELAY_INFO = false;
+		/* convert [10KHz] into [KHz] */
+		ss_info->target_clock_range =
+				le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
+		ss_info->spread_spectrum_percentage =
+				(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
+		ss_info->spread_spectrum_range =
+				(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
+
+		return BP_RESULT_OK;
+	}
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_transmitter_control(
+	struct dc_bios *dcb,
+	struct bp_transmitter_control *cntl)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.transmitter_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.transmitter_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_encoder_control(
+	struct dc_bios *dcb,
+	struct bp_encoder_control *cntl)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.dig_encoder_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.dig_encoder_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_adjust_pixel_clock(
+	struct dc_bios *dcb,
+	struct bp_adjust_pixel_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.adjust_display_pll)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.adjust_display_pll(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_pixel_clock(
+	struct dc_bios *dcb,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_pixel_clock)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_dce_clock(
+	struct dc_bios *dcb,
+	struct bp_set_dce_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_dce_clock)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_dce_clock(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_spread_spectrum_on_ppll(
+	struct dc_bios *dcb,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_spread_spectrum_on_ppll(
+			bp, bp_params, enable);
+
+}
+
+static enum bp_result bios_parser_program_crtc_timing(
+	struct dc_bios *dcb,
+	struct bp_hw_crtc_timing_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_crtc_timing)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
+}
+
+static enum bp_result bios_parser_program_display_engine_pll(
+	struct dc_bios *dcb,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.program_clock)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.program_clock(bp, bp_params);
+
+}
+
+static enum signal_type bios_parser_dac_load_detect(
+	struct dc_bios *dcb,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type display_signal)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.dac_load_detection)
+		return SIGNAL_TYPE_NONE;
+
+	return bp->cmd_tbl.dac_load_detection(bp, encoder, connector,
+		display_signal);
+}
+
+static enum bp_result bios_parser_get_divider_for_target_display_clock(
+	struct dc_bios *dcb,
+	struct bp_display_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.compute_memore_engine_pll)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.compute_memore_engine_pll(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_crtc(
+	struct dc_bios *dcb,
+	enum controller_id id,
+	bool enable)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_crtc)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_crtc(bp, id, enable);
+}
+
+static enum bp_result bios_parser_blank_crtc(
+	struct dc_bios *dcb,
+	struct bp_blank_crtc_parameters *bp_params,
+	bool blank)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.blank_crtc)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.blank_crtc(bp, bp_params, blank);
+}
+
+static enum bp_result bios_parser_crtc_source_select(
+	struct dc_bios *dcb,
+	struct bp_crtc_source_select *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.select_crtc_source)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.select_crtc_source(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_overscan(
+	struct dc_bios *dcb,
+	struct bp_hw_crtc_overscan_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_crtc_overscan)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_crtc_overscan(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_memory_requests(
+	struct dc_bios *dcb,
+	enum controller_id controller_id,
+	bool enable)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_crtc_mem_req)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_crtc_mem_req(bp, controller_id, enable);
+}
+
+static enum bp_result bios_parser_external_encoder_control(
+	struct dc_bios *dcb,
+	struct bp_external_encoder_control *cntl)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.external_encoder_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.external_encoder_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_enable_disp_power_gating(
+	struct dc_bios *dcb,
+	enum controller_id controller_id,
+	enum bp_pipe_control_action action)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_disp_power_gating)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
+		action);
+}
+
+static bool bios_parser_is_device_id_supported(
+	struct dc_bios *dcb,
+	struct device_id id)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	uint32_t mask = get_support_mask_for_device_id(id);
+
+	return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0;
+}
+
+static enum bp_result bios_parser_crt_control(
+	struct dc_bios *dcb,
+	enum engine_id engine_id,
+	bool enable,
+	uint32_t pixel_clock)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	uint8_t standard;
+
+	if (!bp->cmd_tbl.dac1_encoder_control &&
+		engine_id == ENGINE_ID_DACA)
+		return BP_RESULT_FAILURE;
+	if (!bp->cmd_tbl.dac2_encoder_control &&
+		engine_id == ENGINE_ID_DACB)
+		return BP_RESULT_FAILURE;
+	/* validate params */
+	switch (engine_id) {
+	case ENGINE_ID_DACA:
+	case ENGINE_ID_DACB:
+		break;
+	default:
+		/* unsupported engine */
+		return BP_RESULT_FAILURE;
+	}
+
+	standard = ATOM_DAC1_PS2; /* == ATOM_DAC2_PS2 */
+
+	if (enable) {
+		if (engine_id == ENGINE_ID_DACA) {
+			bp->cmd_tbl.dac1_encoder_control(bp, enable,
+				pixel_clock, standard);
+			if (bp->cmd_tbl.dac1_output_control != NULL)
+				bp->cmd_tbl.dac1_output_control(bp, enable);
+		} else {
+			bp->cmd_tbl.dac2_encoder_control(bp, enable,
+				pixel_clock, standard);
+			if (bp->cmd_tbl.dac2_output_control != NULL)
+				bp->cmd_tbl.dac2_output_control(bp, enable);
+		}
+	} else {
+		if (engine_id == ENGINE_ID_DACA) {
+			if (bp->cmd_tbl.dac1_output_control != NULL)
+				bp->cmd_tbl.dac1_output_control(bp, enable);
+			bp->cmd_tbl.dac1_encoder_control(bp, enable,
+				pixel_clock, standard);
+		} else {
+			if (bp->cmd_tbl.dac2_output_control != NULL)
+				bp->cmd_tbl.dac2_output_control(bp, enable);
+			bp->cmd_tbl.dac2_encoder_control(bp, enable,
+				pixel_clock, standard);
+		}
+	}
+
+	return BP_RESULT_OK;
+}
+
+static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	ATOM_COMMON_RECORD_HEADER *header;
+	uint32_t offset;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+			!header->ucRecordSize)
+			break;
+
+		if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType
+			&& sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize)
+			return (ATOM_HPD_INT_RECORD *) header;
+
+		offset += header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+/**
+ * Get I2C information of input object id
+ *
+ * search all records to find the ATOM_I2C_RECORD_TYPE record IR
+ */
+static ATOM_I2C_RECORD *get_i2c_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	ATOM_COMMON_RECORD_HEADER *record_header;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER();
+		/* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!record_header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == record_header->ucRecordType ||
+			0 == record_header->ucRecordSize)
+			break;
+
+		if (ATOM_I2C_RECORD_TYPE == record_header->ucRecordType &&
+			sizeof(ATOM_I2C_RECORD) <=
+			record_header->ucRecordSize) {
+			return (ATOM_I2C_RECORD *)record_header;
+		}
+
+		offset += record_header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+
+static enum bp_result get_ss_info_from_ss_info_table(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info);
+static enum bp_result get_ss_info_from_tbl(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info);
+/**
+ * bios_parser_get_spread_spectrum_info
+ * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
+ * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
+ * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,
+ * there is only one entry for each signal /ss id.  However, there is
+ * no planning of supporting multiple spread Sprectum entry for EverGreen
+ * @param [in] this
+ * @param [in] signal, ASSignalType to be converted to info index
+ * @param [in] index, number of entries that match the converted info index
+ * @param [out] ss_info, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_get_spread_spectrum_info(
+	struct dc_bios *dcb,
+	enum as_signal_type signal,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	uint32_t clk_id_ss = 0;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision tbl_revision;
+
+	if (!ss_info) /* check for bad input */
+		return BP_RESULT_BADINPUT;
+	/* signal translation */
+	clk_id_ss = signal_to_ss_id(signal);
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		if (!index)
+			return get_ss_info_from_ss_info_table(bp, clk_id_ss,
+				ss_info);
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+		DATA_TABLES(ASIC_InternalSS_Info));
+	get_atom_data_table_revision(header, &tbl_revision);
+
+	switch (tbl_revision.major) {
+	case 2:
+		switch (tbl_revision.minor) {
+		case 1:
+			/* there can not be more then one entry for Internal
+			 * SS Info table version 2.1 */
+			if (!index)
+				return get_ss_info_from_tbl(bp, clk_id_ss,
+						ss_info);
+			break;
+		default:
+			break;
+		}
+		break;
+
+	case 3:
+		switch (tbl_revision.minor) {
+		case 1:
+			return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info);
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+	/* there can not be more then one entry for SS Info table */
+	return result;
+}
+
+static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *info);
+
+/**
+ * get_ss_info_from_table
+ * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info table from the VBIOS
+ * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info.
+ *
+ * @param this
+ * @param id, spread sprectrum info index
+ * @param pSSinfo, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result get_ss_info_from_tbl(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info)
+{
+	if (!ss_info) /* check for bad input, if ss_info is not NULL */
+		return BP_RESULT_BADINPUT;
+	/* for SS_Info table only support DP and LVDS */
+	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
+		return get_ss_info_from_ss_info_table(bp, id, ss_info);
+	else
+		return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id,
+			ss_info);
+}
+
+/**
+ * get_ss_info_from_internal_ss_info_tbl_V2_1
+ * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1
+ * from the VBIOS
+ * There will not be multiple entry for Ver 2.1
+ *
+ * @param id, spread sprectrum info index
+ * @param pSSinfo, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *info)
+{
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header;
+	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
+	uint32_t tbl_size, i;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return result;
+
+	header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
+		DATA_TABLES(ASIC_InternalSS_Info));
+
+	dm_memset(info, 0, sizeof(struct spread_spectrum_info));
+
+	tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+					/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
+					&(header->asSpreadSpectrum[0]);
+	for (i = 0; i < tbl_size; i++) {
+		result = BP_RESULT_NORECORD;
+
+		if (tbl[i].ucClockIndication != (uint8_t)id)
+			continue;
+
+		if (ATOM_EXTERNAL_SS_MASK
+			& tbl[i].ucSpreadSpectrumMode) {
+			info->type.EXTERNAL = true;
+		}
+		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
+			& tbl[i].ucSpreadSpectrumMode) {
+			info->type.CENTER_MODE = true;
+		}
+		info->type.STEP_AND_DELAY_INFO = false;
+		/* convert [10KHz] into [KHz] */
+		info->target_clock_range =
+			le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
+		info->spread_spectrum_percentage =
+			(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
+		info->spread_spectrum_range =
+			(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
+		result = BP_RESULT_OK;
+		break;
+	}
+
+	return result;
+
+}
+
+/**
+ * get_ss_info_from_ss_info_table
+ * Get spread sprectrum information from the SS_Info table from the VBIOS
+ * if the pointer to info is NULL, indicate the caller what to know the number
+ * of entries that matches the id
+ * for, the SS_Info table, there should not be more than 1 entry match.
+ *
+ * @param [in] id, spread sprectrum id
+ * @param [out] pSSinfo, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result get_ss_info_from_ss_info_table(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info)
+{
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	ATOM_SPREAD_SPECTRUM_INFO *tbl;
+	ATOM_COMMON_TABLE_HEADER *header;
+	uint32_t table_size;
+	uint32_t i;
+	uint32_t id_local = SS_ID_UNKNOWN;
+	struct atom_data_revision revision;
+
+	/* exist of the SS_Info table */
+	/* check for bad input, pSSinfo can not be NULL */
+	if (!DATA_TABLES(SS_Info) || !ss_info)
+		return result;
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));
+	get_atom_data_table_revision(header, &revision);
+
+	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
+
+	if (1 != revision.major || 2 > revision.minor)
+		return result;
+
+	/* have to convert from Internal_SS format to SS_Info format */
+	switch (id) {
+	case ASIC_INTERNAL_SS_ON_DP:
+		id_local = SS_ID_DP1;
+		break;
+	case ASIC_INTERNAL_SS_ON_LVDS:
+	{
+		struct embedded_panel_info panel_info;
+
+		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
+				== BP_RESULT_OK)
+			id_local = panel_info.ss_id;
+		break;
+	}
+	default:
+		break;
+	}
+
+	if (id_local == SS_ID_UNKNOWN)
+		return result;
+
+	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
+			sizeof(ATOM_COMMON_TABLE_HEADER)) /
+					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
+
+	for (i = 0; i < table_size; i++) {
+		if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)
+			continue;
+
+		dm_memset(ss_info, 0, sizeof(struct spread_spectrum_info));
+
+		if (ATOM_EXTERNAL_SS_MASK &
+				tbl->asSS_Info[i].ucSpreadSpectrumType)
+			ss_info->type.EXTERNAL = true;
+
+		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &
+				tbl->asSS_Info[i].ucSpreadSpectrumType)
+			ss_info->type.CENTER_MODE = true;
+
+		ss_info->type.STEP_AND_DELAY_INFO = true;
+		ss_info->spread_spectrum_percentage =
+			(uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);
+		ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;
+		ss_info->step_and_delay_info.delay =
+			tbl->asSS_Info[i].ucSS_Delay;
+		ss_info->step_and_delay_info.recommended_ref_div =
+			tbl->asSS_Info[i].ucRecommendedRef_Div;
+		ss_info->spread_spectrum_range =
+			(uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;
+
+		/* there will be only one entry for each display type in SS_info
+		 * table */
+		result = BP_RESULT_OK;
+		break;
+	}
+
+	return result;
+}
+static enum bp_result get_embedded_panel_info_v1_2(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info);
+static enum bp_result get_embedded_panel_info_v1_3(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info);
+
+static enum bp_result bios_parser_get_embedded_panel_info(
+	struct dc_bios *dcb,
+	struct embedded_panel_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_COMMON_TABLE_HEADER *hdr;
+
+	if (!DATA_TABLES(LCD_Info))
+		return BP_RESULT_FAILURE;
+
+	hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));
+
+	if (!hdr)
+		return BP_RESULT_BADBIOSTABLE;
+
+	switch (hdr->ucTableFormatRevision) {
+	case 1:
+		switch (hdr->ucTableContentRevision) {
+		case 0:
+		case 1:
+		case 2:
+			return get_embedded_panel_info_v1_2(bp, info);
+		case 3:
+			return get_embedded_panel_info_v1_3(bp, info);
+		default:
+			break;
+		}
+		default:
+			break;
+	}
+
+	return BP_RESULT_FAILURE;
+}
+
+static enum bp_result get_embedded_panel_info_v1_2(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info)
+{
+	ATOM_LVDS_INFO_V12 *lvds;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(LVDS_Info))
+		return BP_RESULT_UNSUPPORTED;
+
+	lvds =
+		GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
+
+	if (!lvds)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != lvds->sHeader.ucTableFormatRevision
+		|| 2 > lvds->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	dm_memset(info, 0, sizeof(struct embedded_panel_info));
+
+	/* We need to convert from 10KHz units into KHz units*/
+	info->lcd_timing.pixel_clk =
+		le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
+	/* usHActive does not include borders, according to VBIOS team*/
+	info->lcd_timing.horizontal_addressable =
+		le16_to_cpu(lvds->sLCDTiming.usHActive);
+	/* usHBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now.  May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.horizontal_blanking_time =
+			le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
+	/* usVActive does not include borders, according to VBIOS team*/
+	info->lcd_timing.vertical_addressable =
+			le16_to_cpu(lvds->sLCDTiming.usVActive);
+	/* usVBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now. May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.vertical_blanking_time =
+		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
+	info->lcd_timing.horizontal_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
+	info->lcd_timing.horizontal_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
+	info->lcd_timing.vertical_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
+	info->lcd_timing.vertical_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
+	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
+	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
+	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
+	info->lcd_timing.misc_info.H_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
+	info->lcd_timing.misc_info.V_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
+	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
+	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
+	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
+	info->lcd_timing.misc_info.COMPOSITE_SYNC =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
+	info->lcd_timing.misc_info.INTERLACE =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
+	info->lcd_timing.misc_info.DOUBLE_CLOCK =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
+	info->ss_id = lvds->ucSS_Id;
+
+	{
+		uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
+		/* Get minimum supported refresh rate*/
+		if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
+			info->supported_rr.REFRESH_RATE_30HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
+			info->supported_rr.REFRESH_RATE_40HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
+			info->supported_rr.REFRESH_RATE_48HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
+			info->supported_rr.REFRESH_RATE_50HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
+			info->supported_rr.REFRESH_RATE_60HZ = 1;
+	}
+
+	/*Drr panel support can be reported by VBIOS*/
+	if (LCDPANEL_CAP_DRR_SUPPORTED
+			& lvds->ucLCDPanel_SpecialHandlingCap)
+		info->drr_enabled = 1;
+
+	if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
+
+	if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.RGB888 = true;
+
+	info->lcd_timing.misc_info.GREY_LEVEL =
+		(uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
+			lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
+
+	if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.SPATIAL = true;
+
+	if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.TEMPORAL = true;
+
+	if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.API_ENABLED = true;
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_embedded_panel_info_v1_3(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info)
+{
+	ATOM_LCD_INFO_V13 *lvds;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(LCD_Info))
+		return BP_RESULT_UNSUPPORTED;
+
+	lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
+
+	if (!lvds)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (!((1 == lvds->sHeader.ucTableFormatRevision)
+			&& (3 <= lvds->sHeader.ucTableContentRevision)))
+		return BP_RESULT_UNSUPPORTED;
+
+	dm_memset(info, 0, sizeof(struct embedded_panel_info));
+
+	/* We need to convert from 10KHz units into KHz units */
+	info->lcd_timing.pixel_clk =
+			le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
+	/* usHActive does not include borders, according to VBIOS team */
+	info->lcd_timing.horizontal_addressable =
+			le16_to_cpu(lvds->sLCDTiming.usHActive);
+	/* usHBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now.  May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.horizontal_blanking_time =
+		le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
+	/* usVActive does not include borders, according to VBIOS team*/
+	info->lcd_timing.vertical_addressable =
+		le16_to_cpu(lvds->sLCDTiming.usVActive);
+	/* usVBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now. May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.vertical_blanking_time =
+		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
+	info->lcd_timing.horizontal_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
+	info->lcd_timing.horizontal_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
+	info->lcd_timing.vertical_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
+	info->lcd_timing.vertical_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
+	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
+	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
+	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
+	info->lcd_timing.misc_info.H_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
+	info->lcd_timing.misc_info.V_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
+	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
+	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
+	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
+	info->lcd_timing.misc_info.COMPOSITE_SYNC =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
+	info->lcd_timing.misc_info.INTERLACE =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
+	info->lcd_timing.misc_info.DOUBLE_CLOCK =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
+	info->ss_id = lvds->ucSS_Id;
+
+	/* Drr panel support can be reported by VBIOS*/
+	if (LCDPANEL_CAP_V13_DRR_SUPPORTED
+			& lvds->ucLCDPanel_SpecialHandlingCap)
+		info->drr_enabled = 1;
+
+	/* Get supported refresh rate*/
+	if (info->drr_enabled == 1) {
+		uint8_t min_rr =
+				lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
+		uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
+
+		if (min_rr != 0) {
+			if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_30HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_40HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_48HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_50HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_60HZ = 1;
+		} else {
+			if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
+				info->supported_rr.REFRESH_RATE_30HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
+				info->supported_rr.REFRESH_RATE_40HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
+				info->supported_rr.REFRESH_RATE_48HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
+				info->supported_rr.REFRESH_RATE_50HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
+				info->supported_rr.REFRESH_RATE_60HZ = 1;
+		}
+	}
+
+	if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
+		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
+
+	if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
+		info->lcd_timing.misc_info.RGB888 = true;
+
+	info->lcd_timing.misc_info.GREY_LEVEL =
+			(uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
+				lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
+
+	return BP_RESULT_OK;
+}
+
+/**
+ * bios_parser_get_encoder_cap_info
+ *
+ * @brief
+ *  Get encoder capability information of input object id
+ *
+ * @param object_id, Object id
+ * @param object_id, encoder cap information structure
+ *
+ * @return Bios parser result code
+ *
+ */
+static enum bp_result bios_parser_get_encoder_cap_info(
+	struct dc_bios *dcb,
+	struct graphics_object_id object_id,
+	struct bp_encoder_cap_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object;
+	ATOM_ENCODER_CAP_RECORD *record = NULL;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, object_id);
+
+	if (!object)
+		return BP_RESULT_BADINPUT;
+
+	record = get_encoder_cap_record(bp, object);
+	if (!record)
+		return BP_RESULT_NORECORD;
+
+	info->DP_HBR2_CAP = record->usHBR2Cap;
+	info->DP_HBR2_EN = record->usHBR2En;
+	return BP_RESULT_OK;
+}
+
+/**
+ * get_encoder_cap_record
+ *
+ * @brief
+ *  Get encoder cap record for the object
+ *
+ * @param object, ATOM object
+ *
+ * @return atom encoder cap record
+ *
+ * @note
+ *  search all records to find the ATOM_ENCODER_CAP_RECORD record
+ */
+static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	ATOM_COMMON_RECORD_HEADER *header;
+	uint32_t offset;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+					+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		offset += header->ucRecordSize;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				!header->ucRecordSize)
+			break;
+
+		if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
+			continue;
+
+		if (sizeof(ATOM_ENCODER_CAP_RECORD) <= header->ucRecordSize)
+			return (ATOM_ENCODER_CAP_RECORD *)header;
+	}
+
+	return NULL;
+}
+
+/**
+ * bios_parser_get_din_connector_info
+ * @brief
+ *   Get GPIO record for the DIN connector, this GPIO tells whether there is a
+ *    CV dumb dongle
+ *   attached to the DIN connector to perform load detection for the the
+ *    appropriate signal
+ *
+ * @param id - DIN connector object id
+ * @param info             - GPIO record infor
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_get_din_connector_info(
+	struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct din_connector_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_COMMON_RECORD_HEADER *header;
+	ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD *record = NULL;
+	ATOM_OBJECT *object;
+	uint32_t offset;
+	enum bp_result result = BP_RESULT_NORECORD;
+
+	/* no output buffer provided */
+	if (!info) {
+		BREAK_TO_DEBUGGER(); /* Invalid output buffer */
+		return BP_RESULT_BADINPUT;
+	}
+
+	object = get_bios_object(bp, id);
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */;
+		return BP_RESULT_BADINPUT;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+						+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header) {
+			result = BP_RESULT_BADBIOSTABLE;
+			break;
+		}
+
+		offset += header->ucRecordSize;
+
+		/* get out of the loop if no more records */
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				!header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD_TYPE !=
+				header->ucRecordType)
+			continue;
+
+		if (sizeof(ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD)
+				> header->ucRecordSize)
+			continue;
+
+		record = (ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD *)header;
+		result = BP_RESULT_OK;
+		break;
+	}
+
+	/* return if the record not found */
+	if (result != BP_RESULT_OK)
+		return result;
+
+	info->gpio_id = record->ucGPIOID;
+	info->gpio_tv_active_state = (record->ucTVActiveState != 0);
+
+	return result;
+}
+
+static uint32_t get_ss_entry_number(
+	struct bios_parser *bp,
+	uint32_t id);
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
+	struct bios_parser *bp,
+	uint32_t id);
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
+	struct bios_parser *bp,
+	uint32_t id);
+static uint32_t get_ss_entry_number_from_ss_info_tbl(
+	struct bios_parser *bp,
+	uint32_t id);
+
+/**
+ * BiosParserObject::GetNumberofSpreadSpectrumEntry
+ * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
+ * the VBIOS that match the SSid (to be converted from signal)
+ *
+ * @param[in] signal, ASSignalType to be converted to SSid
+ * @return number of SS Entry that match the signal
+ */
+static uint32_t bios_parser_get_ss_entry_number(
+	struct dc_bios *dcb,
+	enum as_signal_type signal)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	uint32_t ss_id = 0;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision;
+
+	ss_id = signal_to_ss_id(signal);
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+			DATA_TABLES(ASIC_InternalSS_Info));
+	get_atom_data_table_revision(header, &revision);
+
+	switch (revision.major) {
+	case 2:
+		switch (revision.minor) {
+		case 1:
+			return get_ss_entry_number(bp, ss_id);
+		default:
+			break;
+		}
+		break;
+	case 3:
+		switch (revision.minor) {
+		case 1:
+			return
+				get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
+						bp, ss_id);
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+
+/**
+ * get_ss_entry_number_from_ss_info_tbl
+ * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
+ *
+ * @note There can only be one entry for each id for SS_Info Table
+ *
+ * @param [in] id, spread spectrum id
+ * @return number of SS Entry that match the id
+ */
+static uint32_t get_ss_entry_number_from_ss_info_tbl(
+	struct bios_parser *bp,
+	uint32_t id)
+{
+	ATOM_SPREAD_SPECTRUM_INFO *tbl;
+	ATOM_COMMON_TABLE_HEADER *header;
+	uint32_t table_size;
+	uint32_t i;
+	uint32_t number = 0;
+	uint32_t id_local = SS_ID_UNKNOWN;
+	struct atom_data_revision revision;
+
+	/* SS_Info table exist */
+	if (!DATA_TABLES(SS_Info))
+		return number;
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+			DATA_TABLES(SS_Info));
+	get_atom_data_table_revision(header, &revision);
+
+	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
+			DATA_TABLES(SS_Info));
+
+	if (1 != revision.major || 2 > revision.minor)
+		return number;
+
+	/* have to convert from Internal_SS format to SS_Info format */
+	switch (id) {
+	case ASIC_INTERNAL_SS_ON_DP:
+		id_local = SS_ID_DP1;
+		break;
+	case ASIC_INTERNAL_SS_ON_LVDS: {
+		struct embedded_panel_info panel_info;
+
+		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
+				== BP_RESULT_OK)
+			id_local = panel_info.ss_id;
+		break;
+	}
+	default:
+		break;
+	}
+
+	if (id_local == SS_ID_UNKNOWN)
+		return number;
+
+	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
+			sizeof(ATOM_COMMON_TABLE_HEADER)) /
+					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
+
+	for (i = 0; i < table_size; i++)
+		if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
+			number = 1;
+			break;
+		}
+
+	return number;
+}
+
+
+/**
+ * get_ss_entry_number
+ * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info table from the VBIOS
+ * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info.
+ *
+ * @param id, spread sprectrum info index
+ * @return Bios parser result code
+ */
+static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
+{
+	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
+		return get_ss_entry_number_from_ss_info_tbl(bp, id);
+
+	return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
+}
+
+/**
+ * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
+ * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
+ * Ver 2.1 from the VBIOS
+ * There will not be multiple entry for Ver 2.1
+ *
+ * @param id, spread sprectrum info index
+ * @return number of SS Entry that match the id
+ */
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
+	struct bios_parser *bp,
+	uint32_t id)
+{
+	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
+	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
+	uint32_t size;
+	uint32_t i;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return 0;
+
+	header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
+			DATA_TABLES(ASIC_InternalSS_Info));
+
+	size = (le16_to_cpu(header_include->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+						/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
+				&header_include->asSpreadSpectrum[0];
+	for (i = 0; i < size; i++)
+		if (tbl[i].ucClockIndication == (uint8_t)id)
+			return 1;
+
+	return 0;
+}
+/**
+ * get_ss_entry_number_from_internal_ss_info_table_V3_1
+ * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
+ * the VBIOS that matches id
+ *
+ * @param[in]  id, spread sprectrum id
+ * @return number of SS Entry that match the id
+ */
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
+	struct bios_parser *bp,
+	uint32_t id)
+{
+	uint32_t number = 0;
+	ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
+	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
+	uint32_t size;
+	uint32_t i;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return number;
+
+	header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
+			DATA_TABLES(ASIC_InternalSS_Info));
+	size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
+			sizeof(ATOM_COMMON_TABLE_HEADER)) /
+					sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
+				&header_include->asSpreadSpectrum[0];
+
+	for (i = 0; i < size; i++)
+		if (tbl[i].ucClockIndication == (uint8_t)id)
+			number++;
+
+	return number;
+}
+
+static ATOM_FAKE_EDID_PATCH_RECORD *get_faked_edid_record(
+	struct bios_parser *bp)
+{
+	uint32_t size;
+	uint8_t *record;
+	ATOM_LVDS_INFO_V12 *info;
+
+	if (!DATA_TABLES(LVDS_Info))
+		return NULL;
+
+	info = GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
+
+	if (!info)
+		return NULL;
+
+	if (1 != info->sHeader.ucTableFormatRevision
+			|| 2 > info->sHeader.ucTableContentRevision)
+		return NULL;
+
+	if (!le16_to_cpu(info->usExtInfoTableOffset))
+		return NULL;
+
+	record = GET_IMAGE(uint8_t, DATA_TABLES(LVDS_Info)
+			+ le16_to_cpu(info->usExtInfoTableOffset));
+
+	if (!record)
+		return NULL;
+
+	for (;;) {
+		if (ATOM_RECORD_END_TYPE == *record)
+			return NULL;
+
+		if (LCD_FAKE_EDID_PATCH_RECORD_TYPE == *record)
+			break;
+
+		size = get_record_size(record);
+
+		if (!size)
+			return NULL;
+
+		record += size;
+	}
+
+	return (ATOM_FAKE_EDID_PATCH_RECORD *)record;
+}
+
+static enum bp_result bios_parser_get_faked_edid_len(
+	struct dc_bios *dcb,
+	uint32_t *len)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_FAKE_EDID_PATCH_RECORD *edid_record = get_faked_edid_record(bp);
+
+	if (!edid_record)
+		return BP_RESULT_NORECORD;
+
+	*len = get_edid_size(edid_record);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_faked_edid_buf(
+	struct dc_bios *dcb,
+	uint8_t *buff,
+	uint32_t len)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_FAKE_EDID_PATCH_RECORD *edid_record = get_faked_edid_record(bp);
+	uint32_t edid_size;
+
+	if (!edid_record)
+		return BP_RESULT_NORECORD;
+
+	edid_size = get_edid_size(edid_record);
+
+	if (len < edid_size)
+		return BP_RESULT_BADINPUT; /* buffer not big enough to fill */
+
+	dm_memmove(buff, &edid_record->ucFakeEDIDString, edid_size);
+
+	return BP_RESULT_OK;
+}
+
+/**
+ * bios_parser_get_gpio_pin_info
+ * Get GpioPin information of input gpio id
+ *
+ * @param gpio_id, GPIO ID
+ * @param info, GpioPin information structure
+ * @return Bios parser result code
+ * @note
+ *  to get the GPIO PIN INFO, we need:
+ *  1. get the GPIO_ID from other object table, see GetHPDInfo()
+ *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
+ *  offset/mask
+ */
+static enum bp_result bios_parser_get_gpio_pin_info(
+	struct dc_bios *dcb,
+	uint32_t gpio_id,
+	struct gpio_pin_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_GPIO_PIN_LUT *header;
+	uint32_t count = 0;
+	uint32_t i = 0;
+
+	if (!DATA_TABLES(GPIO_Pin_LUT))
+		return BP_RESULT_BADBIOSTABLE;
+
+	header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT));
+	if (!header)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT)
+			> le16_to_cpu(header->sHeader.usStructureSize))
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != header->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	count = (le16_to_cpu(header->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
+	for (i = 0; i < count; ++i) {
+		if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
+			continue;
+
+		info->offset =
+			(uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
+		info->offset_y = info->offset + 2;
+		info->offset_en = info->offset + 1;
+		info->offset_mask = info->offset - 1;
+
+		info->mask = (uint32_t) (1 <<
+			header->asGPIO_Pin[i].ucGpioPinBitShift);
+		info->mask_y = info->mask + 2;
+		info->mask_en = info->mask + 1;
+		info->mask_mask = info->mask - 1;
+
+		return BP_RESULT_OK;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+/**
+ * BiosParserObject::EnumEmbeddedPanelPatchMode
+ * Get embedded panel patch mode
+ *
+ * @param index, mode index
+ * @param info, embedded panel patch mode structure
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_enum_embedded_panel_patch_mode(
+	struct dc_bios *dcb,
+	uint32_t index,
+	struct embedded_panel_patch_mode *mode)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	uint32_t record_size;
+	uint32_t record_index;
+	uint8_t *record;
+	ATOM_LVDS_INFO_V12 *info;
+	ATOM_PATCH_RECORD_MODE *mode_record;
+	ATOM_MASTER_LIST_OF_DATA_TABLES *list_of_tables;
+
+	if (!mode)
+		return BP_RESULT_BADINPUT;
+
+	list_of_tables = &bp->master_data_tbl->ListOfDataTables;
+	if (!list_of_tables->LVDS_Info)
+		return BP_RESULT_UNSUPPORTED;
+
+	info = GET_IMAGE(ATOM_LVDS_INFO_V12, list_of_tables->LVDS_Info);
+
+	if (!info)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != info->sHeader.ucTableFormatRevision
+			|| 2 > info->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	if (!le16_to_cpu(info->usExtInfoTableOffset))
+		return BP_RESULT_UNSUPPORTED;
+
+	record = GET_IMAGE(uint8_t, list_of_tables->LVDS_Info +
+			le16_to_cpu(info->usExtInfoTableOffset));
+
+	if (!record)
+		return BP_RESULT_BADBIOSTABLE;
+
+	for (record_index = 0;;) {
+		if (ATOM_RECORD_END_TYPE == *record)
+			return BP_RESULT_NORECORD;
+
+		if (LCD_MODE_PATCH_RECORD_MODE_TYPE == *record) {
+			if (record_index == index)
+				break;
+			record_index++;
+		}
+
+		record_size = get_record_size(record);
+
+		if (!record_size)
+			return BP_RESULT_NORECORD;
+
+		record += record_size;
+	}
+
+	mode_record = (ATOM_PATCH_RECORD_MODE *) record;
+
+	mode->width = le16_to_cpu(mode_record->usHDisp);
+	mode->height = le16_to_cpu(mode_record->usVDisp);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
+	ATOM_I2C_RECORD *record,
+	struct graphics_object_i2c_info *info)
+{
+	ATOM_GPIO_I2C_INFO *header;
+	uint32_t count = 0;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	/* get the GPIO_I2C info */
+	if (!DATA_TABLES(GPIO_I2C_Info))
+		return BP_RESULT_BADBIOSTABLE;
+
+	header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
+	if (!header)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
+			> le16_to_cpu(header->sHeader.usStructureSize))
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != header->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	/* get data count */
+	count = (le16_to_cpu(header->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+	if (count < record->sucI2cId.bfI2C_LineMux)
+		return BP_RESULT_BADBIOSTABLE;
+
+	/* get the GPIO_I2C_INFO */
+	info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
+	info->i2c_line = record->sucI2cId.bfI2C_LineMux;
+	info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
+	info->i2c_slave_address = record->ucI2CAddr;
+
+	info->gpio_info.clk_mask_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
+	info->gpio_info.clk_en_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
+	info->gpio_info.clk_y_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
+	info->gpio_info.clk_a_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
+	info->gpio_info.data_mask_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
+	info->gpio_info.data_en_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
+	info->gpio_info.data_y_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
+	info->gpio_info.data_a_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
+
+	info->gpio_info.clk_mask_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
+	info->gpio_info.clk_en_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkEnShift;
+	info->gpio_info.clk_y_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
+	info->gpio_info.clk_a_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
+	info->gpio_info.data_mask_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
+	info->gpio_info.data_en_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataEnShift;
+	info->gpio_info.data_y_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
+	info->gpio_info.data_a_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
+
+	return BP_RESULT_OK;
+}
+
+static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
+	struct graphics_object_id id)
+{
+	uint32_t offset;
+	ATOM_OBJECT_TABLE *tbl;
+	uint32_t i;
+
+	switch (id.type) {
+	case OBJECT_TYPE_ENCODER:
+		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
+		break;
+
+	case OBJECT_TYPE_CONNECTOR:
+		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+		break;
+
+	case OBJECT_TYPE_ROUTER:
+		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
+		break;
+
+	case OBJECT_TYPE_GENERIC:
+		if (bp->object_info_tbl.revision.minor < 3)
+			return NULL;
+		offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
+		break;
+
+	default:
+		return NULL;
+	}
+
+	offset += bp->object_info_tbl_offset;
+
+	tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
+	if (!tbl)
+		return NULL;
+
+	for (i = 0; i < tbl->ucNumberOfObjects; i++)
+		if (dal_graphics_object_id_is_equal(id,
+				object_id_from_bios_object_id(
+						le16_to_cpu(tbl->asObjects[i].usObjectID))))
+			return &tbl->asObjects[i];
+
+	return NULL;
+}
+
+static uint32_t get_dest_obj_list(struct bios_parser *bp,
+	ATOM_OBJECT *object, uint16_t **id_list)
+{
+	uint32_t offset;
+	uint8_t *number;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+						+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	offset += sizeof(uint8_t);
+	offset += sizeof(uint16_t) * (*number);
+
+	number = GET_IMAGE(uint8_t, offset);
+	if ((!number) || (!*number))
+		return 0;
+
+	offset += sizeof(uint8_t);
+	*id_list = (uint16_t *)get_image(bp, offset,
+			*number * sizeof(uint16_t));
+
+	if (!*id_list)
+		return 0;
+
+	return *number;
+}
+
+static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
+	uint16_t **id_list)
+{
+	uint32_t offset;
+	uint8_t *number;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+					+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	offset += sizeof(uint8_t);
+	*id_list = (uint16_t *)get_image(bp, offset,
+			*number * sizeof(uint16_t));
+
+	if (!*id_list)
+		return 0;
+
+	return *number;
+}
+
+static uint32_t get_dst_number_from_object(struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	uint8_t *number;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+					+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	offset += sizeof(uint8_t);
+	offset += sizeof(uint16_t) * (*number);
+
+	number = GET_IMAGE(uint8_t, offset);
+
+	if (!number)
+		return 0;
+
+	return *number;
+}
+
+static uint8_t *get_image(struct bios_parser *bp,
+	uint32_t offset,
+	uint32_t size)
+{
+	if (bp->bios && offset + size < bp->bios_size)
+		return bp->bios + offset;
+	else
+		return NULL;
+}
+
+static uint32_t get_record_size(uint8_t *record)
+{
+	switch (*record) {
+	case LCD_MODE_PATCH_RECORD_MODE_TYPE:
+		return sizeof(ATOM_PATCH_RECORD_MODE);
+
+	case LCD_RTS_RECORD_TYPE:
+		return sizeof(ATOM_LCD_RTS_RECORD);
+
+	case LCD_CAP_RECORD_TYPE:
+		return sizeof(ATOM_LCD_MODE_CONTROL_CAP);
+
+	case LCD_FAKE_EDID_PATCH_RECORD_TYPE: {
+		ATOM_FAKE_EDID_PATCH_RECORD *fake_record =
+				(ATOM_FAKE_EDID_PATCH_RECORD *) record;
+		uint32_t edid_size = get_edid_size(fake_record);
+
+		return sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + edid_size
+				- sizeof(fake_record->ucFakeEDIDString);
+	}
+
+	case LCD_PANEL_RESOLUTION_RECORD_TYPE:
+		return sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
+
+	default:
+		return 0;
+	}
+}
+
+static uint32_t get_edid_size(const ATOM_FAKE_EDID_PATCH_RECORD *edid)
+{
+	uint32_t length = edid->ucFakeEDIDLength;
+
+	if (length < 128)
+		length = length * 128;
+
+	return length;
+}
+
+static struct graphics_object_id object_id_from_bios_object_id(
+	uint32_t bios_object_id)
+{
+	enum object_type type;
+	enum object_enum_id enum_id;
+	struct graphics_object_id go_id = { 0 };
+
+	type = object_type_from_bios_object_id(bios_object_id);
+
+	if (OBJECT_TYPE_UNKNOWN == type)
+		return go_id;
+
+	enum_id = enum_id_from_bios_object_id(bios_object_id);
+
+	if (ENUM_ID_UNKNOWN == enum_id)
+		return go_id;
+
+	go_id = dal_graphics_object_id_init(
+			id_from_bios_object_id(type, bios_object_id), enum_id, type);
+
+	return go_id;
+}
+
+static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK)
+				>> OBJECT_TYPE_SHIFT;
+	enum object_type object_type;
+
+	switch (bios_object_type) {
+	case GRAPH_OBJECT_TYPE_GPU:
+		object_type = OBJECT_TYPE_GPU;
+		break;
+	case GRAPH_OBJECT_TYPE_ENCODER:
+		object_type = OBJECT_TYPE_ENCODER;
+		break;
+	case GRAPH_OBJECT_TYPE_CONNECTOR:
+		object_type = OBJECT_TYPE_CONNECTOR;
+		break;
+	case GRAPH_OBJECT_TYPE_ROUTER:
+		object_type = OBJECT_TYPE_ROUTER;
+		break;
+	case GRAPH_OBJECT_TYPE_GENERIC:
+		object_type = OBJECT_TYPE_GENERIC;
+		break;
+	default:
+		object_type = OBJECT_TYPE_UNKNOWN;
+		break;
+	}
+
+	return object_type;
+}
+
+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_enum_id =
+			(bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+	enum object_enum_id id;
+
+	switch (bios_enum_id) {
+	case GRAPH_OBJECT_ENUM_ID1:
+		id = ENUM_ID_1;
+		break;
+	case GRAPH_OBJECT_ENUM_ID2:
+		id = ENUM_ID_2;
+		break;
+	case GRAPH_OBJECT_ENUM_ID3:
+		id = ENUM_ID_3;
+		break;
+	case GRAPH_OBJECT_ENUM_ID4:
+		id = ENUM_ID_4;
+		break;
+	case GRAPH_OBJECT_ENUM_ID5:
+		id = ENUM_ID_5;
+		break;
+	case GRAPH_OBJECT_ENUM_ID6:
+		id = ENUM_ID_6;
+		break;
+	case GRAPH_OBJECT_ENUM_ID7:
+		id = ENUM_ID_7;
+		break;
+	default:
+		id = ENUM_ID_UNKNOWN;
+		break;
+	}
+
+	return id;
+}
+
+static uint32_t id_from_bios_object_id(enum object_type type,
+	uint32_t bios_object_id)
+{
+	switch (type) {
+	case OBJECT_TYPE_GPU:
+		return gpu_id_from_bios_object_id(bios_object_id);
+	case OBJECT_TYPE_ENCODER:
+		return (uint32_t)encoder_id_from_bios_object_id(bios_object_id);
+	case OBJECT_TYPE_CONNECTOR:
+		return (uint32_t)connector_id_from_bios_object_id(
+				bios_object_id);
+	case OBJECT_TYPE_GENERIC:
+		return generic_id_from_bios_object_id(bios_object_id);
+	default:
+		return 0;
+	}
+}
+
+static enum connector_id connector_id_from_bios_object_id(
+	uint32_t bios_object_id)
+{
+	uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id);
+
+	enum connector_id id;
+
+	switch (bios_connector_id) {
+	case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I:
+		id = CONNECTOR_ID_SINGLE_LINK_DVII;
+		break;
+	case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I:
+		id = CONNECTOR_ID_DUAL_LINK_DVII;
+		break;
+	case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D:
+		id = CONNECTOR_ID_SINGLE_LINK_DVID;
+		break;
+	case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D:
+		id = CONNECTOR_ID_DUAL_LINK_DVID;
+		break;
+	case CONNECTOR_OBJECT_ID_VGA:
+		id = CONNECTOR_ID_VGA;
+		break;
+	case CONNECTOR_OBJECT_ID_HDMI_TYPE_A:
+		id = CONNECTOR_ID_HDMI_TYPE_A;
+		break;
+	case CONNECTOR_OBJECT_ID_LVDS:
+		id = CONNECTOR_ID_LVDS;
+		break;
+	case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR:
+		id = CONNECTOR_ID_PCIE;
+		break;
+	case CONNECTOR_OBJECT_ID_HARDCODE_DVI:
+		id = CONNECTOR_ID_HARDCODE_DVI;
+		break;
+	case CONNECTOR_OBJECT_ID_DISPLAYPORT:
+		id = CONNECTOR_ID_DISPLAY_PORT;
+		break;
+	case CONNECTOR_OBJECT_ID_eDP:
+		id = CONNECTOR_ID_EDP;
+		break;
+	case CONNECTOR_OBJECT_ID_MXM:
+		id = CONNECTOR_ID_MXM;
+		break;
+	default:
+		id = CONNECTOR_ID_UNKNOWN;
+		break;
+	}
+
+	return id;
+}
+
+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id);
+	enum encoder_id id;
+
+	switch (bios_encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		id = ENCODER_ID_INTERNAL_LVDS;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+		id = ENCODER_ID_INTERNAL_TMDS1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS2:
+		id = ENCODER_ID_INTERNAL_TMDS2;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+		id = ENCODER_ID_INTERNAL_DAC1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+		id = ENCODER_ID_INTERNAL_DAC2;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		id = ENCODER_ID_INTERNAL_LVTM1;
+		break;
+	case ENCODER_OBJECT_ID_HDMI_INTERNAL:
+		id = ENCODER_ID_INTERNAL_HDMI;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		id = ENCODER_ID_INTERNAL_KLDSCP_DAC1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		id = ENCODER_ID_INTERNAL_KLDSCP_DAC2;
+		break;
+	case ENCODER_OBJECT_ID_MVPU_FPGA:
+		id = ENCODER_ID_EXTERNAL_MVPU_FPGA;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+		id = ENCODER_ID_INTERNAL_DDI;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+		id = ENCODER_ID_INTERNAL_UNIPHY;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		id = ENCODER_ID_INTERNAL_UNIPHY1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		id = ENCODER_ID_INTERNAL_UNIPHY2;
+		break;
+	case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */
+		id = ENCODER_ID_EXTERNAL_NUTMEG;
+		break;
+	case ENCODER_OBJECT_ID_TRAVIS:
+		id = ENCODER_ID_EXTERNAL_TRAVIS;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
+		id = ENCODER_ID_INTERNAL_UNIPHY3;
+		break;
+	default:
+		id = ENCODER_ID_UNKNOWN;
+		ASSERT(0);
+		break;
+	}
+
+	return id;
+}
+
+uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+}
+
+enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id);
+
+	enum generic_id id;
+
+	switch (bios_generic_id) {
+	case GENERIC_OBJECT_ID_MXM_OPM:
+		id = GENERIC_ID_MXM_OPM;
+		break;
+	case GENERIC_OBJECT_ID_GLSYNC:
+		id = GENERIC_ID_GLSYNC;
+		break;
+	case GENERIC_OBJECT_ID_STEREO_PIN:
+		id = GENERIC_ID_STEREO;
+		break;
+	default:
+		id = GENERIC_ID_UNKNOWN;
+		break;
+	}
+
+	return id;
+}
+
+static struct device_id device_type_from_device_id(uint16_t device_id)
+{
+
+	struct device_id result_device_id;
+
+	switch (device_id) {
+	case ATOM_DEVICE_LCD1_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_LCD;
+		result_device_id.enum_id = 1;
+		break;
+
+	case ATOM_DEVICE_LCD2_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_LCD;
+		result_device_id.enum_id = 2;
+		break;
+
+	case ATOM_DEVICE_CRT1_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_CRT;
+		result_device_id.enum_id = 1;
+		break;
+
+	case ATOM_DEVICE_CRT2_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_CRT;
+		result_device_id.enum_id = 2;
+		break;
+
+	case ATOM_DEVICE_DFP1_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 1;
+		break;
+
+	case ATOM_DEVICE_DFP2_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 2;
+		break;
+
+	case ATOM_DEVICE_DFP3_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 3;
+		break;
+
+	case ATOM_DEVICE_DFP4_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 4;
+		break;
+
+	case ATOM_DEVICE_DFP5_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 5;
+		break;
+
+	case ATOM_DEVICE_DFP6_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 6;
+		break;
+
+	default:
+		BREAK_TO_DEBUGGER(); /* Invalid device Id */
+		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
+		result_device_id.enum_id = 0;
+	}
+	return result_device_id;
+}
+
+static void get_atom_data_table_revision(
+	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
+	struct atom_data_revision *tbl_revision)
+{
+	if (!tbl_revision)
+		return;
+
+	/* initialize the revision to 0 which is invalid revision */
+	tbl_revision->major = 0;
+	tbl_revision->minor = 0;
+
+	if (!atom_data_tbl)
+		return;
+
+	tbl_revision->major =
+			(uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
+	tbl_revision->minor =
+			(uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
+}
+
+static uint32_t signal_to_ss_id(enum as_signal_type signal)
+{
+	uint32_t clk_id_ss = 0;
+
+	switch (signal) {
+	case AS_SIGNAL_TYPE_DVI:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
+		break;
+	case AS_SIGNAL_TYPE_HDMI:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
+		break;
+	case AS_SIGNAL_TYPE_LVDS:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
+		break;
+	case AS_SIGNAL_TYPE_DISPLAY_PORT:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
+		break;
+	case AS_SIGNAL_TYPE_GPU_PLL:
+		clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
+		break;
+	default:
+		break;
+	}
+	return clk_id_ss;
+}
+
+static uint32_t get_support_mask_for_device_id(struct device_id device_id)
+{
+	enum dal_device_type device_type = device_id.device_type;
+	uint32_t enum_id = device_id.enum_id;
+
+	switch (device_type) {
+	case DEVICE_TYPE_LCD:
+		switch (enum_id) {
+		case 1:
+			return ATOM_DEVICE_LCD1_SUPPORT;
+		case 2:
+			return ATOM_DEVICE_LCD2_SUPPORT;
+		default:
+			break;
+		}
+		break;
+		case DEVICE_TYPE_CRT:
+			switch (enum_id) {
+			case 1:
+				return ATOM_DEVICE_CRT1_SUPPORT;
+			case 2:
+				return ATOM_DEVICE_CRT2_SUPPORT;
+			default:
+				break;
+			}
+			break;
+			case DEVICE_TYPE_DFP:
+				switch (enum_id) {
+				case 1:
+					return ATOM_DEVICE_DFP1_SUPPORT;
+				case 2:
+					return ATOM_DEVICE_DFP2_SUPPORT;
+				case 3:
+					return ATOM_DEVICE_DFP3_SUPPORT;
+				case 4:
+					return ATOM_DEVICE_DFP4_SUPPORT;
+				case 5:
+					return ATOM_DEVICE_DFP5_SUPPORT;
+				case 6:
+					return ATOM_DEVICE_DFP6_SUPPORT;
+				default:
+					break;
+				}
+				break;
+				case DEVICE_TYPE_CV:
+					switch (enum_id) {
+					case 1:
+						return ATOM_DEVICE_CV_SUPPORT;
+					default:
+						break;
+					}
+					break;
+					case DEVICE_TYPE_TV:
+						switch (enum_id) {
+						case 1:
+							return ATOM_DEVICE_TV1_SUPPORT;
+						default:
+							break;
+						}
+						break;
+						default:
+							break;
+	};
+
+	/* Unidentified device ID, return empty support mask. */
+	return 0;
+}
+
+/**
+ *  HwContext interface for writing MM registers
+ */
+
+static bool i2c_read(
+	struct bios_parser *bp,
+	struct graphics_object_i2c_info *i2c_info,
+	uint8_t *buffer,
+	uint32_t length)
+{
+	struct ddc *ddc;
+	uint8_t offset[2] = { 0, 0 };
+	bool result = false;
+	struct i2c_command cmd;
+
+	ddc = dal_adapter_service_obtain_ddc_from_i2c_info(bp->as, i2c_info);
+
+	if (!ddc)
+		return result;
+
+	/*Using SW engine */
+	cmd.engine = I2C_COMMAND_ENGINE_SW;
+	cmd.speed = dal_adapter_service_get_sw_i2c_speed(bp->as);
+
+	{
+		struct i2c_payload payloads[] = {
+				{
+						.address = i2c_info->i2c_slave_address >> 1,
+						.data = offset,
+						.length = sizeof(offset),
+						.write = true
+				},
+				{
+						.address = i2c_info->i2c_slave_address >> 1,
+						.data = buffer,
+						.length = length,
+						.write = false
+				}
+		};
+
+		cmd.payloads = payloads;
+		cmd.number_of_payloads = ARRAY_SIZE(payloads);
+
+		result = dal_i2caux_submit_i2c_command(
+				dal_adapter_service_get_i2caux(bp->as),
+				ddc,
+				&cmd);
+	}
+
+	dal_adapter_service_release_ddc(bp->as, ddc);
+
+	return result;
+}
+
+/**
+ * Read external display connection info table through i2c.
+ * validate the GUID and checksum.
+ *
+ * @return enum bp_result whether all data was sucessfully read
+ */
+static enum bp_result get_ext_display_connection_info(
+	struct bios_parser *bp,
+	ATOM_OBJECT *opm_object,
+	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl)
+{
+	bool config_tbl_present = false;
+	ATOM_I2C_RECORD *i2c_record = NULL;
+	uint32_t i = 0;
+
+	if (opm_object == NULL)
+		return BP_RESULT_BADINPUT;
+
+	i2c_record = get_i2c_record(bp, opm_object);
+
+	if (i2c_record != NULL) {
+		ATOM_GPIO_I2C_INFO *gpio_i2c_header;
+		struct graphics_object_i2c_info i2c_info;
+
+		gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO,
+				bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info);
+
+		if (NULL == gpio_i2c_header)
+			return BP_RESULT_BADBIOSTABLE;
+
+		if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) !=
+				BP_RESULT_OK)
+			return BP_RESULT_BADBIOSTABLE;
+
+		if (i2c_read(
+				bp,
+				&i2c_info,
+				(uint8_t *)ext_display_connection_info_tbl,
+				sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) {
+			config_tbl_present = true;
+		}
+	}
+
+	/* Validate GUID */
+	if (config_tbl_present)
+		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) {
+			if (ext_display_connection_info_tbl->ucGuid[i]
+														!= ext_display_connection_guid[i]) {
+				config_tbl_present = false;
+				break;
+			}
+		}
+
+	/* Validate checksum */
+	if (config_tbl_present) {
+		uint8_t check_sum = 0;
+		uint8_t *buf =
+				(uint8_t *)ext_display_connection_info_tbl;
+
+		for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO);
+				i++) {
+			check_sum += buf[i];
+		}
+
+		if (check_sum != 0)
+			config_tbl_present = false;
+	}
+
+	if (config_tbl_present)
+		return BP_RESULT_OK;
+	else
+		return BP_RESULT_FAILURE;
+}
+
+/*
+ * Gets the first device ID in the same group as the given ID for enumerating.
+ * For instance, if any DFP device ID is passed, returns the device ID for DFP1.
+ *
+ * The first device ID in the same group as the passed device ID, or 0 if no
+ * matching device group found.
+ */
+static uint32_t enum_first_device_id(uint32_t dev_id)
+{
+	/* Return the first in the group that this ID belongs to. */
+	if (dev_id & ATOM_DEVICE_CRT_SUPPORT)
+		return ATOM_DEVICE_CRT1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_DFP_SUPPORT)
+		return ATOM_DEVICE_DFP1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_LCD_SUPPORT)
+		return ATOM_DEVICE_LCD1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_TV_SUPPORT)
+		return ATOM_DEVICE_TV1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_CV_SUPPORT)
+		return ATOM_DEVICE_CV_SUPPORT;
+
+	/* No group found for this device ID. */
+
+	dm_error("%s: incorrect input %d\n", __func__, dev_id);
+	/* No matching support flag for given device ID */
+	return 0;
+}
+
+/*
+ * Gets the next device ID in the group for a given device ID.
+ *
+ * The current device ID being enumerated on.
+ *
+ * The next device ID in the group, or 0 if no device exists.
+ */
+static uint32_t enum_next_dev_id(uint32_t dev_id)
+{
+	/* Get next device ID in the group. */
+	switch (dev_id) {
+	case ATOM_DEVICE_CRT1_SUPPORT:
+		return ATOM_DEVICE_CRT2_SUPPORT;
+	case ATOM_DEVICE_LCD1_SUPPORT:
+		return ATOM_DEVICE_LCD2_SUPPORT;
+	case ATOM_DEVICE_DFP1_SUPPORT:
+		return ATOM_DEVICE_DFP2_SUPPORT;
+	case ATOM_DEVICE_DFP2_SUPPORT:
+		return ATOM_DEVICE_DFP3_SUPPORT;
+	case ATOM_DEVICE_DFP3_SUPPORT:
+		return ATOM_DEVICE_DFP4_SUPPORT;
+	case ATOM_DEVICE_DFP4_SUPPORT:
+		return ATOM_DEVICE_DFP5_SUPPORT;
+	case ATOM_DEVICE_DFP5_SUPPORT:
+		return ATOM_DEVICE_DFP6_SUPPORT;
+	}
+
+	/* Done enumerating through devices. */
+	return 0;
+}
+
+/*
+ * Returns the new device tag record for patched BIOS object.
+ *
+ * [IN] pExtDisplayPath - External display path to copy device tag from.
+ * [IN] deviceSupport - Bit vector for device ID support flags.
+ * [OUT] pDeviceTag - Device tag structure to fill with patched data.
+ *
+ * True if a compatible device ID was found, false otherwise.
+ */
+static bool get_patched_device_tag(
+	struct bios_parser *bp,
+	EXT_DISPLAY_PATH *ext_display_path,
+	uint32_t device_support,
+	ATOM_CONNECTOR_DEVICE_TAG *device_tag)
+{
+	uint32_t dev_id;
+	/* Use fallback behaviour if not supported. */
+	if (!bp->remap_device_tags) {
+		device_tag->ulACPIDeviceEnum =
+				cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
+		device_tag->usDeviceID =
+				cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceTag));
+		return true;
+	}
+
+	/* Find the first unused in the same group. */
+	dev_id = enum_first_device_id(le16_to_cpu(ext_display_path->usDeviceTag));
+	while (dev_id != 0) {
+		/* Assign this device ID if supported. */
+		if ((device_support & dev_id) != 0) {
+			device_tag->ulACPIDeviceEnum =
+					cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
+			device_tag->usDeviceID = cpu_to_le16((USHORT) dev_id);
+			return true;
+		}
+
+		dev_id = enum_next_dev_id(dev_id);
+	}
+
+	/* No compatible device ID found. */
+	return false;
+}
+
+/*
+ * Adds a device tag to a BIOS object's device tag record if there is
+ * matching device ID supported.
+ *
+ * pObject - Pointer to the BIOS object to add the device tag to.
+ * pExtDisplayPath - Display path to retrieve base device ID from.
+ * pDeviceSupport - Pointer to bit vector for supported device IDs.
+ */
+static void add_device_tag_from_ext_display_path(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object,
+	EXT_DISPLAY_PATH *ext_display_path,
+	uint32_t *device_support)
+{
+	/* Get device tag record for object. */
+	ATOM_CONNECTOR_DEVICE_TAG *device_tag = NULL;
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD *device_tag_record = NULL;
+	enum bp_result result =
+			bios_parser_get_device_tag_record(
+					bp, object, &device_tag_record);
+
+	if ((le16_to_cpu(ext_display_path->usDeviceTag) != CONNECTOR_OBJECT_ID_NONE)
+			&& (result == BP_RESULT_OK)) {
+		uint8_t index;
+
+		if ((device_tag_record->ucNumberOfDevice == 1) &&
+				(le16_to_cpu(device_tag_record->asDeviceTag[0].usDeviceID) == 0)) {
+			/*Workaround bug in current VBIOS releases where
+			 * ucNumberOfDevice = 1 but there is no actual device
+			 * tag data. This w/a is temporary until the updated
+			 * VBIOS is distributed. */
+			device_tag_record->ucNumberOfDevice =
+					device_tag_record->ucNumberOfDevice - 1;
+		}
+
+		/* Attempt to find a matching device ID. */
+		index = device_tag_record->ucNumberOfDevice;
+		device_tag = &device_tag_record->asDeviceTag[index];
+		if (get_patched_device_tag(
+				bp,
+				ext_display_path,
+				*device_support,
+				device_tag)) {
+			/* Update cached device support to remove assigned ID.
+			 */
+			*device_support &= ~le16_to_cpu(device_tag->usDeviceID);
+			device_tag_record->ucNumberOfDevice++;
+		}
+	}
+}
+
+/*
+ * Read out a single EXT_DISPLAY_PATH from the external display connection info
+ * table. The specific entry in the table is determined by the enum_id passed
+ * in.
+ *
+ * EXT_DISPLAY_PATH describing a single Configuration table entry
+ */
+
+#define INVALID_CONNECTOR 0xffff
+
+static EXT_DISPLAY_PATH *get_ext_display_path_entry(
+	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *config_table,
+	uint32_t bios_object_id)
+{
+	EXT_DISPLAY_PATH *ext_display_path;
+	uint32_t ext_display_path_index =
+			((bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT) - 1;
+
+	if (ext_display_path_index >= MAX_NUMBER_OF_EXT_DISPLAY_PATH)
+		return NULL;
+
+	ext_display_path = &config_table->sPath[ext_display_path_index];
+
+	if (le16_to_cpu(ext_display_path->usDeviceConnector) == INVALID_CONNECTOR)
+		ext_display_path->usDeviceConnector = cpu_to_le16(0);
+
+	return ext_display_path;
+}
+
+/*
+ * Get AUX/DDC information of input object id
+ *
+ * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
+ * IR
+ */
+static ATOM_CONNECTOR_AUXDDC_LUT_RECORD *get_ext_connector_aux_ddc_lut_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	ATOM_COMMON_RECORD_HEADER *header;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER();
+		/* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+					+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				0 == header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE ==
+				header->ucRecordType &&
+				sizeof(ATOM_CONNECTOR_AUXDDC_LUT_RECORD) <=
+				header->ucRecordSize)
+			return (ATOM_CONNECTOR_AUXDDC_LUT_RECORD *)(header);
+
+		offset += header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+/*
+ * Get AUX/DDC information of input object id
+ *
+ * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
+ * IR
+ */
+static ATOM_CONNECTOR_HPDPIN_LUT_RECORD *get_ext_connector_hpd_pin_lut_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	ATOM_COMMON_RECORD_HEADER *header;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER();
+		/* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+					+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				0 == header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE ==
+				header->ucRecordType &&
+				sizeof(ATOM_CONNECTOR_HPDPIN_LUT_RECORD) <=
+				header->ucRecordSize)
+			return (ATOM_CONNECTOR_HPDPIN_LUT_RECORD *)header;
+
+		offset += header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+/*
+ * Check whether we need to patch the VBIOS connector info table with
+ * data from an external display connection info table.  This is
+ * necessary to support MXM boards with an OPM (output personality
+ * module).  With these designs, the VBIOS connector info table
+ * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
+ * the external connection info table through i2c and then looks up the
+ * connector ID to find the real connector type (e.g. DFP1).
+ *
+ */
+static enum bp_result patch_bios_image_from_ext_display_connection_info(
+	struct bios_parser *bp)
+{
+	ATOM_OBJECT_TABLE *connector_tbl;
+	uint32_t connector_tbl_offset;
+	struct graphics_object_id object_id;
+	ATOM_OBJECT *object;
+	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ext_display_connection_info_tbl;
+	EXT_DISPLAY_PATH *ext_display_path;
+	ATOM_CONNECTOR_AUXDDC_LUT_RECORD *aux_ddc_lut_record = NULL;
+	ATOM_I2C_RECORD *i2c_record = NULL;
+	ATOM_CONNECTOR_HPDPIN_LUT_RECORD *hpd_pin_lut_record = NULL;
+	ATOM_HPD_INT_RECORD *hpd_record = NULL;
+	ATOM_OBJECT_TABLE *encoder_table;
+	uint32_t encoder_table_offset;
+	ATOM_OBJECT *opm_object = NULL;
+	uint32_t i = 0;
+	struct graphics_object_id opm_object_id =
+			dal_graphics_object_id_init(
+					GENERIC_ID_MXM_OPM,
+					ENUM_ID_1,
+					OBJECT_TYPE_GENERIC);
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD *dev_tag_record;
+	uint32_t cached_device_support =
+			le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport);
+
+	uint32_t dst_number;
+	uint16_t *dst_object_id_list;
+
+	opm_object = get_bios_object(bp, opm_object_id);
+	if (!opm_object)
+		return BP_RESULT_UNSUPPORTED;
+
+	dm_memset(&ext_display_connection_info_tbl, 0,
+			sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO));
+
+	connector_tbl_offset = bp->object_info_tbl_offset
+			+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+	connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
+
+	/* Read Connector info table from EEPROM through i2c */
+	if (get_ext_display_connection_info(
+			bp,
+			opm_object,
+			&ext_display_connection_info_tbl) != BP_RESULT_OK) {
+		if (bp->headless_no_opm) {
+			/* Failed to read OPM, remove all non-CF connectors. */
+			for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) {
+				object = &connector_tbl->asObjects[i];
+				object_id = object_id_from_bios_object_id(
+						le16_to_cpu(object->usObjectID));
+				if (OBJECT_TYPE_CONNECTOR == object_id.type)
+					object->usObjectID = cpu_to_le16(0);
+			}
+
+			return BP_RESULT_OK;
+		}
+
+		dal_logger_write(bp->ctx->logger,
+				LOG_MAJOR_BIOS,
+				LOG_MINOR_BIOS_CMD_TABLE,
+				"%s: Failed to read Connection Info Table", __func__);
+		return BP_RESULT_UNSUPPORTED;
+	}
+
+	/* Get pointer to AUX/DDC and HPD LUTs */
+	aux_ddc_lut_record =
+			get_ext_connector_aux_ddc_lut_record(bp, opm_object);
+	hpd_pin_lut_record =
+			get_ext_connector_hpd_pin_lut_record(bp, opm_object);
+
+	if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL))
+		return BP_RESULT_UNSUPPORTED;
+
+	/* Cache support bits for currently unmapped device types. */
+	if (bp->remap_device_tags) {
+		for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) {
+			uint32_t j;
+			/* Remove support for all non-MXM connectors. */
+			object = &connector_tbl->asObjects[i];
+			object_id = object_id_from_bios_object_id(
+					le16_to_cpu(object->usObjectID));
+			if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
+					(CONNECTOR_ID_MXM == object_id.id))
+				continue;
+
+			/* Remove support for all device tags. */
+			if (bios_parser_get_device_tag_record(
+					bp, object, &dev_tag_record) != BP_RESULT_OK)
+				continue;
+
+			for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) {
+				ATOM_CONNECTOR_DEVICE_TAG *device_tag =
+						&dev_tag_record->asDeviceTag[j];
+				cached_device_support &=
+						~le16_to_cpu(device_tag->usDeviceID);
+			}
+		}
+	}
+
+	/* Find all MXM connector objects and patch them with connector info
+	 * from the external display connection info table. */
+	for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
+		uint32_t j;
+
+		object = &connector_tbl->asObjects[i];
+		object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
+		if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
+				(CONNECTOR_ID_MXM != object_id.id))
+			continue;
+
+		/* Get the correct connection info table entry based on the enum
+		 * id. */
+		ext_display_path = get_ext_display_path_entry(
+				&ext_display_connection_info_tbl,
+				le16_to_cpu(object->usObjectID));
+		if (!ext_display_path)
+			return BP_RESULT_FAILURE;
+
+		/* Patch device connector ID */
+		object->usObjectID =
+				cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector));
+
+		/* Patch device tag, ulACPIDeviceEnum. */
+		add_device_tag_from_ext_display_path(
+				bp,
+				object,
+				ext_display_path,
+				&cached_device_support);
+
+		/* Patch HPD info */
+		if (ext_display_path->ucExtHPDPINLutIndex <
+				MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) {
+			hpd_record = get_hpd_record(bp, object);
+			if (hpd_record) {
+				uint8_t index =
+						ext_display_path->ucExtHPDPINLutIndex;
+				hpd_record->ucHPDIntGPIOID =
+						hpd_pin_lut_record->ucHPDPINMap[index];
+			} else {
+				BREAK_TO_DEBUGGER();
+				/* Invalid hpd record */
+				return BP_RESULT_FAILURE;
+			}
+		}
+
+		/* Patch I2C/AUX info */
+		if (ext_display_path->ucExtHPDPINLutIndex <
+				MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) {
+			i2c_record = get_i2c_record(bp, object);
+			if (i2c_record) {
+				uint8_t index =
+						ext_display_path->ucExtAUXDDCLutIndex;
+				i2c_record->sucI2cId =
+						aux_ddc_lut_record->ucAUXDDCMap[index];
+			} else {
+				BREAK_TO_DEBUGGER();
+				/* Invalid I2C record */
+				return BP_RESULT_FAILURE;
+			}
+		}
+
+		/* Merge with other MXM connectors that map to the same physical
+		 * connector. */
+		for (j = i + 1;
+				j < connector_tbl->ucNumberOfObjects; j++) {
+			ATOM_OBJECT *next_object;
+			struct graphics_object_id next_object_id;
+			EXT_DISPLAY_PATH *next_ext_display_path;
+
+			next_object = &connector_tbl->asObjects[j];
+			next_object_id = object_id_from_bios_object_id(
+					le16_to_cpu(next_object->usObjectID));
+
+			if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) &&
+					(CONNECTOR_ID_MXM == next_object_id.id))
+				continue;
+
+			next_ext_display_path = get_ext_display_path_entry(
+					&ext_display_connection_info_tbl,
+					le16_to_cpu(next_object->usObjectID));
+
+			if (next_ext_display_path == NULL)
+				return BP_RESULT_FAILURE;
+
+			/* Merge if using same connector. */
+			if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) ==
+					le16_to_cpu(ext_display_path->usDeviceConnector)) &&
+					(le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) {
+				/* Clear duplicate connector from table. */
+				next_object->usObjectID = cpu_to_le16(0);
+				add_device_tag_from_ext_display_path(
+						bp,
+						object,
+						ext_display_path,
+						&cached_device_support);
+			}
+		}
+	}
+
+	/* Find all encoders which have an MXM object as their destination.
+	 *  Replace the MXM object with the real connector Id from the external
+	 *  display connection info table */
+
+	encoder_table_offset = bp->object_info_tbl_offset
+			+ le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
+	encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
+
+	for (i = 0; i < encoder_table->ucNumberOfObjects; i++) {
+		uint32_t j;
+
+		object = &encoder_table->asObjects[i];
+
+		dst_number = get_dest_obj_list(bp, object, &dst_object_id_list);
+
+		for (j = 0; j < dst_number; j++) {
+			object_id = object_id_from_bios_object_id(
+					dst_object_id_list[j]);
+
+			if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
+					(CONNECTOR_ID_MXM != object_id.id))
+				continue;
+
+			/* Get the correct connection info table entry based on
+			 * the enum id. */
+			ext_display_path =
+					get_ext_display_path_entry(
+							&ext_display_connection_info_tbl,
+							dst_object_id_list[j]);
+
+			if (ext_display_path == NULL)
+				return BP_RESULT_FAILURE;
+
+			dst_object_id_list[j] =
+					le16_to_cpu(ext_display_path->usDeviceConnector);
+		}
+	}
+
+	return BP_RESULT_OK;
+}
+
+/*
+ * Check whether we need to patch the VBIOS connector info table with
+ * data from an external display connection info table.  This is
+ * necessary to support MXM boards with an OPM (output personality
+ * module).  With these designs, the VBIOS connector info table
+ * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
+ * the external connection info table through i2c and then looks up the
+ * connector ID to find the real connector type (e.g. DFP1).
+ *
+ */
+
+static void process_ext_display_connection_info(struct bios_parser *bp)
+{
+	ATOM_OBJECT_TABLE *connector_tbl;
+	uint32_t connector_tbl_offset;
+	struct graphics_object_id object_id;
+	ATOM_OBJECT *object;
+	bool mxm_connector_found = false;
+	bool null_entry_found = false;
+	uint32_t i = 0;
+
+	connector_tbl_offset = bp->object_info_tbl_offset +
+			le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+	connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
+
+	/* Look for MXM connectors to determine whether we need patch the VBIOS
+	 * connector info table. Look for null entries to determine whether we
+	 * need to compact connector table. */
+	for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
+		object = &connector_tbl->asObjects[i];
+		object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
+
+		if ((OBJECT_TYPE_CONNECTOR == object_id.type) &&
+				(CONNECTOR_ID_MXM == object_id.id)) {
+			/* Once we found MXM connector - we can break */
+			mxm_connector_found = true;
+			break;
+		} else if (OBJECT_TYPE_CONNECTOR != object_id.type) {
+			/* We need to continue looping - to check if MXM
+			 * connector present */
+			null_entry_found = true;
+		}
+	}
+
+	/* Patch BIOS image */
+	if (mxm_connector_found || null_entry_found) {
+		uint32_t connectors_num = 0;
+		uint8_t *original_bios;
+		/* Step 1: Replace bios image with the new copy which will be
+		 * patched */
+		bp->bios_local_image = dm_alloc(bp->ctx, bp->bios_size);
+		if (bp->bios_local_image == NULL) {
+			BREAK_TO_DEBUGGER();
+			/* Failed to alloc bp->bios_local_image */
+			return;
+		}
+
+		dm_memmove(bp->bios_local_image, bp->bios, bp->bios_size);
+		original_bios = bp->bios;
+		bp->bios = bp->bios_local_image;
+		connector_tbl =
+				GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
+
+		/* Step 2: (only if MXM connector found) Patch BIOS image with
+		 * info from external module */
+		if (mxm_connector_found &&
+				patch_bios_image_from_ext_display_connection_info(bp) !=
+						BP_RESULT_OK) {
+			/* Patching the bios image has failed. We will copy
+			 * again original image provided and afterwards
+			 * only remove null entries */
+			dm_memmove(
+					bp->bios_local_image,
+					original_bios,
+					bp->bios_size);
+		}
+
+		/* Step 3: Compact connector table (remove null entries, valid
+		 * entries moved to beginning) */
+		for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
+			object = &connector_tbl->asObjects[i];
+			object_id = object_id_from_bios_object_id(
+					le16_to_cpu(object->usObjectID));
+
+			if (OBJECT_TYPE_CONNECTOR != object_id.type)
+				continue;
+
+			if (i != connectors_num) {
+				dm_memmove(
+						&connector_tbl->
+						asObjects[connectors_num],
+						object,
+						sizeof(ATOM_OBJECT));
+			}
+			++connectors_num;
+		}
+		connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num;
+	}
+}
+
+static void bios_parser_post_init(struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	process_ext_display_connection_info(bp);
+}
+
+static bool bios_parser_is_accelerated_mode(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	return bp->bios_helper->is_accelerated_mode(
+			bp->ctx);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+	return false;
+#endif
+}
+
+/**
+ * bios_parser_set_scratch_connected
+ *
+ * @brief
+ *  update VBIOS scratch register about connected displays
+ *
+ * @param
+ *  bool - update scratch register or just prepare info to be updated
+ *  bool - connection state
+ *  const ConnectorDeviceTagInfo* - pointer to device type and enum ID
+ */
+static void bios_parser_set_scratch_connected(
+	struct dc_bios *dcb,
+	struct graphics_object_id connector_id,
+	bool connected,
+	const struct connector_device_tag_info *device_tag)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_connected(
+			bp->ctx,
+			connector_id, connected, device_tag);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+/**
+ * bios_parser_set_scratch_critical_state
+ *
+ * @brief
+ *  update critical state bit in VBIOS scratch register
+ *
+ * @param
+ *  bool - to set or reset state
+ */
+static void bios_parser_set_scratch_critical_state(
+	struct dc_bios *dcb,
+	bool state)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_critical_state(
+			bp->ctx, state);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+static void bios_parser_set_scratch_acc_mode_change(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_acc_mode_change(
+			bp->ctx);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+/**
+ * bios_parser_prepare_scratch_active_and_requested
+ *
+ * @brief
+ *  update VBIOS scratch registers about active and requested displays
+ *
+ * @param
+ *  enum controller_id - controller Id
+ *  enum signal_type signal - signal type used on display
+ *  const struct connector_device_tag_info * - pointer to display type and
+ *  enum Id
+ */
+static void bios_parser_prepare_scratch_active_and_requested(
+	struct dc_bios *dcb,
+	enum controller_id controller_id,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->prepare_scratch_active_and_requested(
+			bp->ctx,
+			&bp->vbios_helper_data,
+			controller_id,
+			signal,
+			device_tag);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+static void bios_parser_set_scratch_active_and_requested(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_active_and_requested(
+			bp->ctx,
+			&bp->vbios_helper_data);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+/*
+ * get_integrated_info_v8
+ *
+ * @brief
+ * Get V8 integrated BIOS information
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result get_integrated_info_v8(
+	struct bios_parser *bp,
+	struct integrated_info *info)
+{
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
+	uint32_t i;
+
+	info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
+			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
+
+	if (info_v8 != NULL) {
+		info->boot_up_engine_clock =
+				le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
+		info->dentist_vco_freq =
+				le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
+		info->boot_up_uma_clock =
+				le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
+
+		for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->disp_clk_voltage[i].max_supported_clk =
+					le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
+							ulMaximumSupportedCLK) * 10;
+			info->disp_clk_voltage[i].voltage_index =
+					le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
+		}
+
+		info->boot_up_req_display_vector =
+				le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
+		info->gpu_cap_info =
+				le32_to_cpu(info_v8->ulGPUCapInfo);
+
+		/*
+		 * system_config: Bit[0] = 0 : PCIE power gating disabled
+		 *                       = 1 : PCIE power gating enabled
+		 *                Bit[1] = 0 : DDR-PLL shut down disabled
+		 *                       = 1 : DDR-PLL shut down enabled
+		 *                Bit[2] = 0 : DDR-PLL power down disabled
+		 *                       = 1 : DDR-PLL power down enabled
+		 */
+		info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
+		info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
+		info->boot_up_nb_voltage =
+				le16_to_cpu(info_v8->usBootUpNBVoltage);
+		info->ext_disp_conn_info_offset =
+				le16_to_cpu(info_v8->usExtDispConnInfoOffset);
+		info->memory_type = info_v8->ucMemoryType;
+		info->ma_channel_number = info_v8->ucUMAChannelNumber;
+		info->gmc_restore_reset_time =
+				le32_to_cpu(info_v8->ulGMCRestoreResetTime);
+
+		info->minimum_n_clk =
+				le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
+		for (i = 1; i < 4; ++i)
+			info->minimum_n_clk =
+					info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
+							info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
+
+		info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
+		info->ddr_dll_power_up_time =
+				le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
+		info->ddr_pll_power_up_time =
+				le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
+		info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
+		info->lvds_ss_percentage =
+				le16_to_cpu(info_v8->usLvdsSSPercentage);
+		info->lvds_sspread_rate_in_10hz =
+				le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
+		info->hdmi_ss_percentage =
+				le16_to_cpu(info_v8->usHDMISSPercentage);
+		info->hdmi_sspread_rate_in_10hz =
+				le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
+		info->dvi_ss_percentage =
+				le16_to_cpu(info_v8->usDVISSPercentage);
+		info->dvi_sspread_rate_in_10_hz =
+				le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
+
+		info->max_lvds_pclk_freq_in_single_link =
+				le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
+		info->lvds_misc = info_v8->ucLvdsMisc;
+		info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
+				info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
+		info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
+				info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
+		info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
+				info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
+		info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
+				info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
+		info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
+				info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
+		info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
+				info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
+		info->lvds_off_to_on_delay_in_4ms =
+				info_v8->ucLVDSOffToOnDelay_in4Ms;
+		info->lvds_bit_depth_control_val =
+				le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
+
+		for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->avail_s_clk[i].supported_s_clk =
+					le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
+			info->avail_s_clk[i].voltage_index =
+					le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
+			info->avail_s_clk[i].voltage_id =
+					le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
+		}
+
+		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
+			info->ext_disp_conn_info.gu_id[i] =
+					info_v8->sExtDispConnInfo.ucGuid[i];
+		}
+
+		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
+			info->ext_disp_conn_info.path[i].device_connector_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
+
+			info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
+
+			info->ext_disp_conn_info.path[i].device_tag =
+					le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
+			info->ext_disp_conn_info.path[i].device_acpi_enum =
+					le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
+			info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
+					info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
+			info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
+					info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
+			info->ext_disp_conn_info.path[i].channel_mapping.raw =
+					info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
+		}
+		info->ext_disp_conn_info.checksum =
+				info_v8->sExtDispConnInfo.ucChecksum;
+
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*
+ * get_integrated_info_v8
+ *
+ * @brief
+ * Get V8 integrated BIOS information
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result get_integrated_info_v9(
+	struct bios_parser *bp,
+	struct integrated_info *info)
+{
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
+	uint32_t i;
+
+	info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
+			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
+
+	if (info_v9 != NULL) {
+		info->boot_up_engine_clock =
+				le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
+		info->dentist_vco_freq =
+				le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
+		info->boot_up_uma_clock =
+				le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
+
+		for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->disp_clk_voltage[i].max_supported_clk =
+					le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
+			info->disp_clk_voltage[i].voltage_index =
+					le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
+		}
+
+		info->boot_up_req_display_vector =
+				le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
+		info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
+
+		/*
+		 * system_config: Bit[0] = 0 : PCIE power gating disabled
+		 *                       = 1 : PCIE power gating enabled
+		 *                Bit[1] = 0 : DDR-PLL shut down disabled
+		 *                       = 1 : DDR-PLL shut down enabled
+		 *                Bit[2] = 0 : DDR-PLL power down disabled
+		 *                       = 1 : DDR-PLL power down enabled
+		 */
+		info->system_config = le32_to_cpu(info_v9->ulSystemConfig);
+		info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
+		info->boot_up_nb_voltage =
+				le16_to_cpu(info_v9->usBootUpNBVoltage);
+		info->ext_disp_conn_info_offset =
+				le16_to_cpu(info_v9->usExtDispConnInfoOffset);
+		info->memory_type = info_v9->ucMemoryType;
+		info->ma_channel_number = info_v9->ucUMAChannelNumber;
+		info->gmc_restore_reset_time =
+				le32_to_cpu(info_v9->ulGMCRestoreResetTime);
+
+		info->minimum_n_clk =
+				le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
+		for (i = 1; i < 4; ++i)
+			info->minimum_n_clk =
+					info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
+							info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
+
+		info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
+		info->ddr_dll_power_up_time =
+				le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
+		info->ddr_pll_power_up_time =
+				le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
+		info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
+		info->lvds_ss_percentage =
+				le16_to_cpu(info_v9->usLvdsSSPercentage);
+		info->lvds_sspread_rate_in_10hz =
+				le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
+		info->hdmi_ss_percentage =
+				le16_to_cpu(info_v9->usHDMISSPercentage);
+		info->hdmi_sspread_rate_in_10hz =
+				le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
+		info->dvi_ss_percentage =
+				le16_to_cpu(info_v9->usDVISSPercentage);
+		info->dvi_sspread_rate_in_10_hz =
+				le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
+
+		info->max_lvds_pclk_freq_in_single_link =
+				le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
+		info->lvds_misc = info_v9->ucLvdsMisc;
+		info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
+				info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
+		info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
+				info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
+		info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
+				info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
+		info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
+				info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
+		info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
+				info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
+		info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
+				info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
+		info->lvds_off_to_on_delay_in_4ms =
+				info_v9->ucLVDSOffToOnDelay_in4Ms;
+		info->lvds_bit_depth_control_val =
+				le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
+
+		for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->avail_s_clk[i].supported_s_clk =
+					le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
+			info->avail_s_clk[i].voltage_index =
+					le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
+			info->avail_s_clk[i].voltage_id =
+					le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
+		}
+
+		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
+			info->ext_disp_conn_info.gu_id[i] =
+					info_v9->sExtDispConnInfo.ucGuid[i];
+		}
+
+		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
+			info->ext_disp_conn_info.path[i].device_connector_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
+
+			info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
+
+			info->ext_disp_conn_info.path[i].device_tag =
+					le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
+			info->ext_disp_conn_info.path[i].device_acpi_enum =
+					le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
+			info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
+					info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
+			info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
+					info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
+			info->ext_disp_conn_info.path[i].channel_mapping.raw =
+					info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
+		}
+		info->ext_disp_conn_info.checksum =
+				info_v9->sExtDispConnInfo.ucChecksum;
+
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*
+ * construct_integrated_info
+ *
+ * @brief
+ * Get integrated BIOS information based on table revision
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result construct_integrated_info(
+	struct bios_parser *bp,
+	struct integrated_info *info)
+{
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision;
+
+	if (info != NULL &&
+			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
+		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+				bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
+
+		get_atom_data_table_revision(header, &revision);
+
+		/* Don't need to check major revision as they are all 1 */
+		switch (revision.minor) {
+		case 8:
+			result = get_integrated_info_v8(bp, info);
+			break;
+		case 9:
+			result = get_integrated_info_v9(bp, info);
+			break;
+		default:
+			return result;
+
+		}
+	}
+
+	/* Sort voltage table from low to high*/
+	if (result == BP_RESULT_OK) {
+		struct clock_voltage_caps temp = {0, 0};
+		uint32_t i;
+		uint32_t j;
+
+		for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+			for (j = i; j > 0; --j) {
+				if (
+						info->disp_clk_voltage[j].max_supported_clk <
+						info->disp_clk_voltage[j-1].max_supported_clk) {
+					/* swap j and j - 1*/
+					temp = info->disp_clk_voltage[j-1];
+					info->disp_clk_voltage[j-1] =
+							info->disp_clk_voltage[j];
+					info->disp_clk_voltage[j] = temp;
+				}
+			}
+		}
+
+	}
+
+	return result;
+}
+
+
+static struct integrated_info *bios_parser_create_integrated_info(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct integrated_info *info = NULL;
+
+	info = dm_alloc(bp->ctx, sizeof(struct integrated_info));
+
+	if (info == NULL) {
+		ASSERT_CRITICAL(0);
+		return NULL;
+	}
+
+	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
+		return info;
+
+	dm_free(bp->ctx, info);
+
+	return NULL;
+}
+
+static void bios_parser_destroy_integrated_info(
+	struct dc_bios *dcb,
+	struct integrated_info **info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (info == NULL) {
+		ASSERT_CRITICAL(0);
+		return;
+	}
+
+	if (*info != NULL) {
+		dm_free(bp->ctx, *info);
+		*info = NULL;
+	}
+}
+
+/******************************************************************************
+ * Stub-functions */
+static bool is_lid_open(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static bool is_lid_status_changed(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static bool is_display_config_changed(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static void set_scratch_lcd_scale(
+	struct dc_bios *bios,
+	enum lcd_scale scale)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static enum lcd_scale get_scratch_lcd_scale(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return LCD_SCALE_NONE;
+}
+
+static void get_bios_event_info(
+	struct dc_bios *bios,
+	struct bios_event_info *info)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static void update_requested_backlight_level(
+	struct dc_bios *bios,
+	uint32_t backlight_8bit)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static uint32_t get_requested_backlight_level(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return 0;
+}
+
+static void take_backlight_control(
+	struct dc_bios *bios,
+	bool cntl)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static bool is_active_display(
+	struct dc_bios *bios,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static enum controller_id get_embedded_display_controller_id(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return CONTROLLER_ID_UNDEFINED;
+}
+
+static uint32_t get_embedded_display_refresh_rate(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return 0;
+}
+
+/******************************************************************************/
+
+static const struct dc_vbios_funcs vbios_funcs = {
+	.get_connectors_number = bios_parser_get_connectors_number,
+
+	.power_down = bios_parser_power_down,
+
+	.power_up = bios_parser_power_up,
+
+	.get_encoders_number = bios_parser_get_encoders_number,
+
+	.get_oem_ddc_lines_number = bios_parser_get_oem_ddc_lines_number,
+
+	.get_encoder_id = bios_parser_get_encoder_id,
+
+	.get_connector_id = bios_parser_get_connector_id,
+
+	.get_src_number = bios_parser_get_src_number,
+
+	.get_dst_number = bios_parser_get_dst_number,
+
+	.get_gpio_record = bios_parser_get_gpio_record,
+
+	.get_src_obj = bios_parser_get_src_obj,
+
+	.get_dst_obj = bios_parser_get_dst_obj,
+
+	.get_i2c_info = bios_parser_get_i2c_info,
+
+	.get_oem_ddc_info = bios_parser_get_oem_ddc_info,
+
+	.get_voltage_ddc_info = bios_parser_get_voltage_ddc_info,
+
+	.get_thermal_ddc_info = bios_parser_get_thermal_ddc_info,
+
+	.get_hpd_info = bios_parser_get_hpd_info,
+
+	.get_device_tag = bios_parser_get_device_tag,
+
+	.get_firmware_info = bios_parser_get_firmware_info,
+
+	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
+
+	.get_ss_entry_number = bios_parser_get_ss_entry_number,
+
+	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
+
+	.enum_embedded_panel_patch_mode = bios_parser_enum_embedded_panel_patch_mode,
+
+	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
+
+	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
+
+	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
+
+	.get_faked_edid_len = bios_parser_get_faked_edid_len,
+
+	.get_faked_edid_buf = bios_parser_get_faked_edid_buf,
+
+	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,
+
+	.get_din_connector_info = bios_parser_get_din_connector_info,
+
+	.is_lid_open = is_lid_open,
+
+	.is_lid_status_changed = is_lid_status_changed,
+
+	.is_display_config_changed = is_display_config_changed,
+
+	.is_accelerated_mode = bios_parser_is_accelerated_mode,
+
+	.set_scratch_lcd_scale = set_scratch_lcd_scale,
+
+	.get_scratch_lcd_scale = get_scratch_lcd_scale,
+
+	.get_bios_event_info = get_bios_event_info,
+
+	.update_requested_backlight_level = update_requested_backlight_level,
+
+	.get_requested_backlight_level = get_requested_backlight_level,
+
+	.take_backlight_control = take_backlight_control,
+
+	.is_active_display = is_active_display,
+
+	.get_embedded_display_controller_id = get_embedded_display_controller_id,
+
+	.get_embedded_display_refresh_rate = get_embedded_display_refresh_rate,
+
+	.set_scratch_connected = bios_parser_set_scratch_connected,
+
+	.prepare_scratch_active_and_requested = bios_parser_prepare_scratch_active_and_requested,
+
+	.set_scratch_active_and_requested = bios_parser_set_scratch_active_and_requested,
+
+	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
+
+	.set_scratch_acc_mode_change = bios_parser_set_scratch_acc_mode_change,
+
+	.is_device_id_supported = bios_parser_is_device_id_supported,
+
+	/* COMMANDS */
+	.encoder_control = bios_parser_encoder_control,
+
+	.transmitter_control = bios_parser_transmitter_control,
+
+	.crt_control = bios_parser_crt_control,
+
+	.enable_crtc = bios_parser_enable_crtc,
+
+	.adjust_pixel_clock = bios_parser_adjust_pixel_clock,
+
+	.set_pixel_clock = bios_parser_set_pixel_clock,
+
+	.set_dce_clock = bios_parser_set_dce_clock,
+
+	.enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,
+
+	.program_crtc_timing = bios_parser_program_crtc_timing,
+
+	.blank_crtc = bios_parser_blank_crtc,
+
+	.set_overscan = bios_parser_set_overscan,
+
+	.crtc_source_select = bios_parser_crtc_source_select,
+
+	.program_display_engine_pll = bios_parser_program_display_engine_pll,
+
+	.get_divider_for_target_display_clock = bios_parser_get_divider_for_target_display_clock,
+
+	.dac_load_detect = bios_parser_dac_load_detect,
+
+	.enable_memory_requests = bios_parser_enable_memory_requests,
+
+	.external_encoder_control = bios_parser_external_encoder_control,
+
+	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
+
+	.post_init = bios_parser_post_init,
+
+	.create_integrated_info = bios_parser_create_integrated_info,
+
+	.destroy_integrated_info = bios_parser_destroy_integrated_info,
+};
+
+static bool bios_parser_construct(
+	struct bios_parser *bp,
+	struct bp_init_data *init,
+	struct adapter_service *as)
+{
+	uint16_t *rom_header_offset = NULL;
+	ATOM_ROM_HEADER *rom_header = NULL;
+	ATOM_OBJECT_HEADER *object_info_tbl;
+	enum dce_version dce_version;
+
+	if (!as)
+		return false;
+
+	if (!init)
+		return false;
+
+	if (!init->bios)
+		return false;
+
+	bp->base.funcs = &vbios_funcs;
+
+	dce_version = dal_adapter_service_get_dce_version(as);
+	bp->ctx = init->ctx;
+	bp->as = as;
+	bp->bios = init->bios;
+	bp->bios_size = bp->bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
+	bp->bios_local_image = NULL;
+	bp->lcd_scale = LCD_SCALE_UNKNOWN;
+
+	rom_header_offset =
+	GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
+
+	if (!rom_header_offset)
+		return false;
+
+	rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);
+
+	if (!rom_header)
+		return false;
+
+	bp->master_data_tbl =
+	GET_IMAGE(ATOM_MASTER_DATA_TABLE,
+		rom_header->usMasterDataTableOffset);
+
+	if (!bp->master_data_tbl)
+		return false;
+
+	bp->object_info_tbl_offset = DATA_TABLES(Object_Header);
+
+	if (!bp->object_info_tbl_offset)
+		return false;
+
+	object_info_tbl =
+	GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);
+
+	if (!object_info_tbl)
+		return false;
+
+	get_atom_data_table_revision(&object_info_tbl->sHeader,
+		&bp->object_info_tbl.revision);
+
+	if (bp->object_info_tbl.revision.major == 1
+		&& bp->object_info_tbl.revision.minor >= 3) {
+		ATOM_OBJECT_HEADER_V3 *tbl_v3;
+
+		tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,
+			bp->object_info_tbl_offset);
+		if (!tbl_v3)
+			return false;
+
+		bp->object_info_tbl.v1_3 = tbl_v3;
+	} else if (bp->object_info_tbl.revision.major == 1
+		&& bp->object_info_tbl.revision.minor >= 1)
+		bp->object_info_tbl.v1_1 = object_info_tbl;
+	else
+		return false;
+
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	bp->vbios_helper_data.active = 0;
+	bp->vbios_helper_data.requested = 0;
+	dal_bios_parser_init_bios_helper(bp, dce_version);
+#endif
+	dal_bios_parser_init_cmd_tbl(bp);
+	dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
+
+	return true;
+}
+
+/******************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
new file mode 100644
index 000000000000..f8fa10889fd9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_H__
+#define __DAL_BIOS_PARSER_H__
+
+#include "dc_bios_types.h"
+#include "bios_parser_helper.h"
+
+struct atom_data_revision {
+	uint32_t major;
+	uint32_t minor;
+};
+
+struct object_info_table {
+	struct atom_data_revision revision;
+	union {
+		ATOM_OBJECT_HEADER *v1_1;
+		ATOM_OBJECT_HEADER_V3 *v1_3;
+	};
+};
+
+enum spread_spectrum_id {
+	SS_ID_UNKNOWN = 0,
+	SS_ID_DP1 = 0xf1,
+	SS_ID_DP2 = 0xf2,
+	SS_ID_LVLINK_2700MHZ = 0xf3,
+	SS_ID_LVLINK_1620MHZ = 0xf4
+};
+
+struct bios_parser {
+	struct dc_bios base;
+	struct dc_context *ctx;
+	struct adapter_service *as;
+
+	struct object_info_table object_info_tbl;
+	uint32_t object_info_tbl_offset;
+	ATOM_MASTER_DATA_TABLE *master_data_tbl;
+
+	uint8_t *bios;
+	uint32_t bios_size;
+
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	const struct bios_parser_helper *bios_helper;
+	struct vbios_helper_data vbios_helper_data;
+#endif /* CONFIG_DRM_AMD_DAL_VBIOS_PRESENT */
+
+	const struct command_table_helper *cmd_helper;
+	struct cmd_tbl cmd_tbl;
+
+	uint8_t *bios_local_image;
+	enum lcd_scale lcd_scale;
+
+	bool remap_device_tags;
+	bool headless_no_opm;
+};
+
+/* Bios Parser from DC Bios */
+#define BP_FROM_DCB(dc_bios) \
+	container_of(dc_bios, struct bios_parser, base)
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
new file mode 100644
index 000000000000..0aa227aa557a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "bios_parser_helper.h"
+#include "command_table_helper.h"
+#include "command_table.h"
+#include "bios_parser.h"
+
+bool dal_bios_parser_init_bios_helper(
+	struct bios_parser *bp,
+	enum dce_version version)
+{
+	switch (version) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		bp->bios_helper = dal_bios_parser_helper_dce110_get_table();
+		return true;
+
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		bp->bios_helper = dal_bios_parser_helper_dce110_get_table();
+		return true;
+
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+bool dal_bios_parser_is_lid_open(
+	struct bios_parser *bp)
+{
+	const struct graphics_object_id encoder = dal_graphics_object_id_init(
+		ENCODER_ID_INTERNAL_UNIPHY,
+		ENUM_ID_UNKNOWN,
+		OBJECT_TYPE_UNKNOWN);
+	const struct graphics_object_id connector = dal_graphics_object_id_init(
+		CONNECTOR_ID_LVDS,
+		ENUM_ID_UNKNOWN,
+		OBJECT_TYPE_UNKNOWN);
+
+	enum signal_type signal;
+
+	/* check if VBIOS reported LCD as connected */
+	signal = bp->bios_helper->detect_sink(bp->ctx,
+		encoder, connector, SIGNAL_TYPE_LVDS);
+
+	if (signal == SIGNAL_TYPE_NONE)
+		return false;
+
+	return bp->bios_helper->is_lid_open(bp->ctx);
+}
+
+bool dal_bios_parser_is_lid_status_changed(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->is_lid_status_changed(
+			bp->ctx);
+}
+
+bool dal_bios_parser_is_display_config_changed(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->is_display_config_changed(
+			bp->ctx);
+}
+
+/**
+* dal_bios_parser_set_scratch_lcd_scale
+*
+* @brief
+*  update VBIOS scratch pad registers about LCD scale
+*
+* @param
+*  bool - to set to full panel mode or aspect-ratio mode
+*/
+void dal_bios_parser_set_scratch_lcd_scale(
+	struct bios_parser *bp,
+	enum lcd_scale scale)
+{
+	bp->bios_helper->set_scratch_lcd_scale(
+		bp->ctx, scale);
+}
+
+/**
+* dal_bios_parser_get_scratch_lcd_scale
+*
+* @brief
+*  get LCD Scale Mode from VBIOS scratch register
+*
+* @param
+*  NONE
+*/
+enum lcd_scale  dal_bios_parser_get_scratch_lcd_scale(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_scratch_lcd_scale(
+			bp->ctx);
+}
+
+void dal_bios_parser_get_bios_event_info(
+	struct bios_parser *bp,
+	struct bios_event_info *info)
+{
+	bp->bios_helper->get_bios_event_info(
+		bp->ctx, info);
+}
+
+/* ABM related */
+
+void dal_bios_parser_update_requested_backlight_level(
+	struct bios_parser *bp,
+	uint32_t backlight_8bit)
+{
+	bp->bios_helper->update_requested_backlight_level(
+		bp->ctx,
+		backlight_8bit);
+}
+
+uint32_t dal_bios_parser_get_requested_backlight_level(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_requested_backlight_level(
+			bp->ctx);
+}
+
+void dal_bios_parser_take_backlight_control(
+	struct bios_parser *bp,
+	bool cntl)
+{
+	bp->bios_helper->take_backlight_control(
+		bp->ctx, cntl);
+}
+
+/**
+ * dal_bios_parser_is_active_display
+ *  Check video bios active display.
+ */
+bool dal_bios_parser_is_active_display(
+	struct bios_parser *bp,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag)
+{
+	return bp->bios_helper->is_active_display(
+			bp->ctx, signal, device_tag);
+}
+
+/**
+ * dal_bios_parser_get_embedded_display_controller_id
+ * Get controller ID for embedded display from scratch registers
+ */
+enum controller_id dal_bios_parser_get_embedded_display_controller_id(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_embedded_display_controller_id(
+			bp->ctx);
+}
+
+/**
+ * dal_bios_parser_get_embedded_display_refresh_rate
+ * Get refresh rate for embedded display from scratch registers
+ */
+uint32_t dal_bios_parser_get_embedded_display_refresh_rate(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_embedded_display_refresh_rate(
+			bp->ctx);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
new file mode 100644
index 000000000000..1ad745561d15
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_HELPER_H__
+#define __DAL_BIOS_PARSER_HELPER_H__
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce110/bios_parser_helper_dce110.h"
+#endif
+
+struct bios_parser;
+
+struct vbios_helper_data {
+	uint32_t active;
+	uint32_t requested;
+};
+
+struct bios_parser_helper {
+	enum signal_type (*detect_sink)(
+		struct dc_context *ctx,
+		struct graphics_object_id encoder,
+		struct graphics_object_id connector,
+		enum signal_type signal);
+	bool (*is_lid_open)(
+		struct dc_context *ctx);
+	bool (*is_lid_status_changed)(
+		struct dc_context *ctx);
+	bool (*is_display_config_changed)(
+		struct dc_context *ctx);
+	void (*set_scratch_acc_mode_change)(
+		struct dc_context *ctx);
+	bool (*is_accelerated_mode)(
+		struct dc_context *ctx);
+	void (*set_scratch_critical_state)(
+		struct dc_context *ctx,
+		bool state);
+	void (*prepare_scratch_active_and_requested)(
+		struct dc_context *ctx,
+		struct vbios_helper_data *data,
+		enum controller_id id, enum signal_type s,
+		const struct connector_device_tag_info *dev_tag);
+	void (*set_scratch_active_and_requested)(
+		struct dc_context *ctx,
+		struct vbios_helper_data *d);
+	void (*set_scratch_connected)(
+		struct dc_context *ctx,
+		struct graphics_object_id id,
+		bool connected,
+		const struct connector_device_tag_info *device_tag);
+	void (*set_scratch_lcd_scale)(
+		struct dc_context *ctx,
+		enum lcd_scale lcd_scale_request);
+	enum lcd_scale (*get_scratch_lcd_scale)(
+		struct dc_context *ctx);
+	uint32_t (*fmt_control)(
+		struct dc_context *ctx,
+		enum controller_id id, uint32_t *value);
+	uint32_t (*fmt_bit_depth_control)(
+		struct dc_context *ctx,
+		enum controller_id id,
+		uint32_t *value);
+	void (*get_bios_event_info)(
+		struct dc_context *ctx,
+		struct bios_event_info *info);
+	void (*take_backlight_control)(
+		struct dc_context *ctx, bool control);
+	uint32_t (*get_requested_backlight_level)(
+		struct dc_context *ctx);
+	void (*update_requested_backlight_level)(
+		struct dc_context *ctx,
+		uint32_t backlight_8bit);
+	bool (*is_active_display)(
+		struct dc_context *ctx,
+		enum signal_type signal,
+		const struct connector_device_tag_info *dev_tag);
+	enum controller_id (*get_embedded_display_controller_id)(
+		struct dc_context *ctx);
+	uint32_t (*get_embedded_display_refresh_rate)(
+		struct dc_context *ctx);
+};
+
+bool dal_bios_parser_init_bios_helper(
+	struct bios_parser *bp,
+	enum dce_version ver);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c
new file mode 100644
index 000000000000..3bc52f5bab24
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c
@@ -0,0 +1,2730 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_interface.h"
+
+#include "command_table.h"
+#include "command_table_helper.h"
+#include "bios_parser_helper.h"
+#include "bios_parser.h"
+
+#define EXEC_BIOS_CMD_TABLE(command, params)\
+	(cgs_atom_exec_cmd_table(bp->ctx->cgs_device, \
+		GetIndexIntoMasterTable(COMMAND, command), \
+		&params) == 0)
+
+#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
+	cgs_atom_get_cmd_table_revs(bp->ctx->cgs_device, \
+		GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
+
+#define BIOS_CMD_TABLE_PARA_REVISION(command)\
+	dm_bios_cmd_table_para_revision(bp->ctx, \
+		GetIndexIntoMasterTable(COMMAND, command))
+
+
+static void init_dig_encoder_control(struct bios_parser *bp);
+static void init_transmitter_control(struct bios_parser *bp);
+static void init_set_pixel_clock(struct bios_parser *bp);
+static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);
+static void init_adjust_display_pll(struct bios_parser *bp);
+static void init_dac_encoder_control(struct bios_parser *bp);
+static void init_dac_output_control(struct bios_parser *bp);
+static void init_dac_load_detection(struct bios_parser *bp);
+static void init_blank_crtc(struct bios_parser *bp);
+static void init_set_crtc_timing(struct bios_parser *bp);
+static void init_set_crtc_overscan(struct bios_parser *bp);
+static void init_select_crtc_source(struct bios_parser *bp);
+static void init_enable_crtc(struct bios_parser *bp);
+static void init_enable_crtc_mem_req(struct bios_parser *bp);
+static void init_compute_memore_engine_pll(struct bios_parser *bp);
+static void init_external_encoder_control(struct bios_parser *bp);
+static void init_enable_disp_power_gating(struct bios_parser *bp);
+static void init_program_clock(struct bios_parser *bp);
+static void init_set_dce_clock(struct bios_parser *bp);
+
+void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
+{
+	init_dig_encoder_control(bp);
+	init_transmitter_control(bp);
+	init_set_pixel_clock(bp);
+	init_enable_spread_spectrum_on_ppll(bp);
+	init_adjust_display_pll(bp);
+	init_dac_encoder_control(bp);
+	init_dac_output_control(bp);
+	init_dac_load_detection(bp);
+	init_blank_crtc(bp);
+	init_set_crtc_timing(bp);
+	init_set_crtc_overscan(bp);
+	init_select_crtc_source(bp);
+	init_enable_crtc(bp);
+	init_enable_crtc_mem_req(bp);
+	init_program_clock(bp);
+	init_compute_memore_engine_pll(bp);
+	init_external_encoder_control(bp);
+	init_enable_disp_power_gating(bp);
+	init_set_dce_clock(bp);
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  D I G E N C O D E R C O N T R O L
+ **
+ ********************************************************************************
+ *******************************************************************************/
+static enum bp_result encoder_control_digx_v3(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+
+static enum bp_result encoder_control_digx_v4(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+static void init_encoder_control_dig_v1(struct bios_parser *bp);
+
+static void init_dig_encoder_control(struct bios_parser *bp)
+{
+	uint32_t version =
+		BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl);
+
+	switch (version) {
+	case 4:
+		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;
+		break;
+	case 2:
+		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;
+		break;
+	default:
+		init_encoder_control_dig_v1(bp);
+		break;
+	}
+}
+
+static enum bp_result encoder_control_dig_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+static enum bp_result encoder_control_dig1_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+static enum bp_result encoder_control_dig2_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+
+static void init_encoder_control_dig_v1(struct bios_parser *bp)
+{
+	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
+
+	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))
+		cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;
+	else
+		cmd_tbl->encoder_control_dig1 = NULL;
+
+	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))
+		cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;
+	else
+		cmd_tbl->encoder_control_dig2 = NULL;
+
+	cmd_tbl->dig_encoder_control = encoder_control_dig_v1;
+}
+
+static enum bp_result encoder_control_dig_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
+
+	if (cntl != NULL)
+		switch (cntl->engine_id) {
+		case ENGINE_ID_DIGA:
+			if (cmd_tbl->encoder_control_dig1 != NULL)
+				result =
+					cmd_tbl->encoder_control_dig1(bp, cntl);
+			break;
+		case ENGINE_ID_DIGB:
+			if (cmd_tbl->encoder_control_dig2 != NULL)
+				result =
+					cmd_tbl->encoder_control_dig2(bp, cntl);
+			break;
+
+		default:
+			break;
+		}
+
+	return result;
+}
+
+static enum bp_result encoder_control_dig1_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
+
+	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
+
+	if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result encoder_control_dig2_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
+
+	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
+
+	if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result encoder_control_digx_v3(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0};
+
+	if (LANE_COUNT_FOUR < cntl->lanes_number)
+		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
+	else
+		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
+
+	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
+	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+	params.ucEncoderMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					cntl->signal,
+					cntl->enable_dp_audio);
+	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+
+	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+
+	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result encoder_control_digx_v4(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};
+
+	if (LANE_COUNT_FOUR < cntl->lanes_number)
+		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
+	else
+		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
+
+
+	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
+	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+	params.ucEncoderMode =
+			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
+					cntl->signal,
+					cntl->enable_dp_audio));
+	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+
+	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+
+	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  TRANSMITTER CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result transmitter_control_v2(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v3(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v4(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v1_5(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v1_6(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+
+static void init_transmitter_control(struct bios_parser *bp)
+{
+	uint8_t frev;
+	uint8_t crev;
+
+	if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
+			frev, crev) != 0)
+		BREAK_TO_DEBUGGER();
+	switch (crev) {
+	case 2:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v3;
+		break;
+	case 4:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v4;
+		break;
+	case 5:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;
+		break;
+	case 6:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
+		break;
+	default:
+		bp->cmd_tbl.transmitter_control = NULL;
+		break;
+	}
+}
+
+static enum bp_result transmitter_control_v2(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;
+	enum connector_id connector_id =
+		dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (cntl->transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+	case TRANSMITTER_TRAVIS_LCD:
+		break;
+	default:
+		return BP_RESULT_BADINPUT;
+	}
+
+	switch (cntl->action) {
+	case TRANSMITTER_CONTROL_INIT:
+		if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||
+				(CONNECTOR_ID_DUAL_LINK_DVID == connector_id))
+			/* on INIT this bit should be set according to the
+			 * phisycal connector
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* connector object id */
+		params.usInitInfo =
+				cpu_to_le16((uint8_t)cntl->connector_obj_id.id);
+		break;
+	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
+		/* votage swing and pre-emphsis */
+		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
+		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
+		break;
+	default:
+		/* if dual-link */
+		if (LANE_COUNT_FOUR < cntl->lanes_number) {
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 20KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
+		} else
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 10KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+		break;
+	}
+
+	/* 00 - coherent mode
+	 * 01 - incoherent mode
+	 */
+
+	params.acConfig.fCoherentMode = cntl->coherent;
+
+	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
+			|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
+			|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
+		/* Bit2: Transmitter Link selection
+		 * =0 when bit0=0, single link A/C/E, when bit0=1,
+		 * master link A/C/E
+		 * =1 when bit0=0, single link B/D/F, when bit0=1,
+		 * master link B/D/F
+		 */
+		params.acConfig.ucLinkSel = 1;
+
+	if (ENGINE_ID_DIGB == cntl->engine_id)
+		/* Bit3: Transmitter data source selection
+		 * =0 DIGA is data source.
+		 * =1 DIGB is data source.
+		 * This bit is only useful when ucAction= ATOM_ENABLE
+		 */
+		params.acConfig.ucEncoderSel = 1;
+
+	if (CONNECTOR_ID_DISPLAY_PORT == connector_id)
+		/* Bit4: DP connector flag
+		 * =0 connector is none-DP connector
+		 * =1 connector is DP connector
+		 */
+		params.acConfig.fDPConnector = 1;
+
+	/* Bit[7:6]: Transmitter selection
+	 * =0 UNIPHY_ENCODER: UNIPHYA/B
+	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
+	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
+	 * =3 reserved
+	 */
+	params.acConfig.ucTransmitterSel =
+			(uint8_t)bp->cmd_helper->transmitter_bp_to_atom(
+					cntl->transmitter);
+
+	params.ucAction = (uint8_t)cntl->action;
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v3(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;
+	uint32_t pll_id;
+	enum connector_id conn_id =
+			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
+	const struct command_table_helper *cmd = bp->cmd_helper;
+	bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id)
+					|| (CONNECTOR_ID_DUAL_LINK_DVID == conn_id);
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (cntl->transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+	case TRANSMITTER_TRAVIS_LCD:
+		break;
+	default:
+		return BP_RESULT_BADINPUT;
+	}
+
+	if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))
+		return BP_RESULT_BADINPUT;
+
+	/* fill information based on the action */
+	switch (cntl->action) {
+	case TRANSMITTER_CONTROL_INIT:
+		if (dual_link_conn) {
+			/* on INIT this bit should be set according to the
+			 * phisycal connector
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+		}
+
+		/* connector object id */
+		params.usInitInfo =
+				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
+		break;
+	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
+		/* votage swing and pre-emphsis */
+		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
+		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
+		break;
+	default:
+		if (dual_link_conn && cntl->multi_path)
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* if dual-link */
+		if (LANE_COUNT_FOUR < cntl->lanes_number) {
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 20KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
+		} else {
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 10KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+			if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+				switch (cntl->color_depth) {
+				case COLOR_DEPTH_101010:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 30) / 24);
+					break;
+				case COLOR_DEPTH_121212:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 36) / 24);
+					break;
+				case COLOR_DEPTH_161616:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 48) / 24);
+					break;
+				default:
+					break;
+				}
+		}
+		break;
+	}
+
+	/* 00 - coherent mode
+	 * 01 - incoherent mode
+	 */
+
+	params.acConfig.fCoherentMode = cntl->coherent;
+
+	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
+		/* Bit2: Transmitter Link selection
+		 * =0 when bit0=0, single link A/C/E, when bit0=1,
+		 * master link A/C/E
+		 * =1 when bit0=0, single link B/D/F, when bit0=1,
+		 * master link B/D/F
+		 */
+		params.acConfig.ucLinkSel = 1;
+
+	if (ENGINE_ID_DIGB == cntl->engine_id)
+		/* Bit3: Transmitter data source selection
+		 * =0 DIGA is data source.
+		 * =1 DIGB is data source.
+		 * This bit is only useful when ucAction= ATOM_ENABLE
+		 */
+		params.acConfig.ucEncoderSel = 1;
+
+	/* Bit[7:6]: Transmitter selection
+	 * =0 UNIPHY_ENCODER: UNIPHYA/B
+	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
+	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
+	 * =3 reserved
+	 */
+	params.acConfig.ucTransmitterSel =
+			(uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);
+
+	params.ucLaneNum = (uint8_t)cntl->lanes_number;
+
+	params.acConfig.ucRefClkSource = (uint8_t)pll_id;
+
+	params.ucAction = (uint8_t)cntl->action;
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v4(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params;
+	uint32_t ref_clk_src_id;
+	enum connector_id conn_id =
+			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
+	const struct command_table_helper *cmd = bp->cmd_helper;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (cntl->transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+	case TRANSMITTER_TRAVIS_LCD:
+		break;
+	default:
+		return BP_RESULT_BADINPUT;
+	}
+
+	if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))
+		return BP_RESULT_BADINPUT;
+
+	switch (cntl->action) {
+	case TRANSMITTER_CONTROL_INIT:
+	{
+		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
+				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
+			/* on INIT this bit should be set according to the
+			 * phisycal connector
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* connector object id */
+		params.usInitInfo =
+				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
+	}
+	break;
+	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
+		/* votage swing and pre-emphsis */
+		params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select);
+		params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings);
+		break;
+	default:
+		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
+				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* if dual-link */
+		if (LANE_COUNT_FOUR < cntl->lanes_number)
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 20KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
+		else {
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 10KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+
+			if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+				switch (cntl->color_depth) {
+				case COLOR_DEPTH_101010:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 30) / 24);
+					break;
+				case COLOR_DEPTH_121212:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 36) / 24);
+					break;
+				case COLOR_DEPTH_161616:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 48) / 24);
+					break;
+				default:
+					break;
+				}
+		}
+		break;
+	}
+
+	/* 00 - coherent mode
+	 * 01 - incoherent mode
+	 */
+
+	params.acConfig.fCoherentMode = cntl->coherent;
+
+	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
+		/* Bit2: Transmitter Link selection
+		 * =0 when bit0=0, single link A/C/E, when bit0=1,
+		 * master link A/C/E
+		 * =1 when bit0=0, single link B/D/F, when bit0=1,
+		 * master link B/D/F
+		 */
+		params.acConfig.ucLinkSel = 1;
+
+	if (ENGINE_ID_DIGB == cntl->engine_id)
+		/* Bit3: Transmitter data source selection
+		 * =0 DIGA is data source.
+		 * =1 DIGB is data source.
+		 * This bit is only useful when ucAction= ATOM_ENABLE
+		 */
+		params.acConfig.ucEncoderSel = 1;
+
+	/* Bit[7:6]: Transmitter selection
+	 * =0 UNIPHY_ENCODER: UNIPHYA/B
+	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
+	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
+	 * =3 reserved
+	 */
+	params.acConfig.ucTransmitterSel =
+		(uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter));
+	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+	params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id);
+	params.ucAction = (uint8_t)(cntl->action);
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v1_5(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	const struct command_table_helper *cmd = bp->cmd_helper;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params;
+
+	dm_memset(&params, 0, sizeof(params));
+	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
+	params.ucAction = (uint8_t)cntl->action;
+	params.ucLaneNum = (uint8_t)cntl->lanes_number;
+	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
+
+	params.ucDigMode =
+		cmd->signal_type_to_atom_dig_mode(cntl->signal);
+	params.asConfig.ucPhyClkSrcId =
+		cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id);
+	/* 00 - coherent mode */
+	params.asConfig.ucCoherentMode = cntl->coherent;
+	params.asConfig.ucHPDSel =
+		cmd->hpd_sel_to_atom(cntl->hpd_sel);
+	params.ucDigEncoderSel =
+		cmd->dig_encoder_sel_to_atom(cntl->engine_id);
+	params.ucDPLaneSet = (uint8_t) cntl->lane_settings;
+	params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10));
+	/*
+	 * In SI/TN case, caller have to set usPixelClock as following:
+	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
+	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
+	 * DVI single link mode: usPixelClock = pixel clock
+	 * DVI dual link mode: usPixelClock = pixel clock
+	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
+	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
+	 * LVDS mode: usPixelClock = pixel clock
+	 */
+	switch (cntl->signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.usSymClock =
+				cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.usSymClock =
+				cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.usSymClock =
+				cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v1_6(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+	const struct command_table_helper *cmd = bp->cmd_helper;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
+
+	dm_memset(&params, 0, sizeof(params));
+	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
+	params.ucAction = (uint8_t)cntl->action;
+
+	if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
+		params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
+	else
+		params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
+
+	params.ucLaneNum = (uint8_t)cntl->lanes_number;
+	params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
+	params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
+	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
+	params.ulSymClock = cntl->pixel_clock/10;
+
+	/*
+	 * In SI/TN case, caller have to set usPixelClock as following:
+	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
+	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
+	 * DVI single link mode: usPixelClock = pixel clock
+	 * DVI dual link mode: usPixelClock = pixel clock
+	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
+	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
+	 * LVDS mode: usPixelClock = pixel clock
+	 */
+	switch (cntl->signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.ulSymClock =
+				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.ulSymClock =
+				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.ulSymClock =
+				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+#endif
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET PIXEL CLOCK
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result set_pixel_clock_v3(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result set_pixel_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result set_pixel_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result set_pixel_clock_v7(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+
+static void init_set_pixel_clock(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
+	case 3:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
+		break;
+	case 5:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
+		break;
+	case 6:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
+		break;
+	case 7:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
+		break;
+	default:
+		bp->cmd_tbl.set_pixel_clock = NULL;
+		break;
+	}
+}
+
+static enum bp_result set_pixel_clock_v3(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	PIXEL_CLOCK_PARAMETERS_V3 *params;
+	SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
+
+	dm_memset(&allocation, 0, sizeof(allocation));
+
+	if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
+		allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
+	else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
+		allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
+	else
+		return BP_RESULT_BADINPUT;
+
+	allocation.sPCLKInput.usRefDiv =
+			cpu_to_le16((uint16_t)bp_params->reference_divider);
+	allocation.sPCLKInput.usFbDiv =
+			cpu_to_le16((uint16_t)bp_params->feedback_divider);
+	allocation.sPCLKInput.ucFracFbDiv =
+			(uint8_t)bp_params->fractional_feedback_divider;
+	allocation.sPCLKInput.ucPostDiv =
+			(uint8_t)bp_params->pixel_clock_post_divider;
+
+	/* We need to convert from KHz units into 10KHz units */
+	allocation.sPCLKInput.usPixelClock =
+			cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
+
+	params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
+	params->ucTransmitterId =
+			bp->cmd_helper->encoder_id_to_atom(
+					dal_graphics_object_id_get_encoder_id(
+							bp_params->encoder_object_id));
+	params->ucEncoderMode =
+			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
+					bp_params->signal_type, false));
+
+	if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+		params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
+
+	if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
+		params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
+
+	if (CONTROLLER_ID_D1 != bp_params->controller_id)
+		params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
+
+	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
+/* video bios did not define this: */
+typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
+	PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
+	/* Caller doesn't need to init this portion */
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
+} SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
+#endif
+
+#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
+/* video bios did not define this: */
+typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
+	PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
+	/* Caller doesn't need to init this portion */
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
+} SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
+#endif
+
+static enum bp_result set_pixel_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
+	uint8_t controller_id;
+	uint32_t pll_id;
+
+	dm_memset(&clk, 0, sizeof(clk));
+
+	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+			&& bp->cmd_helper->controller_id_to_atom(
+					bp_params->controller_id, &controller_id)) {
+		clk.sPCLKInput.ucCRTC = controller_id;
+		clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
+		clk.sPCLKInput.ucRefDiv =
+				(uint8_t)(bp_params->reference_divider);
+		clk.sPCLKInput.usFbDiv =
+				cpu_to_le16((uint16_t)(bp_params->feedback_divider));
+		clk.sPCLKInput.ulFbDivDecFrac =
+				cpu_to_le32(bp_params->fractional_feedback_divider);
+		clk.sPCLKInput.ucPostDiv =
+				(uint8_t)(bp_params->pixel_clock_post_divider);
+		clk.sPCLKInput.ucTransmitterID =
+				bp->cmd_helper->encoder_id_to_atom(
+						dal_graphics_object_id_get_encoder_id(
+								bp_params->encoder_object_id));
+		clk.sPCLKInput.ucEncoderMode =
+				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+						bp_params->signal_type, false);
+
+		/* We need to convert from KHz units into 10KHz units */
+		clk.sPCLKInput.usPixelClock =
+				cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
+
+		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
+
+		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_MISC_REF_DIV_SRC;
+
+		/* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
+		 * =1:30bpp, =2:32bpp
+		 * driver choose program it itself, i.e. here we program it
+		 * to 888 by default.
+		 */
+
+		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
+			result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+static enum bp_result set_pixel_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
+	uint8_t controller_id;
+	uint32_t pll_id;
+
+	dm_memset(&clk, 0, sizeof(clk));
+
+	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+			&& bp->cmd_helper->controller_id_to_atom(
+					bp_params->controller_id, &controller_id)) {
+		/* Note: VBIOS still wants to use ucCRTC name which is now
+		 * 1 byte in ULONG
+		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
+		 *{
+		 * target the pixel clock to drive the CRTC timing.
+		 * ULONG ulPixelClock:24;
+		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
+		 * previous version.
+		 * ATOM_CRTC1~6, indicate the CRTC controller to
+		 * ULONG ucCRTC:8;
+		 * drive the pixel clock. not used for DCPLL case.
+		 *}CRTC_PIXEL_CLOCK_FREQ;
+		 *union
+		 *{
+		 * pixel clock and CRTC id frequency
+		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
+		 * ULONG ulDispEngClkFreq; dispclk frequency
+		 *};
+		 */
+		clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
+		clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
+		clk.sPCLKInput.ucRefDiv =
+				(uint8_t) bp_params->reference_divider;
+		clk.sPCLKInput.usFbDiv =
+				cpu_to_le16((uint16_t) bp_params->feedback_divider);
+		clk.sPCLKInput.ulFbDivDecFrac =
+				cpu_to_le32(bp_params->fractional_feedback_divider);
+		clk.sPCLKInput.ucPostDiv =
+				(uint8_t) bp_params->pixel_clock_post_divider;
+		clk.sPCLKInput.ucTransmitterID =
+				bp->cmd_helper->encoder_id_to_atom(
+						dal_graphics_object_id_get_encoder_id(
+								bp_params->encoder_object_id));
+		clk.sPCLKInput.ucEncoderMode =
+				(uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
+						bp_params->signal_type, false);
+
+		/* We need to convert from KHz units into 10KHz units */
+		clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
+				cpu_to_le32(bp_params->target_pixel_clock / 10);
+
+		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
+		}
+
+		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
+		}
+
+		/* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
+		 * 24bpp =1:30bpp, =2:32bpp
+		 * driver choose program it itself, i.e. here we pass required
+		 * target rate that includes deep color.
+		 */
+
+		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
+			result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+static enum bp_result set_pixel_clock_v7(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+	PIXEL_CLOCK_PARAMETERS_V7 clk;
+	uint8_t controller_id;
+	uint32_t pll_id;
+
+	dm_memset(&clk, 0, sizeof(clk));
+
+	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+			&& bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
+		/* Note: VBIOS still wants to use ucCRTC name which is now
+		 * 1 byte in ULONG
+		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
+		 *{
+		 * target the pixel clock to drive the CRTC timing.
+		 * ULONG ulPixelClock:24;
+		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
+		 * previous version.
+		 * ATOM_CRTC1~6, indicate the CRTC controller to
+		 * ULONG ucCRTC:8;
+		 * drive the pixel clock. not used for DCPLL case.
+		 *}CRTC_PIXEL_CLOCK_FREQ;
+		 *union
+		 *{
+		 * pixel clock and CRTC id frequency
+		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
+		 * ULONG ulDispEngClkFreq; dispclk frequency
+		 *};
+		 */
+		clk.ucCRTC = controller_id;
+		clk.ucPpll = (uint8_t) pll_id;
+		clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
+		clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
+
+		/* We need to convert from KHz units into 10KHz units */
+		clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10);
+
+		clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
+
+		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
+
+		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
+
+		if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
+
+		if (bp_params->flags.SUPPORT_YUV_420)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
+
+		if (bp_params->flags.SET_XTALIN_REF_SRC)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
+
+		if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
+
+		if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
+
+		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
+			result = BP_RESULT_OK;
+	}
+#endif
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE PIXEL CLOCK SS
+ **
+ ********************************************************************************
+ *******************************************************************************/
+static enum bp_result enable_spread_spectrum_on_ppll_v1(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable);
+static enum bp_result enable_spread_spectrum_on_ppll_v2(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable);
+static enum bp_result enable_spread_spectrum_on_ppll_v3(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable);
+
+static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
+	case 1:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
+				enable_spread_spectrum_on_ppll_v1;
+		break;
+	case 2:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
+				enable_spread_spectrum_on_ppll_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
+				enable_spread_spectrum_on_ppll_v3;
+		break;
+	default:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_spread_spectrum_on_ppll_v1(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if ((enable == true) && (bp_params->percentage > 0))
+		params.ucEnable = ATOM_ENABLE;
+	else
+		params.ucEnable = ATOM_DISABLE;
+
+	params.usSpreadSpectrumPercentage =
+			cpu_to_le16((uint16_t)bp_params->percentage);
+	params.ucSpreadSpectrumStep =
+			(uint8_t)bp_params->ver1.step;
+	params.ucSpreadSpectrumDelay =
+			(uint8_t)bp_params->ver1.delay;
+	/* convert back to unit of 10KHz */
+	params.ucSpreadSpectrumRange =
+			(uint8_t)(bp_params->ver1.range / 10000);
+
+	if (bp_params->flags.EXTERNAL_SS)
+		params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
+
+	if (bp_params->flags.CENTER_SPREAD)
+		params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
+
+	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
+		params.ucPpll = ATOM_PPLL1;
+	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
+		params.ucPpll = ATOM_PPLL2;
+	else
+		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
+
+	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result enable_spread_spectrum_on_ppll_v2(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
+	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
+	else
+		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
+
+	if ((enable == true) && (bp_params->percentage > 0)) {
+		params.ucEnable = ATOM_ENABLE;
+
+		params.usSpreadSpectrumPercentage =
+				cpu_to_le16((uint16_t)(bp_params->percentage));
+		params.usSpreadSpectrumStep =
+				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
+
+		if (bp_params->flags.EXTERNAL_SS)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
+
+		if (bp_params->flags.CENTER_SPREAD)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
+
+		/* Both amounts need to be left shifted first before bit
+		 * comparison. Otherwise, the result will always be zero here
+		 */
+		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
+				((bp_params->ds.feedback_amount <<
+						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
+						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
+						((bp_params->ds.nfrac_amount <<
+								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
+								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
+	} else
+		params.ucEnable = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result enable_spread_spectrum_on_ppll_v3(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (bp_params->pll_id) {
+	case CLOCK_SOURCE_ID_PLL0:
+		/* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
+		 * not for SI display clock.
+		 */
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
+		break;
+	case CLOCK_SOURCE_ID_PLL1:
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
+		break;
+
+	case CLOCK_SOURCE_ID_PLL2:
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
+		break;
+
+	case CLOCK_SOURCE_ID_DCPLL:
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
+		break;
+
+	default:
+		BREAK_TO_DEBUGGER();
+		/* Unexpected PLL value!! */
+		return result;
+	}
+
+	if (enable == true) {
+		params.ucEnable = ATOM_ENABLE;
+
+		params.usSpreadSpectrumAmountFrac =
+				cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
+		params.usSpreadSpectrumStep =
+				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
+
+		if (bp_params->flags.EXTERNAL_SS)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
+		if (bp_params->flags.CENTER_SPREAD)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
+
+		/* Both amounts need to be left shifted first before bit
+		 * comparison. Otherwise, the result will always be zero here
+		 */
+		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
+				((bp_params->ds.feedback_amount <<
+						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
+						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
+						((bp_params->ds.nfrac_amount <<
+								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
+								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
+	} else
+		params.ucEnable = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ADJUST DISPLAY PLL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result adjust_display_pll_v2(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params);
+static enum bp_result adjust_display_pll_v3(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params);
+
+static void init_adjust_display_pll(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
+	case 2:
+		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
+		break;
+	default:
+		bp->cmd_tbl.adjust_display_pll = NULL;
+		break;
+	}
+}
+
+static enum bp_result adjust_display_pll_v2(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
+
+	/* We need to convert from KHz units into 10KHz units and then convert
+	 * output pixel clock back 10KHz-->KHz */
+	uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
+
+	params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
+	params.ucTransmitterID =
+			bp->cmd_helper->encoder_id_to_atom(
+					dal_graphics_object_id_get_encoder_id(
+							bp_params->encoder_object_id));
+	params.ucEncodeMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					bp_params->signal_type, false);
+	return result;
+}
+
+static enum bp_result adjust_display_pll_v3(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
+	uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	/* We need to convert from KHz units into 10KHz units and then convert
+	 * output pixel clock back 10KHz-->KHz */
+	params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
+	params.sInput.ucTransmitterID =
+			bp->cmd_helper->encoder_id_to_atom(
+					dal_graphics_object_id_get_encoder_id(
+							bp_params->encoder_object_id));
+	params.sInput.ucEncodeMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					bp_params->signal_type, false);
+
+	if (bp_params->ss_enable == true)
+		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
+
+	if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
+		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
+
+	if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
+		/* Convert output pixel clock back 10KHz-->KHz: multiply
+		 * original pixel clock in KHz by ratio
+		 * [output pxlClk/input pxlClk] */
+		uint64_t pixel_clk_10_khz_out =
+				(uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
+		uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
+
+		if (pixel_clk_10_kHz_in != 0) {
+			bp_params->adjusted_pixel_clock =
+					div_u64(pixel_clk * pixel_clk_10_khz_out,
+							pixel_clk_10_kHz_in);
+		} else {
+			bp_params->adjusted_pixel_clock = 0;
+			BREAK_TO_DEBUGGER();
+		}
+
+		bp_params->reference_divider = params.sOutput.ucRefDiv;
+		bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
+
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC ENCODER CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result dac1_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard);
+static enum bp_result dac2_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard);
+
+static void init_dac_encoder_control(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
+	case 1:
+		bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac1_encoder_control = NULL;
+		break;
+	}
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
+	case 1:
+		bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac2_encoder_control = NULL;
+		break;
+	}
+}
+
+static void dac_encoder_control_prepare_params(
+	DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard)
+{
+	params->ucDacStandard = dac_standard;
+	if (enable)
+		params->ucAction = ATOM_ENABLE;
+	else
+		params->ucAction = ATOM_DISABLE;
+
+	/* We need to convert from KHz units into 10KHz units
+	 * it looks as if the TvControl do not care about pixel clock
+	 */
+	params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
+}
+
+static enum bp_result dac1_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
+
+	dac_encoder_control_prepare_params(
+		&params,
+		enable,
+		pixel_clock,
+		dac_standard);
+
+	if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result dac2_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
+
+	dac_encoder_control_prepare_params(
+		&params,
+		enable,
+		pixel_clock,
+		dac_standard);
+
+	if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC OUTPUT CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+static enum bp_result dac1_output_control_v1(
+	struct bios_parser *bp,
+	bool enable);
+static enum bp_result dac2_output_control_v1(
+	struct bios_parser *bp,
+	bool enable);
+
+static void init_dac_output_control(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
+	case 1:
+		bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac1_output_control = NULL;
+		break;
+	}
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
+	case 1:
+		bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac2_output_control = NULL;
+		break;
+	}
+}
+
+static enum bp_result dac1_output_control_v1(
+	struct bios_parser *bp, bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
+
+	if (enable)
+		params.ucAction = ATOM_ENABLE;
+	else
+		params.ucAction = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result dac2_output_control_v1(
+	struct bios_parser *bp, bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
+
+	if (enable)
+		params.ucAction = ATOM_ENABLE;
+	else
+		params.ucAction = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC LOAD DETECTION
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum signal_type dac_load_detection_v3(
+	struct bios_parser *bp,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type display_signal);
+
+static void init_dac_load_detection(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC_LoadDetection)) {
+	case 3:
+		bp->cmd_tbl.dac_load_detection = dac_load_detection_v3;
+		break;
+	default:
+		bp->cmd_tbl.dac_load_detection = NULL;
+		break;
+	}
+}
+
+static enum signal_type dac_load_detection_v3(
+	struct bios_parser *bp,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type display_signal)
+{
+	DAC_LOAD_DETECTION_PS_ALLOCATION params;
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	/* load detection is cupported for CRT, TV and CV */
+	switch (display_signal) {
+	case SIGNAL_TYPE_RGB:
+		switch (dal_graphics_object_id_get_encoder_id(encoder)) {
+		case ENCODER_ID_INTERNAL_DAC1:
+		case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+			params.sDacload.usDeviceID =
+				cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
+			break;
+		case ENCODER_ID_INTERNAL_DAC2:
+		case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+			params.sDacload.usDeviceID =
+				cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
+			break;
+		default:
+			break;
+		}
+		break;
+		default:
+			return signal;
+	}
+
+	/* set the encoder to detect on */
+	switch (dal_graphics_object_id_get_encoder_id(encoder)) {
+	case ENCODER_ID_INTERNAL_DAC1:
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+		params.sDacload.ucDacType = ATOM_DAC_A;
+		break;
+	case ENCODER_ID_INTERNAL_DAC2:
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+		params.sDacload.ucDacType = ATOM_DAC_B;
+		break;
+	default:
+		return signal;
+	}
+
+	if (!EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params))
+		return signal;
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	signal = bp->bios_helper->detect_sink(
+			bp->ctx,
+			encoder,
+			connector,
+			display_signal);
+#else
+	BREAK_TO_DEBUGGER(); /* VBios is needed */
+#endif
+
+	return signal;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                 BLANK CRTC
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result blank_crtc_v1(
+	struct bios_parser *bp,
+	struct bp_blank_crtc_parameters *bp_params,
+	bool blank);
+
+static void init_blank_crtc(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(BlankCRTC)) {
+	case 1:
+		bp->cmd_tbl.blank_crtc = blank_crtc_v1;
+		break;
+	default:
+		bp->cmd_tbl.blank_crtc = NULL;
+		break;
+	}
+}
+
+static enum bp_result blank_crtc_v1(
+	struct bios_parser *bp,
+	struct bp_blank_crtc_parameters *bp_params,
+	bool blank)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	BLANK_CRTC_PARAMETERS params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
+			&atom_controller_id)) {
+		params.ucCRTC = (uint8_t)atom_controller_id;
+
+		if (blank)
+			params.ucBlanking = ATOM_BLANKING;
+		else
+			params.ucBlanking = ATOM_BLANKING_OFF;
+		params.usBlackColorRCr =
+				cpu_to_le16((uint16_t)bp_params->black_color_rcr);
+		params.usBlackColorGY =
+				cpu_to_le16((uint16_t)bp_params->black_color_gy);
+		params.usBlackColorBCb =
+				cpu_to_le16((uint16_t)bp_params->black_color_bcb);
+
+		if (EXEC_BIOS_CMD_TABLE(BlankCRTC, params))
+			result = BP_RESULT_OK;
+	} else
+		/* Not support more than two CRTC as current ASIC, update this
+		 * if needed.
+		 */
+		result = BP_RESULT_BADINPUT;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET CRTC TIMING
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result set_crtc_using_dtd_timing_v3(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params);
+static enum bp_result set_crtc_timing_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params);
+
+static void init_set_crtc_timing(struct bios_parser *bp)
+{
+	uint32_t dtd_version =
+			BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
+	if (dtd_version > 2)
+		switch (dtd_version) {
+		case 3:
+			bp->cmd_tbl.set_crtc_timing =
+					set_crtc_using_dtd_timing_v3;
+			break;
+		default:
+			bp->cmd_tbl.set_crtc_timing = NULL;
+			break;
+		}
+	else
+		switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
+		case 1:
+			bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
+			break;
+		default:
+			bp->cmd_tbl.set_crtc_timing = NULL;
+			break;
+		}
+}
+
+static enum bp_result set_crtc_timing_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+
+	params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
+	params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
+	params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
+	params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
+	params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
+	params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
+	params.usV_SyncStart =
+			cpu_to_le16((uint16_t)(bp_params->v_sync_start));
+	params.usV_SyncWidth =
+			cpu_to_le16((uint16_t)(bp_params->v_sync_width));
+
+
+	/* VBIOS does not expect any value except zero into this call, for
+	 * underscan use another entry ProgramOverscan call but when mode
+	 * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
+	 * but when same ,but 60 Hz there is corruption
+	 * DAL1 does not allow the mode 1776x1000@60
+	 */
+	params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
+	params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
+	params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
+	params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
+
+	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
+
+	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
+
+	if (bp_params->flags.INTERLACE) {
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
+
+		/* original DAL code has this condition to apply tis for
+		 * non-TV/CV only due to complex MV testing for possible
+		 * impact
+		 * if (pACParameters->signal != SignalType_YPbPr &&
+		 *  pACParameters->signal != SignalType_Composite &&
+		 *  pACParameters->signal != SignalType_SVideo)
+		 */
+		/* HW will deduct 0.5 line from 2nd feild.
+		 * i.e. for 1080i, it is 2 lines for 1st field, 2.5
+		 * lines for the 2nd feild. we need input as 5 instead
+		 * of 4, but it is 4 either from Edid data
+		 * (spec CEA 861) or CEA timing table.
+		 */
+		params.usV_SyncStart =
+				cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
+	}
+
+	if (bp_params->flags.HORZ_COUNT_BY_TWO)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
+
+	if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result set_crtc_using_dtd_timing_v3(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+
+	/* bios usH_Size wants h addressable size */
+	params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
+	/* bios usH_Blanking_Time wants borders included in blanking */
+	params.usH_Blanking_Time =
+			cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
+	/* bios usV_Size wants v addressable size */
+	params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
+	/* bios usV_Blanking_Time wants borders included in blanking */
+	params.usV_Blanking_Time =
+			cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
+	/* bios usHSyncOffset is the offset from the end of h addressable,
+	 * our horizontalSyncStart is the offset from the beginning
+	 * of h addressable */
+	params.usH_SyncOffset =
+			cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
+	params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
+	/* bios usHSyncOffset is the offset from the end of v addressable,
+	 * our verticalSyncStart is the offset from the beginning of
+	 * v addressable */
+	params.usV_SyncOffset =
+			cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
+	params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
+
+	/* we assume that overscan from original timing does not get bigger
+	 * than 255
+	 * we will program all the borders in the Set CRTC Overscan call below
+	 */
+
+	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
+
+	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
+
+
+	if (bp_params->flags.INTERLACE)	{
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
+
+		/* original DAL code has this condition to apply this
+		 * for non-TV/CV only
+		 * due to complex MV testing for possible impact
+		 * if ( pACParameters->signal != SignalType_YPbPr &&
+		 *  pACParameters->signal != SignalType_Composite &&
+		 *  pACParameters->signal != SignalType_SVideo)
+		 */
+		{
+			/* HW will deduct 0.5 line from 2nd feild.
+			 * i.e. for 1080i, it is 2 lines for 1st field,
+			 * 2.5 lines for the 2nd feild. we need input as 5
+			 * instead of 4.
+			 * but it is 4 either from Edid data (spec CEA 861)
+			 * or CEA timing table.
+			 */
+			params.usV_SyncOffset =
+					cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1);
+
+		}
+	}
+
+	if (bp_params->flags.HORZ_COUNT_BY_TWO)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
+
+	if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET CRTC OVERSCAN
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result set_crtc_overscan_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_overscan_parameters *bp_params);
+
+static void init_set_crtc_overscan(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_OverScan))	{
+	case 1:
+		bp->cmd_tbl.set_crtc_overscan = set_crtc_overscan_v1;
+		break;
+	default:
+		bp->cmd_tbl.set_crtc_overscan = NULL;
+		break;
+	}
+}
+
+static enum bp_result set_crtc_overscan_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_overscan_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_CRTC_OVERSCAN_PARAMETERS params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+	else
+		return BP_RESULT_BADINPUT;
+
+	params.usOverscanRight =
+			cpu_to_le16((uint16_t)bp_params->h_overscan_right);
+	params.usOverscanLeft =
+			cpu_to_le16((uint16_t)bp_params->h_overscan_left);
+	params.usOverscanBottom =
+			cpu_to_le16((uint16_t)bp_params->v_overscan_bottom);
+	params.usOverscanTop =
+			cpu_to_le16((uint16_t)bp_params->v_overscan_top);
+
+	if (EXEC_BIOS_CMD_TABLE(SetCRTC_OverScan, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SELECT CRTC SOURCE
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result select_crtc_source_v2(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params);
+static enum bp_result select_crtc_source_v3(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params);
+
+static void init_select_crtc_source(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) {
+	case 2:
+		bp->cmd_tbl.select_crtc_source = select_crtc_source_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
+		break;
+	default:
+		bp->cmd_tbl.select_crtc_source = NULL;
+		break;
+	}
+}
+
+static enum bp_result select_crtc_source_v2(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SELECT_CRTC_SOURCE_PARAMETERS_V2 params;
+	uint8_t atom_controller_id;
+	uint32_t atom_engine_id;
+	enum signal_type s = bp_params->signal;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	/* set controller id */
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+	else
+		return BP_RESULT_FAILURE;
+
+	/* set encoder id */
+	if (bp->cmd_helper->engine_bp_to_atom(
+			bp_params->engine_id, &atom_engine_id))
+		params.ucEncoderID = (uint8_t)atom_engine_id;
+	else
+		return BP_RESULT_FAILURE;
+
+	if (SIGNAL_TYPE_EDP == s ||
+			(SIGNAL_TYPE_DISPLAY_PORT == s &&
+					SIGNAL_TYPE_LVDS == bp_params->sink_signal))
+		s = SIGNAL_TYPE_LVDS;
+
+	params.ucEncodeMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					s, bp_params->enable_dp_audio);
+
+	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result select_crtc_source_v3(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params)
+{
+	bool result = BP_RESULT_FAILURE;
+	SELECT_CRTC_SOURCE_PARAMETERS_V3 params;
+	uint8_t atom_controller_id;
+	uint32_t atom_engine_id;
+	enum signal_type s = bp_params->signal;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
+			&atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+	else
+		return result;
+
+	if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
+			&atom_engine_id))
+		params.ucEncoderID = (uint8_t)atom_engine_id;
+	else
+		return result;
+
+	if (SIGNAL_TYPE_EDP == s ||
+			(SIGNAL_TYPE_DISPLAY_PORT == s &&
+					SIGNAL_TYPE_LVDS == bp_params->sink_signal))
+		s = SIGNAL_TYPE_LVDS;
+
+	params.ucEncodeMode =
+			bp->cmd_helper->encoder_mode_bp_to_atom(
+					s, bp_params->enable_dp_audio);
+	/* Needed for VBIOS Random Spatial Dithering feature */
+	params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth);
+
+	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE CRTC
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result enable_crtc_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable);
+
+static void init_enable_crtc(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
+	case 1:
+		bp->cmd_tbl.enable_crtc = enable_crtc_v1;
+		break;
+	default:
+		bp->cmd_tbl.enable_crtc = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_crtc_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable)
+{
+	bool result = BP_RESULT_FAILURE;
+	ENABLE_CRTC_PARAMETERS params = {0};
+	uint8_t id;
+
+	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
+		params.ucCRTC = id;
+	else
+		return BP_RESULT_BADINPUT;
+
+	if (enable)
+		params.ucEnable = ATOM_ENABLE;
+	else
+		params.ucEnable = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE CRTC MEM REQ
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result enable_crtc_mem_req_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable);
+
+static void init_enable_crtc_mem_req(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
+	case 1:
+		bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
+		break;
+	default:
+		bp->cmd_tbl.enable_crtc_mem_req = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_crtc_mem_req_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable)
+{
+	bool result = BP_RESULT_BADINPUT;
+	ENABLE_CRTC_PARAMETERS params = {0};
+	uint8_t id;
+
+	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
+		params.ucCRTC = id;
+
+		if (enable)
+			params.ucEnable = ATOM_ENABLE;
+		else
+			params.ucEnable = ATOM_DISABLE;
+
+		if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
+			result = BP_RESULT_OK;
+		else
+			result = BP_RESULT_FAILURE;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DISPLAY PLL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result program_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result program_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+
+static void init_program_clock(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
+	case 5:
+		bp->cmd_tbl.program_clock = program_clock_v5;
+		break;
+	case 6:
+		bp->cmd_tbl.program_clock = program_clock_v6;
+		break;
+	default:
+		bp->cmd_tbl.program_clock = NULL;
+		break;
+	}
+}
+
+static enum bp_result program_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
+	uint32_t atom_pll_id;
+
+	dm_memset(&params, 0, sizeof(params));
+	if (!bp->cmd_helper->clock_source_id_to_atom(
+			bp_params->pll_id, &atom_pll_id)) {
+		BREAK_TO_DEBUGGER(); /* Invalid Inpute!! */
+		return BP_RESULT_BADINPUT;
+	}
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
+	params.sPCLKInput.usPixelClock =
+			cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10));
+	params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
+
+	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
+
+	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result program_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
+	uint32_t atom_pll_id;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (!bp->cmd_helper->clock_source_id_to_atom(
+			bp_params->pll_id, &atom_pll_id)) {
+		BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
+		return BP_RESULT_BADINPUT;
+	}
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
+	params.sPCLKInput.ulDispEngClkFreq =
+			cpu_to_le32(bp_params->target_pixel_clock / 10);
+
+	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
+
+	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
+		/* True display clock is returned by VBIOS if DFS bypass
+		 * is enabled. */
+		bp_params->dfs_bypass_display_clock =
+				(uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                 COMPUTE MEMORY ENGINE PLL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result compute_memore_engine_pll_v4(
+	struct bios_parser *bp,
+	struct bp_display_clock_parameters *bp_params);
+
+static void init_compute_memore_engine_pll(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(ComputeMemoryEnginePLL)) {
+	case 4:
+		bp->cmd_tbl.compute_memore_engine_pll =
+				compute_memore_engine_pll_v4;
+		break;
+	default:
+		bp->cmd_tbl.compute_memore_engine_pll = NULL;
+		break;
+	}
+}
+
+static enum bp_result compute_memore_engine_pll_v4(
+	struct bios_parser *bp,
+	struct bp_display_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	params.ulClock = cpu_to_le32(bp_params->target_display_clock / 10);
+
+	/* Initialize this to the target clock in case this call fails */
+	bp_params->actual_display_clock = bp_params->target_display_clock;
+
+	if (EXEC_BIOS_CMD_TABLE(ComputeMemoryEnginePLL, params)) {
+		/* Convert from 10KHz units back to KHz */
+		bp_params->actual_display_clock =
+				le32_to_cpu(params.ulClock) * 10;
+		bp_params->actual_post_divider_id = params.ucPostDiv;
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  EXTERNAL ENCODER CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result external_encoder_control_v3(
+	struct bios_parser *bp,
+	struct bp_external_encoder_control *cntl);
+
+static void init_external_encoder_control(
+	struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
+	case 3:
+		bp->cmd_tbl.external_encoder_control =
+				external_encoder_control_v3;
+		break;
+	default:
+		bp->cmd_tbl.external_encoder_control = NULL;
+		break;
+	}
+}
+
+static enum bp_result external_encoder_control_v3(
+	struct bios_parser *bp,
+	struct bp_external_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	/* we need use _PS_Alloc struct */
+	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
+	EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
+	struct graphics_object_id encoder;
+	bool is_input_signal_dp = false;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	cntl_params = &params.sExtEncoder;
+
+	encoder = cntl->encoder_id;
+
+	/* check if encoder supports external encoder control table */
+	switch (dal_graphics_object_id_get_encoder_id(encoder)) {
+	case ENCODER_ID_EXTERNAL_NUTMEG:
+	case ENCODER_ID_EXTERNAL_TRAVIS:
+		is_input_signal_dp = true;
+		break;
+
+	default:
+		BREAK_TO_DEBUGGER();
+		return BP_RESULT_BADINPUT;
+	}
+
+	/* Fill information based on the action
+	 *
+	 * Bit[6:4]: indicate external encoder, applied to all functions.
+	 * =0: external encoder1, mapped to external encoder enum id1
+	 * =1: external encoder2, mapped to external encoder enum id2
+	 *
+	 * enum ObjectEnumId
+	 * {
+	 *  EnumId_Unknown = 0,
+	 *  EnumId_1,
+	 *  EnumId_2,
+	 * };
+	 */
+	cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
+
+	switch (cntl->action) {
+	case EXTERNAL_ENCODER_CONTROL_INIT:
+		/* output display connector type. Only valid in encoder
+		 * initialization */
+		cntl_params->usConnectorId =
+				cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
+		break;
+	case EXTERNAL_ENCODER_CONTROL_SETUP:
+		/* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
+		 * 10KHz
+		 * output display device pixel clock frequency in unit of 10KHz.
+		 * Only valid in setup and enableoutput
+		 */
+		cntl_params->usPixelClock =
+				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+		/* Indicate display output signal type drive by external
+		 * encoder, only valid in setup and enableoutput */
+		cntl_params->ucEncoderMode =
+				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+						cntl->signal, false);
+
+		if (is_input_signal_dp) {
+			/* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
+			 * only valid in encoder setup with DP mode. */
+			if (LINK_RATE_HIGH == cntl->link_rate)
+				cntl_params->ucConfig |= 1;
+			/* output color depth Indicate encoder data bpc format
+			 * in DP mode, only valid in encoder setup in DP mode.
+			 */
+			cntl_params->ucBitPerColor =
+					(uint8_t)(cntl->color_depth);
+		}
+		/* Indicate how many lanes used by external encoder, only valid
+		 * in encoder setup and enableoutput. */
+		cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
+		break;
+	case EXTERNAL_ENCODER_CONTROL_ENABLE:
+		cntl_params->usPixelClock =
+				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+		cntl_params->ucEncoderMode =
+				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+						cntl->signal, false);
+		cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
+		break;
+	default:
+		break;
+	}
+
+	cntl_params->ucAction = (uint8_t)cntl->action;
+
+	if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
+		result = BP_RESULT_OK;
+
+	if (EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT == cntl->action) {
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+		if (BP_RESULT_OK == result)
+			/* get VBIOS result from scratch register.
+			 * ExternalEncoderControl runs detection and save result
+			 * in BIOS scratch registers. */
+			cntl->signal = bp->bios_helper->detect_sink(
+					bp->ctx,
+					encoder,
+					cntl->connector_obj_id,
+					cntl->signal);
+		else/* BIOS table does not work. */
+#endif
+		{
+			BREAK_TO_DEBUGGER(); /* VBios is needed */
+			cntl->signal = SIGNAL_TYPE_NONE;
+		}
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE DISPLAY POWER GATING
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result enable_disp_power_gating_v2_1(
+	struct bios_parser *bp,
+	enum controller_id crtc_id,
+	enum bp_pipe_control_action action);
+
+static void init_enable_disp_power_gating(
+	struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
+	case 1:
+		bp->cmd_tbl.enable_disp_power_gating =
+				enable_disp_power_gating_v2_1;
+		break;
+	default:
+		bp->cmd_tbl.enable_disp_power_gating = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_disp_power_gating_v2_1(
+	struct bios_parser *bp,
+	enum controller_id crtc_id,
+	enum bp_pipe_control_action action)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 params = {0};
+	uint8_t atom_crtc_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
+		params.ucDispPipeId = atom_crtc_id;
+	else
+		return BP_RESULT_BADINPUT;
+
+	params.ucEnable =
+			bp->cmd_helper->disp_power_gating_action_to_atom(action);
+
+	if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET DCE CLOCK
+ **
+ ********************************************************************************
+ *******************************************************************************/
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+static enum bp_result set_dce_clock_v2_1(
+	struct bios_parser *bp,
+	struct bp_set_dce_clock_parameters *bp_params);
+#endif
+
+static void init_set_dce_clock(struct bios_parser *bp)
+{
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
+	case 1:
+		bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
+		break;
+	default:
+		bp->cmd_tbl.set_dce_clock = NULL;
+		break;
+	}
+#endif
+}
+
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+static enum bp_result set_dce_clock_v2_1(
+	struct bios_parser *bp,
+	struct bp_set_dce_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
+	uint32_t atom_pll_id;
+	uint32_t atom_clock_type;
+	const struct command_table_helper *cmd = bp->cmd_helper;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
+			!cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
+		return BP_RESULT_BADINPUT;
+
+	params.asParam.ucDCEClkSrc  = atom_pll_id;
+	params.asParam.ucDCEClkType = atom_clock_type;
+
+	if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
+		if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
+
+		if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
+
+		if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
+
+		if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
+	}
+	else
+		/* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
+		/* We need to convert from KHz units into 10KHz units */
+		params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
+
+	if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
+		/* Convert from 10KHz units back to KHz */
+		bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table.h b/drivers/gpu/drm/amd/dal/dc/bios/command_table.h
new file mode 100644
index 000000000000..3cb0c7f8c202
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_H__
+#define __DAL_COMMAND_TABLE_H__
+
+struct bios_parser;
+struct bp_encoder_control;
+
+struct cmd_tbl {
+	enum bp_result (*dig_encoder_control)(
+		struct bios_parser *bp,
+		struct bp_encoder_control *control);
+	enum bp_result (*encoder_control_dig1)(
+		struct bios_parser *bp,
+		struct bp_encoder_control *control);
+	enum bp_result (*encoder_control_dig2)(
+		struct bios_parser *bp,
+		struct bp_encoder_control *control);
+	enum bp_result (*transmitter_control)(
+		struct bios_parser *bp,
+		struct bp_transmitter_control *control);
+	enum bp_result (*set_pixel_clock)(
+		struct bios_parser *bp,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*enable_spread_spectrum_on_ppll)(
+		struct bios_parser *bp,
+		struct bp_spread_spectrum_parameters *bp_params,
+		bool enable);
+	enum bp_result (*adjust_display_pll)(
+		struct bios_parser *bp,
+		struct bp_adjust_pixel_clock_parameters *bp_params);
+	enum bp_result (*dac1_encoder_control)(
+		struct bios_parser *bp,
+		bool enable,
+		uint32_t pixel_clock,
+		uint8_t dac_standard);
+	enum bp_result (*dac2_encoder_control)(
+		struct bios_parser *bp,
+		bool enable,
+		uint32_t pixel_clock,
+		uint8_t dac_standard);
+	enum bp_result (*dac1_output_control)(
+		struct bios_parser *bp,
+		bool enable);
+	enum bp_result (*dac2_output_control)(
+		struct bios_parser *bp,
+		bool enable);
+	enum signal_type (*dac_load_detection)(
+		struct bios_parser *bp,
+		struct graphics_object_id encoder,
+		struct graphics_object_id connector,
+		enum signal_type display_signal);
+	enum bp_result (*blank_crtc)(
+		struct bios_parser *bp,
+		struct bp_blank_crtc_parameters *bp_params,
+		bool blank);
+	enum bp_result (*set_crtc_timing)(
+		struct bios_parser *bp,
+		struct bp_hw_crtc_timing_parameters *bp_params);
+	enum bp_result (*set_crtc_overscan)(
+		struct bios_parser *bp,
+		struct bp_hw_crtc_overscan_parameters *bp_params);
+	enum bp_result (*select_crtc_source)(
+		struct bios_parser *bp,
+		struct bp_crtc_source_select *bp_params);
+	enum bp_result (*enable_crtc)(
+		struct bios_parser *bp,
+		enum controller_id controller_id,
+		bool enable);
+	enum bp_result (*enable_crtc_mem_req)(
+		struct bios_parser *bp,
+		enum controller_id controller_id,
+		bool enable);
+	enum bp_result (*program_clock)(
+		struct bios_parser *bp,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*compute_memore_engine_pll)(
+		struct bios_parser *bp,
+		struct bp_display_clock_parameters *bp_params);
+	enum bp_result (*external_encoder_control)(
+			struct bios_parser *bp,
+			struct bp_external_encoder_control *cntl);
+	enum bp_result (*enable_disp_power_gating)(
+		struct bios_parser *bp,
+		enum controller_id crtc_id,
+		enum bp_pipe_control_action action);
+	enum bp_result (*set_dce_clock)(
+		struct bios_parser *bp,
+		struct bp_set_dce_clock_parameters *bp_params);
+};
+
+void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
new file mode 100644
index 000000000000..566604ea877a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "include/adapter_service_types.h"
+
+#include "command_table_helper.h"
+
+bool dal_bios_parser_init_cmd_tbl_helper(
+	const struct command_table_helper **h,
+	enum dce_version dce)
+{
+	switch (dce) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		*h = dal_cmd_tbl_helper_dce110_get_table();
+		return true;
+#endif
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		*h = dal_cmd_tbl_helper_dce110_get_table();
+		return true;
+#endif
+
+	default:
+		/* Unsupported DCE */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+/* real implementations */
+
+bool dal_cmd_table_helper_controller_id_to_atom(
+	enum controller_id id,
+	uint8_t *atom_id)
+{
+	if (atom_id == NULL) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	switch (id) {
+	case CONTROLLER_ID_D0:
+		*atom_id = ATOM_CRTC1;
+		return true;
+	case CONTROLLER_ID_D1:
+		*atom_id = ATOM_CRTC2;
+		return true;
+	case CONTROLLER_ID_D2:
+		*atom_id = ATOM_CRTC3;
+		return true;
+	case CONTROLLER_ID_D3:
+		*atom_id = ATOM_CRTC4;
+		return true;
+	case CONTROLLER_ID_D4:
+		*atom_id = ATOM_CRTC5;
+		return true;
+	case CONTROLLER_ID_D5:
+		*atom_id = ATOM_CRTC6;
+		return true;
+	case CONTROLLER_ID_UNDERLAY0:
+		*atom_id = ATOM_UNDERLAY_PIPE0;
+		return true;
+	case CONTROLLER_ID_UNDEFINED:
+		*atom_id = ATOM_CRTC_INVALID;
+		return true;
+	default:
+		/* Wrong controller id */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+/**
+* translate_transmitter_bp_to_atom
+*
+* @brief
+*  Translate the Transmitter to the corresponding ATOM BIOS value
+*
+* @param
+*   input transmitter
+*   output digitalTransmitter
+*    // =00: Digital Transmitter1 ( UNIPHY linkAB )
+*    // =01: Digital Transmitter2 ( UNIPHY linkCD )
+*    // =02: Digital Transmitter3 ( UNIPHY linkEF )
+*/
+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom(
+	enum transmitter t)
+{
+	switch (t) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_TRAVIS_LCD:
+		return 0;
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+		return 1;
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+		return 2;
+	default:
+		/* Invalid Transmitter Type! */
+		BREAK_TO_DEBUGGER();
+		return 0;
+	}
+}
+
+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom(
+	enum signal_type s,
+	bool enable_dp_audio)
+{
+	switch (s) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		return ATOM_ENCODER_MODE_DVI;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		return ATOM_ENCODER_MODE_HDMI;
+	case SIGNAL_TYPE_LVDS:
+		return ATOM_ENCODER_MODE_LVDS;
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+		if (enable_dp_audio)
+			return ATOM_ENCODER_MODE_DP_AUDIO;
+		else
+			return ATOM_ENCODER_MODE_DP;
+	case SIGNAL_TYPE_RGB:
+		return ATOM_ENCODER_MODE_CRT;
+	default:
+		return ATOM_ENCODER_MODE_CRT;
+	}
+}
+
+void dal_cmd_table_helper_assign_control_parameter(
+	const struct command_table_helper *h,
+	struct bp_encoder_control *control,
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param)
+{
+	/* there are three transmitter blocks, each one has two links 4-lanes
+	 * each, A+B, C+D, E+F, Uniphy A, C and E are enumerated as link 0 in
+	 * each transmitter block B, D and F as link 1, third transmitter block
+	 * has non splitable links (UniphyE and UniphyF can not be configured
+	 * separately to drive two different streams)
+	 */
+	if ((control->transmitter == TRANSMITTER_UNIPHY_B) ||
+		(control->transmitter == TRANSMITTER_UNIPHY_D) ||
+		(control->transmitter == TRANSMITTER_UNIPHY_F)) {
+		/* Bit2: Link Select
+		 * =0: PHY linkA/C/E
+		 * =1: PHY linkB/D/F
+		 */
+		ctrl_param->acConfig.ucLinkSel = 1;
+	}
+
+	/* Bit[4:3]: Transmitter Selection
+	 * =00: Digital Transmitter1 ( UNIPHY linkAB )
+	 * =01: Digital Transmitter2 ( UNIPHY linkCD )
+	 * =02: Digital Transmitter3 ( UNIPHY linkEF )
+	 * =03: Reserved
+	 */
+	ctrl_param->acConfig.ucTransmitterSel =
+		(uint8_t)(h->transmitter_bp_to_atom(control->transmitter));
+
+	/* We need to convert from KHz units into 10KHz units */
+	ctrl_param->ucAction = h->encoder_action_to_atom(control->action);
+	ctrl_param->usPixelClock = cpu_to_le16((uint16_t)(control->pixel_clock / 10));
+	ctrl_param->ucEncoderMode =
+		(uint8_t)(h->encoder_mode_bp_to_atom(
+			control->signal, control->enable_dp_audio));
+	ctrl_param->ucLaneNum = (uint8_t)(control->lanes_number);
+}
+
+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src(
+	enum clock_source_id id,
+	uint32_t *ref_clk_src_id)
+{
+	if (ref_clk_src_id == NULL) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	switch (id) {
+	case CLOCK_SOURCE_ID_PLL1:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL;
+		return true;
+	case CLOCK_SOURCE_ID_PLL2:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL;
+		return true;
+	case CLOCK_SOURCE_ID_DCPLL:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL;
+		return true;
+	case CLOCK_SOURCE_ID_EXTERNAL:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK;
+		return true;
+	case CLOCK_SOURCE_ID_UNDEFINED:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID;
+		return true;
+	default:
+		/* Unsupported clock source id */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+uint8_t dal_cmd_table_helper_encoder_id_to_atom(
+	enum encoder_id id)
+{
+	switch (id) {
+	case ENCODER_ID_INTERNAL_LVDS:
+		return ENCODER_OBJECT_ID_INTERNAL_LVDS;
+	case ENCODER_ID_INTERNAL_TMDS1:
+		return ENCODER_OBJECT_ID_INTERNAL_TMDS1;
+	case ENCODER_ID_INTERNAL_TMDS2:
+		return ENCODER_OBJECT_ID_INTERNAL_TMDS2;
+	case ENCODER_ID_INTERNAL_DAC1:
+		return ENCODER_OBJECT_ID_INTERNAL_DAC1;
+	case ENCODER_ID_INTERNAL_DAC2:
+		return ENCODER_OBJECT_ID_INTERNAL_DAC2;
+	case ENCODER_ID_INTERNAL_LVTM1:
+		return ENCODER_OBJECT_ID_INTERNAL_LVTM1;
+	case ENCODER_ID_INTERNAL_HDMI:
+		return ENCODER_OBJECT_ID_HDMI_INTERNAL;
+	case ENCODER_ID_EXTERNAL_TRAVIS:
+		return ENCODER_OBJECT_ID_TRAVIS;
+	case ENCODER_ID_EXTERNAL_NUTMEG:
+		return ENCODER_OBJECT_ID_NUTMEG;
+	case ENCODER_ID_INTERNAL_KLDSCP_TMDS1:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
+	case ENCODER_ID_EXTERNAL_MVPU_FPGA:
+		return ENCODER_OBJECT_ID_MVPU_FPGA;
+	case ENCODER_ID_INTERNAL_DDI:
+		return ENCODER_OBJECT_ID_INTERNAL_DDI;
+	case ENCODER_ID_INTERNAL_UNIPHY:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY;
+	case ENCODER_ID_INTERNAL_KLDSCP_LVTMA:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA;
+	case ENCODER_ID_INTERNAL_UNIPHY1:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY1;
+	case ENCODER_ID_INTERNAL_UNIPHY2:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY2;
+	case ENCODER_ID_INTERNAL_UNIPHY3:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY3;
+	case ENCODER_ID_INTERNAL_WIRELESS:
+		return ENCODER_OBJECT_ID_INTERNAL_VCE;
+	case ENCODER_ID_UNKNOWN:
+		return ENCODER_OBJECT_ID_NONE;
+	default:
+		/* Invalid encoder id */
+		BREAK_TO_DEBUGGER();
+		return ENCODER_OBJECT_ID_NONE;
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
new file mode 100644
index 000000000000..4646cabd2b40
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_HELPER_H__
+#define __DAL_COMMAND_TABLE_HELPER_H__
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce110/command_table_helper_dce110.h"
+#endif
+
+struct command_table_helper {
+	bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id);
+	uint8_t (*encoder_action_to_atom)(
+			enum bp_encoder_control_action action);
+	uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s,
+			bool enable_dp_audio);
+	bool (*engine_bp_to_atom)(enum engine_id engine_id,
+			uint32_t *atom_engine_id);
+	void (*assign_control_parameter)(
+			const struct command_table_helper *h,
+			struct bp_encoder_control *control,
+			DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param);
+	bool (*clock_source_id_to_atom)(enum clock_source_id id,
+			uint32_t *atom_pll_id);
+	bool (*clock_source_id_to_ref_clk_src)(
+			enum clock_source_id id,
+			uint32_t *ref_clk_src_id);
+	uint8_t (*transmitter_bp_to_atom)(enum transmitter t);
+	uint8_t (*encoder_id_to_atom)(enum encoder_id id);
+	uint8_t (*clock_source_id_to_atom_phy_clk_src_id)(
+			enum clock_source_id id);
+	uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s);
+	uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id);
+	uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id);
+	uint8_t (*phy_id_to_atom)(enum transmitter t);
+	uint8_t (*disp_power_gating_action_to_atom)(
+			enum bp_pipe_control_action action);
+	bool (*dc_clock_type_to_atom)(enum bp_dce_clock_type id,
+			uint32_t *atom_clock_type);
+    uint8_t (*transmitter_color_depth_to_atom)(enum transmitter_color_depth id);
+};
+
+bool dal_bios_parser_init_cmd_tbl_helper(const struct command_table_helper **h,
+	enum dce_version dce);
+
+bool dal_cmd_table_helper_controller_id_to_atom(
+	enum controller_id id,
+	uint8_t *atom_id);
+
+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom(
+	enum signal_type s,
+	bool enable_dp_audio);
+
+void dal_cmd_table_helper_assign_control_parameter(
+	const struct command_table_helper *h,
+	struct bp_encoder_control *control,
+DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param);
+
+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src(
+	enum clock_source_id id,
+	uint32_t *ref_clk_src_id);
+
+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom(
+	enum transmitter t);
+
+uint8_t dal_cmd_table_helper_encoder_id_to_atom(
+	enum encoder_id id);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
new file mode 100644
index 000000000000..85d3103a1de7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
@@ -0,0 +1,484 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "include/adapter_service_types.h"
+#include "include/logger_interface.h"
+
+#include "../bios_parser_helper.h"
+
+#include "dce/dce_11_0_d.h"
+#include "bif/bif_5_1_d.h"
+
+/**
+ * set_scratch_acc_mode_change
+ *
+ * @brief
+ *  set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when
+ *  VGA/non-Accelerated mode is set
+ *
+ * @param
+ *  struct dc_context *ctx - [in] DAL context
+ */
+static void set_scratch_acc_mode_change(
+	struct dc_context *ctx)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = 0;
+
+	value = dm_read_reg(ctx, addr);
+
+	value |= ATOM_S6_ACC_MODE;
+
+	dm_write_reg(ctx, addr, value);
+}
+
+/*
+ * set_scratch_active_and_requested
+ *
+ * @brief
+ * Set VBIOS scratch pad registers about active and requested displays
+ *
+ * @param
+ * struct dc_context *ctx - [in] DAL context for register accessing
+ * struct vbios_helper_data *d - [in] values to write
+ */
+static void set_scratch_active_and_requested(
+	struct dc_context *ctx,
+	struct vbios_helper_data *d)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* mmBIOS_SCRATCH_3 = mmBIOS_SCRATCH_0 + ATOM_ACTIVE_INFO_DEF */
+	addr = mmBIOS_SCRATCH_3;
+
+	value = dm_read_reg(ctx, addr);
+
+	value &= ~ATOM_S3_DEVICE_ACTIVE_MASK;
+	value |= (d->active & ATOM_S3_DEVICE_ACTIVE_MASK);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* mmBIOS_SCRATCH_6 =  mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF */
+	addr = mmBIOS_SCRATCH_6;
+
+	value = dm_read_reg(ctx, addr);
+
+	value &= ~ATOM_S6_ACC_REQ_MASK;
+	value |= (d->requested & ATOM_S6_ACC_REQ_MASK);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* mmBIOS_SCRATCH_5 =  mmBIOS_SCRATCH_0 + ATOM_DOS_REQ_INFO_DEF */
+	addr = mmBIOS_SCRATCH_5;
+
+	value = dm_read_reg(ctx, addr);
+
+	value &= ~ATOM_S5_DOS_REQ_DEVICEw0;
+	value |= (d->active & ATOM_S5_DOS_REQ_DEVICEw0);
+
+	dm_write_reg(ctx, addr, value);
+
+	d->active = 0;
+	d->requested = 0;
+}
+
+/**
+ * get LCD Scale Mode from VBIOS scratch register
+ */
+static enum lcd_scale get_scratch_lcd_scale(
+	struct dc_context *ctx)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = 0;
+
+	value = dm_read_reg(ctx, addr);
+
+	if (value & ATOM_S6_REQ_LCD_EXPANSION_FULL)
+		return LCD_SCALE_FULLPANEL;
+	else if (value & ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO)
+		return LCD_SCALE_ASPECTRATIO;
+	else
+		return LCD_SCALE_NONE;
+}
+
+/**
+ * prepare_scratch_active_and_requested
+ *
+ * @brief
+ *  prepare and update VBIOS scratch pad registers about active and requested
+ *  displays
+ *
+ * @param
+ * data - helper's shared data
+ * enum controller_ild - controller Id
+ * enum signal_type - signal type used on display
+ * const struct connector_device_tag_info* - pointer to display type and enum id
+ */
+static void prepare_scratch_active_and_requested(
+	struct dc_context *ctx,
+	struct vbios_helper_data *data,
+	enum controller_id id,
+	enum signal_type s,
+	const struct connector_device_tag_info *dev_tag)
+{
+	switch (s) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		if (dev_tag->dev_id.device_type == DEVICE_TYPE_DFP)
+			switch (dev_tag->dev_id.enum_id) {
+			case 1:
+				data->requested |= ATOM_S6_ACC_REQ_DFP1;
+				data->active |= ATOM_S3_DFP1_ACTIVE;
+				break;
+			case 2:
+				data->requested |= ATOM_S6_ACC_REQ_DFP2;
+				data->active |= ATOM_S3_DFP2_ACTIVE;
+				break;
+			case 3:
+				data->requested |= ATOM_S6_ACC_REQ_DFP3;
+				data->active |= ATOM_S3_DFP3_ACTIVE;
+				break;
+			case 4:
+				data->requested |= ATOM_S6_ACC_REQ_DFP4;
+				data->active |= ATOM_S3_DFP4_ACTIVE;
+				break;
+			case 5:
+				data->requested |= ATOM_S6_ACC_REQ_DFP5;
+				data->active |= ATOM_S3_DFP5_ACTIVE;
+				break;
+			case 6:
+				data->requested |= ATOM_S6_ACC_REQ_DFP6;
+				data->active |= ATOM_S3_DFP6_ACTIVE;
+				break;
+			default:
+				break;
+			}
+		break;
+	case SIGNAL_TYPE_LVDS:
+	case SIGNAL_TYPE_EDP:
+		data->requested |= ATOM_S6_ACC_REQ_LCD1;
+		data->active |= ATOM_S3_LCD1_ACTIVE;
+		break;
+	case SIGNAL_TYPE_RGB:
+		if (dev_tag->dev_id.device_type == DEVICE_TYPE_CRT)
+			switch (dev_tag->dev_id.enum_id) {
+			case 1:
+				data->requested |= ATOM_S6_ACC_REQ_CRT1;
+				data->active |= ATOM_S3_CRT1_ACTIVE;
+				break;
+			case 2:
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_BIOS,
+					LOG_MINOR_COMPONENT_BIOS,
+					"%s: DAL does not support DAC2!\n",
+					__func__);
+				break;
+			default:
+				break;
+			}
+		break;
+	default:
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_BIOS,
+				LOG_MINOR_COMPONENT_BIOS,
+				"%s: No such signal!\n",
+				__func__);
+		break;
+	}
+}
+
+/*
+ * is_accelerated_mode
+ *
+ * @brief
+ *  set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when
+ *  VGA/non-Accelerated mode is set
+ *
+ * @param
+ * struct dc_context *ctx
+ *
+ * @return
+ * true if in acceleration mode, false otherwise.
+ */
+static bool is_accelerated_mode(
+	struct dc_context *ctx)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	return (value & ATOM_S6_ACC_MODE) ? true : false;
+}
+
+#define BIOS_SCRATCH0_DAC_B_SHIFT 8
+
+/**
+ * detect_sink
+ *
+ * @brief
+ *  read VBIOS scratch register to determine whether display for the specified
+ *  signal is present and return the actual sink signal type
+ *  For analog signals VBIOS load detection has to be called prior reading the
+ *  register
+ *
+ * @param
+ *  encoder - encoder id (to specify DAC)
+ *  connector - connector id (to check CV on DIN)
+ *  signal - signal (as display type) to check
+ *
+ * @return
+ *  signal_type - actual (on the sink) signal type detected
+ */
+static enum signal_type detect_sink(
+	struct dc_context *ctx,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type signal)
+{
+	uint32_t bios_scratch0;
+	uint32_t encoder_id = encoder.id;
+	/* after DCE 10.x does not support DAC2, so assert and return
+	 * SIGNAL_TYPE_NONE */
+	if (encoder_id == ENCODER_ID_INTERNAL_DAC2
+		|| encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC2) {
+		ASSERT(false);
+		return SIGNAL_TYPE_NONE;
+	}
+
+	bios_scratch0 = dm_read_reg(ctx,
+		mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF);
+
+	/* In further processing we use DACB masks. If we want detect load on
+	 * DACA, we need to shift the register so DACA bits will be in place of
+	 * DACB bits
+	 */
+	if (encoder_id == ENCODER_ID_INTERNAL_DAC1
+		|| encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC1
+		|| encoder_id == ENCODER_ID_EXTERNAL_NUTMEG
+		|| encoder_id == ENCODER_ID_EXTERNAL_TRAVIS) {
+		bios_scratch0 <<= BIOS_SCRATCH0_DAC_B_SHIFT;
+	}
+
+	switch (signal) {
+	case SIGNAL_TYPE_RGB: {
+		if (bios_scratch0 & ATOM_S0_CRT2_MASK)
+			return SIGNAL_TYPE_RGB;
+		break;
+	}
+	case SIGNAL_TYPE_LVDS: {
+		if (bios_scratch0 & ATOM_S0_LCD1)
+			return SIGNAL_TYPE_LVDS;
+		break;
+	}
+	case SIGNAL_TYPE_EDP: {
+		if (bios_scratch0 & ATOM_S0_LCD1)
+			return SIGNAL_TYPE_EDP;
+		break;
+	}
+	default:
+		break;
+	}
+
+	return SIGNAL_TYPE_NONE;
+}
+
+/**
+ * set_scratch_connected
+ *
+ * @brief
+ *    update BIOS_SCRATCH_0 register about connected displays
+ *
+ * @param
+ * bool - update scratch register or just prepare info to be updated
+ * bool - connection state
+ * const struct connector_device_tag_info * - pointer to device type and enum ID
+ */
+static void set_scratch_connected(
+	struct dc_context *ctx,
+	struct graphics_object_id id,
+	bool connected,
+	const struct connector_device_tag_info *device_tag)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	uint32_t update = 0;
+
+	switch (device_tag->dev_id.device_type) {
+	case DEVICE_TYPE_LCD:
+		/* For LCD VBIOS will update LCD Panel connected bit always and
+		 * Lid state bit based on SBIOS info do not do anything here
+		 * for LCD
+		 */
+		break;
+	case DEVICE_TYPE_CRT:
+		/*
+		 * CRT is not supported in DCE11
+		 */
+		break;
+	case DEVICE_TYPE_DFP:
+		switch (device_tag->dev_id.enum_id) {
+		case 1:
+			update |= ATOM_S0_DFP1;
+			break;
+		case 2:
+			update |= ATOM_S0_DFP2;
+			break;
+		case 3:
+			update |= ATOM_S0_DFP3;
+			break;
+		case 4:
+			update |= ATOM_S0_DFP4;
+			break;
+		case 5:
+			update |= ATOM_S0_DFP5;
+			break;
+		case 6:
+			update |= ATOM_S0_DFP6;
+			break;
+		default:
+			break;
+		}
+		break;
+	case DEVICE_TYPE_CV:
+		/* DCE 8.0 does not support CV,
+		 * so don't do anything */
+		break;
+
+	case DEVICE_TYPE_TV:
+		/* For TV VBIOS will update S-Video or
+		 * Composite scratch bits on DAL_LoadDetect
+		 * when called by driver, do not do anything
+		 * here for TV
+		 */
+		break;
+
+	default:
+		break;
+
+	}
+
+	/* update scratch register */
+	addr = mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF;
+
+	value = dm_read_reg(ctx, addr);
+
+	if (connected)
+		value |= update;
+	else
+		value &= ~update;
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_scratch_critical_state(
+	struct dc_context *ctx,
+	bool state)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	if (state)
+		value |= ATOM_S6_CRITICAL_STATE;
+	else
+		value &= ~ATOM_S6_CRITICAL_STATE;
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_scratch_lcd_scale(
+	struct dc_context *ctx,
+	enum lcd_scale lcd_scale_request)
+{
+	DAL_LOGGER_NOT_IMPL(
+		LOG_MINOR_COMPONENT_BIOS,
+		"Bios Parser:%s\n",
+		__func__);
+}
+
+static bool is_lid_open(struct dc_context *ctx)
+{
+	uint32_t bios_scratch6;
+
+	bios_scratch6 =
+		dm_read_reg(
+			ctx,
+			mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF);
+
+	/* lid is open if the bit is not set */
+	if (!(bios_scratch6 & ATOM_S6_LID_STATE))
+		return true;
+
+	return false;
+}
+
+/* function table */
+static const struct bios_parser_helper bios_parser_helper_funcs = {
+	.detect_sink = detect_sink,
+	.fmt_bit_depth_control = NULL,
+	.fmt_control = NULL,
+	.get_bios_event_info = NULL,
+	.get_embedded_display_controller_id = NULL,
+	.get_embedded_display_refresh_rate = NULL,
+	.get_requested_backlight_level = NULL,
+	.get_scratch_lcd_scale = get_scratch_lcd_scale,
+	.is_accelerated_mode = is_accelerated_mode,
+	.is_active_display = NULL,
+	.is_display_config_changed = NULL,
+	.is_lid_open = is_lid_open,
+	.is_lid_status_changed = NULL,
+	.prepare_scratch_active_and_requested =
+			prepare_scratch_active_and_requested,
+	.set_scratch_acc_mode_change = set_scratch_acc_mode_change,
+	.set_scratch_active_and_requested = set_scratch_active_and_requested,
+	.set_scratch_connected = set_scratch_connected,
+	.set_scratch_critical_state = set_scratch_critical_state,
+	.set_scratch_lcd_scale = set_scratch_lcd_scale,
+	.take_backlight_control = NULL,
+	.update_requested_backlight_level = NULL,
+};
+
+/*
+ * dal_bios_parser_dce110_init_bios_helper
+ *
+ * @brief
+ * Initialize BIOS helper functions
+ *
+ * @param
+ * const struct command_table_helper **h - [out] struct of functions
+ *
+ */
+
+const struct bios_parser_helper *dal_bios_parser_helper_dce110_get_table()
+{
+	return &bios_parser_helper_funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
new file mode 100644
index 000000000000..915f31ab9c1a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_HELPER_DCE110_H__
+#define __DAL_BIOS_PARSER_HELPER_DCE110_H__
+
+struct bios_parser_helper;
+
+/* Initialize BIOS helper functions */
+const struct bios_parser_helper *dal_bios_parser_helper_dce110_get_table(void);
+
+#endif /* __DAL_BIOS_PARSER_HELPER_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
new file mode 100644
index 000000000000..614ba94ac0c3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "include/adapter_service_types.h"
+
+#include "../command_table_helper.h"
+
+static uint8_t phy_id_to_atom(enum transmitter t)
+{
+	uint8_t atom_phy_id;
+
+	switch (t) {
+	case TRANSMITTER_UNIPHY_A:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYA;
+		break;
+	case TRANSMITTER_UNIPHY_B:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYB;
+		break;
+	case TRANSMITTER_UNIPHY_C:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYC;
+		break;
+	case TRANSMITTER_UNIPHY_D:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYD;
+		break;
+	case TRANSMITTER_UNIPHY_E:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYE;
+		break;
+	case TRANSMITTER_UNIPHY_F:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYF;
+		break;
+	case TRANSMITTER_UNIPHY_G:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYG;
+		break;
+	default:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYA;
+		break;
+	}
+	return atom_phy_id;
+}
+
+
+static uint8_t signal_type_to_atom_dig_mode(enum signal_type s)
+{
+	uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
+
+	switch (s) {
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_EDP:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
+		break;
+	case SIGNAL_TYPE_LVDS:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS;
+		break;
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
+		break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI;
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST;
+		break;
+	default:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
+		break;
+	}
+
+	return atom_dig_mode;
+}
+
+static uint8_t clock_source_id_to_atom_phy_clk_src_id(
+		enum clock_source_id id)
+{
+	uint8_t atom_phy_clk_src_id = 0;
+
+	switch (id) {
+	case CLOCK_SOURCE_ID_PLL0:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL;
+		break;
+	case CLOCK_SOURCE_ID_PLL1:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
+		break;
+	case CLOCK_SOURCE_ID_PLL2:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL;
+		break;
+	case CLOCK_SOURCE_ID_EXTERNAL:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT;
+		break;
+	default:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
+		break;
+	}
+
+	return atom_phy_clk_src_id >> 2;
+}
+
+static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
+{
+	uint8_t atom_hpd_sel = 0;
+
+	switch (id) {
+	case HPD_SOURCEID1:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL;
+		break;
+	case HPD_SOURCEID2:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL;
+		break;
+	case HPD_SOURCEID3:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL;
+		break;
+	case HPD_SOURCEID4:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL;
+		break;
+	case HPD_SOURCEID5:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL;
+		break;
+	case HPD_SOURCEID6:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL;
+		break;
+	case HPD_SOURCEID_UNKNOWN:
+	default:
+		atom_hpd_sel = 0;
+		break;
+	}
+	return atom_hpd_sel >> 4;
+}
+
+static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
+{
+	uint8_t atom_dig_encoder_sel = 0;
+
+	switch (id) {
+	case ENGINE_ID_DIGA:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
+		break;
+	case ENGINE_ID_DIGB:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL;
+		break;
+	case ENGINE_ID_DIGC:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL;
+		break;
+	case ENGINE_ID_DIGD:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL;
+		break;
+	case ENGINE_ID_DIGE:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL;
+		break;
+	case ENGINE_ID_DIGF:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL;
+		break;
+	case ENGINE_ID_DIGG:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL;
+		break;
+	case ENGINE_ID_UNKNOWN:
+		 /* No DIG_FRONT is associated to DIG_BACKEND */
+		atom_dig_encoder_sel = 0;
+		break;
+	default:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
+		break;
+	}
+
+	return atom_dig_encoder_sel;
+}
+
+static bool clock_source_id_to_atom(
+	enum clock_source_id id,
+	uint32_t *atom_pll_id)
+{
+	bool result = true;
+
+	if (atom_pll_id != NULL)
+		switch (id) {
+		case CLOCK_SOURCE_ID_PLL0:
+			*atom_pll_id = ATOM_PPLL0;
+			break;
+		case CLOCK_SOURCE_ID_PLL1:
+			*atom_pll_id = ATOM_PPLL1;
+			break;
+		case CLOCK_SOURCE_ID_PLL2:
+			*atom_pll_id = ATOM_PPLL2;
+			break;
+		case CLOCK_SOURCE_ID_EXTERNAL:
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			break;
+		case CLOCK_SOURCE_ID_DFS:
+			*atom_pll_id = ATOM_EXT_PLL1;
+			break;
+		case CLOCK_SOURCE_ID_VCE:
+			/* for VCE encoding,
+			 * we need to pass in ATOM_PPLL_INVALID
+			 */
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			break;
+		case CLOCK_SOURCE_ID_DP_DTO:
+			/* When programming DP DTO PLL ID should be invalid */
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			break;
+		case CLOCK_SOURCE_ID_UNDEFINED:
+			/* Should not happen */
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			result = false;
+			break;
+		default:
+			result = false;
+			break;
+		}
+
+	return result;
+}
+
+static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id)
+{
+	bool result = false;
+
+	if (atom_engine_id != NULL)
+		switch (id) {
+		case ENGINE_ID_DIGA:
+			*atom_engine_id = ASIC_INT_DIG1_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGB:
+			*atom_engine_id = ASIC_INT_DIG2_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGC:
+			*atom_engine_id = ASIC_INT_DIG3_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGD:
+			*atom_engine_id = ASIC_INT_DIG4_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGE:
+			*atom_engine_id = ASIC_INT_DIG5_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGF:
+			*atom_engine_id = ASIC_INT_DIG6_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGG:
+			*atom_engine_id = ASIC_INT_DIG7_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DACA:
+			*atom_engine_id = ASIC_INT_DAC1_ENCODER_ID;
+			result = true;
+			break;
+		default:
+			break;
+		}
+
+	return result;
+}
+
+static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action)
+{
+	uint8_t atom_action = 0;
+
+	switch (action) {
+	case ENCODER_CONTROL_ENABLE:
+		atom_action = ATOM_ENABLE;
+		break;
+	case ENCODER_CONTROL_DISABLE:
+		atom_action = ATOM_DISABLE;
+		break;
+	case ENCODER_CONTROL_SETUP:
+		atom_action = ATOM_ENCODER_CMD_SETUP;
+		break;
+	case ENCODER_CONTROL_INIT:
+		atom_action = ATOM_ENCODER_INIT;
+		break;
+	default:
+		BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */
+		break;
+	}
+
+	return atom_action;
+}
+
+static uint8_t disp_power_gating_action_to_atom(
+	enum bp_pipe_control_action action)
+{
+	uint8_t atom_pipe_action = 0;
+
+	switch (action) {
+	case ASIC_PIPE_DISABLE:
+		atom_pipe_action = ATOM_DISABLE;
+		break;
+	case ASIC_PIPE_ENABLE:
+		atom_pipe_action = ATOM_ENABLE;
+		break;
+	case ASIC_PIPE_INIT:
+		atom_pipe_action = ATOM_INIT;
+		break;
+	default:
+		ASSERT_CRITICAL(false); /* Unhandle action in driver! */
+		break;
+	}
+
+	return atom_pipe_action;
+}
+
+/* function table */
+static const struct command_table_helper command_table_helper_funcs = {
+	.controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom,
+	.encoder_action_to_atom = encoder_action_to_atom,
+	.engine_bp_to_atom = engine_bp_to_atom,
+	.clock_source_id_to_atom = clock_source_id_to_atom,
+	.clock_source_id_to_atom_phy_clk_src_id =
+			clock_source_id_to_atom_phy_clk_src_id,
+	.signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode,
+	.hpd_sel_to_atom = hpd_sel_to_atom,
+	.dig_encoder_sel_to_atom = dig_encoder_sel_to_atom,
+	.phy_id_to_atom = phy_id_to_atom,
+	.disp_power_gating_action_to_atom = disp_power_gating_action_to_atom,
+	.assign_control_parameter = NULL,
+	.clock_source_id_to_ref_clk_src = NULL,
+	.transmitter_bp_to_atom = NULL,
+	.encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom,
+	.encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom,
+};
+
+/*
+ * dal_cmd_tbl_helper_dce110_get_table
+ *
+ * @brief
+ * Initialize command table helper functions
+ *
+ * @param
+ * const struct command_table_helper **h - [out] struct of functions
+ *
+ */
+const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table()
+{
+	return &command_table_helper_funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
new file mode 100644
index 000000000000..eb60c2ead992
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_HELPER_DCE110_H__
+#define __DAL_COMMAND_TABLE_HELPER_DCE110_H__
+
+struct command_table_helper;
+
+/* Initialize command table helper functions */
+const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table(void);
+
+#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 08/29] drm/amd/dal: I2C Aux Manager
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (6 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 07/29] drm/amd/dal: BIOS Parser Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 20:19   ` Rob Clark
  2016-02-11 17:19 ` [PATCH 09/29] drm/amd/dal: IRQ Service Harry Wentland
                   ` (24 subsequent siblings)
  32 siblings, 1 reply; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Implements low-level communication layer over I2C and Aux lines using
GPIO handles.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |  33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     | 567 ++++++++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     | 119 +++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   | 788 +++++++++++++++++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |  56 ++
 .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |  25 +
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    | 954 +++++++++++++++++++++
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |  58 ++
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    | 172 ++++
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |  43 +
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   | 266 ++++++
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |  39 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    | 112 +++
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |  33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         | 129 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |  67 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     | 121 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     | 113 +++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  | 286 ++++++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |  77 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  | 246 ++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |  80 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  | 614 +++++++++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |  81 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         | 529 ++++++++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         | 123 +++
 26 files changed, 5731 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h

diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile b/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
new file mode 100644
index 000000000000..390d83d649f5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
@@ -0,0 +1,33 @@
+#
+# Makefile for the 'i2c' sub-component of DAL.
+# It provides the control and status of HW i2c engine of the adapter.
+
+I2CAUX = aux_engine.o engine_base.o i2caux.o i2c_engine.o \
+	 i2c_generic_hw_engine.o i2c_hw_engine.o i2c_sw_engine.o
+
+AMD_DAL_I2CAUX = $(addprefix $(AMDDALPATH)/dc/i2caux/,$(I2CAUX))
+
+AMD_DAL_FILES += $(AMD_DAL_I2CAUX)
+
+
+###############################################################################
+# DCE 11x family
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+I2CAUX_DCE110 = i2caux_dce110.o i2c_sw_engine_dce110.o i2c_hw_engine_dce110.o \
+	aux_engine_dce110.o
+
+AMD_DAL_I2CAUX_DCE110 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce110/,$(I2CAUX_DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_I2CAUX_DCE110)
+endif
+
+###############################################################################
+# Diagnostics on FPGA
+###############################################################################
+I2CAUX_DIAG = i2caux_diag.o
+
+AMD_DAL_I2CAUX_DIAG = $(addprefix $(AMDDALPATH)/dc/i2caux/diagnostics/,$(I2CAUX_DIAG))
+
+AMD_DAL_FILES += $(AMD_DAL_I2CAUX_DIAG)
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
new file mode 100644
index 000000000000..7042d10ee7dc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "aux_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "include/link_service_types.h"
+
+/*
+ * This unit
+ */
+
+enum {
+	AUX_INVALID_REPLY_RETRY_COUNTER = 1,
+	AUX_TIMED_OUT_RETRY_COUNTER = 2,
+	AUX_DEFER_RETRY_COUNTER = 6
+};
+
+#define FROM_ENGINE(ptr) \
+	container_of((ptr), struct aux_engine, base)
+
+enum i2caux_engine_type dal_aux_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_AUX;
+}
+
+bool dal_aux_engine_acquire(
+	struct engine *engine,
+	struct ddc *ddc)
+{
+	struct aux_engine *aux_engine = FROM_ENGINE(engine);
+
+	enum gpio_result result;
+
+	result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
+		GPIO_DDC_CONFIG_TYPE_MODE_AUX);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	if (!aux_engine->funcs->acquire_engine(aux_engine)) {
+		dal_ddc_close(ddc);
+		return false;
+	}
+
+	engine->ddc = ddc;
+
+	return true;
+}
+
+struct read_command_context {
+	uint8_t *buffer;
+	uint8_t current_read_length;
+	uint32_t offset;
+	enum i2caux_transaction_status status;
+
+	struct aux_request_transaction_data request;
+	struct aux_reply_transaction_data reply;
+
+	uint8_t returned_byte;
+
+	uint32_t timed_out_retry_aux;
+	uint32_t invalid_reply_retry_aux;
+	uint32_t defer_retry_aux;
+	uint32_t defer_retry_i2c;
+	uint32_t invalid_reply_retry_aux_on_ack;
+
+	bool transaction_complete;
+	bool operation_succeeded;
+};
+
+static void process_read_reply(
+	struct aux_engine *engine,
+	struct read_command_context *ctx)
+{
+	engine->funcs->process_channel_reply(engine, &ctx->reply);
+
+	switch (ctx->reply.status) {
+	case AUX_TRANSACTION_REPLY_AUX_ACK:
+		ctx->defer_retry_aux = 0;
+		if (ctx->returned_byte > ctx->current_read_length) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else if (ctx->returned_byte < ctx->current_read_length) {
+			ctx->current_read_length -= ctx->returned_byte;
+
+			ctx->offset += ctx->returned_byte;
+
+			++ctx->invalid_reply_retry_aux_on_ack;
+
+			if (ctx->invalid_reply_retry_aux_on_ack >
+				AUX_INVALID_REPLY_RETRY_COUNTER) {
+				ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+				ctx->operation_succeeded = false;
+			}
+		} else {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+			ctx->transaction_complete = true;
+			ctx->operation_succeeded = true;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_NACK:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+		ctx->operation_succeeded = false;
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_DEFER:
+		++ctx->defer_retry_aux;
+
+		if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_I2C_DEFER:
+		ctx->defer_retry_aux = 0;
+
+		++ctx->defer_retry_i2c;
+
+		if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static void process_read_request(
+	struct aux_engine *engine,
+	struct read_command_context *ctx)
+{
+	enum aux_channel_operation_result operation_result;
+
+	engine->funcs->submit_channel_request(engine, &ctx->request);
+
+	operation_result = engine->funcs->get_channel_status(
+		engine, &ctx->returned_byte);
+
+	switch (operation_result) {
+	case AUX_CHANNEL_OPERATION_SUCCEEDED:
+		if (ctx->returned_byte > ctx->current_read_length) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else {
+			ctx->timed_out_retry_aux = 0;
+			ctx->invalid_reply_retry_aux = 0;
+
+			ctx->reply.length = ctx->returned_byte;
+			ctx->reply.data = ctx->buffer;
+
+			process_read_reply(engine, ctx);
+		}
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
+		++ctx->invalid_reply_retry_aux;
+
+		if (ctx->invalid_reply_retry_aux >
+			AUX_INVALID_REPLY_RETRY_COUNTER) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else
+			dm_delay_in_microseconds(engine->base.ctx, 400);
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
+		++ctx->timed_out_retry_aux;
+
+		if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		} else {
+			/* DP 1.2a, table 2-58:
+			 * "S3: AUX Request CMD PENDING:
+			 * retry 3 times, with 400usec wait on each"
+			 * The HW timeout is set to 550usec,
+			 * so we should not wait here */
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static bool read_command(
+	struct aux_engine *engine,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction)
+{
+	struct read_command_context ctx;
+
+	ctx.buffer = request->payload.data;
+	ctx.current_read_length = request->payload.length;
+	ctx.offset = 0;
+	ctx.timed_out_retry_aux = 0;
+	ctx.invalid_reply_retry_aux = 0;
+	ctx.defer_retry_aux = 0;
+	ctx.defer_retry_i2c = 0;
+	ctx.invalid_reply_retry_aux_on_ack = 0;
+	ctx.transaction_complete = false;
+	ctx.operation_succeeded = true;
+
+	if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_DP;
+		ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ;
+		ctx.request.address = request->payload.address;
+	} else if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
+		ctx.request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_READ;
+		ctx.request.address = request->payload.address >> 1;
+	} else {
+		/* in DAL2, there was no return in such case */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	ctx.request.delay = 0;
+
+	do {
+		dm_memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length);
+
+		ctx.request.data = ctx.buffer + ctx.offset;
+		ctx.request.length = ctx.current_read_length;
+
+		process_read_request(engine, &ctx);
+
+		request->status = ctx.status;
+
+		if (ctx.operation_succeeded && !ctx.transaction_complete)
+			if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
+				dm_sleep_in_milliseconds(engine->base.ctx, engine->delay);
+	} while (ctx.operation_succeeded && !ctx.transaction_complete);
+
+	return ctx.operation_succeeded;
+}
+
+struct write_command_context {
+	bool mot;
+
+	uint8_t *buffer;
+	uint8_t current_write_length;
+	enum i2caux_transaction_status status;
+
+	struct aux_request_transaction_data request;
+	struct aux_reply_transaction_data reply;
+
+	uint8_t returned_byte;
+
+	uint32_t timed_out_retry_aux;
+	uint32_t invalid_reply_retry_aux;
+	uint32_t defer_retry_aux;
+	uint32_t defer_retry_i2c;
+	uint32_t max_defer_retry;
+	uint32_t ack_m_retry;
+
+	uint8_t reply_data[DEFAULT_AUX_MAX_DATA_SIZE];
+
+	bool transaction_complete;
+	bool operation_succeeded;
+};
+
+static void process_write_reply(
+	struct aux_engine *engine,
+	struct write_command_context *ctx)
+{
+	engine->funcs->process_channel_reply(engine, &ctx->reply);
+
+	switch (ctx->reply.status) {
+	case AUX_TRANSACTION_REPLY_AUX_ACK:
+		ctx->operation_succeeded = true;
+
+		if (ctx->returned_byte) {
+			ctx->request.action = ctx->mot ?
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
+
+			ctx->current_write_length = 0;
+
+			++ctx->ack_m_retry;
+
+			if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) {
+				ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+				ctx->operation_succeeded = false;
+			} else
+				dm_delay_in_microseconds(engine->base.ctx, 300);
+		} else {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+			ctx->defer_retry_aux = 0;
+			ctx->ack_m_retry = 0;
+			ctx->transaction_complete = true;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_NACK:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+		ctx->operation_succeeded = false;
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_DEFER:
+		++ctx->defer_retry_aux;
+
+		if (ctx->defer_retry_aux > ctx->max_defer_retry) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_I2C_DEFER:
+		ctx->defer_retry_aux = 0;
+		ctx->current_write_length = 0;
+
+		ctx->request.action = ctx->mot ?
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
+
+		++ctx->defer_retry_i2c;
+
+		if (ctx->defer_retry_i2c > ctx->max_defer_retry) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static void process_write_request(
+	struct aux_engine *engine,
+	struct write_command_context *ctx)
+{
+	enum aux_channel_operation_result operation_result;
+
+	engine->funcs->submit_channel_request(engine, &ctx->request);
+
+	operation_result = engine->funcs->get_channel_status(
+		engine, &ctx->returned_byte);
+
+	switch (operation_result) {
+	case AUX_CHANNEL_OPERATION_SUCCEEDED:
+		ctx->timed_out_retry_aux = 0;
+		ctx->invalid_reply_retry_aux = 0;
+
+		ctx->reply.length = ctx->returned_byte;
+		ctx->reply.data = ctx->reply_data;
+
+		process_write_reply(engine, ctx);
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
+		++ctx->invalid_reply_retry_aux;
+
+		if (ctx->invalid_reply_retry_aux >
+			AUX_INVALID_REPLY_RETRY_COUNTER) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else
+			dm_delay_in_microseconds(engine->base.ctx, 400);
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
+		++ctx->timed_out_retry_aux;
+
+		if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		} else {
+			/* DP 1.2a, table 2-58:
+			 * "S3: AUX Request CMD PENDING:
+			 * retry 3 times, with 400usec wait on each"
+			 * The HW timeout is set to 550usec,
+			 * so we should not wait here */
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static bool write_command(
+	struct aux_engine *engine,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction)
+{
+	struct write_command_context ctx;
+
+	ctx.mot = middle_of_transaction;
+	ctx.buffer = request->payload.data;
+	ctx.current_write_length = request->payload.length;
+	ctx.timed_out_retry_aux = 0;
+	ctx.invalid_reply_retry_aux = 0;
+	ctx.defer_retry_aux = 0;
+	ctx.defer_retry_i2c = 0;
+	ctx.ack_m_retry = 0;
+	ctx.transaction_complete = false;
+	ctx.operation_succeeded = true;
+
+	if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_DP;
+		ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
+		ctx.request.address = request->payload.address;
+	} else if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
+		ctx.request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+		ctx.request.address = request->payload.address >> 1;
+	} else {
+		/* in DAL2, there was no return in such case */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	ctx.request.delay = 0;
+
+	ctx.max_defer_retry =
+		(engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ?
+			engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER;
+
+	do {
+		ctx.request.data = ctx.buffer;
+		ctx.request.length = ctx.current_write_length;
+
+		process_write_request(engine, &ctx);
+
+		request->status = ctx.status;
+
+		if (ctx.operation_succeeded && !ctx.transaction_complete)
+			if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
+				dm_sleep_in_milliseconds(engine->base.ctx, engine->delay);
+	} while (ctx.operation_succeeded && !ctx.transaction_complete);
+
+	return ctx.operation_succeeded;
+}
+
+static bool end_of_transaction_command(
+	struct aux_engine *engine,
+	struct i2caux_transaction_request *request)
+{
+	struct i2caux_transaction_request dummy_request;
+	uint8_t dummy_data;
+
+	/* [tcheng] We only need to send the stop (read with MOT = 0)
+	 * for I2C-over-Aux, not native AUX */
+
+	if (request->payload.address_space !=
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C)
+		return false;
+
+	dummy_request.operation = request->operation;
+	dummy_request.payload.address_space = request->payload.address_space;
+	dummy_request.payload.address = request->payload.address;
+
+	/*
+	 * Add a dummy byte due to some receiver quirk
+	 * where one byte is sent along with MOT = 0.
+	 * Ideally this should be 0.
+	 */
+
+	dummy_request.payload.length = 0;
+	dummy_request.payload.data = &dummy_data;
+
+	if (request->operation == I2CAUX_TRANSACTION_READ)
+		return read_command(engine, &dummy_request, false);
+	else
+		return write_command(engine, &dummy_request, false);
+
+	/* according Syed, it does not need now DoDummyMOT */
+}
+
+bool dal_aux_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction)
+{
+	struct aux_engine *aux_engine = FROM_ENGINE(engine);
+
+	bool result;
+	bool mot_used = true;
+
+	switch (request->operation) {
+	case I2CAUX_TRANSACTION_READ:
+		result = read_command(aux_engine, request, mot_used);
+	break;
+	case I2CAUX_TRANSACTION_WRITE:
+		result = write_command(aux_engine, request, mot_used);
+	break;
+	default:
+		result = false;
+	}
+
+	/* [tcheng]
+	 * need to send stop for the last transaction to free up the AUX
+	 * if the above command fails, this would be the last transaction */
+
+	if (!middle_of_transaction || !result)
+		end_of_transaction_command(aux_engine, request);
+
+	/* mask AUX interrupt */
+
+	return result;
+}
+
+bool dal_aux_engine_construct(
+	struct aux_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2caux_construct_engine(&engine->base, ctx))
+		return false;
+	engine->delay = 0;
+	engine->max_defer_write_retry = 0;
+	return true;
+}
+
+void dal_aux_engine_destruct(
+	struct aux_engine *engine)
+{
+	dal_i2caux_destruct_engine(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
new file mode 100644
index 000000000000..474f5e911f49
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUX_ENGINE_H__
+#define __DAL_AUX_ENGINE_H__
+
+enum aux_transaction_type {
+	AUX_TRANSACTION_TYPE_DP,
+	AUX_TRANSACTION_TYPE_I2C
+};
+
+struct aux_request_transaction_data {
+	enum aux_transaction_type type;
+	enum i2caux_transaction_action action;
+	/* 20-bit AUX channel transaction address */
+	uint32_t address;
+	/* delay, in 100-microsecond units */
+	uint8_t delay;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum aux_transaction_reply {
+	AUX_TRANSACTION_REPLY_AUX_ACK = 0x00,
+	AUX_TRANSACTION_REPLY_AUX_NACK = 0x01,
+	AUX_TRANSACTION_REPLY_AUX_DEFER = 0x02,
+
+	AUX_TRANSACTION_REPLY_I2C_ACK = 0x00,
+	AUX_TRANSACTION_REPLY_I2C_NACK = 0x10,
+	AUX_TRANSACTION_REPLY_I2C_DEFER = 0x20,
+
+	AUX_TRANSACTION_REPLY_INVALID = 0xFF
+};
+
+struct aux_reply_transaction_data {
+	enum aux_transaction_reply status;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum aux_channel_operation_result {
+	AUX_CHANNEL_OPERATION_SUCCEEDED,
+	AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN,
+	AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY,
+	AUX_CHANNEL_OPERATION_FAILED_TIMEOUT
+};
+
+struct aux_engine;
+
+struct aux_engine_funcs {
+	void (*destroy)(
+		struct aux_engine **ptr);
+	bool (*acquire_engine)(
+		struct aux_engine *engine);
+	void (*configure)(
+		struct aux_engine *engine,
+		union aux_config cfg);
+	bool (*start_gtc_sync)(
+		struct aux_engine *engine);
+	void (*stop_gtc_sync)(
+		struct aux_engine *engine);
+	void (*submit_channel_request)(
+		struct aux_engine *engine,
+		struct aux_request_transaction_data *request);
+	void (*process_channel_reply)(
+		struct aux_engine *engine,
+		struct aux_reply_transaction_data *reply);
+	enum aux_channel_operation_result (*get_channel_status)(
+		struct aux_engine *engine,
+		uint8_t *returned_bytes);
+};
+
+struct aux_engine {
+	struct engine base;
+	const struct aux_engine_funcs *funcs;
+	/* following values are expressed in milliseconds */
+	uint32_t delay;
+	uint32_t max_defer_write_retry;
+};
+
+bool dal_aux_engine_construct(
+	struct aux_engine *engine,
+	struct dc_context *ctx);
+
+void dal_aux_engine_destruct(
+	struct aux_engine *engine);
+bool dal_aux_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction);
+bool dal_aux_engine_acquire(
+	struct engine *ptr,
+	struct ddc *ddc);
+enum i2caux_engine_type dal_aux_engine_get_engine_type(
+	const struct engine *engine);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
new file mode 100644
index 000000000000..f9c55435b5a0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
@@ -0,0 +1,788 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../engine.h"
+#include "../aux_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "aux_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct aux_engine *'
+ * to 'struct aux_engine_dce110 *'
+ */
+#define FROM_AUX_ENGINE(ptr) \
+	container_of((ptr), struct aux_engine_dce110, base)
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct aux_engine_dce110 *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base))
+
+static void release_engine(
+	struct engine *engine)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_ENGINE(engine);
+
+	const uint32_t addr = aux_engine->addr.aux_arb_control;
+
+	uint32_t value = dm_read_reg(engine->ctx, addr);
+
+	set_reg_field_value(
+		value,
+		1,
+		AUX_ARB_CONTROL,
+		AUX_SW_DONE_USING_AUX_REG);
+
+	dm_write_reg(engine->ctx, addr, value);
+}
+
+static void destruct(
+	struct aux_engine_dce110 *engine);
+
+static void destroy(
+	struct aux_engine **aux_engine)
+{
+	struct aux_engine_dce110 *engine = FROM_AUX_ENGINE(*aux_engine);
+
+	destruct(engine);
+
+	dm_free((*aux_engine)->base.ctx, engine);
+
+	*aux_engine = NULL;
+}
+
+#define SW_CAN_ACCESS_AUX 1
+
+static bool acquire_engine(
+	struct aux_engine *engine)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+	uint32_t value;
+	uint32_t field;
+
+	/* enable AUX before request SW to access AUX */
+	{
+		const uint32_t addr = aux_engine->addr.aux_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		field = get_reg_field_value(
+				value,
+				AUX_CONTROL,
+				AUX_EN);
+
+		if (field == 0) {
+			uint8_t counter = 0;
+
+			set_reg_field_value(
+				value,
+				1,
+				AUX_CONTROL,
+				AUX_EN);
+
+			/*DP_AUX block as part of the enable sequence*/
+			set_reg_field_value(
+				value,
+				1,
+				AUX_CONTROL,
+				AUX_RESET);
+
+			dm_write_reg(engine->base.ctx, addr, value);
+
+			/*poll HW to make sure reset it done*/
+			do {
+				dm_delay_in_microseconds(engine->base.ctx, 1);
+
+				value = dm_read_reg(engine->base.ctx, addr);
+
+				field = get_reg_field_value(
+						value,
+						AUX_CONTROL,
+						AUX_RESET_DONE);
+
+				counter++;
+
+			} while ((field == 0) && (counter < 11));
+
+			set_reg_field_value(
+				value,
+				0,
+				AUX_CONTROL,
+				AUX_RESET);
+
+			dm_write_reg(engine->base.ctx, addr, value);
+
+			counter = 0;
+
+			do {
+				dm_delay_in_microseconds(engine->base.ctx, 1);
+
+				value = dm_read_reg(engine->base.ctx, addr);
+
+				field = get_reg_field_value(
+						value,
+						AUX_CONTROL,
+						AUX_RESET_DONE);
+
+				counter++;
+
+			} while ((field == 1) && (counter < 11));
+		} /*if (field)*/
+	}
+
+	/* request SW to access AUX */
+	{
+		const uint32_t addr = aux_engine->addr.aux_arb_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_ARB_CONTROL,
+			AUX_SW_USE_AUX_REG_REQ);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		field = get_reg_field_value(
+				value,
+				AUX_ARB_CONTROL,
+				AUX_REG_RW_CNTL_STATUS);
+
+		return field == SW_CAN_ACCESS_AUX;
+	}
+}
+
+static void configure(
+	struct aux_engine *engine,
+	union aux_config cfg)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+
+	const uint32_t addr = aux_engine->addr.aux_control;
+
+	uint32_t value = dm_read_reg(engine->base.ctx, addr);
+
+	set_reg_field_value(
+		value,
+		(0 != cfg.bits.ALLOW_AUX_WHEN_HPD_LOW),
+		AUX_CONTROL,
+		AUX_IGNORE_HPD_DISCON);
+
+	dm_write_reg(engine->base.ctx, addr, value);
+}
+
+static bool start_gtc_sync(
+	struct aux_engine *engine)
+{
+	/*TODO*/
+	return false;
+}
+
+static void stop_gtc_sync(
+	struct aux_engine *engine)
+{
+	/*TODO*/
+}
+
+#define COMPOSE_AUX_SW_DATA_16_20(command, address) \
+	((command) | ((0xF0000 & (address)) >> 16))
+
+#define COMPOSE_AUX_SW_DATA_8_15(address) \
+	((0xFF00 & (address)) >> 8)
+
+#define COMPOSE_AUX_SW_DATA_0_7(address) \
+	(0xFF & (address))
+
+static void submit_channel_request(
+	struct aux_engine *engine,
+	struct aux_request_transaction_data *request)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+	uint32_t value;
+	uint32_t length;
+
+	bool is_write =
+		((request->type == AUX_TRANSACTION_TYPE_DP) &&
+		 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
+		((request->type == AUX_TRANSACTION_TYPE_I2C) &&
+		((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
+		 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
+
+	/* clear_aux_error */
+	{
+		const uint32_t addr = mmAUXN_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXN_IMPCAL,
+			AUXN_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXN_IMPCAL,
+			AUXN_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+	{
+		const uint32_t addr = mmAUXP_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXP_IMPCAL,
+			AUXP_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXP_IMPCAL,
+			AUXP_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	/* force_default_calibrate */
+	{
+		const uint32_t addr = mmAUXN_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXN_IMPCAL,
+			AUXN_IMPCAL_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXN_IMPCAL,
+			AUXN_IMPCAL_OVERRIDE_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+	{
+		const uint32_t addr = mmAUXP_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXP_IMPCAL,
+			AUXP_IMPCAL_OVERRIDE_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXP_IMPCAL,
+			AUXP_IMPCAL_OVERRIDE_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	/* set the delay and the number of bytes to write */
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			request->delay,
+			AUX_SW_CONTROL,
+			AUX_SW_START_DELAY);
+
+		/* The length include
+		 * the 4 bit header and the 20 bit address
+		 * (that is 3 byte).
+		 * If the requested length is non zero this means
+		 * an addition byte specifying the length is required. */
+
+		length = request->length ? 4 : 3;
+		if (is_write)
+			length += request->length;
+
+		set_reg_field_value(
+			value,
+			length,
+			AUX_SW_CONTROL,
+			AUX_SW_WR_BYTES);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	/* program action and address and payload data (if 'is_write') */
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_data;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_INDEX);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_DATA_RW);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_DATA,
+			AUX_SW_AUTOINCREMENT_DISABLE);
+
+		set_reg_field_value(
+			value,
+			COMPOSE_AUX_SW_DATA_16_20(
+				request->action, request->address),
+			AUX_SW_DATA,
+			AUX_SW_DATA);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_AUTOINCREMENT_DISABLE);
+
+		set_reg_field_value(
+			value,
+			COMPOSE_AUX_SW_DATA_8_15(request->address),
+			AUX_SW_DATA,
+			AUX_SW_DATA);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			COMPOSE_AUX_SW_DATA_0_7(request->address),
+			AUX_SW_DATA,
+			AUX_SW_DATA);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		if (request->length) {
+			set_reg_field_value(
+				value,
+				request->length - 1,
+				AUX_SW_DATA,
+				AUX_SW_DATA);
+
+			dm_write_reg(engine->base.ctx, addr, value);
+		}
+
+		if (is_write) {
+			/* Load the HW buffer with the Data to be sent.
+			 * This is relevant for write operation.
+			 * For read, the data recived data will be
+			 * processed in process_channel_reply(). */
+			uint32_t i = 0;
+
+			while (i < request->length) {
+
+				set_reg_field_value(
+					value,
+					request->data[i],
+					AUX_SW_DATA,
+					AUX_SW_DATA);
+
+				dm_write_reg(
+					engine->base.ctx, addr, value);
+
+				++i;
+			}
+		}
+	}
+
+	{
+		const uint32_t addr = aux_engine->addr.aux_interrupt_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_INTERRUPT_CONTROL,
+			AUX_SW_DONE_ACK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_CONTROL,
+			AUX_SW_GO);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+}
+
+static void process_channel_reply(
+	struct aux_engine *engine,
+	struct aux_reply_transaction_data *reply)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+
+	/* Need to do a read to get the number of bytes to process
+	 * Alternatively, this information can be passed -
+	 * but that causes coupling which isn't good either. */
+
+	uint32_t bytes_replied;
+	uint32_t value;
+
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_status;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		bytes_replied = get_reg_field_value(
+				value,
+				AUX_SW_STATUS,
+				AUX_SW_REPLY_BYTE_COUNT);
+	}
+
+	if (bytes_replied) {
+		uint32_t reply_result;
+
+		const uint32_t addr = aux_engine->addr.aux_sw_data;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_INDEX);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_DATA,
+			AUX_SW_AUTOINCREMENT_DISABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_DATA,
+			AUX_SW_DATA_RW);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		reply_result = get_reg_field_value(
+				value,
+				AUX_SW_DATA,
+				AUX_SW_DATA);
+
+		reply_result = reply_result >> 4;
+
+		switch (reply_result) {
+		case 0: /* ACK */ {
+			uint32_t i = 0;
+
+			/* first byte was already used
+			 * to get the command status */
+			--bytes_replied;
+
+			while (i < bytes_replied) {
+				value = dm_read_reg(
+					engine->base.ctx, addr);
+
+				reply->data[i] = get_reg_field_value(
+						value,
+						AUX_SW_DATA,
+						AUX_SW_DATA);
+
+				++i;
+			}
+
+			reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
+		}
+		break;
+		case 1: /* NACK */
+			reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
+		break;
+		case 2: /* DEFER */
+			reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
+		break;
+		case 4: /* AUX ACK / I2C NACK */
+			reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
+		break;
+		case 8: /* AUX ACK / I2C DEFER */
+			reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
+		break;
+		default:
+			reply->status = AUX_TRANSACTION_REPLY_INVALID;
+		}
+	} else {
+		/* Need to handle an error case...
+		 * hopefully, upper layer function won't call this function
+		 * if the number of bytes in the reply was 0
+		 * because there was surely an error that was asserted
+		 * that should have been handled
+		 * for hot plug case, this could happens*/
+		if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
+			ASSERT_CRITICAL(false);
+	}
+}
+
+static enum aux_channel_operation_result get_channel_status(
+	struct aux_engine *engine,
+	uint8_t *returned_bytes)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+
+	const uint32_t addr = aux_engine->addr.aux_sw_status;
+
+	uint32_t value;
+	uint32_t aux_sw_done;
+
+	if (returned_bytes == NULL) {
+		/*caller pass NULL pointer*/
+		ASSERT_CRITICAL(false);
+		return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
+	}
+	*returned_bytes = 0;
+
+	/* poll to make sure that SW_DONE is asserted */
+	{
+		uint32_t time_elapsed = 0;
+
+		do {
+			value = dm_read_reg(engine->base.ctx, addr);
+
+			aux_sw_done = get_reg_field_value(
+					value,
+					AUX_SW_STATUS,
+					AUX_SW_DONE);
+
+			if (aux_sw_done)
+				break;
+
+			dm_delay_in_microseconds(engine->base.ctx, 10);
+
+			time_elapsed += 10;
+		} while (time_elapsed < aux_engine->timeout_period);
+
+
+	}
+
+	/* Note that the following bits are set in 'status.bits'
+	 * during CTS 4.2.1.2:
+	 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
+	 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
+	 *
+	 * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
+	 * HW debugging bit and should be ignored. */
+	if (aux_sw_done) {
+		if (get_reg_field_value(
+			value,
+			AUX_SW_STATUS,
+			AUX_SW_RX_TIMEOUT_STATE) ||
+			get_reg_field_value(
+				value,
+				AUX_SW_STATUS,
+				AUX_SW_RX_TIMEOUT))
+			return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
+		else if (get_reg_field_value(
+			value,
+			AUX_SW_STATUS,
+			AUX_SW_RX_INVALID_STOP))
+			return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
+
+		*returned_bytes = get_reg_field_value(
+				value,
+				AUX_SW_STATUS,
+				AUX_SW_REPLY_BYTE_COUNT);
+		if (*returned_bytes == 0)
+			return
+			AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
+		else {
+			*returned_bytes -= 1;
+			return AUX_CHANNEL_OPERATION_SUCCEEDED;
+		}
+	} else {
+		/*time_elapsed >= aux_engine->timeout_period */
+		if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
+			ASSERT_CRITICAL(false);
+		return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
+	}
+}
+
+static const int32_t aux_channel_offset[] = {
+	mmDP_AUX0_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX1_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX2_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX3_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX4_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX5_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL
+};
+
+static const struct aux_engine_funcs aux_engine_funcs = {
+	.destroy = destroy,
+	.acquire_engine = acquire_engine,
+	.configure = configure,
+	.start_gtc_sync = start_gtc_sync,
+	.stop_gtc_sync = stop_gtc_sync,
+	.submit_channel_request = submit_channel_request,
+	.process_channel_reply = process_channel_reply,
+	.get_channel_status = get_channel_status,
+};
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.submit_request = dal_aux_engine_submit_request,
+	.keep_power_up_count = dal_i2caux_keep_power_up_count,
+	.get_engine_type = dal_aux_engine_get_engine_type,
+	.acquire = dal_aux_engine_acquire,
+};
+
+static bool construct(
+	struct aux_engine_dce110 *engine,
+	const struct aux_engine_dce110_init_data *aux_init_data)
+{
+	int32_t offset;
+
+	if (aux_init_data->engine_id >=
+		sizeof(aux_channel_offset) / sizeof(int32_t)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (!dal_aux_engine_construct(
+		&engine->base, aux_init_data->ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+	engine->base.base.funcs = &engine_funcs;
+	engine->base.funcs = &aux_engine_funcs;
+	offset = aux_channel_offset[aux_init_data->engine_id];
+	engine->addr.aux_control = mmAUX_CONTROL + offset;
+	engine->addr.aux_arb_control = mmAUX_ARB_CONTROL + offset;
+	engine->addr.aux_sw_data = mmAUX_SW_DATA + offset;
+	engine->addr.aux_sw_control = mmAUX_SW_CONTROL + offset;
+	engine->addr.aux_interrupt_control = mmAUX_INTERRUPT_CONTROL + offset;
+	engine->addr.aux_sw_status = mmAUX_SW_STATUS + offset;
+	engine->addr.aux_gtc_sync_control = mmAUX_GTC_SYNC_CONTROL + offset;
+	engine->addr.aux_gtc_sync_status = mmAUX_GTC_SYNC_STATUS + offset;
+	engine->addr.aux_gtc_sync_controller_status =
+		mmAUX_GTC_SYNC_CONTROLLER_STATUS + offset;
+
+	engine->timeout_period = aux_init_data->timeout_period;
+
+	return true;
+}
+
+static void destruct(
+	struct aux_engine_dce110 *engine)
+{
+	dal_aux_engine_destruct(&engine->base);
+}
+
+struct aux_engine *dal_aux_engine_dce110_create(
+	const struct aux_engine_dce110_init_data *aux_init_data)
+{
+	struct aux_engine_dce110 *engine;
+
+	if (!aux_init_data) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	engine = dm_alloc(aux_init_data->ctx, sizeof(*engine));
+
+	if (!engine) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(engine, aux_init_data))
+		return &engine->base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(aux_init_data->ctx, engine);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
new file mode 100644
index 000000000000..ec6899ed5b40
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUX_ENGINE_DCE110_H__
+#define __DAL_AUX_ENGINE_DCE110_H__
+
+#include "../aux_engine.h"
+
+struct aux_engine_dce110 {
+	struct aux_engine base;
+	struct {
+		uint32_t aux_control;
+		uint32_t aux_arb_control;
+		uint32_t aux_sw_data;
+		uint32_t aux_sw_control;
+		uint32_t aux_interrupt_control;
+		uint32_t aux_sw_status;
+		uint32_t aux_gtc_sync_control;
+		uint32_t aux_gtc_sync_status;
+		uint32_t aux_gtc_sync_controller_status;
+	} addr;
+	uint32_t timeout_period;
+};
+
+struct aux_engine_dce110_init_data {
+	uint32_t engine_id;
+	uint32_t timeout_period;
+	struct dc_context *ctx;
+};
+
+struct aux_engine *dal_aux_engine_dce110_create(
+	const struct aux_engine_dce110_init_data *aux_init_data);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
new file mode 100644
index 000000000000..e6b6a972a0e5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
new file mode 100644
index 000000000000..2517f44f7297
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
@@ -0,0 +1,954 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "include/i2caux_interface.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_hw_engine.h"
+#include "../i2c_generic_hw_engine.h"
+/*
+ * Header of this unit
+ */
+
+#include "i2c_hw_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+/*
+ * This unit
+ */
+
+enum dc_i2c_status {
+	DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
+	DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
+	DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW
+};
+
+enum dc_i2c_arbitration {
+	DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
+	DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
+};
+
+enum {
+	/* No timeout in HW
+	 * (timeout implemented in SW by querying status) */
+	I2C_SETUP_TIME_LIMIT = 255,
+	I2C_HW_BUFFER_SIZE = 144
+};
+
+/*
+ * @brief
+ * Cast pointer to 'struct i2c_hw_engine *'
+ * to pointer 'struct i2c_hw_engine_dce110 *'
+ */
+#define FROM_I2C_HW_ENGINE(ptr) \
+	container_of((ptr), struct i2c_hw_engine_dce110, base)
+/*
+ * @brief
+ * Cast pointer to 'struct i2c_engine *'
+ * to pointer to 'struct i2c_hw_engine_dce110 *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
+
+/*
+ * @brief
+ * Cast pointer to 'struct engine *'
+ * to 'pointer to struct i2c_hw_engine_dce110 *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+
+static void disable_i2c_hw_engine(
+	struct i2c_hw_engine_dce110 *engine)
+{
+	const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
+	uint32_t value = 0;
+
+	struct dc_context *ctx = NULL;
+
+	ctx = engine->base.base.base.ctx;
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		DC_I2C_DDC1_SETUP,
+		DC_I2C_DDC1_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void release_engine(
+	struct engine *engine)
+{
+	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
+
+	struct i2c_engine *base = NULL;
+	bool safe_to_reset;
+	uint32_t value = 0;
+
+	base = &hw_engine->base.base;
+
+	/* Restore original HW engine speed */
+
+	base->funcs->set_speed(base, hw_engine->base.original_speed);
+
+	/* Release I2C */
+	{
+		value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION);
+
+		set_reg_field_value(
+				value,
+				1,
+				DC_I2C_ARBITRATION,
+				DC_I2C_SW_DONE_USING_I2C_REG);
+
+		dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value);
+	}
+
+	/* Reset HW engine */
+	{
+		uint32_t i2c_sw_status = 0;
+
+		value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
+
+		i2c_sw_status = get_reg_field_value(
+				value,
+				DC_I2C_SW_STATUS,
+				DC_I2C_SW_STATUS);
+		/* if used by SW, safe to reset */
+		safe_to_reset = (i2c_sw_status == 1);
+	}
+	{
+		value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
+
+		if (safe_to_reset)
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_CONTROL,
+				DC_I2C_SOFT_RESET);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_CONTROL,
+			DC_I2C_SW_STATUS_RESET);
+
+		dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
+	}
+
+	/* HW I2c engine - clock gating feature */
+	if (!hw_engine->engine_keep_power_up_count)
+		disable_i2c_hw_engine(hw_engine);
+}
+
+static void keep_power_up_count(
+	struct engine *engine,
+	bool keep_power_up)
+{
+	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
+
+	if (keep_power_up)
+		++hw_engine->engine_keep_power_up_count;
+	else {
+		--hw_engine->engine_keep_power_up_count;
+
+		if (!hw_engine->engine_keep_power_up_count)
+			disable_i2c_hw_engine(hw_engine);
+	}
+}
+
+static bool setup_engine(
+	struct i2c_engine *i2c_engine)
+{
+	uint32_t value = 0;
+	struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine);
+
+	/* Program pin select */
+	{
+		const uint32_t addr = mmDC_I2C_CONTROL;
+
+		value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_GO);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SOFT_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SEND_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SW_STATUS_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_TRANSACTION_COUNT);
+
+		set_reg_field_value(
+			value,
+			engine->engine_id,
+			DC_I2C_CONTROL,
+			DC_I2C_DDC_SELECT);
+
+
+		dm_write_reg(i2c_engine->base.ctx, addr, value);
+	}
+
+	/* Program time limit */
+	{
+		const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
+
+		value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			I2C_SETUP_TIME_LIMIT,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_TIME_LIMIT);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_ENABLE);
+
+		dm_write_reg(i2c_engine->base.ctx, addr, value);
+	}
+
+	/* Program HW priority
+	 * set to High - interrupt software I2C at any time
+	 * Enable restart of SW I2C that was interrupted by HW
+	 * disable queuing of software while I2C is in use by HW */
+	{
+		value = dm_read_reg(i2c_engine->base.ctx,
+				mmDC_I2C_ARBITRATION);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_ARBITRATION,
+			DC_I2C_NO_QUEUED_SW_GO);
+
+		set_reg_field_value(
+			value,
+			DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
+			DC_I2C_ARBITRATION,
+			DC_I2C_SW_PRIORITY);
+
+		dm_write_reg(i2c_engine->base.ctx,
+				mmDC_I2C_ARBITRATION, value);
+	}
+
+	return true;
+}
+
+static uint32_t get_speed(
+	const struct i2c_engine *i2c_engine)
+{
+	const struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine);
+
+	const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
+
+	uint32_t pre_scale = 0;
+
+	uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+	pre_scale = get_reg_field_value(
+			value,
+			DC_I2C_DDC1_SPEED,
+			DC_I2C_DDC1_PRESCALE);
+
+	/* [anaumov] it seems following is unnecessary */
+	/*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
+
+	return pre_scale ?
+		engine->reference_frequency / pre_scale :
+		engine->base.default_speed;
+}
+
+static void set_speed(
+	struct i2c_engine *i2c_engine,
+	uint32_t speed)
+{
+	struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine);
+
+	if (speed) {
+		const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
+
+		uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			engine->reference_frequency / speed,
+			DC_I2C_DDC1_SPEED,
+			DC_I2C_DDC1_PRESCALE);
+
+		set_reg_field_value(
+			value,
+			2,
+			DC_I2C_DDC1_SPEED,
+			DC_I2C_DDC1_THRESHOLD);
+
+		/*DCE11, HW add 100Khz support for I2c*/
+		if (speed > 50) {
+			set_reg_field_value(
+				value,
+				2,
+				DC_I2C_DDC1_SPEED,
+				DC_I2C_DDC1_START_STOP_TIMING_CNTL);
+		} else {
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_DDC1_SPEED,
+				DC_I2C_DDC1_START_STOP_TIMING_CNTL);
+		}
+
+		dm_write_reg(i2c_engine->base.ctx, addr, value);
+	}
+}
+
+static inline void reset_hw_engine(struct engine *engine)
+{
+	uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_CONTROL,
+		DC_I2C_SOFT_RESET);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_CONTROL,
+		DC_I2C_SW_STATUS_RESET);
+
+	dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
+}
+
+static bool is_hw_busy(struct engine *engine)
+{
+	uint32_t i2c_sw_status = 0;
+
+	uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
+
+	i2c_sw_status = get_reg_field_value(
+			value,
+			DC_I2C_SW_STATUS,
+			DC_I2C_SW_STATUS);
+
+	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
+		return false;
+
+	reset_hw_engine(engine);
+
+	value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
+
+	i2c_sw_status = get_reg_field_value(
+			value,
+			DC_I2C_SW_STATUS,
+			DC_I2C_SW_STATUS);
+
+	return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
+}
+
+/*
+ * @brief
+ * DC_GPIO_DDC MM register offsets
+ */
+static const uint32_t transaction_addr[] = {
+	mmDC_I2C_TRANSACTION0,
+	mmDC_I2C_TRANSACTION1,
+	mmDC_I2C_TRANSACTION2,
+	mmDC_I2C_TRANSACTION3
+};
+
+static bool process_transaction(
+	struct i2c_hw_engine_dce110 *engine,
+	struct i2c_request_transaction_data *request)
+{
+	uint8_t length = request->length;
+	uint8_t *buffer = request->data;
+
+	bool last_transaction = false;
+	uint32_t value = 0;
+
+	struct dc_context *ctx = NULL;
+
+	ctx = engine->base.base.base.ctx;
+
+	{
+		const uint32_t addr =
+			transaction_addr[engine->transaction_count];
+
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_TRANSACTION0,
+			DC_I2C_STOP_ON_NACK0);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_TRANSACTION0,
+			DC_I2C_START0);
+
+
+		if ((engine->transaction_count == 3) ||
+		(request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
+		(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
+
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_TRANSACTION0,
+				DC_I2C_STOP0);
+
+			last_transaction = true;
+		} else
+			set_reg_field_value(
+				value,
+				0,
+				DC_I2C_TRANSACTION0,
+				DC_I2C_STOP0);
+
+		set_reg_field_value(
+			value,
+			(0 != (request->action &
+					I2CAUX_TRANSACTION_ACTION_I2C_READ)),
+			DC_I2C_TRANSACTION0,
+			DC_I2C_RW0);
+
+		set_reg_field_value(
+			value,
+			length,
+			DC_I2C_TRANSACTION0,
+			DC_I2C_COUNT0);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* Write the I2C address and I2C data
+	 * into the hardware circular buffer, one byte per entry.
+	 * As an example, the 7-bit I2C slave address for CRT monitor
+	 * for reading DDC/EDID information is 0b1010001.
+	 * For an I2C send operation, the LSB must be programmed to 0;
+	 * for I2C receive operation, the LSB must be programmed to 1. */
+
+	{
+		value = 0;
+
+		set_reg_field_value(
+			value,
+			false,
+			DC_I2C_DATA,
+			DC_I2C_DATA_RW);
+
+		set_reg_field_value(
+			value,
+			request->address,
+			DC_I2C_DATA,
+			DC_I2C_DATA);
+
+		if (engine->transaction_count == 0) {
+			set_reg_field_value(
+				value,
+				0,
+				DC_I2C_DATA,
+				DC_I2C_INDEX);
+
+			/*enable index write*/
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_DATA,
+				DC_I2C_INDEX_WRITE);
+
+			engine->buffer_used_write = 0;
+		}
+
+		dm_write_reg(ctx, mmDC_I2C_DATA, value);
+
+		engine->buffer_used_write++;
+
+		if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
+
+			set_reg_field_value(
+				value,
+				0,
+				DC_I2C_DATA,
+				DC_I2C_INDEX_WRITE);
+
+			while (length) {
+
+				set_reg_field_value(
+					value,
+					*buffer++,
+					DC_I2C_DATA,
+					DC_I2C_DATA);
+
+				dm_write_reg(ctx, mmDC_I2C_DATA, value);
+
+				engine->buffer_used_write++;
+				--length;
+			}
+		}
+	}
+
+	++engine->transaction_count;
+	engine->buffer_used_bytes += length + 1;
+
+	return last_transaction;
+}
+
+static void execute_transaction(
+	struct i2c_hw_engine_dce110 *engine)
+{
+	uint32_t value = 0;
+	struct dc_context *ctx = NULL;
+
+	ctx = engine->base.base.base.ctx;
+
+	{
+		const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
+
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_DATA_DRIVE_EN);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_CLK_DRIVE_EN);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_DATA_DRIVE_SEL);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_INTRA_TRANSACTION_DELAY);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_INTRA_BYTE_DELAY);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = mmDC_I2C_CONTROL;
+
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SOFT_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SW_STATUS_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SEND_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_GO);
+
+		set_reg_field_value(
+			value,
+			engine->transaction_count - 1,
+			DC_I2C_CONTROL,
+			DC_I2C_TRANSACTION_COUNT);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* start I2C transfer */
+	{
+		const uint32_t addr = mmDC_I2C_CONTROL;
+
+		value	= dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_CONTROL,
+			DC_I2C_GO);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* all transactions were executed and HW buffer became empty
+	 * (even though it actually happens when status becomes DONE) */
+	engine->transaction_count = 0;
+	engine->buffer_used_bytes = 0;
+}
+
+static void submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *request)
+{
+	request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	if (!process_transaction(FROM_I2C_ENGINE(engine), request))
+		return;
+
+	if (is_hw_busy(&engine->base)) {
+		request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
+		return;
+	}
+
+	execute_transaction(FROM_I2C_ENGINE(engine));
+}
+
+static void process_channel_reply(
+	struct i2c_engine *engine,
+	struct i2c_reply_transaction_data *reply)
+{
+	uint8_t length = reply->length;
+	uint8_t *buffer = reply->data;
+
+	struct i2c_hw_engine_dce110 *i2c_hw_engine_dce110 =
+		FROM_I2C_ENGINE(engine);
+
+	uint32_t value = 0;
+
+	/*set index*/
+	set_reg_field_value(
+		value,
+		i2c_hw_engine_dce110->buffer_used_write,
+		DC_I2C_DATA,
+		DC_I2C_INDEX);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_DATA,
+		DC_I2C_DATA_RW);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_DATA,
+		DC_I2C_INDEX_WRITE);
+
+	dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value);
+
+	while (length) {
+		/* after reading the status,
+		 * if the I2C operation executed successfully
+		 * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
+		 * should read data bytes from I2C circular data buffer */
+
+		value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA);
+
+		*buffer++ = get_reg_field_value(
+				value,
+				DC_I2C_DATA,
+				DC_I2C_DATA);
+
+		--length;
+	}
+}
+
+static enum i2c_channel_operation_result get_channel_status(
+	struct i2c_engine *engine,
+	uint8_t *returned_bytes)
+{
+	uint32_t i2c_sw_status = 0;
+	uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS);
+
+	i2c_sw_status = get_reg_field_value(
+			value,
+			DC_I2C_SW_STATUS,
+			DC_I2C_SW_STATUS);
+
+	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
+		return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK)
+		return I2C_CHANNEL_OPERATION_NO_RESPONSE;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK)
+		return I2C_CHANNEL_OPERATION_TIMEOUT;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK)
+		return I2C_CHANNEL_OPERATION_FAILED;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK)
+		return I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	/* in DAL2, I2C_RESULT_OK was returned */
+	return I2C_CHANNEL_OPERATION_NOT_STARTED;
+}
+
+static uint8_t get_hw_buffer_available_size(
+	const struct i2c_hw_engine *engine)
+{
+	return I2C_HW_BUFFER_SIZE -
+		FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes;
+}
+
+static uint32_t get_transaction_timeout(
+	const struct i2c_hw_engine *engine,
+	uint32_t length)
+{
+	uint32_t speed = engine->base.funcs->get_speed(&engine->base);
+
+	uint32_t period_timeout;
+	uint32_t num_of_clock_stretches;
+
+	if (!speed)
+		return 0;
+
+	period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
+
+	num_of_clock_stretches = 1 + (length << 3) + 1;
+	num_of_clock_stretches +=
+		(FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) +
+		(FROM_I2C_HW_ENGINE(engine)->transaction_count << 1);
+
+	return period_timeout * num_of_clock_stretches;
+}
+
+static void destroy(
+	struct i2c_engine **i2c_engine)
+{
+	struct i2c_hw_engine_dce110 *engine_dce110 =
+			FROM_I2C_ENGINE(*i2c_engine);
+
+	dal_i2c_hw_engine_destruct(&engine_dce110->base);
+
+	dm_free((*i2c_engine)->base.ctx, engine_dce110);
+
+	*i2c_engine = NULL;
+}
+/*
+ * @brief
+ * DC_I2C_DDC1_SETUP MM register offsets
+ *
+ * @note
+ * The indices of this offset array are DDC engine IDs
+ */
+static const int32_t ddc_setup_offset[] = {
+
+	mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */
+	mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */
+	mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */
+	mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */
+	mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */
+	mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */
+	mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */
+};
+
+/*
+ * @brief
+ * DC_I2C_DDC1_SPEED MM register offsets
+ *
+ * @note
+ * The indices of this offset array are DDC engine IDs
+ */
+static const int32_t ddc_speed_offset[] = {
+	mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */
+	mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */
+	mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */
+	mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */
+	mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */
+	mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */
+	mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */
+};
+
+static const struct i2c_engine_funcs i2c_engine_funcs = {
+	.destroy = destroy,
+	.get_speed = get_speed,
+	.set_speed = set_speed,
+	.setup_engine = setup_engine,
+	.submit_channel_request = submit_channel_request,
+	.process_channel_reply = process_channel_reply,
+	.get_channel_status = get_channel_status,
+	.acquire_engine = dal_i2c_hw_engine_acquire_engine,
+};
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.keep_power_up_count = keep_power_up_count,
+	.get_engine_type = dal_i2c_hw_engine_get_engine_type,
+	.acquire = dal_i2c_engine_acquire,
+	.submit_request = dal_i2c_hw_engine_submit_request,
+};
+
+static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = {
+	.get_hw_buffer_available_size = get_hw_buffer_available_size,
+	.get_transaction_timeout = get_transaction_timeout,
+	.wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result,
+};
+
+static bool construct(
+	struct i2c_hw_engine_dce110 *engine_dce110,
+	const struct i2c_hw_engine_dce110_create_arg *arg)
+{
+	uint32_t xtal_ref_div = 0;
+	uint32_t value = 0;
+
+	/*ddc_setup_offset of dce80 and dce110 have the same register name
+	 * but different offset. Do not need different array*/
+	if (arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t))
+		return false;
+	if (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t))
+		return false;
+	if (!arg->reference_frequency)
+		return false;
+
+	if (!dal_i2c_hw_engine_construct(&engine_dce110->base, arg->ctx))
+		return false;
+
+	engine_dce110->base.base.base.funcs = &engine_funcs;
+	engine_dce110->base.base.funcs = &i2c_engine_funcs;
+	engine_dce110->base.funcs = &i2c_hw_engine_funcs;
+	engine_dce110->base.default_speed = arg->default_speed;
+
+	engine_dce110->engine_id = arg->engine_id;
+
+	engine_dce110->buffer_used_bytes = 0;
+	engine_dce110->transaction_count = 0;
+	engine_dce110->engine_keep_power_up_count = 1;
+
+	/*values which are not included by arg*/
+	engine_dce110->addr.DC_I2C_DDCX_SETUP =
+		mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id];
+	engine_dce110->addr.DC_I2C_DDCX_SPEED =
+		mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id];
+
+
+	value = dm_read_reg(
+		engine_dce110->base.base.base.ctx,
+		mmMICROSECOND_TIME_BASE_DIV);
+
+	xtal_ref_div = get_reg_field_value(
+			value,
+			MICROSECOND_TIME_BASE_DIV,
+			XTAL_REF_DIV);
+
+	if (xtal_ref_div == 0) {
+		dal_logger_write(
+				engine_dce110->base.base.base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_I2C_AUX,
+				"Invalid base timer divider\n",
+				__func__);
+		xtal_ref_div = 2;
+	}
+
+	/*Calculating Reference Clock by divding original frequency by
+	 * XTAL_REF_DIV.
+	 * At upper level, uint32_t reference_frequency =
+	 *  dal_i2caux_get_reference_clock(as) >> 1
+	 *  which already divided by 2. So we need x2 to get original
+	 *  reference clock from ppll_info
+	 */
+	engine_dce110->reference_frequency =
+		(arg->reference_frequency * 2) / xtal_ref_div;
+
+
+	return true;
+}
+
+struct i2c_engine *dal_i2c_hw_engine_dce110_create(
+	const struct i2c_hw_engine_dce110_create_arg *arg)
+{
+	struct i2c_hw_engine_dce110 *engine_dce10;
+
+	if (!arg) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	engine_dce10 = dm_alloc(arg->ctx, sizeof(struct i2c_hw_engine_dce110));
+
+	if (!engine_dce10) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(engine_dce10, arg))
+		return &engine_dce10->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(arg->ctx, engine_dce10);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
new file mode 100644
index 000000000000..fc2ae365f8ed
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_HW_ENGINE_DCE110_H__
+#define __DAL_I2C_HW_ENGINE_DCE110_H__
+
+struct i2c_hw_engine_dce110 {
+	struct i2c_hw_engine base;
+	struct {
+		uint32_t DC_I2C_DDCX_SETUP;
+		uint32_t DC_I2C_DDCX_SPEED;
+	} addr;
+	uint32_t engine_id;
+	/* expressed in kilohertz */
+	uint32_t reference_frequency;
+	/* number of bytes currently used in HW buffer */
+	uint32_t buffer_used_bytes;
+	/* number of bytes used for write transaction in HW buffer
+	 * - this will be used as the index to read from*/
+	uint32_t buffer_used_write;
+	/* number of pending transactions (before GO) */
+	uint32_t transaction_count;
+	uint32_t engine_keep_power_up_count;
+};
+
+struct i2c_hw_engine_dce110_create_arg {
+	uint32_t engine_id;
+	uint32_t reference_frequency;
+	uint32_t default_speed;
+	struct dc_context *ctx;
+};
+
+struct i2c_engine *dal_i2c_hw_engine_dce110_create(
+	const struct i2c_hw_engine_dce110_create_arg *arg);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
new file mode 100644
index 000000000000..f060b25d1618
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_sw_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_sw_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct i2c_sw_engine *'
+ * to 'struct i2c_sw_engine_dce110 *'
+ */
+#define FROM_I2C_SW_ENGINE(ptr) \
+	container_of((ptr), struct i2c_sw_engine_dce110, base)
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_sw_engine_dce80 *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base))
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_sw_engine_dce80 *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+static void release_engine(
+	struct engine *engine)
+{
+}
+
+static void destruct(
+	struct i2c_sw_engine_dce110 *engine)
+{
+	dal_i2c_sw_engine_destruct(&engine->base);
+}
+
+static void destroy(
+	struct i2c_engine **engine)
+{
+	struct i2c_sw_engine_dce110 *sw_engine = FROM_I2C_ENGINE(*engine);
+
+	destruct(sw_engine);
+
+	dm_free((*engine)->base.ctx, sw_engine);
+
+	*engine = NULL;
+}
+
+static bool acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc_handle)
+{
+	return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle);
+}
+
+static const struct i2c_engine_funcs i2c_engine_funcs = {
+	.acquire_engine = acquire_engine,
+	.destroy = destroy,
+	.get_speed = dal_i2c_sw_engine_get_speed,
+	.set_speed = dal_i2c_sw_engine_set_speed,
+	.setup_engine = dal_i2c_engine_setup_i2c_engine,
+	.submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
+	.process_channel_reply = dal_i2c_engine_process_channel_reply,
+	.get_channel_status = dal_i2c_sw_engine_get_channel_status,
+};
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.get_engine_type = dal_i2c_sw_engine_get_engine_type,
+	.acquire = dal_i2c_engine_acquire,
+	.submit_request = dal_i2c_sw_engine_submit_request,
+	.keep_power_up_count = dal_i2caux_keep_power_up_count,
+};
+
+static bool construct(
+	struct i2c_sw_engine_dce110 *engine_dce110,
+	const struct i2c_sw_engine_dce110_create_arg *arg_dce110)
+{
+	struct i2c_sw_engine_create_arg arg_base;
+
+	arg_base.ctx = arg_dce110->ctx;
+	arg_base.default_speed = arg_dce110->default_speed;
+
+	if (!dal_i2c_sw_engine_construct(
+			&engine_dce110->base, &arg_base)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	/*struct engine   struct engine_funcs*/
+	engine_dce110->base.base.base.funcs = &engine_funcs;
+	/*struct i2c_engine  struct i2c_engine_funcs*/
+	engine_dce110->base.base.funcs = &i2c_engine_funcs;
+	engine_dce110->base.default_speed = arg_dce110->default_speed;
+	engine_dce110->engine_id = arg_dce110->engine_id;
+
+	return true;
+}
+
+struct i2c_engine *dal_i2c_sw_engine_dce110_create(
+	const struct i2c_sw_engine_dce110_create_arg *arg)
+{
+	struct i2c_sw_engine_dce110 *engine_dce110;
+
+	if (!arg) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	engine_dce110 = dm_alloc(arg->ctx, sizeof(struct i2c_sw_engine_dce110));
+
+	if (!engine_dce110) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(engine_dce110, arg))
+		return &engine_dce110->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(arg->ctx, engine_dce110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
new file mode 100644
index 000000000000..c48c61f540a8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_SW_ENGINE_DCE110_H__
+#define __DAL_I2C_SW_ENGINE_DCE110_H__
+
+struct i2c_sw_engine_dce110 {
+	struct i2c_sw_engine base;
+	uint32_t engine_id;
+};
+
+struct i2c_sw_engine_dce110_create_arg {
+	uint32_t engine_id;
+	uint32_t default_speed;
+	struct dc_context *ctx;
+};
+
+struct i2c_engine *dal_i2c_sw_engine_dce110_create(
+	const struct i2c_sw_engine_dce110_create_arg *arg);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
new file mode 100644
index 000000000000..9c88762dbd0c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../i2caux.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_sw_engine.h"
+#include "../i2c_hw_engine.h"
+
+/*
+ * Header of this unit
+ */
+#include "i2caux_dce110.h"
+
+#include "i2c_sw_engine_dce110.h"
+#include "i2c_hw_engine_dce110.h"
+#include "aux_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+/*cast pointer to struct i2caux TO pointer to struct i2caux_dce110*/
+#define FROM_I2C_AUX(ptr) \
+	container_of((ptr), struct i2caux_dce110, base)
+
+static void destruct(
+	struct i2caux_dce110 *i2caux_dce110)
+{
+	dal_i2caux_destruct(&i2caux_dce110->base);
+}
+
+static void destroy(
+	struct i2caux **i2c_engine)
+{
+	struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(*i2c_engine);
+
+	destruct(i2caux_dce110);
+
+	dm_free((*i2c_engine)->ctx, i2caux_dce110);
+
+	*i2c_engine = NULL;
+}
+
+static struct i2c_engine *acquire_i2c_hw_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux);
+
+	struct i2c_engine *engine = NULL;
+	/* generic hw engine is not used for EDID read
+	 * It may be needed for external i2c device, like thermal chip,
+	 * TODO will be implemented when needed.
+	 * check dce80 bool non_generic for generic hw engine;
+	 */
+
+	if (!ddc)
+		return NULL;
+
+	if (dal_ddc_is_hw_supported(ddc)) {
+		enum gpio_ddc_line line = dal_ddc_get_line(ddc);
+
+		if (line < GPIO_DDC_LINE_COUNT)
+			engine = i2caux->i2c_hw_engines[line];
+	}
+
+	if (!engine)
+		return NULL;
+
+	if (!i2caux_dce110->i2c_hw_buffer_in_use &&
+		engine->base.funcs->acquire(&engine->base, ddc)) {
+		i2caux_dce110->i2c_hw_buffer_in_use = true;
+		return engine;
+	}
+
+	return NULL;
+}
+
+static void release_engine(
+	struct i2caux *i2caux,
+	struct engine *engine)
+{
+	struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux);
+
+	if (engine->funcs->get_engine_type(engine) ==
+		I2CAUX_ENGINE_TYPE_I2C_DDC_HW)
+		i2caux_dce110->i2c_hw_buffer_in_use = false;
+
+	dal_i2caux_release_engine(i2caux, engine);
+}
+
+static const enum gpio_ddc_line hw_ddc_lines[] = {
+	GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_DDC2,
+	GPIO_DDC_LINE_DDC3,
+	GPIO_DDC_LINE_DDC4,
+	GPIO_DDC_LINE_DDC5,
+	GPIO_DDC_LINE_DDC6,
+};
+
+static const enum gpio_ddc_line hw_aux_lines[] = {
+	GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_DDC2,
+	GPIO_DDC_LINE_DDC3,
+	GPIO_DDC_LINE_DDC4,
+	GPIO_DDC_LINE_DDC5,
+	GPIO_DDC_LINE_DDC6,
+};
+
+/* function table */
+static const struct i2caux_funcs i2caux_funcs = {
+	.destroy = destroy,
+	.acquire_i2c_hw_engine = acquire_i2c_hw_engine,
+	.release_engine = release_engine,
+	.acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine,
+	.acquire_aux_engine = dal_i2caux_acquire_aux_engine,
+};
+
+static bool construct(
+	struct i2caux_dce110 *i2caux_dce110,
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	uint32_t i = 0;
+	uint32_t reference_frequency = 0;
+	bool use_i2c_sw_engine = false;
+	struct i2caux *base = NULL;
+	/*TODO: For CZ bring up, if dal_i2caux_get_reference_clock
+	 * does not return 48KHz, we need hard coded for 48Khz.
+	 * Some BIOS setting incorrect cause this
+	 * For production, we always get value from BIOS*/
+	reference_frequency =
+		dal_i2caux_get_reference_clock(as) >> 1;
+
+	use_i2c_sw_engine = dal_adapter_service_is_feature_supported(
+		FEATURE_RESTORE_USAGE_I2C_SW_ENGINE);
+
+	base = &i2caux_dce110->base;
+
+	if (!dal_i2caux_construct(base, as, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	i2caux_dce110->base.funcs = &i2caux_funcs;
+	i2caux_dce110->i2c_hw_buffer_in_use = false;
+	/* Create I2C engines (DDC lines per connector)
+	 * different I2C/AUX usage cases, DDC, Generic GPIO, AUX.
+	 */
+	do {
+		enum gpio_ddc_line line_id = hw_ddc_lines[i];
+
+		struct i2c_hw_engine_dce110_create_arg hw_arg_dce110;
+
+		if (use_i2c_sw_engine) {
+			struct i2c_sw_engine_dce110_create_arg sw_arg;
+
+			sw_arg.engine_id = i;
+			sw_arg.default_speed = base->default_i2c_sw_speed;
+			sw_arg.ctx = ctx;
+			base->i2c_sw_engines[line_id] =
+				dal_i2c_sw_engine_dce110_create(&sw_arg);
+		}
+
+		hw_arg_dce110.engine_id = i;
+		hw_arg_dce110.reference_frequency = reference_frequency;
+		hw_arg_dce110.default_speed = base->default_i2c_hw_speed;
+		hw_arg_dce110.ctx = ctx;
+
+		base->i2c_hw_engines[line_id] =
+			dal_i2c_hw_engine_dce110_create(&hw_arg_dce110);
+
+		++i;
+	} while (i < ARRAY_SIZE(hw_ddc_lines));
+
+	/* Create AUX engines for all lines which has assisted HW AUX
+	 * 'i' (loop counter) used as DDC/AUX engine_id */
+
+	i = 0;
+
+	do {
+		enum gpio_ddc_line line_id = hw_aux_lines[i];
+
+		struct aux_engine_dce110_init_data aux_init_data;
+
+		aux_init_data.engine_id = i;
+		aux_init_data.timeout_period = base->aux_timeout_period;
+		aux_init_data.ctx = ctx;
+
+		base->aux_engines[line_id] =
+			dal_aux_engine_dce110_create(&aux_init_data);
+
+		++i;
+	} while (i < ARRAY_SIZE(hw_aux_lines));
+
+	/*TODO Generic I2C SW and HW*/
+
+	return true;
+}
+
+/*
+ * dal_i2caux_dce110_create
+ *
+ * @brief
+ * public interface to allocate memory for DCE11 I2CAUX
+ *
+ * @param
+ * struct adapter_service *as - [in]
+ * struct dc_context *ctx - [in]
+ *
+ * @return
+ * pointer to the base struct of DCE11 I2CAUX
+ */
+struct i2caux *dal_i2caux_dce110_create(
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	struct i2caux_dce110 *i2caux_dce110 =
+		dm_alloc(ctx, sizeof(struct i2caux_dce110));
+
+	if (!i2caux_dce110) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(i2caux_dce110, as, ctx))
+		return &i2caux_dce110->base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, i2caux_dce110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
new file mode 100644
index 000000000000..1a7ba1baf3d0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_AUX_DCE110_H__
+#define __DAL_I2C_AUX_DCE110_H__
+
+struct i2caux_dce110 {
+	struct i2caux base;
+	/* indicate the I2C HW circular buffer is in use */
+	bool i2c_hw_buffer_in_use;
+};
+
+struct i2caux *dal_i2caux_dce110_create(
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+#endif /* __DAL_I2C_AUX_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
new file mode 100644
index 000000000000..f4bc39d786c8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../i2caux.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_sw_engine.h"
+#include "../i2c_hw_engine.h"
+
+/*
+ * Header of this unit
+ */
+#include "i2caux_diag.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+static void destruct(
+	struct i2caux *i2caux)
+{
+	dal_i2caux_destruct(i2caux);
+}
+
+static void destroy(
+	struct i2caux **i2c_engine)
+{
+	destruct(*i2c_engine);
+
+	dm_free((*i2c_engine)->ctx, *i2c_engine);
+
+	*i2c_engine = NULL;
+}
+
+
+
+/* function table */
+static const struct i2caux_funcs i2caux_funcs = {
+	.destroy = destroy,
+	.acquire_i2c_hw_engine = NULL,
+	.release_engine = NULL,
+	.acquire_i2c_sw_engine = NULL,
+	.acquire_aux_engine = NULL,
+};
+
+static bool construct(
+	struct i2caux *i2caux,
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	if (!dal_i2caux_construct(i2caux, as, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	i2caux->funcs = &i2caux_funcs;
+
+	return true;
+}
+
+struct i2caux *dal_i2caux_diag_fpga_create(
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	struct i2caux *i2caux =	dm_alloc(ctx, sizeof(struct i2caux));
+
+	if (!i2caux) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(i2caux, as, ctx))
+		return i2caux;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, i2caux);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
new file mode 100644
index 000000000000..3de250bd7660
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_AUX_DIAG_FPGA_H__
+#define __DAL_I2C_AUX_DIAG_FPGA_H__
+
+struct i2caux *dal_i2caux_diag_fpga_create(
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+#endif /* __DAL_I2C_AUX_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
new file mode 100644
index 000000000000..d3635f884579
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ENGINE_H__
+#define __DAL_ENGINE_H__
+
+enum i2caux_transaction_operation {
+	I2CAUX_TRANSACTION_READ,
+	I2CAUX_TRANSACTION_WRITE
+};
+
+enum i2caux_transaction_address_space {
+	I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1,
+	I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD
+};
+
+struct i2caux_transaction_payload {
+	enum i2caux_transaction_address_space address_space;
+	uint32_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum i2caux_transaction_status {
+	I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L),
+	I2CAUX_TRANSACTION_STATUS_SUCCEEDED,
+	I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY,
+	I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT,
+	I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR,
+	I2CAUX_TRANSACTION_STATUS_FAILED_NACK,
+	I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE,
+	I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION,
+	I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION,
+	I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW
+};
+
+struct i2caux_transaction_request {
+	enum i2caux_transaction_operation operation;
+	struct i2caux_transaction_payload payload;
+	enum i2caux_transaction_status status;
+};
+
+enum i2caux_engine_type {
+	I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L),
+	I2CAUX_ENGINE_TYPE_AUX,
+	I2CAUX_ENGINE_TYPE_I2C_DDC_HW,
+	I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW,
+	I2CAUX_ENGINE_TYPE_I2C_SW
+};
+
+enum i2c_default_speed {
+	I2CAUX_DEFAULT_I2C_HW_SPEED = 50,
+	I2CAUX_DEFAULT_I2C_SW_SPEED = 50
+};
+
+enum i2caux_transaction_action {
+	I2CAUX_TRANSACTION_ACTION_I2C_WRITE = 0x00,
+	I2CAUX_TRANSACTION_ACTION_I2C_READ = 0x10,
+	I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST = 0x20,
+
+	I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT = 0x40,
+	I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT = 0x50,
+	I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT = 0x60,
+
+	I2CAUX_TRANSACTION_ACTION_DP_WRITE = 0x80,
+	I2CAUX_TRANSACTION_ACTION_DP_READ = 0x90
+};
+
+struct engine;
+
+struct engine_funcs {
+	enum i2caux_engine_type (*get_engine_type)(
+		const struct engine *engine);
+	bool (*acquire)(
+		struct engine *engine,
+		struct ddc *ddc);
+	bool (*submit_request)(
+		struct engine *engine,
+		struct i2caux_transaction_request *request,
+		bool middle_of_transaction);
+	/* [anaumov] Actually, following method is meaningful
+	 * only in I2C HW engines */
+	void (*keep_power_up_count)(
+		struct engine *engine,
+		bool keep_power_up);
+	void (*release_engine)(
+		struct engine *engine);
+};
+
+struct engine {
+	const struct engine_funcs *funcs;
+	struct ddc *ddc;
+	struct dc_context *ctx;
+};
+
+bool dal_i2caux_construct_engine(
+	struct engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2caux_destruct_engine(
+	struct engine *engine);
+
+void dal_i2caux_keep_power_up_count(
+	struct engine *engine,
+	bool keep_power_up);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
new file mode 100644
index 000000000000..9c472b9db5ba
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+void dal_i2caux_keep_power_up_count(
+	struct engine *engine,
+	bool keep_power_up)
+{
+
+}
+
+bool dal_i2caux_construct_engine(
+	struct engine *engine,
+	struct dc_context *ctx)
+{
+	engine->ddc = NULL;
+	engine->ctx = ctx;
+	return true;
+}
+
+void dal_i2caux_destruct_engine(
+	struct engine *engine)
+{
+	/* nothing to do */
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
new file mode 100644
index 000000000000..dccb1c51a3be
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define FROM_ENGINE(ptr) \
+	container_of((ptr), struct i2c_engine, base)
+
+bool dal_i2c_engine_acquire(
+	struct engine *engine,
+	struct ddc *ddc_handle)
+{
+	struct i2c_engine *i2c_engine = FROM_ENGINE(engine);
+
+	uint32_t counter = 0;
+	bool result;
+
+	do {
+		result = i2c_engine->funcs->acquire_engine(
+			i2c_engine, ddc_handle);
+
+		if (result)
+			break;
+
+		/* i2c_engine is busy by VBios, lets wait and retry */
+
+		dm_delay_in_microseconds(engine->ctx, 10);
+
+		++counter;
+	} while (counter < 2);
+
+	if (result) {
+		if (!i2c_engine->funcs->setup_engine(i2c_engine)) {
+			engine->funcs->release_engine(engine);
+			result = false;
+		}
+	}
+
+	return result;
+}
+
+bool dal_i2c_engine_setup_i2c_engine(
+	struct i2c_engine *engine)
+{
+	/* Derivative classes do not have to override this */
+
+	return true;
+}
+
+void dal_i2c_engine_submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *request)
+{
+
+}
+
+void dal_i2c_engine_process_channel_reply(
+	struct i2c_engine *engine,
+	struct i2c_reply_transaction_data *reply)
+{
+
+}
+
+bool dal_i2c_engine_construct(
+	struct i2c_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2caux_construct_engine(&engine->base, ctx))
+		return false;
+
+	engine->timeout_delay = 0;
+	return true;
+}
+
+void dal_i2c_engine_destruct(
+	struct i2c_engine *engine)
+{
+	dal_i2caux_destruct_engine(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
new file mode 100644
index 000000000000..20299fd08e9c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_ENGINE_H__
+#define __DAL_I2C_ENGINE_H__
+
+enum i2c_channel_operation_result {
+	I2C_CHANNEL_OPERATION_SUCCEEDED,
+	I2C_CHANNEL_OPERATION_FAILED,
+	I2C_CHANNEL_OPERATION_NOT_GRANTED,
+	I2C_CHANNEL_OPERATION_IS_BUSY,
+	I2C_CHANNEL_OPERATION_NO_HANDLE_PROVIDED,
+	I2C_CHANNEL_OPERATION_CHANNEL_IN_USE,
+	I2C_CHANNEL_OPERATION_CHANNEL_CLIENT_MAX_ALLOWED,
+	I2C_CHANNEL_OPERATION_ENGINE_BUSY,
+	I2C_CHANNEL_OPERATION_TIMEOUT,
+	I2C_CHANNEL_OPERATION_NO_RESPONSE,
+	I2C_CHANNEL_OPERATION_HW_REQUEST_I2C_BUS,
+	I2C_CHANNEL_OPERATION_WRONG_PARAMETER,
+	I2C_CHANNEL_OPERATION_OUT_NB_OF_RETRIES,
+	I2C_CHANNEL_OPERATION_NOT_STARTED
+};
+
+struct i2c_request_transaction_data {
+	enum i2caux_transaction_action action;
+	enum i2c_channel_operation_result status;
+	uint8_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+struct i2c_reply_transaction_data {
+	uint8_t length;
+	uint8_t *data;
+};
+
+struct i2c_engine;
+
+struct i2c_engine_funcs {
+	void (*destroy)(
+		struct i2c_engine **ptr);
+	uint32_t (*get_speed)(
+		const struct i2c_engine *engine);
+	void (*set_speed)(
+		struct i2c_engine *engine,
+		uint32_t speed);
+	bool (*acquire_engine)(
+		struct i2c_engine *engine,
+		struct ddc *ddc);
+	bool (*setup_engine)(
+		struct i2c_engine *engine);
+	void (*submit_channel_request)(
+		struct i2c_engine *engine,
+		struct i2c_request_transaction_data *request);
+	void (*process_channel_reply)(
+		struct i2c_engine *engine,
+		struct i2c_reply_transaction_data *reply);
+	enum i2c_channel_operation_result (*get_channel_status)(
+		struct i2c_engine *engine,
+		uint8_t *returned_bytes);
+};
+
+struct i2c_engine {
+	struct engine base;
+	const struct i2c_engine_funcs *funcs;
+	uint32_t timeout_delay;
+};
+
+bool dal_i2c_engine_construct(
+	struct i2c_engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2c_engine_destruct(
+	struct i2c_engine *engine);
+
+bool dal_i2c_engine_setup_i2c_engine(
+	struct i2c_engine *engine);
+
+void dal_i2c_engine_submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *request);
+
+void dal_i2c_engine_process_channel_reply(
+	struct i2c_engine *engine,
+	struct i2c_reply_transaction_data *reply);
+
+bool dal_i2c_engine_acquire(
+	struct engine *ptr,
+	struct ddc *ddc_handle);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
new file mode 100644
index 000000000000..6429b55dd697
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+#include "i2c_engine.h"
+#include "i2c_hw_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_generic_hw_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct i2c_hw_engine *'
+ * to 'struct i2c_generic_hw_engine *'
+ */
+#define FROM_I2C_HW_ENGINE(ptr) \
+	container_of((ptr), struct i2c_generic_hw_engine, base)
+
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_generic_hw_engine *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_generic_hw_engine *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW;
+}
+
+/*
+ * @brief
+ * Single transaction handling.
+ * Since transaction may be bigger than HW buffer size,
+ * it divides transaction to sub-transactions
+ * and uses batch transaction feature of the engine.
+ */
+bool dal_i2c_generic_hw_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction)
+{
+	struct i2c_generic_hw_engine *hw_engine = FROM_ENGINE(engine);
+
+	struct i2c_hw_engine *base = &hw_engine->base;
+
+	uint8_t max_payload_size =
+		base->funcs->get_hw_buffer_available_size(base);
+
+	bool initial_stop_bit = !middle_of_transaction;
+
+	struct i2c_generic_transaction_attributes attributes;
+
+	enum i2c_channel_operation_result operation_result =
+		I2C_CHANNEL_OPERATION_FAILED;
+
+	bool result = false;
+
+	/* setup transaction initial properties */
+
+	uint8_t address = i2caux_request->payload.address;
+	uint8_t *current_payload = i2caux_request->payload.data;
+	uint8_t remaining_payload_size = i2caux_request->payload.length;
+
+	bool first_iteration = true;
+
+	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+		attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_READ;
+	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+		attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+	else {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
+		return false;
+	}
+
+	/* Do batch transaction.
+	 * Divide read/write data into payloads which fit HW buffer size.
+	 * 1. Single transaction:
+	 *    start_bit = 1, stop_bit depends on session state, ack_on_read = 0;
+	 * 2. Start of batch transaction:
+	 *    start_bit = 1, stop_bit = 0, ack_on_read = 1;
+	 * 3. Middle of batch transaction:
+	 *    start_bit = 0, stop_bit = 0, ack_on_read = 1;
+	 * 4. End of batch transaction:
+	 *    start_bit = 0, stop_bit depends on session state, ack_on_read = 0.
+	 * Session stop bit is set if 'middle_of_transaction' = 0. */
+
+	while (remaining_payload_size) {
+		uint8_t current_transaction_size;
+		uint8_t current_payload_size;
+
+		bool last_iteration;
+		bool stop_bit;
+
+		/* Calculate current transaction size and payload size.
+		 * Transaction size = total number of bytes in transaction,
+		 * including slave's address;
+		 * Payload size = number of data bytes in transaction. */
+
+		if (first_iteration) {
+			/* In the first sub-transaction we send slave's address
+			 * thus we need to reserve one byte for it */
+			current_transaction_size =
+			(remaining_payload_size > max_payload_size - 1) ?
+				max_payload_size :
+				remaining_payload_size + 1;
+
+			current_payload_size = current_transaction_size - 1;
+		} else {
+			/* Second and further sub-transactions will have
+			 * entire buffer reserved for data */
+			current_transaction_size =
+				(remaining_payload_size > max_payload_size) ?
+				max_payload_size :
+				remaining_payload_size;
+
+			current_payload_size = current_transaction_size;
+		}
+
+		last_iteration =
+			(remaining_payload_size == current_payload_size);
+
+		stop_bit = last_iteration ? initial_stop_bit : false;
+
+		/* write slave device address */
+
+		if (first_iteration)
+			hw_engine->funcs->write_address(hw_engine, address);
+
+		/* write current portion of data, if requested */
+
+		if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+			hw_engine->funcs->write_data(
+				hw_engine,
+				current_payload,
+				current_payload_size);
+
+		/* execute transaction */
+
+		attributes.start_bit = first_iteration;
+		attributes.stop_bit = stop_bit;
+		attributes.last_read = last_iteration;
+		attributes.transaction_size = current_transaction_size;
+
+		hw_engine->funcs->execute_transaction(hw_engine, &attributes);
+
+		/* wait until transaction is processed; if it fails - quit */
+
+		operation_result = base->funcs->wait_on_operation_result(
+			base,
+			base->funcs->get_transaction_timeout(
+				base, current_transaction_size),
+			I2C_CHANNEL_OPERATION_ENGINE_BUSY);
+
+		if (operation_result != I2C_CHANNEL_OPERATION_SUCCEEDED)
+			break;
+
+		/* read current portion of data, if requested */
+
+		/* the read offset should be 1 for first sub-transaction,
+		 * and 0 for any next one */
+
+		if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+			hw_engine->funcs->read_data(hw_engine, current_payload,
+				current_payload_size, first_iteration ? 1 : 0);
+
+		/* update loop variables */
+
+		first_iteration = false;
+		current_payload += current_payload_size;
+		remaining_payload_size -= current_payload_size;
+	}
+
+	/* update transaction status */
+
+	switch (operation_result) {
+	case I2C_CHANNEL_OPERATION_SUCCEEDED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+		result = true;
+	break;
+	case I2C_CHANNEL_OPERATION_NO_RESPONSE:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+	break;
+	case I2C_CHANNEL_OPERATION_TIMEOUT:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+	break;
+	case I2C_CHANNEL_OPERATION_FAILED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
+	break;
+	default:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
+	}
+
+	return result;
+}
+
+/*
+ * @brief
+ * Returns number of microseconds to wait until timeout to be considered
+ */
+uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout(
+	const struct i2c_hw_engine *engine,
+	uint32_t length)
+{
+	const struct i2c_engine *base = &engine->base;
+
+	uint32_t speed = base->funcs->get_speed(base);
+
+	if (!speed)
+		return 0;
+
+	/* total timeout = period_timeout * (start + data bits count + stop) */
+
+	return ((1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed) *
+		(1 + (length << 3) + 1);
+}
+
+bool dal_i2c_generic_hw_engine_construct(
+	struct i2c_generic_hw_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2c_hw_engine_construct(&engine->base, ctx))
+		return false;
+	return true;
+}
+
+void dal_i2c_generic_hw_engine_destruct(
+	struct i2c_generic_hw_engine *engine)
+{
+	dal_i2c_hw_engine_destruct(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
new file mode 100644
index 000000000000..52f2aa248d95
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_GENERIC_HW_ENGINE_H__
+#define __DAL_I2C_GENERIC_HW_ENGINE_H__
+
+struct i2c_generic_transaction_attributes {
+	enum i2caux_transaction_action action;
+	uint8_t transaction_size;
+	bool start_bit;
+	bool stop_bit;
+	bool last_read;
+};
+
+struct i2c_generic_hw_engine;
+
+struct i2c_generic_hw_engine_funcs {
+	void (*write_address)(
+		struct i2c_generic_hw_engine *engine,
+		uint8_t address);
+	void (*write_data)(
+		struct i2c_generic_hw_engine *engine,
+		const uint8_t *buffer,
+		uint8_t length);
+	void (*read_data)(
+		struct i2c_generic_hw_engine *engine,
+		uint8_t *buffer,
+		uint8_t length,
+		uint32_t offset);
+	void (*execute_transaction)(
+		struct i2c_generic_hw_engine *engine,
+		struct i2c_generic_transaction_attributes *attributes);
+};
+
+struct i2c_generic_hw_engine {
+	struct i2c_hw_engine base;
+	const struct i2c_generic_hw_engine_funcs *funcs;
+};
+
+bool dal_i2c_generic_hw_engine_construct(
+	struct i2c_generic_hw_engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2c_generic_hw_engine_destruct(
+	struct i2c_generic_hw_engine *engine);
+enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type(
+	const struct engine *engine);
+bool dal_i2c_generic_hw_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction);
+uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout(
+	const struct i2c_hw_engine *engine,
+	uint32_t length);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
new file mode 100644
index 000000000000..b02ba7927d5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+#include "i2c_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_hw_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_hw_engine *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	container_of((ptr), struct i2c_hw_engine, base)
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_hw_engine *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_I2C_DDC_HW;
+}
+
+bool dal_i2c_hw_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction)
+{
+	struct i2c_hw_engine *hw_engine = FROM_ENGINE(engine);
+
+	struct i2c_request_transaction_data request;
+
+	uint32_t transaction_timeout;
+
+	enum i2c_channel_operation_result operation_result;
+
+	bool result = false;
+
+	/* We need following:
+	 * transaction length will not exceed
+	 * the number of free bytes in HW buffer (minus one for address)*/
+
+	if (i2caux_request->payload.length >=
+		hw_engine->funcs->get_hw_buffer_available_size(hw_engine)) {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW;
+		return false;
+	}
+
+	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_READ;
+	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+	else {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
+		/* [anaumov] in DAL2, there was no "return false" */
+		return false;
+	}
+
+	request.address = (uint8_t)i2caux_request->payload.address;
+	request.length = i2caux_request->payload.length;
+	request.data = i2caux_request->payload.data;
+
+	/* obtain timeout value before submitting request */
+
+	transaction_timeout = hw_engine->funcs->get_transaction_timeout(
+		hw_engine, i2caux_request->payload.length + 1);
+
+	hw_engine->base.funcs->submit_channel_request(
+		&hw_engine->base, &request);
+
+	if ((request.status == I2C_CHANNEL_OPERATION_FAILED) ||
+		(request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY)) {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
+		return false;
+	}
+
+	/* wait until transaction proceed */
+
+	operation_result = hw_engine->funcs->wait_on_operation_result(
+		hw_engine,
+		transaction_timeout,
+		I2C_CHANNEL_OPERATION_ENGINE_BUSY);
+
+	/* update transaction status */
+
+	switch (operation_result) {
+	case I2C_CHANNEL_OPERATION_SUCCEEDED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+		result = true;
+	break;
+	case I2C_CHANNEL_OPERATION_NO_RESPONSE:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+	break;
+	case I2C_CHANNEL_OPERATION_TIMEOUT:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+	break;
+	case I2C_CHANNEL_OPERATION_FAILED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
+	break;
+	default:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
+	}
+
+	if (result && (i2caux_request->operation == I2CAUX_TRANSACTION_READ)) {
+		struct i2c_reply_transaction_data reply;
+
+		reply.data = i2caux_request->payload.data;
+		reply.length = i2caux_request->payload.length;
+
+		hw_engine->base.funcs->
+			process_channel_reply(&hw_engine->base, &reply);
+	}
+
+	return result;
+}
+
+bool dal_i2c_hw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc)
+{
+	enum gpio_result result;
+	uint32_t current_speed;
+
+	result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
+		GPIO_DDC_CONFIG_TYPE_MODE_I2C);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	engine->base.ddc = ddc;
+
+	current_speed = engine->funcs->get_speed(engine);
+
+	if (current_speed)
+		FROM_I2C_ENGINE(engine)->original_speed = current_speed;
+
+	return true;
+}
+/*
+ * @brief
+ * Queries in a loop for current engine status
+ * until retrieved status matches 'expected_result', or timeout occurs.
+ * Timeout given in microseconds
+ * and the status query frequency is also one per microsecond.
+ */
+enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result(
+	struct i2c_hw_engine *engine,
+	uint32_t timeout,
+	enum i2c_channel_operation_result expected_result)
+{
+	enum i2c_channel_operation_result result;
+	uint32_t i = 0;
+
+	if (!timeout)
+		return I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	do {
+		result = engine->base.funcs->get_channel_status(
+			&engine->base, NULL);
+
+		if (result != expected_result)
+			break;
+
+		dm_delay_in_microseconds(engine->base.base.ctx, 1);
+
+		++i;
+	} while (i < timeout);
+
+	return result;
+}
+
+bool dal_i2c_hw_engine_construct(
+	struct i2c_hw_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2c_engine_construct(&engine->base, ctx))
+		return false;
+	engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED;
+	engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED;
+	return true;
+}
+
+void dal_i2c_hw_engine_destruct(
+	struct i2c_hw_engine *engine)
+{
+	dal_i2c_engine_destruct(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
new file mode 100644
index 000000000000..5afbd7067a1f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_HW_ENGINE_H__
+#define __DAL_I2C_HW_ENGINE_H__
+
+enum {
+	TRANSACTION_TIMEOUT_IN_I2C_CLOCKS = 32
+};
+
+struct i2c_hw_engine;
+
+struct i2c_hw_engine_funcs {
+	uint8_t (*get_hw_buffer_available_size)(
+		const struct i2c_hw_engine *engine);
+	enum i2c_channel_operation_result (*wait_on_operation_result)(
+		struct i2c_hw_engine *engine,
+		uint32_t timeout,
+		enum i2c_channel_operation_result expected_result);
+	uint32_t (*get_transaction_timeout)(
+		const struct i2c_hw_engine *engine,
+		uint32_t length);
+};
+
+struct i2c_hw_engine {
+	struct i2c_engine base;
+	const struct i2c_hw_engine_funcs *funcs;
+
+	/* Values below are in kilohertz */
+	uint32_t original_speed;
+	uint32_t default_speed;
+};
+
+bool dal_i2c_hw_engine_construct(
+	struct i2c_hw_engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2c_hw_engine_destruct(
+	struct i2c_hw_engine *engine);
+
+enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result(
+	struct i2c_hw_engine *engine,
+	uint32_t timeout,
+	enum i2c_channel_operation_result expected_result);
+
+bool dal_i2c_hw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc);
+
+bool dal_i2c_hw_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction);
+
+enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type(
+	const struct engine *engine);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
new file mode 100644
index 000000000000..21e8fa2c08ee
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
@@ -0,0 +1,614 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+#include "i2c_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_sw_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define SCL false
+#define SDA true
+
+static inline bool read_bit_from_ddc(
+	struct ddc *ddc,
+	bool data_nor_clock)
+{
+	uint32_t value = 0;
+
+	if (data_nor_clock)
+		dal_ddc_get_data(ddc, &value);
+	else
+		dal_ddc_get_clock(ddc, &value);
+
+	return (value != 0);
+}
+
+static inline void write_bit_to_ddc(
+	struct ddc *ddc,
+	bool data_nor_clock,
+	bool bit)
+{
+	uint32_t value = bit ? 1 : 0;
+
+	if (data_nor_clock)
+		dal_ddc_set_data(ddc, value);
+	else
+		dal_ddc_set_clock(ddc, value);
+}
+
+static bool wait_for_scl_high(
+	struct dc_context *ctx,
+	struct ddc *ddc,
+	uint16_t clock_delay_div_4)
+{
+	uint32_t scl_retry = 0;
+	uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	/* 3 milliseconds delay
+	 * to wake up some displays from "low power" state.
+	 */
+
+	do {
+		if (read_bit_from_ddc(ddc, SCL))
+			return true;
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		++scl_retry;
+	} while (scl_retry <= scl_retry_max);
+
+	return false;
+}
+
+static bool start_sync(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4)
+{
+	uint32_t retry = 0;
+
+	/* The I2C communications start signal is:
+	 * the SDA going low from high, while the SCL is high. */
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	do {
+		write_bit_to_ddc(ddc_handle, SDA, true);
+
+		if (!read_bit_from_ddc(ddc_handle, SDA)) {
+			++retry;
+			continue;
+		}
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SCL, true);
+
+		if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+			break;
+
+		write_bit_to_ddc(ddc_handle, SDA, false);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SCL, false);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		return true;
+	} while (retry <= I2C_SW_RETRIES);
+
+	return false;
+}
+
+static bool stop_sync(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4)
+{
+	uint32_t retry = 0;
+
+	/* The I2C communications stop signal is:
+	 * the SDA going high from low, while the SCL is high. */
+
+	write_bit_to_ddc(ddc_handle, SCL, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SDA, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+		return false;
+
+	write_bit_to_ddc(ddc_handle, SDA, true);
+
+	do {
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		if (read_bit_from_ddc(ddc_handle, SDA))
+			return true;
+
+		++retry;
+	} while (retry <= 2);
+
+	return false;
+}
+
+static bool write_byte(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t byte)
+{
+	int32_t shift = 7;
+	bool ack;
+
+	/* bits are transmitted serially, starting from MSB */
+
+	do {
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SCL, true);
+
+		if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+			return false;
+
+		write_bit_to_ddc(ddc_handle, SCL, false);
+
+		--shift;
+	} while (shift >= 0);
+
+	/* The display sends ACK by preventing the SDA from going high
+	 * after the SCL pulse we use to send our last data bit.
+	 * If the SDA goes high after that bit, it's a NACK */
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SDA, true);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+		return false;
+
+	/* read ACK bit */
+
+	ack = !read_bit_from_ddc(ddc_handle, SDA);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4 << 1);
+
+	write_bit_to_ddc(ddc_handle, SCL, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4 << 1);
+
+	return ack;
+}
+
+static bool read_byte(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t *byte,
+	bool more)
+{
+	int32_t shift = 7;
+
+	uint8_t data = 0;
+
+	/* The data bits are read from MSB to LSB;
+	 * bit is read while SCL is high */
+
+	do {
+		write_bit_to_ddc(ddc_handle, SCL, true);
+
+		if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+			return false;
+
+		if (read_bit_from_ddc(ddc_handle, SDA))
+			data |= (1 << shift);
+
+		write_bit_to_ddc(ddc_handle, SCL, false);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4 << 1);
+
+		--shift;
+	} while (shift >= 0);
+
+	/* read only whole byte */
+
+	*byte = data;
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	/* send the acknowledge bit:
+	 * SDA low means ACK, SDA high means NACK */
+
+	write_bit_to_ddc(ddc_handle, SDA, !more);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+		return false;
+
+	write_bit_to_ddc(ddc_handle, SCL, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SDA, true);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	return true;
+}
+
+static bool i2c_write(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t address,
+	uint8_t length,
+	const uint8_t *data)
+{
+	uint32_t i = 0;
+
+	if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
+		return false;
+
+	while (i < length) {
+		if (!write_byte(ctx, ddc_handle, clock_delay_div_4, data[i]))
+			return false;
+		++i;
+	}
+
+	return true;
+}
+
+static bool i2c_read(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t address,
+	uint8_t length,
+	uint8_t *data)
+{
+	uint32_t i = 0;
+
+	if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
+		return false;
+
+	while (i < length) {
+		if (!read_byte(ctx, ddc_handle, clock_delay_div_4, data + i,
+			i < length - 1))
+			return false;
+		++i;
+	}
+
+	return true;
+}
+
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_sw_engine *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	container_of((ptr), struct i2c_sw_engine, base)
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_sw_engine *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_I2C_SW;
+}
+
+bool dal_i2c_sw_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction)
+{
+	struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine);
+
+	struct i2c_engine *base = &sw_engine->base;
+
+	struct i2c_request_transaction_data request;
+	bool operation_succeeded = false;
+
+	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_READ;
+	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+	else {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
+		/* in DAL2, there was no "return false" */
+		return false;
+	}
+
+	request.address = (uint8_t)i2caux_request->payload.address;
+	request.length = i2caux_request->payload.length;
+	request.data = i2caux_request->payload.data;
+
+	base->funcs->submit_channel_request(base, &request);
+
+	if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
+		(request.status == I2C_CHANNEL_OPERATION_FAILED))
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
+	else {
+		enum i2c_channel_operation_result operation_result;
+
+		do {
+			operation_result =
+				base->funcs->get_channel_status(base, NULL);
+
+			switch (operation_result) {
+			case I2C_CHANNEL_OPERATION_SUCCEEDED:
+				i2caux_request->status =
+					I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+				operation_succeeded = true;
+			break;
+			case I2C_CHANNEL_OPERATION_NO_RESPONSE:
+				i2caux_request->status =
+					I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+			break;
+			case I2C_CHANNEL_OPERATION_TIMEOUT:
+				i2caux_request->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			break;
+			case I2C_CHANNEL_OPERATION_FAILED:
+				i2caux_request->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
+			break;
+			default:
+				i2caux_request->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
+			break;
+			}
+		} while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY);
+	}
+
+	return operation_succeeded;
+}
+
+uint32_t dal_i2c_sw_engine_get_speed(
+	const struct i2c_engine *engine)
+{
+	return FROM_I2C_ENGINE(engine)->speed;
+}
+
+void dal_i2c_sw_engine_set_speed(
+	struct i2c_engine *engine,
+	uint32_t speed)
+{
+	struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
+
+	ASSERT(speed);
+
+	sw_engine->speed = speed ? speed : I2CAUX_DEFAULT_I2C_SW_SPEED;
+
+	sw_engine->clock_delay = 1000 / sw_engine->speed;
+
+	if (sw_engine->clock_delay < 12)
+		sw_engine->clock_delay = 12;
+}
+
+bool dal_i2caux_i2c_sw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc)
+{
+	enum gpio_result result;
+
+	result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
+		GPIO_DDC_CONFIG_TYPE_MODE_I2C);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	engine->base.ddc = ddc;
+
+	return true;
+}
+
+void dal_i2c_sw_engine_submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *req)
+{
+	struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
+
+	struct ddc *ddc = engine->base.ddc;
+	uint16_t clock_delay_div_4 = sw_engine->clock_delay >> 2;
+
+	/* send sync (start / repeated start) */
+
+	bool result = start_sync(engine->base.ctx, ddc, clock_delay_div_4);
+
+	/* process payload */
+
+	if (result) {
+		switch (req->action) {
+		case I2CAUX_TRANSACTION_ACTION_I2C_WRITE:
+		case I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT:
+			result = i2c_write(engine->base.ctx, ddc, clock_delay_div_4,
+				req->address, req->length, req->data);
+		break;
+		case I2CAUX_TRANSACTION_ACTION_I2C_READ:
+		case I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT:
+			result = i2c_read(engine->base.ctx, ddc, clock_delay_div_4,
+				req->address, req->length, req->data);
+		break;
+		default:
+			result = false;
+		break;
+		}
+	}
+
+	/* send stop if not 'mot' or operation failed */
+
+	if (!result ||
+		(req->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
+		(req->action == I2CAUX_TRANSACTION_ACTION_I2C_READ))
+		if (!stop_sync(engine->base.ctx, ddc, clock_delay_div_4))
+			result = false;
+
+	req->status = result ?
+		I2C_CHANNEL_OPERATION_SUCCEEDED :
+		I2C_CHANNEL_OPERATION_FAILED;
+}
+
+enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status(
+	struct i2c_engine *engine,
+	uint8_t *returned_bytes)
+{
+	return dal_ddc_check_line_aborted(engine->base.ddc) ?
+		I2C_CHANNEL_OPERATION_FAILED :
+		I2C_CHANNEL_OPERATION_SUCCEEDED;
+}
+
+void dal_i2c_sw_engine_destruct(
+	struct i2c_sw_engine *engine)
+{
+	dal_i2c_engine_destruct(&engine->base);
+}
+
+static void destroy(
+	struct i2c_engine **ptr)
+{
+	dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr));
+
+	dm_free((*ptr)->base.ctx, *ptr);
+	*ptr = NULL;
+}
+
+static const struct i2c_engine_funcs i2c_engine_funcs = {
+	.acquire_engine = dal_i2caux_i2c_sw_engine_acquire_engine,
+	.destroy = destroy,
+	.get_speed = dal_i2c_sw_engine_get_speed,
+	.set_speed = dal_i2c_sw_engine_set_speed,
+	.setup_engine = dal_i2c_engine_setup_i2c_engine,
+	.submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
+	.process_channel_reply = dal_i2c_engine_process_channel_reply,
+	.get_channel_status = dal_i2c_sw_engine_get_channel_status,
+};
+
+static void release_engine(
+	struct engine *engine)
+{
+
+}
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.get_engine_type = dal_i2c_sw_engine_get_engine_type,
+	.acquire = dal_i2c_engine_acquire,
+	.submit_request = dal_i2c_sw_engine_submit_request,
+	.keep_power_up_count = dal_i2caux_keep_power_up_count,
+};
+
+bool dal_i2c_sw_engine_construct(
+	struct i2c_sw_engine *engine,
+	const struct i2c_sw_engine_create_arg *arg)
+{
+	if (!dal_i2c_engine_construct(&engine->base, arg->ctx))
+		return false;
+
+	dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed);
+	engine->base.funcs = &i2c_engine_funcs;
+	engine->base.base.funcs = &engine_funcs;
+	return true;
+}
+
+
+
+struct i2c_engine *dal_i2c_sw_engine_create(
+	const struct i2c_sw_engine_create_arg *arg)
+{
+	struct i2c_sw_engine *engine;
+
+	if (!arg) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	engine = dm_alloc(arg->ctx, sizeof(struct i2c_sw_engine));
+
+	if (!engine) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (dal_i2c_sw_engine_construct(engine, arg))
+		return &engine->base;
+
+	BREAK_TO_DEBUGGER();
+
+	dm_free(arg->ctx, engine);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
new file mode 100644
index 000000000000..e0cb4c3d483d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_SW_ENGINE_H__
+#define __DAL_I2C_SW_ENGINE_H__
+
+enum {
+	I2C_SW_RETRIES = 10,
+	I2C_SW_SCL_READ_RETRIES = 128,
+	/* following value is in microseconds */
+	I2C_SW_TIMEOUT_DELAY = 3000
+};
+
+struct i2c_sw_engine;
+
+struct i2c_sw_engine {
+	struct i2c_engine base;
+	uint32_t clock_delay;
+	/* Values below are in KHz */
+	uint32_t speed;
+	uint32_t default_speed;
+};
+
+struct i2c_sw_engine_create_arg {
+	uint32_t default_speed;
+	struct dc_context *ctx;
+};
+
+bool dal_i2c_sw_engine_construct(
+	struct i2c_sw_engine *engine,
+	const struct i2c_sw_engine_create_arg *arg);
+
+bool dal_i2caux_i2c_sw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc_handle);
+
+void dal_i2c_sw_engine_destruct(
+	struct i2c_sw_engine *engine);
+
+struct i2c_engine *dal_i2c_sw_engine_create(
+	const struct i2c_sw_engine_create_arg *arg);
+enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type(
+	const struct engine *engine);
+bool dal_i2c_sw_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction);
+uint32_t dal_i2c_sw_engine_get_speed(
+	const struct i2c_engine *engine);
+void dal_i2c_sw_engine_set_speed(
+	struct i2c_engine *ptr,
+	uint32_t speed);
+void dal_i2c_sw_engine_submit_channel_request(
+	struct i2c_engine *ptr,
+	struct i2c_request_transaction_data *req);
+enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status(
+	struct i2c_engine *engine,
+	uint8_t *returned_bytes);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
new file mode 100644
index 000000000000..4c2f2cb64315
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2caux.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "engine.h"
+#include "i2c_engine.h"
+#include "aux_engine.h"
+
+/*
+ * This unit
+ */
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce110/i2caux_dce110.h"
+#endif
+
+#include "diagnostics/i2caux_diag.h"
+
+/*
+ * @brief
+ * Plain API, available publicly
+ */
+
+struct i2caux *dal_i2caux_create(
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	enum dce_version dce_version;
+	enum dce_environment dce_environment;
+
+	if (!as) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	dce_version = dal_adapter_service_get_dce_version(as);
+	dce_environment = dal_adapter_service_get_dce_environment(as);
+
+	if (IS_FPGA_MAXIMUS_DC(dce_environment)) {
+		return dal_i2caux_diag_fpga_create(as, ctx);
+	}
+
+	switch (dce_version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+#endif
+	case DCE_VERSION_11_0:
+		return dal_i2caux_dce110_create(as, ctx);
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+}
+
+bool dal_i2caux_submit_i2c_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct i2c_command *cmd)
+{
+	struct i2c_engine *engine;
+	uint8_t index_of_payload = 0;
+	bool result;
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!cmd) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	switch (cmd->engine) {
+	case I2C_COMMAND_ENGINE_SW:
+		/* try to acquire SW engine first,
+		 * acquire HW engine if SW engine not available */
+		engine = i2caux->funcs->acquire_i2c_sw_engine(i2caux, ddc);
+
+		if (!engine)
+			engine = i2caux->funcs->acquire_i2c_hw_engine(
+				i2caux, ddc);
+	break;
+	case I2C_COMMAND_ENGINE_HW:
+	case I2C_COMMAND_ENGINE_DEFAULT:
+	default:
+		/* try to acquire HW engine first,
+		 * acquire SW engine if HW engine not available */
+		engine = i2caux->funcs->acquire_i2c_hw_engine(i2caux, ddc);
+
+		if (!engine)
+			engine = i2caux->funcs->acquire_i2c_sw_engine(
+				i2caux, ddc);
+	}
+
+	if (!engine)
+		return false;
+
+	engine->funcs->set_speed(engine, cmd->speed);
+
+	result = true;
+
+	while (index_of_payload < cmd->number_of_payloads) {
+		bool mot = (index_of_payload != cmd->number_of_payloads - 1);
+
+		struct i2c_payload *payload = cmd->payloads + index_of_payload;
+
+		struct i2caux_transaction_request request = { 0 };
+
+		request.operation = payload->write ?
+			I2CAUX_TRANSACTION_WRITE :
+			I2CAUX_TRANSACTION_READ;
+
+		request.payload.address_space =
+			I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C;
+		request.payload.address = (payload->address << 1) |
+			!payload->write;
+		request.payload.length = payload->length;
+		request.payload.data = payload->data;
+
+		if (!engine->base.funcs->submit_request(
+			&engine->base, &request, mot)) {
+			result = false;
+			break;
+		}
+
+		++index_of_payload;
+	}
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return result;
+}
+
+bool dal_i2caux_submit_aux_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct aux_command *cmd)
+{
+	struct aux_engine *engine;
+	uint8_t index_of_payload = 0;
+	bool result;
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!cmd) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc);
+
+	if (!engine)
+		return false;
+
+	engine->delay = cmd->defer_delay;
+	engine->max_defer_write_retry = cmd->max_defer_write_retry;
+
+	result = true;
+
+	while (index_of_payload < cmd->number_of_payloads) {
+		bool mot = (index_of_payload != cmd->number_of_payloads - 1);
+
+		struct aux_payload *payload = cmd->payloads + index_of_payload;
+
+		struct i2caux_transaction_request request = { 0 };
+
+		request.operation = payload->write ?
+			I2CAUX_TRANSACTION_WRITE :
+			I2CAUX_TRANSACTION_READ;
+
+		if (payload->i2c_over_aux) {
+			request.payload.address_space =
+				I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C;
+
+			request.payload.address = (payload->address << 1) |
+				!payload->write;
+		} else {
+			request.payload.address_space =
+				I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD;
+
+			request.payload.address = payload->address;
+		}
+
+		request.payload.length = payload->length;
+		request.payload.data = payload->data;
+
+		if (!engine->base.funcs->submit_request(
+			&engine->base, &request, mot)) {
+			result = false;
+			break;
+		}
+
+		++index_of_payload;
+	}
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return result;
+}
+
+static bool get_hw_supported_ddc_line(
+	struct ddc *ddc,
+	enum gpio_ddc_line *line)
+{
+	enum gpio_ddc_line line_found;
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!dal_ddc_is_hw_supported(ddc))
+		return false;
+
+	line_found = dal_ddc_get_line(ddc);
+
+	if (line_found >= GPIO_DDC_LINE_COUNT)
+		return false;
+
+	*line = line_found;
+
+	return true;
+}
+
+void dal_i2caux_keep_engine_power_up(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	bool keep_power_up)
+{
+	enum gpio_ddc_line line;
+	struct i2c_engine *engine;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return;
+
+	engine = i2caux->i2c_hw_engines[line];
+
+	engine->base.funcs->keep_power_up_count(&engine->base, keep_power_up);
+}
+
+bool dal_i2caux_start_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+
+	struct aux_engine *engine;
+
+	bool result;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return false;
+
+	engine = i2caux->aux_engines[line];
+
+	if (!engine)
+		return false;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return false;
+
+	result = engine->funcs->start_gtc_sync(engine);
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return result;
+}
+
+bool dal_i2caux_stop_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+
+	struct aux_engine *engine;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return false;
+
+	engine = i2caux->aux_engines[line];
+
+	if (!engine)
+		return false;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return false;
+
+	engine->funcs->stop_gtc_sync(engine);
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return true;
+}
+
+void dal_i2caux_configure_aux(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	union aux_config cfg)
+{
+	struct aux_engine *engine =
+		i2caux->funcs->acquire_aux_engine(i2caux, ddc);
+
+	if (!engine)
+		return;
+
+	engine->funcs->configure(engine, cfg);
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+}
+
+void dal_i2caux_destroy(
+	struct i2caux **i2caux)
+{
+	if (!i2caux || !*i2caux) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*i2caux)->funcs->destroy(i2caux);
+
+	*i2caux = NULL;
+}
+
+/*
+ * @brief
+ * An utility function used by 'struct i2caux' and its descendants
+ */
+
+uint32_t dal_i2caux_get_reference_clock(
+	struct adapter_service *as)
+{
+	struct firmware_info info = { { 0 } };
+
+	if (!dal_adapter_service_get_firmware_info(as, &info))
+		return 0;
+
+	return info.pll_info.crystal_frequency;
+}
+
+/*
+ * @brief
+ * i2caux
+ */
+
+enum {
+	/* following are expressed in KHz */
+	DEFAULT_I2C_SW_SPEED = 50,
+	DEFAULT_I2C_HW_SPEED = 50,
+
+	/* This is the timeout as defined in DP 1.2a,
+	 * 2.3.4 "Detailed uPacket TX AUX CH State Description". */
+	AUX_TIMEOUT_PERIOD = 400,
+
+	/* Ideally, the SW timeout should be just above 550usec
+	 * which is programmed in HW.
+	 * But the SW timeout of 600usec is not reliable,
+	 * because on some systems, delay_in_microseconds()
+	 * returns faster than it should.
+	 * EPR #379763: by trial-and-error on different systems,
+	 * 700usec is the minimum reliable SW timeout for polling
+	 * the AUX_SW_STATUS.AUX_SW_DONE bit.
+	 * This timeout expires *only* when there is
+	 * AUX Error or AUX Timeout conditions - not during normal operation.
+	 * During normal operation, AUX_SW_STATUS.AUX_SW_DONE bit is set
+	 * at most within ~240usec. That means,
+	 * increasing this timeout will not affect normal operation,
+	 * and we'll timeout after
+	 * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD = 1600usec.
+	 * This timeout is especially important for
+	 * resume from S3 and CTS. */
+	SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4
+};
+
+struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+	struct i2c_engine *engine = NULL;
+
+	if (get_hw_supported_ddc_line(ddc, &line))
+		engine = i2caux->i2c_sw_engines[line];
+
+	if (!engine)
+		engine = i2caux->i2c_generic_sw_engine;
+
+	if (!engine)
+		return NULL;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return NULL;
+
+	return engine;
+}
+
+struct aux_engine *dal_i2caux_acquire_aux_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+	struct aux_engine *engine;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return NULL;
+
+	engine = i2caux->aux_engines[line];
+
+	if (!engine)
+		return NULL;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return NULL;
+
+	return engine;
+}
+
+void dal_i2caux_release_engine(
+	struct i2caux *i2caux,
+	struct engine *engine)
+{
+	engine->funcs->release_engine(engine);
+
+	dal_ddc_close(engine->ddc);
+
+	engine->ddc = NULL;
+}
+
+bool dal_i2caux_construct(
+	struct i2caux *i2caux,
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	uint32_t i = 0;
+
+	i2caux->ctx = ctx;
+	do {
+		i2caux->i2c_sw_engines[i] = NULL;
+		i2caux->i2c_hw_engines[i] = NULL;
+		i2caux->aux_engines[i] = NULL;
+
+		++i;
+	} while (i < GPIO_DDC_LINE_COUNT);
+
+	i2caux->i2c_generic_sw_engine = NULL;
+	i2caux->i2c_generic_hw_engine = NULL;
+
+	i2caux->aux_timeout_period =
+		SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD;
+
+	i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED;
+	i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED;
+
+	return true;
+}
+
+void dal_i2caux_destruct(
+	struct i2caux *i2caux)
+{
+	uint32_t i = 0;
+
+	if (i2caux->i2c_generic_hw_engine)
+		i2caux->i2c_generic_hw_engine->funcs->destroy(
+			&i2caux->i2c_generic_hw_engine);
+
+	if (i2caux->i2c_generic_sw_engine)
+		i2caux->i2c_generic_sw_engine->funcs->destroy(
+			&i2caux->i2c_generic_sw_engine);
+
+	do {
+		if (i2caux->aux_engines[i])
+			i2caux->aux_engines[i]->funcs->destroy(
+				&i2caux->aux_engines[i]);
+
+		if (i2caux->i2c_hw_engines[i])
+			i2caux->i2c_hw_engines[i]->funcs->destroy(
+				&i2caux->i2c_hw_engines[i]);
+
+		if (i2caux->i2c_sw_engines[i])
+			i2caux->i2c_sw_engines[i]->funcs->destroy(
+				&i2caux->i2c_sw_engines[i]);
+
+		++i;
+	} while (i < GPIO_DDC_LINE_COUNT);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
new file mode 100644
index 000000000000..76f5b637ec3f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_AUX_H__
+#define __DAL_I2C_AUX_H__
+
+uint32_t dal_i2caux_get_reference_clock(
+	struct adapter_service *as);
+
+struct i2caux;
+
+struct engine;
+
+struct i2caux_funcs {
+	void (*destroy)(struct i2caux **ptr);
+	struct i2c_engine * (*acquire_i2c_sw_engine)(
+		struct i2caux *i2caux,
+		struct ddc *ddc);
+	struct i2c_engine * (*acquire_i2c_hw_engine)(
+		struct i2caux *i2caux,
+		struct ddc *ddc);
+	struct aux_engine * (*acquire_aux_engine)(
+		struct i2caux *i2caux,
+		struct ddc *ddc);
+	void (*release_engine)(
+		struct i2caux *i2caux,
+		struct engine *engine);
+};
+
+struct i2c_engine;
+struct aux_engine;
+
+struct i2caux {
+	struct dc_context *ctx;
+	const struct i2caux_funcs *funcs;
+	/* On ASIC we have certain amount of lines with HW DDC engine
+	 * (4, 6, or maybe more in the future).
+	 * For every such line, we create separate HW DDC engine
+	 * (since we have these engines in HW) and separate SW DDC engine
+	 * (to allow concurrent use of few lines).
+	 * In similar way we have AUX engines. */
+
+	/* I2C SW engines, per DDC line.
+	 * Only lines with HW DDC support will be initialized */
+	struct i2c_engine *i2c_sw_engines[GPIO_DDC_LINE_COUNT];
+
+	/* I2C HW engines, per DDC line.
+	 * Only lines with HW DDC support will be initialized */
+	struct i2c_engine *i2c_hw_engines[GPIO_DDC_LINE_COUNT];
+
+	/* AUX engines, per DDC line.
+	 * Only lines with HW AUX support will be initialized */
+	struct aux_engine *aux_engines[GPIO_DDC_LINE_COUNT];
+
+	/* For all other lines, we can use
+	 * single instance of generic I2C HW engine
+	 * (since in HW, there is single instance of it)
+	 * or single instance of generic I2C SW engine.
+	 * AUX is not supported for other lines. */
+
+	/* General-purpose I2C SW engine.
+	 * Can be assigned dynamically to any line per transaction */
+	struct i2c_engine *i2c_generic_sw_engine;
+
+	/* General-purpose I2C generic HW engine.
+	 * Can be assigned dynamically to almost any line per transaction */
+	struct i2c_engine *i2c_generic_hw_engine;
+
+	/* [anaumov] in DAL2, there is a Mutex */
+
+	uint32_t aux_timeout_period;
+
+	/* expressed in KHz */
+	uint32_t default_i2c_sw_speed;
+	uint32_t default_i2c_hw_speed;
+};
+
+bool dal_i2caux_construct(
+	struct i2caux *i2caux,
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+void dal_i2caux_release_engine(
+	struct i2caux *i2caux,
+	struct engine *engine);
+
+void dal_i2caux_destruct(
+	struct i2caux *i2caux);
+
+void dal_i2caux_destroy(
+	struct i2caux **ptr);
+
+struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+struct aux_engine *dal_i2caux_acquire_aux_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 09/29] drm/amd/dal: IRQ Service
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (7 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 08/29] drm/amd/dal: I2C Aux Manager Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 10/29] drm/amd/dal: GPU Harry Wentland
                   ` (23 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Interface to set and ack DCE interrupts.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/irq/Makefile            |  21 ++
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.c | 389 +++++++++++++++++++++
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.h |  34 ++
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c       | 177 ++++++++++
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h       |  85 +++++
 5 files changed, 706 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h

diff --git a/drivers/gpu/drm/amd/dal/dc/irq/Makefile b/drivers/gpu/drm/amd/dal/dc/irq/Makefile
new file mode 100644
index 000000000000..f1c5faf94b83
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the 'audio' sub-component of DAL.
+# It provides the control and status of HW adapter resources,
+# that are global for the ASIC and sharable between pipes.
+
+IRQ = irq_service.o
+
+AMD_DAL_IRQ = $(addprefix $(AMDDALPATH)/dc/irq/,$(IRQ))
+
+AMD_DAL_FILES += $(AMD_DAL_IRQ)
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+IRQ_DCE11 = irq_service_dce110.o
+
+AMD_DAL_IRQ_DCE11 = $(addprefix $(AMDDALPATH)/dc/irq/dce110/,$(IRQ_DCE11))
+
+AMD_DAL_FILES += $(AMD_DAL_IRQ_DCE11)
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
new file mode 100644
index 000000000000..4085b6f6e7fd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "irq_service_dce110.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "ivsrcid/ivsrcid_vislands30.h"
+
+static bool hpd_ack(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info)
+{
+	uint32_t addr = info->status_reg;
+	uint32_t value = dm_read_reg(irq_service->ctx, addr);
+	uint32_t current_status =
+		get_reg_field_value(
+			value,
+			DC_HPD_INT_STATUS,
+			DC_HPD_SENSE_DELAYED);
+
+	dal_irq_service_ack_generic(irq_service, info);
+
+	value = dm_read_reg(irq_service->ctx, info->enable_reg);
+
+	set_reg_field_value(
+		value,
+		current_status ? 0 : 1,
+		DC_HPD_INT_CONTROL,
+		DC_HPD_INT_POLARITY);
+
+	dm_write_reg(irq_service->ctx, info->enable_reg, value);
+
+	return true;
+}
+
+static const struct irq_source_info_funcs hpd_irq_info_funcs = {
+	.set = NULL,
+	.ack = hpd_ack
+};
+
+static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = {
+	.set = NULL,
+	.ack = NULL
+};
+
+static const struct irq_source_info_funcs pflip_irq_info_funcs = {
+	.set = NULL,
+	.ack = NULL
+};
+
+static const struct irq_source_info_funcs vblank_irq_info_funcs = {
+	.set = NULL,
+	.ack = NULL
+};
+
+#define hpd_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_HPD1 + reg_num] = {\
+		.enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
+		.enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
+		.enable_value = {\
+			DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
+			~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\
+		},\
+		.ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
+		.ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\
+		.ack_value = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\
+		.status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\
+		.funcs = &hpd_irq_info_funcs\
+	}
+
+#define hpd_rx_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_HPD1RX + reg_num] = {\
+		.enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
+		.enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
+		.enable_value = {\
+			DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
+			~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\
+		.ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
+		.ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
+		.ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
+		.status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\
+		.funcs = &hpd_rx_irq_info_funcs\
+	}
+#define pflip_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\
+		.enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\
+		.enable_mask =\
+		GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
+		.enable_value = {\
+			GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
+			~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
+		.ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\
+		.ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
+		.ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
+		.status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\
+		.funcs = &pflip_irq_info_funcs\
+	}
+
+#define vsync_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_CRTC ## reg_num ## VSYNC] = dummy_irq_entry()
+
+#define vupdate_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
+		.enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\
+		.enable_mask =\
+		CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
+		.enable_value = {\
+			CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
+			~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
+		.ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\
+		.ack_mask =\
+		CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
+		.ack_value =\
+		CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
+		.funcs = &vblank_irq_info_funcs\
+	}
+
+#define dummy_irq_entry() \
+	{\
+		.funcs = &dummy_irq_info_funcs\
+	}
+
+#define i2c_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry()
+
+#define azalia_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_AZALIA ## reg_num] = dummy_irq_entry()
+
+#define dp_sink_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry()
+
+#define gpio_pad_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry()
+
+#define dc_underflow_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry()
+
+static bool dummy_set(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info,
+	bool enable)
+{
+	dal_logger_write(
+		irq_service->ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_IRQ_SERVICE,
+		"%s: called for non-implemented irq source\n",
+		__func__);
+	return false;
+}
+
+static bool dummy_ack(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info)
+{
+	dal_logger_write(
+		irq_service->ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_IRQ_SERVICE,
+		"%s: called for non-implemented irq source\n",
+		__func__);
+	return false;
+}
+
+static const struct irq_source_info_funcs dummy_irq_info_funcs = {
+	.set = dummy_set,
+	.ack = dummy_ack
+};
+
+static const struct irq_source_info
+irq_source_info_dce110[DAL_IRQ_SOURCES_NUMBER] = {
+	[DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(),
+	hpd_int_entry(0),
+	hpd_int_entry(1),
+	hpd_int_entry(2),
+	hpd_int_entry(3),
+	hpd_int_entry(4),
+	hpd_int_entry(5),
+	hpd_rx_int_entry(0),
+	hpd_rx_int_entry(1),
+	hpd_rx_int_entry(2),
+	hpd_rx_int_entry(3),
+	hpd_rx_int_entry(4),
+	hpd_rx_int_entry(5),
+	i2c_int_entry(1),
+	i2c_int_entry(2),
+	i2c_int_entry(3),
+	i2c_int_entry(4),
+	i2c_int_entry(5),
+	i2c_int_entry(6),
+	azalia_int_entry(0),
+	azalia_int_entry(1),
+	azalia_int_entry(2),
+	azalia_int_entry(3),
+	azalia_int_entry(4),
+	azalia_int_entry(5),
+	dp_sink_int_entry(1),
+	dp_sink_int_entry(2),
+	dp_sink_int_entry(3),
+	dp_sink_int_entry(4),
+	dp_sink_int_entry(5),
+	dp_sink_int_entry(6),
+	vsync_int_entry(1),
+	vsync_int_entry(2),
+	vsync_int_entry(3),
+	vsync_int_entry(3),
+	vsync_int_entry(4),
+	vsync_int_entry(5),
+	[DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(),
+	pflip_int_entry(0),
+	pflip_int_entry(1),
+	pflip_int_entry(2),
+	pflip_int_entry(3),
+	pflip_int_entry(4),
+	pflip_int_entry(5),
+	[DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(),
+	gpio_pad_int_entry(0),
+	gpio_pad_int_entry(1),
+	gpio_pad_int_entry(2),
+	gpio_pad_int_entry(3),
+	gpio_pad_int_entry(4),
+	gpio_pad_int_entry(5),
+	gpio_pad_int_entry(6),
+	gpio_pad_int_entry(7),
+	gpio_pad_int_entry(8),
+	gpio_pad_int_entry(9),
+	gpio_pad_int_entry(10),
+	gpio_pad_int_entry(11),
+	gpio_pad_int_entry(12),
+	gpio_pad_int_entry(13),
+	gpio_pad_int_entry(14),
+	gpio_pad_int_entry(15),
+	gpio_pad_int_entry(16),
+	gpio_pad_int_entry(17),
+	gpio_pad_int_entry(18),
+	gpio_pad_int_entry(19),
+	gpio_pad_int_entry(20),
+	gpio_pad_int_entry(21),
+	gpio_pad_int_entry(22),
+	gpio_pad_int_entry(23),
+	gpio_pad_int_entry(24),
+	gpio_pad_int_entry(25),
+	gpio_pad_int_entry(26),
+	gpio_pad_int_entry(27),
+	gpio_pad_int_entry(28),
+	gpio_pad_int_entry(29),
+	gpio_pad_int_entry(30),
+	dc_underflow_int_entry(1),
+	dc_underflow_int_entry(2),
+	dc_underflow_int_entry(3),
+	dc_underflow_int_entry(4),
+	dc_underflow_int_entry(5),
+	dc_underflow_int_entry(6),
+	[DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(),
+	[DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(),
+	vupdate_int_entry(0),
+	vupdate_int_entry(1),
+	vupdate_int_entry(2),
+	vupdate_int_entry(3),
+	vupdate_int_entry(4),
+	vupdate_int_entry(5),
+};
+
+static enum dc_irq_source to_dal_irq_source(
+		struct irq_service *irq_service,
+		uint32_t src_id,
+		uint32_t ext_id)
+{
+	switch (src_id) {
+	case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE1;
+	case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE2;
+	case VISLANDS30_IV_SRCID_D3_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE3;
+	case VISLANDS30_IV_SRCID_D4_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE4;
+	case VISLANDS30_IV_SRCID_D5_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE5;
+	case VISLANDS30_IV_SRCID_D6_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE6;
+	case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP1;
+	case VISLANDS30_IV_SRCID_D2_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP2;
+	case VISLANDS30_IV_SRCID_D3_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP3;
+	case VISLANDS30_IV_SRCID_D4_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP4;
+	case VISLANDS30_IV_SRCID_D5_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP5;
+	case VISLANDS30_IV_SRCID_D6_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP6;
+
+	case VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A:
+		/* generic src_id for all HPD and HPDRX interrupts */
+		switch (ext_id) {
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_A:
+			return DC_IRQ_SOURCE_HPD1;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_B:
+			return DC_IRQ_SOURCE_HPD2;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_C:
+			return DC_IRQ_SOURCE_HPD3;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_D:
+			return DC_IRQ_SOURCE_HPD4;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_E:
+			return DC_IRQ_SOURCE_HPD5;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_F:
+			return DC_IRQ_SOURCE_HPD6;
+		case VISLANDS30_IV_EXTID_HPD_RX_A:
+			return DC_IRQ_SOURCE_HPD1RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_B:
+			return DC_IRQ_SOURCE_HPD2RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_C:
+			return DC_IRQ_SOURCE_HPD3RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_D:
+			return DC_IRQ_SOURCE_HPD4RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_E:
+			return DC_IRQ_SOURCE_HPD5RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_F:
+			return DC_IRQ_SOURCE_HPD6RX;
+		default:
+			return DC_IRQ_SOURCE_INVALID;
+		}
+		break;
+
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+static const struct irq_service_funcs irq_service_funcs_dce110 = {
+		.to_dal_irq_source = to_dal_irq_source
+};
+
+bool construct(
+	struct irq_service *irq_service,
+	struct irq_service_init_data *init_data)
+{
+	if (!dal_irq_service_construct(irq_service, init_data))
+		return false;
+
+	irq_service->info = irq_source_info_dce110;
+	irq_service->funcs = &irq_service_funcs_dce110;
+
+	return true;
+}
+
+struct irq_service *dal_irq_service_dce110_create(
+	struct irq_service_init_data *init_data)
+{
+	struct irq_service *irq_service = dm_alloc(init_data->ctx, sizeof(*irq_service));
+
+	if (!irq_service)
+		return NULL;
+
+	if (construct(irq_service, init_data))
+		return irq_service;
+
+	dm_free(init_data->ctx, irq_service);
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
new file mode 100644
index 000000000000..d6c28e940403
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_SERVICE_DCE110_H__
+#define __DAL_IRQ_SERVICE_DCE110_H__
+
+#include "../irq_service.h"
+
+struct irq_service *dal_irq_service_dce110_create(
+	struct irq_service_init_data *init_data);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
new file mode 100644
index 000000000000..137233134a53
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/irq_service_interface.h"
+#include "include/logger_interface.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/irq_service_dce110.h"
+#endif
+
+#include "irq_service.h"
+
+bool dal_irq_service_construct(
+	struct irq_service *irq_service,
+	struct irq_service_init_data *init_data)
+{
+	if (!init_data || !init_data->ctx)
+		return false;
+
+	irq_service->ctx = init_data->ctx;
+	return true;
+}
+
+struct irq_service *dal_irq_service_create(
+	enum dce_version version,
+	struct irq_service_init_data *init_data)
+{
+	switch (version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dal_irq_service_dce110_create(init_data);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dal_irq_service_dce110_create(init_data);
+#endif
+	default:
+		return NULL;
+	}
+}
+
+void dal_irq_service_destroy(struct irq_service **irq_service)
+{
+	if (!irq_service || !*irq_service) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	dm_free((*irq_service)->ctx, *irq_service);
+
+	*irq_service = NULL;
+}
+
+const struct irq_source_info *find_irq_source_info(
+	struct irq_service *irq_service,
+	enum dc_irq_source source)
+{
+	if (source > DAL_IRQ_SOURCES_NUMBER || source < DC_IRQ_SOURCE_INVALID)
+		return NULL;
+
+	return &irq_service->info[source];
+}
+
+void dal_irq_service_set_generic(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info,
+	bool enable)
+{
+	uint32_t addr = info->enable_reg;
+	uint32_t value = dm_read_reg(irq_service->ctx, addr);
+
+	value = (value & ~info->enable_mask) |
+		(info->enable_value[enable ? 0 : 1] & info->enable_mask);
+	dm_write_reg(irq_service->ctx, addr, value);
+}
+
+bool dal_irq_service_set(
+	struct irq_service *irq_service,
+	enum dc_irq_source source,
+	bool enable)
+{
+	const struct irq_source_info *info =
+		find_irq_source_info(irq_service, source);
+
+	if (!info) {
+		dal_logger_write(
+			irq_service->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_IRQ_SERVICE,
+			"%s: cannot find irq info table entry for %d\n",
+			__func__,
+			source);
+		return false;
+	}
+
+	dal_irq_service_ack(irq_service, source);
+
+	if (info->funcs->set)
+		return info->funcs->set(irq_service, info, enable);
+
+	dal_irq_service_set_generic(irq_service, info, enable);
+
+	return true;
+}
+
+void dal_irq_service_ack_generic(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info)
+{
+	uint32_t addr = info->ack_reg;
+	uint32_t value = dm_read_reg(irq_service->ctx, addr);
+
+	value = (value & ~info->ack_mask) |
+		(info->ack_value & info->ack_mask);
+	dm_write_reg(irq_service->ctx, addr, value);
+}
+
+bool dal_irq_service_ack(
+	struct irq_service *irq_service,
+	enum dc_irq_source source)
+{
+	const struct irq_source_info *info =
+		find_irq_source_info(irq_service, source);
+
+	if (!info) {
+		dal_logger_write(
+			irq_service->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_IRQ_SERVICE,
+			"%s: cannot find irq info table entry for %d\n",
+			__func__,
+			source);
+		return false;
+	}
+
+	if (info->funcs->ack)
+		return info->funcs->ack(irq_service, info);
+
+	dal_irq_service_ack_generic(irq_service, info);
+
+	return true;
+}
+
+enum dc_irq_source dal_irq_service_to_irq_source(
+		struct irq_service *irq_service,
+		uint32_t src_id,
+		uint32_t ext_id)
+{
+	return irq_service->funcs->to_dal_irq_source(
+		irq_service,
+		src_id,
+		ext_id);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/irq/irq_service.h b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.h
new file mode 100644
index 000000000000..a2a2d6965c2f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_SERVICE_H__
+#define __DAL_IRQ_SERVICE_H__
+
+#include "include/irq_service_interface.h"
+
+#include "irq_types.h"
+
+struct irq_service;
+struct irq_source_info;
+
+struct irq_source_info_funcs {
+	bool (*set)(
+		struct irq_service *irq_service,
+		const struct irq_source_info *info,
+		bool enable);
+	bool (*ack)(
+		struct irq_service *irq_service,
+		const struct irq_source_info *info);
+};
+
+struct irq_source_info {
+	uint32_t src_id;
+	uint32_t ext_id;
+	uint32_t enable_reg;
+	uint32_t enable_mask;
+	uint32_t enable_value[2];
+	uint32_t ack_reg;
+	uint32_t ack_mask;
+	uint32_t ack_value;
+	uint32_t status_reg;
+	const struct irq_source_info_funcs *funcs;
+};
+
+struct irq_service_funcs {
+	enum dc_irq_source (*to_dal_irq_source)(
+			struct irq_service *irq_service,
+			uint32_t src_id,
+			uint32_t ext_id);
+};
+
+struct irq_service {
+	struct dc_context *ctx;
+	const struct irq_source_info *info;
+	const struct irq_service_funcs *funcs;
+};
+
+bool dal_irq_service_construct(
+	struct irq_service *irq_service,
+	struct irq_service_init_data *init_data);
+
+void dal_irq_service_ack_generic(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info);
+
+void dal_irq_service_set_generic(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info,
+	bool enable);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 10/29] drm/amd/dal: GPU
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (8 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 09/29] drm/amd/dal: IRQ Service Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 11/29] drm/amd/dal: Audio Harry Wentland
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Encapsulates programming for HW blocks which are shared between display
paths, such as clock sources.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/gpu/Makefile            |  22 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c    |  92 ++
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h    |  63 ++
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c |  90 ++
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h |  33 +
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.c   | 968 +++++++++++++++++++++
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.h   |  53 ++
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c     | 205 +++++
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h     |  82 ++
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c     | 127 +++
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h     |  63 ++
 11 files changed, 1798 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h

diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/Makefile b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile
new file mode 100644
index 000000000000..b481a6d5c6bb
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the 'gpu' sub-component of DAL.
+# It provides the control and status of HW adapter resources,
+# that are global for the ASIC and sharable between pipes.
+
+GPU = dc_clock_generator.o display_clock.o divider_range.o
+
+AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU))
+
+AMD_DAL_FILES += $(AMD_DAL_GPU)
+
+
+###############################################################################
+# DCE 110 family
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+GPU_DCE110 = display_clock_dce110.o dc_clock_gating_dce110.o
+
+AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_GPU_DCE110)
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
new file mode 100644
index 000000000000..b3b0f99933f7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dc_clock_generator.h"
+
+void dal_dc_clock_generator_destroy(struct dc_clock_generator **dc)
+{
+	if (dc == NULL || *dc == NULL) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*dc)->funcs->destroy(dc);
+
+	*dc = NULL;
+}
+
+void dal_dc_clock_generator_set_display_pipe_mapping(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_mapping_params *params)
+{
+	dc_clk_gen->funcs->set_display_pipe_mapping(dc_clk_gen, params);
+}
+
+bool dal_dc_clock_generator_get_dp_ref_clk_ds_params(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_dp_ref_clk_ds_params *params)
+{
+	return dc_clk_gen->funcs->get_dp_ref_clk_ds_params(dc_clk_gen, params);
+}
+
+bool dal_dc_clock_generator_enable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen,
+	uint32_t dprefclk)
+{
+	return dc_clk_gen->funcs->enable_gtc_counter(dc_clk_gen, dprefclk);
+}
+
+void dal_dc_clock_generator_disable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen)
+{
+	dc_clk_gen->funcs->disable_gtc_counter(dc_clk_gen);
+}
+
+void dal_dc_clock_generator_set_gtc_group_offset(
+	struct dc_clock_generator *dc_clk_gen,
+	enum gtc_group group_num,
+	uint32_t offset)
+{
+	dc_clk_gen->funcs->set_gtc_group_offset(dc_clk_gen, group_num, offset);
+}
+
+void dal_dc_clock_generator_base_set_display_pipe_mapping(
+	struct dc_clock_generator *base,
+	struct dccg_mapping_params *params)
+{
+
+}
+
+bool dal_dc_clock_generator_construct_base(
+	struct dc_clock_generator *base,
+	struct dc_context *ctx
+)
+{
+	base->ctx = ctx;
+	return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
new file mode 100644
index 000000000000..d1bf1af0500a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DC_CLOCK_GENERATOR_H__
+#define __DAL_DC_CLOCK_GENERATOR_H__
+
+#include "include/dc_clock_generator_interface.h"
+
+struct dc_clock_generator_funcs {
+	void (*destroy)(struct dc_clock_generator **to_destroy);
+
+	void (*set_display_pipe_mapping)(
+		struct dc_clock_generator *dc_clk_gen,
+		struct dccg_mapping_params *params);
+
+	bool (*get_dp_ref_clk_ds_params)(
+		struct dc_clock_generator *dc_clk_gen,
+		struct dccg_dp_ref_clk_ds_params *params);
+	bool (*enable_gtc_counter)(
+		struct dc_clock_generator *dc_clk_gen,
+		uint32_t dprefclk);
+	void (*disable_gtc_counter)(
+		struct dc_clock_generator *dc_clk_gen);
+	void (*set_gtc_group_offset)(
+		struct dc_clock_generator *dc_clk_gen,
+		enum gtc_group group_num,
+		uint32_t offset);
+};
+struct dc_clock_generator {
+	const struct dc_clock_generator_funcs *funcs;
+	struct dc_context *ctx;
+};
+bool dal_dc_clock_generator_construct_base(
+	struct dc_clock_generator *base,
+	struct dc_context *ctx
+);
+void dal_dc_clock_generator_base_set_display_pipe_mapping(
+	struct dc_clock_generator *base,
+	struct dccg_mapping_params *params);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
new file mode 100644
index 000000000000..4c307f6baf5a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dc_clock_gating_dce110.h"
+
+/******************************************************************************
+ * Macro definitions
+ *****************************************************************************/
+
+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_GPU, \
+		"%s:%s()\n", __FILE__, __func__)
+
+/******************************************************************************
+ * static functions
+ *****************************************************************************/
+static void force_hw_base_light_sleep(struct dc_context *ctx)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+
+	addr = mmDC_MEM_GLOBAL_PWR_REQ_CNTL;
+	/* Read the mmDC_MEM_GLOBAL_PWR_REQ_CNTL to get the currently
+	 * programmed DC_MEM_GLOBAL_PWR_REQ_DIS*/
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+			value,
+			1,
+			DC_MEM_GLOBAL_PWR_REQ_CNTL,
+			DC_MEM_GLOBAL_PWR_REQ_DIS);
+
+	dm_write_reg(ctx, addr, value);
+
+}
+
+static void enable_hw_base_light_sleep(struct dc_context *ctx)
+{
+	NOT_IMPLEMENTED();
+}
+
+static void disable_sw_manual_control_light_sleep(
+		struct dc_context *ctx)
+{
+	NOT_IMPLEMENTED();
+}
+
+/******************************************************************************
+ * public functions
+ *****************************************************************************/
+
+void dal_dc_clock_gating_dce110_power_up(
+		struct dc_context *ctx,
+		bool enable)
+{
+	if (enable) {
+		enable_hw_base_light_sleep(ctx);
+		disable_sw_manual_control_light_sleep(ctx);
+	} else {
+		force_hw_base_light_sleep(ctx);
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
new file mode 100644
index 000000000000..1bfd75a1fb51
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DC_CLOCK_GATING_DCE110_H__
+#define __DAL_DC_CLOCK_GATING_DCE110_H__
+
+void dal_dc_clock_gating_dce110_power_up(
+		struct dc_context *ctx,
+		bool enable);
+
+#endif /* __DAL_DC_CLOCK_GATING_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
new file mode 100644
index 000000000000..15243dea3290
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
@@ -0,0 +1,968 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "include/adapter_service_interface.h"
+#include "include/bios_parser_interface.h"
+#include "include/fixed32_32.h"
+#include "include/logger_interface.h"
+
+#include "../divider_range.h"
+
+#include "display_clock_dce110.h"
+
+#define FROM_DISPLAY_CLOCK(base) \
+	container_of(base, struct display_clock_dce110, disp_clk_base)
+
+static struct state_dependent_clocks max_clks_by_state[] = {
+/*ClocksStateInvalid - should not be used*/
+{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
+/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 },
+/*ClocksStateLow*/
+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 },
+/*ClocksStateNominal*/
+{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 },
+/*ClocksStatePerformance*/
+{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } };
+
+
+/* Starting point for each divider range.*/
+enum divider_range_start {
+	DIVIDER_RANGE_01_START = 200, /* 2.00*/
+	DIVIDER_RANGE_02_START = 1600, /* 16.00*/
+	DIVIDER_RANGE_03_START = 3200, /* 32.00*/
+	DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/
+};
+
+/* Array identifiers and count for the divider ranges.*/
+enum divider_range_count {
+	DIVIDER_RANGE_01 = 0,
+	DIVIDER_RANGE_02,
+	DIVIDER_RANGE_03,
+	DIVIDER_RANGE_MAX /* == 3*/
+};
+
+/* Ranges for divider identifiers (Divider ID or DID)
+ mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/
+enum divider_id_register_setting {
+	DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08,
+	DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40,
+	DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60,
+	DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80
+};
+
+/* Step size between each divider within a range.
+ Incrementing the DENTIST_DISPCLK_WDIVIDER by one
+ will increment the divider by this much.*/
+enum divider_range_step_size {
+	DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/
+	DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/
+	DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */
+};
+
+static struct divider_range divider_ranges[DIVIDER_RANGE_MAX];
+
+#define DCE110_DFS_BYPASS_THRESHOLD_KHZ 400000
+/*****************************************************************************
+ * static functions
+ *****************************************************************************/
+
+/*
+ * store_max_clocks_state
+ *
+ * @brief
+ * Cache the clock state
+ *
+ * @param
+ * struct display_clock *base - [out] cach the state in this structure
+ * enum clocks_state max_clocks_state - [in] state to be stored
+ */
+static void store_max_clocks_state(
+	struct display_clock *base,
+	enum clocks_state max_clocks_state)
+{
+	struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base);
+
+	switch (max_clocks_state) {
+	case CLOCKS_STATE_LOW:
+	case CLOCKS_STATE_NOMINAL:
+	case CLOCKS_STATE_PERFORMANCE:
+	case CLOCKS_STATE_ULTRA_LOW:
+		dc->max_clks_state = max_clocks_state;
+		break;
+
+	case CLOCKS_STATE_INVALID:
+	default:
+		/*Invalid Clocks State!*/
+		ASSERT_CRITICAL(false);
+		break;
+	}
+}
+
+static enum clocks_state get_min_clocks_state(struct display_clock *base)
+{
+	return base->cur_min_clks_state;
+}
+
+static bool set_min_clocks_state(
+	struct display_clock *base,
+	enum clocks_state clocks_state)
+{
+	struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base);
+
+	if (clocks_state > dc->max_clks_state) {
+		/*Requested state exceeds max supported state.*/
+		dal_logger_write(base->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"Requested state exceeds max supported state");
+		return false;
+	} else if (clocks_state == base->cur_min_clks_state) {
+		/*if we're trying to set the same state, we can just return
+		 * since nothing needs to be done*/
+		return true;
+	}
+
+	base->cur_min_clks_state = clocks_state;
+
+	return true;
+}
+
+static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc)
+{
+	uint32_t dispclk_cntl_value;
+	uint32_t dp_ref_clk_cntl_value;
+	uint32_t dp_ref_clk_cntl_src_sel_value;
+	uint32_t dp_ref_clk_khz = 600000;
+	uint32_t target_div = INVALID_DIVIDER;
+	struct display_clock_dce110 *disp_clk = FROM_DISPLAY_CLOCK(dc);
+
+	/* ASSERT DP Reference Clock source is from DFS*/
+	dp_ref_clk_cntl_value = dm_read_reg(dc->ctx,
+			mmDPREFCLK_CNTL);
+
+	dp_ref_clk_cntl_src_sel_value =
+			get_reg_field_value(
+				dp_ref_clk_cntl_value,
+				DPREFCLK_CNTL, DPREFCLK_SRC_SEL);
+
+	ASSERT(dp_ref_clk_cntl_src_sel_value == 0);
+
+	/* Read the mmDENTIST_DISPCLK_CNTL to get the currently
+	 * programmed DID DENTIST_DPREFCLK_WDIVIDER*/
+	dispclk_cntl_value = dm_read_reg(dc->ctx,
+			mmDENTIST_DISPCLK_CNTL);
+
+	/* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/
+	target_div = dal_divider_range_get_divider(
+		divider_ranges,
+		DIVIDER_RANGE_MAX,
+		get_reg_field_value(dispclk_cntl_value,
+			DENTIST_DISPCLK_CNTL,
+			DENTIST_DPREFCLK_WDIVIDER));
+
+
+	if (target_div != INVALID_DIVIDER) {
+		/* Calculate the current DFS clock, in kHz.*/
+		dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR
+			* disp_clk->dentist_vco_freq_khz) / target_div;
+	}
+
+	/* SW will adjust DP REF Clock average value for all purposes
+	 * (DP DTO / DP Audio DTO and DP GTC)
+	 if clock is spread for all cases:
+	 -if SS enabled on DP Ref clock and HW de-spreading enabled with SW
+	 calculations for DS_INCR/DS_MODULO (this is planned to be default case)
+	 -if SS enabled on DP Ref clock and HW de-spreading enabled with HW
+	 calculations (not planned to be used, but average clock should still
+	 be valid)
+	 -if SS enabled on DP Ref clock and HW de-spreading disabled
+	 (should not be case with CIK) then SW should program all rates
+	 generated according to average value (case as with previous ASICs)
+	  */
+	if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) {
+		struct fixed32_32 ss_percentage = dal_fixed32_32_div_int(
+				dal_fixed32_32_from_fraction(
+					disp_clk->gpu_pll_ss_percentage,
+					disp_clk->gpu_pll_ss_divider), 200);
+		struct fixed32_32 adj_dp_ref_clk_khz;
+
+		ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one,
+								ss_percentage);
+		adj_dp_ref_clk_khz =
+			dal_fixed32_32_mul_int(
+				ss_percentage,
+				dp_ref_clk_khz);
+		dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz);
+	}
+
+	return dp_ref_clk_khz;
+}
+
+
+static void destroy(struct display_clock **base)
+{
+	struct display_clock_dce110 *dc110;
+
+	dc110 = DCLCK110_FROM_BASE(*base);
+
+	dm_free((*base)->ctx, dc110);
+
+	*base = NULL;
+}
+
+static uint32_t get_validation_clock(struct display_clock *dc)
+{
+	uint32_t clk = 0;
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+
+	switch (disp_clk->max_clks_state) {
+	case CLOCKS_STATE_ULTRA_LOW:
+		/*Currently not supported, it has 0 in table entry*/
+	case CLOCKS_STATE_LOW:
+		clk = max_clks_by_state[CLOCKS_STATE_LOW].
+						display_clk_khz;
+		break;
+
+	case CLOCKS_STATE_NOMINAL:
+		clk = max_clks_by_state[CLOCKS_STATE_NOMINAL].
+						display_clk_khz;
+		break;
+
+	case CLOCKS_STATE_PERFORMANCE:
+		clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE].
+						display_clk_khz;
+		break;
+
+	case CLOCKS_STATE_INVALID:
+	default:
+		/*Invalid Clocks State*/
+		dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"Invalid clock state");
+		/* just return the display engine clock for
+		 * lowest supported state*/
+		clk = max_clks_by_state[CLOCKS_STATE_LOW].
+						display_clk_khz;
+		break;
+	}
+	return clk;
+}
+
+static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params)
+{
+	/* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/
+	struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1);
+
+	if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A)
+		return deep_color_factor;
+
+	switch (params->deep_color_depth) {
+	case COLOR_DEPTH_101010:
+		/*deep color ratio for 30bpp is 30/24 = 1.25*/
+		deep_color_factor = dal_fixed32_32_from_fraction(30, 24);
+		break;
+
+	case COLOR_DEPTH_121212:
+		/* deep color ratio for 36bpp is 36/24 = 1.5*/
+		deep_color_factor = dal_fixed32_32_from_fraction(36, 24);
+		break;
+
+	case COLOR_DEPTH_161616:
+		/* deep color ratio for 48bpp is 48/24 = 2.0 */
+		deep_color_factor = dal_fixed32_32_from_fraction(48, 24);
+		break;
+	default:
+		break;
+	}
+	return deep_color_factor;
+}
+
+static struct fixed32_32 get_scaler_efficiency(
+	struct dc_context *ctx,
+	struct min_clock_params *params)
+{
+	struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3);
+
+	if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) {
+		scaler_efficiency =
+			dal_fixed32_32_add(
+				dal_fixed32_32_from_fraction(35555, 10000),
+				dal_fixed32_32_from_fraction(
+					55556,
+					100000 * 10000));
+	} else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) {
+		scaler_efficiency =
+			dal_fixed32_32_add(
+				dal_fixed32_32_from_fraction(34285, 10000),
+				dal_fixed32_32_from_fraction(
+					71429,
+					100000 * 10000));
+	} else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP)
+		scaler_efficiency = dal_fixed32_32_from_fraction(32, 10);
+
+	return scaler_efficiency;
+}
+
+static struct fixed32_32 get_lb_lines_in_per_line_out(
+		struct min_clock_params *params,
+		struct fixed32_32 v_scale_ratio)
+{
+	struct fixed32_32 two = dal_fixed32_32_from_int(2);
+	struct fixed32_32 four = dal_fixed32_32_from_int(4);
+	struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3);
+	struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4);
+
+	if (params->line_buffer_prefetch_enabled)
+		return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one);
+	else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one))
+		return dal_fixed32_32_one;
+	else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3))
+		return f4_to_3;
+	else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4))
+		return f6_to_4;
+	else if (dal_fixed32_32_le(v_scale_ratio, two))
+		return two;
+	else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3)))
+		return four;
+	else
+		return dal_fixed32_32_zero;
+}
+
+static uint32_t get_actual_required_display_clk(
+	struct display_clock_dce110 *disp_clk,
+	uint32_t target_clk_khz)
+{
+	uint32_t disp_clk_khz = target_clk_khz;
+	uint32_t div = INVALID_DIVIDER;
+	uint32_t did = INVALID_DID;
+	uint32_t scaled_vco =
+		disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR;
+
+	ASSERT_CRITICAL(!!disp_clk_khz);
+
+	if (disp_clk_khz)
+		div = scaled_vco / disp_clk_khz;
+
+	did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div);
+
+	if (did != INVALID_DID) {
+		div = dal_divider_range_get_divider(
+			divider_ranges, DIVIDER_RANGE_MAX, did);
+
+		if ((div != INVALID_DIVIDER) &&
+			(did > DIVIDER_RANGE_01_BASE_DIVIDER_ID))
+			if (disp_clk_khz > (scaled_vco / div))
+				div = dal_divider_range_get_divider(
+					divider_ranges, DIVIDER_RANGE_MAX,
+					did - 1);
+
+		if (div != INVALID_DIVIDER)
+			disp_clk_khz = scaled_vco / div;
+
+	}
+	/* We need to add 10KHz to this value because the accuracy in VBIOS is
+	 in 10KHz units. So we need to always round the last digit up in order
+	 to reach the next div level.*/
+	return disp_clk_khz + 10;
+}
+
+static uint32_t calc_single_display_min_clks(
+	struct display_clock *base,
+	struct min_clock_params *params,
+	bool set_clk)
+{
+	struct fixed32_32 h_scale_ratio = dal_fixed32_32_one;
+	struct fixed32_32 v_scale_ratio = dal_fixed32_32_one;
+	uint32_t pix_clk_khz = 0;
+	uint32_t lb_source_width = 0;
+	struct fixed32_32 deep_color_factor;
+	struct fixed32_32 scaler_efficiency;
+	struct fixed32_32 v_filter_init;
+	uint32_t v_filter_init_trunc;
+	uint32_t num_lines_at_frame_start = 3;
+	struct fixed32_32 v_filter_init_ceil;
+	struct fixed32_32 lines_per_lines_out_at_frame_start;
+	struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/
+	uint32_t src_wdth_rnd_to_chunks;
+	struct fixed32_32 scaling_coeff;
+	struct fixed32_32 h_blank_granularity_factor =
+			dal_fixed32_32_one;
+	struct fixed32_32 fx_disp_clk_mhz;
+	struct fixed32_32 line_time;
+	struct fixed32_32 disp_pipe_pix_throughput;
+	struct fixed32_32 fx_alt_disp_clk_mhz;
+	uint32_t disp_clk_khz;
+	uint32_t alt_disp_clk_khz;
+	struct display_clock_dce110 *disp_clk_110 = DCLCK110_FROM_BASE(base);
+	uint32_t max_clk_khz = get_validation_clock(base);
+	bool panning_allowed = false; /* TODO: receive this value from AS */
+
+	if (params == NULL) {
+		dal_logger_write(base->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"Invalid input parameter in %s",
+				__func__);
+		return 0;
+	}
+
+	deep_color_factor = get_deep_color_factor(params);
+	scaler_efficiency = get_scaler_efficiency(base->ctx, params);
+	pix_clk_khz = params->requested_pixel_clock;
+	lb_source_width = params->source_view.width;
+
+	if (0 != params->dest_view.height && 0 != params->dest_view.width) {
+
+		h_scale_ratio = dal_fixed32_32_from_fraction(
+			params->source_view.width,
+			params->dest_view.width);
+		v_scale_ratio = dal_fixed32_32_from_fraction(
+			params->source_view.height,
+			params->dest_view.height);
+	} else {
+		dal_logger_write(base->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"Destination height or width is 0!\n");
+	}
+
+	v_filter_init =
+		dal_fixed32_32_add(
+			v_scale_ratio,
+			dal_fixed32_32_add_int(
+				dal_fixed32_32_div_int(
+					dal_fixed32_32_mul_int(
+						v_scale_ratio,
+						params->timing_info.INTERLACED),
+					2),
+				params->scaling_info.v_taps + 1));
+	v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2);
+
+	v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init);
+
+	v_filter_init_ceil = dal_fixed32_32_from_fraction(
+						v_filter_init_trunc, 2);
+	v_filter_init_ceil = dal_fixed32_32_from_int(
+		dal_fixed32_32_ceil(v_filter_init_ceil));
+	v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2);
+
+	lines_per_lines_out_at_frame_start =
+			dal_fixed32_32_div_int(v_filter_init_ceil,
+					num_lines_at_frame_start);
+	lb_lines_in_per_line_out =
+			get_lb_lines_in_per_line_out(params, v_scale_ratio);
+
+	if (panning_allowed)
+		src_wdth_rnd_to_chunks =
+			((lb_source_width - 1) / 128) * 128 + 256;
+	else
+		src_wdth_rnd_to_chunks =
+			((lb_source_width + 127) / 128) * 128;
+
+	scaling_coeff =
+		dal_fixed32_32_div(
+			dal_fixed32_32_from_int(params->scaling_info.v_taps),
+			scaler_efficiency);
+
+	if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one))
+		scaling_coeff = dal_fixed32_32_max(
+			dal_fixed32_32_from_int(
+				dal_fixed32_32_ceil(
+					dal_fixed32_32_from_fraction(
+						params->scaling_info.h_taps,
+						4))),
+			dal_fixed32_32_max(
+				dal_fixed32_32_mul(
+					scaling_coeff,
+					h_scale_ratio),
+				dal_fixed32_32_one));
+
+	if (!params->line_buffer_prefetch_enabled &&
+		dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 &&
+		dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) {
+		uint32_t line_total_pixel =
+			params->timing_info.h_total + lb_source_width - 256;
+		h_blank_granularity_factor = dal_fixed32_32_div(
+			dal_fixed32_32_from_int(params->timing_info.h_total),
+			dal_fixed32_32_div(
+			dal_fixed32_32_from_fraction(
+				line_total_pixel, 2),
+				h_scale_ratio));
+	}
+
+	/* Calculate display clock with ramping. Ramping factor is 1.1*/
+	fx_disp_clk_mhz =
+		dal_fixed32_32_div_int(
+			dal_fixed32_32_mul_int(scaling_coeff, 11),
+			10);
+	line_time = dal_fixed32_32_from_fraction(
+			params->timing_info.h_total * 1000, pix_clk_khz);
+
+	disp_pipe_pix_throughput = dal_fixed32_32_mul(
+			lb_lines_in_per_line_out, h_blank_granularity_factor);
+	disp_pipe_pix_throughput = dal_fixed32_32_max(
+			disp_pipe_pix_throughput,
+			lines_per_lines_out_at_frame_start);
+	disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int(
+			disp_pipe_pix_throughput, src_wdth_rnd_to_chunks),
+			line_time);
+
+	if (0 != params->timing_info.h_total) {
+		fx_disp_clk_mhz =
+			dal_fixed32_32_max(
+				dal_fixed32_32_div_int(
+					dal_fixed32_32_mul_int(
+						scaling_coeff, pix_clk_khz),
+						1000),
+				disp_pipe_pix_throughput);
+		fx_disp_clk_mhz =
+			dal_fixed32_32_mul(
+				fx_disp_clk_mhz,
+				dal_fixed32_32_from_fraction(11, 10));
+	}
+
+	fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz,
+		dal_fixed32_32_mul(deep_color_factor,
+		dal_fixed32_32_from_fraction(11, 10)));
+
+	/* Calculate display clock without ramping */
+	fx_alt_disp_clk_mhz = scaling_coeff;
+
+	if (0 != params->timing_info.h_total) {
+		fx_alt_disp_clk_mhz = dal_fixed32_32_max(
+				dal_fixed32_32_div_int(dal_fixed32_32_mul_int(
+						scaling_coeff, pix_clk_khz),
+						1000),
+				dal_fixed32_32_div_int(dal_fixed32_32_mul_int(
+						disp_pipe_pix_throughput, 105),
+						100));
+	}
+
+	if (set_clk && disp_clk_110->ss_on_gpu_pll &&
+			disp_clk_110->gpu_pll_ss_divider)
+		fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz,
+				dal_fixed32_32_add_int(
+				dal_fixed32_32_div_int(
+				dal_fixed32_32_div_int(
+				dal_fixed32_32_from_fraction(
+				disp_clk_110->gpu_pll_ss_percentage,
+				disp_clk_110->gpu_pll_ss_divider), 100),
+				2),
+				1));
+
+	/* convert to integer */
+	disp_clk_khz = dal_fixed32_32_round(
+			dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000));
+	alt_disp_clk_khz = dal_fixed32_32_round(
+			dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000));
+
+	if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz))
+		disp_clk_khz = alt_disp_clk_khz;
+
+	if (set_clk) { /* only compensate clock if we are going to set it.*/
+		disp_clk_khz = get_actual_required_display_clk(
+			disp_clk_110, disp_clk_khz);
+	}
+
+	disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz;
+
+	return disp_clk_khz;
+}
+
+static uint32_t calculate_min_clock(
+	struct display_clock *base,
+	uint32_t path_num,
+	struct min_clock_params *params)
+{
+	uint32_t i;
+	uint32_t validation_clk_khz =
+			get_validation_clock(base);
+	uint32_t min_clk_khz = validation_clk_khz;
+	uint32_t max_clk_khz = 0;
+	struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base);
+
+	if (dc->use_max_disp_clk)
+		return min_clk_khz;
+
+	if (params != NULL) {
+		uint32_t disp_clk_khz = 0;
+
+		for (i = 0; i < path_num; ++i) {
+
+			disp_clk_khz = calc_single_display_min_clks(
+							base, params, true);
+
+			/* update the max required clock found*/
+			if (disp_clk_khz > max_clk_khz)
+				max_clk_khz = disp_clk_khz;
+
+			params++;
+		}
+	}
+
+	min_clk_khz = max_clk_khz;
+
+	if (min_clk_khz > validation_clk_khz)
+		min_clk_khz = validation_clk_khz;
+	else if (min_clk_khz < base->min_display_clk_threshold_khz)
+		min_clk_khz = base->min_display_clk_threshold_khz;
+
+	if (dc->use_max_disp_clk)
+		min_clk_khz = get_validation_clock(base);
+
+	return min_clk_khz;
+}
+
+static bool display_clock_integrated_info_construct(
+	struct display_clock_dce110 *disp_clk,
+	struct adapter_service *as)
+{
+	struct integrated_info info;
+	struct firmware_info fw_info;
+	uint32_t i;
+	struct display_clock *base = &disp_clk->disp_clk_base;
+	bool res;
+
+	dm_memset(&info, 0, sizeof(struct integrated_info));
+	dm_memset(&fw_info, 0, sizeof(struct firmware_info));
+
+	res = dal_adapter_service_get_integrated_info(as, &info);
+
+	disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq;
+	if (disp_clk->dentist_vco_freq_khz == 0) {
+		dal_adapter_service_get_firmware_info(as, &fw_info);
+		disp_clk->dentist_vco_freq_khz =
+			fw_info.smu_gpu_pll_output_freq;
+		if (disp_clk->dentist_vco_freq_khz == 0)
+			disp_clk->dentist_vco_freq_khz = 3600000;
+	}
+
+	base->min_display_clk_threshold_khz =
+		disp_clk->dentist_vco_freq_khz / 64;
+
+	if (!res)
+		return false;
+
+	/*update the maximum display clock for each power state*/
+	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+		enum clocks_state clk_state = CLOCKS_STATE_INVALID;
+
+		switch (i) {
+		case 0:
+			clk_state = CLOCKS_STATE_ULTRA_LOW;
+			break;
+
+		case 1:
+			clk_state = CLOCKS_STATE_LOW;
+			break;
+
+		case 2:
+			clk_state = CLOCKS_STATE_NOMINAL;
+			break;
+
+		case 3:
+			clk_state = CLOCKS_STATE_PERFORMANCE;
+			break;
+
+		default:
+			clk_state = CLOCKS_STATE_INVALID;
+			break;
+		}
+
+		/*Do not allow bad VBIOS/SBIOS to override with invalid values,
+		 * check for > 100MHz*/
+		if (info.disp_clk_voltage[i].max_supported_clk >= 100000) {
+			max_clks_by_state[clk_state].display_clk_khz =
+				info.disp_clk_voltage[i].max_supported_clk;
+		}
+	}
+	disp_clk->dfs_bypass_enabled =
+		dal_adapter_service_is_dfs_bypass_enabled(as);
+	disp_clk->use_max_disp_clk =
+		dal_adapter_service_is_feature_supported(
+			FEATURE_USE_MAX_DISPLAY_CLK);
+
+	return true;
+}
+
+static uint32_t get_clock(struct display_clock *dc)
+{
+	uint32_t disp_clock = get_validation_clock(dc);
+	uint32_t target_div = INVALID_DIVIDER;
+	uint32_t addr = mmDENTIST_DISPCLK_CNTL;
+	uint32_t value = 0;
+	uint32_t field = 0;
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+
+	if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk)
+		return disp_clk->dfs_bypass_disp_clk;
+
+	/* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed
+	 DID DENTIST_DISPCLK_WDIVIDER.*/
+	value = dm_read_reg(dc->ctx, addr);
+	field = get_reg_field_value(
+			value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER);
+
+	/* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/
+	target_div = dal_divider_range_get_divider(
+		divider_ranges,
+		DIVIDER_RANGE_MAX,
+		field);
+
+	if (target_div != INVALID_DIVIDER)
+		/* Calculate the current DFS clock in KHz.
+		 Should be okay up to 42.9 THz before overflowing.*/
+		disp_clock = (DIVIDER_RANGE_SCALE_FACTOR
+			* disp_clk->dentist_vco_freq_khz) / target_div;
+	return disp_clock;
+}
+
+static enum clocks_state get_required_clocks_state(
+		struct display_clock *dc,
+		struct state_dependent_clocks *req_clocks)
+{
+	int32_t i;
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+	enum clocks_state low_req_clk = disp_clk->max_clks_state;
+
+	if (!req_clocks) {
+		/* NULL pointer*/
+		dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"%s: Invalid parameter",
+				__func__);
+		return CLOCKS_STATE_INVALID;
+	}
+
+	/* Iterate from highest supported to lowest valid state, and update
+	 * lowest RequiredState with the lowest state that satisfies
+	 * all required clocks
+	 */
+	for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) {
+		if ((req_clocks->display_clk_khz <=
+			max_clks_by_state[i].display_clk_khz) &&
+			(req_clocks->pixel_clk_khz <=
+				max_clks_by_state[i].pixel_clk_khz))
+			low_req_clk = i;
+	}
+	return low_req_clk;
+}
+
+static void set_clock(
+	struct display_clock *base,
+	uint32_t requested_clk_khz)
+{
+	struct bp_pixel_clock_parameters pxl_clk_params;
+	struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base);
+	struct dc_bios *bp = dal_adapter_service_get_bios_parser(base->as);
+
+	/* Prepare to program display clock*/
+	dm_memset(&pxl_clk_params, 0, sizeof(pxl_clk_params));
+
+	pxl_clk_params.target_pixel_clock = requested_clk_khz;
+	pxl_clk_params.pll_id = base->id;
+
+	bp->funcs->program_display_engine_pll(bp, &pxl_clk_params);
+
+	if (dc->dfs_bypass_enabled) {
+
+		/* Cache the fixed display clock*/
+		dc->dfs_bypass_disp_clk =
+			pxl_clk_params.dfs_bypass_display_clock;
+	}
+
+	/* from power down, we need mark the clock state as ClocksStateNominal
+	 * from HWReset, so when resume we will call pplib voltage regulator.*/
+	if (requested_clk_khz == 0)
+		base->cur_min_clks_state = CLOCKS_STATE_NOMINAL;
+}
+
+static void set_clock_state(
+	struct display_clock *dc,
+	struct display_clock_state clk_state)
+{
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+
+	disp_clk->clock_state = clk_state;
+}
+
+static struct display_clock_state get_clock_state(
+	struct display_clock *dc)
+{
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+
+	return disp_clk->clock_state;
+}
+
+static uint32_t get_dfs_bypass_threshold(struct display_clock *dc)
+{
+	return DCE110_DFS_BYPASS_THRESHOLD_KHZ;
+}
+
+static const struct display_clock_funcs funcs = {
+	.destroy = destroy,
+	.calculate_min_clock = calculate_min_clock,
+	.get_clock = get_clock,
+	.get_clock_state = get_clock_state,
+	.get_dfs_bypass_threshold = get_dfs_bypass_threshold,
+	.get_dp_ref_clk_frequency = get_dp_ref_clk_frequency,
+	.get_min_clocks_state = get_min_clocks_state,
+	.get_required_clocks_state = get_required_clocks_state,
+	.get_validation_clock = get_validation_clock,
+	.set_clock = set_clock,
+	.set_clock_state = set_clock_state,
+	.set_dp_ref_clock_source = NULL,
+	.set_min_clocks_state = set_min_clocks_state,
+	.store_max_clocks_state = store_max_clocks_state,
+	.validate = NULL,
+};
+
+static bool dal_display_clock_dce110_construct(
+	struct display_clock_dce110 *dc110,
+	struct dc_context *ctx,
+	struct adapter_service *as)
+{
+	struct display_clock *dc_base = &dc110->disp_clk_base;
+
+	if (NULL == as)
+		return false;
+
+	if (!dal_display_clock_construct_base(dc_base, ctx, as))
+		return false;
+
+	dc_base->funcs = &funcs;
+
+	dc110->dfs_bypass_disp_clk = 0;
+
+	if (!display_clock_integrated_info_construct(dc110, as))
+		dal_logger_write(dc_base->ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_GPU,
+			"Cannot obtain VBIOS integrated info\n");
+
+	dc110->gpu_pll_ss_percentage = 0;
+	dc110->gpu_pll_ss_divider = 1000;
+	dc110->ss_on_gpu_pll = false;
+
+	dc_base->id = CLOCK_SOURCE_ID_DFS;
+/* Initially set max clocks state to nominal.  This should be updated by
+ * via a pplib call to DAL IRI eventually calling a
+ * DisplayEngineClock_Dce110::StoreMaxClocksState().  This call will come in
+ * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/
+	dc110->max_clks_state = CLOCKS_STATE_NOMINAL;
+
+	dal_divider_range_construct(
+		&divider_ranges[DIVIDER_RANGE_01],
+		DIVIDER_RANGE_01_START,
+		DIVIDER_RANGE_01_STEP_SIZE,
+		DIVIDER_RANGE_01_BASE_DIVIDER_ID,
+		DIVIDER_RANGE_02_BASE_DIVIDER_ID);
+	dal_divider_range_construct(
+		&divider_ranges[DIVIDER_RANGE_02],
+		DIVIDER_RANGE_02_START,
+		DIVIDER_RANGE_02_STEP_SIZE,
+		DIVIDER_RANGE_02_BASE_DIVIDER_ID,
+		DIVIDER_RANGE_03_BASE_DIVIDER_ID);
+	dal_divider_range_construct(
+		&divider_ranges[DIVIDER_RANGE_03],
+		DIVIDER_RANGE_03_START,
+		DIVIDER_RANGE_03_STEP_SIZE,
+		DIVIDER_RANGE_03_BASE_DIVIDER_ID,
+		DIVIDER_RANGE_MAX_DIVIDER_ID);
+
+	{
+		uint32_t ss_info_num =
+			dal_adapter_service_get_ss_info_num(
+				as,
+				AS_SIGNAL_TYPE_GPU_PLL);
+
+		if (ss_info_num) {
+			struct spread_spectrum_info info;
+			bool result;
+
+			dm_memset(&info, 0, sizeof(info));
+
+			result =
+				dal_adapter_service_get_ss_info(
+					as,
+					AS_SIGNAL_TYPE_GPU_PLL,
+					0,
+					&info);
+
+			/* Based on VBIOS, VBIOS will keep entry for GPU PLL SS
+			 * even if SS not enabled and in that case
+			 * SSInfo.spreadSpectrumPercentage !=0 would be sign
+			 * that SS is enabled
+			 */
+			if (result && info.spread_spectrum_percentage != 0) {
+				dc110->ss_on_gpu_pll = true;
+				dc110->gpu_pll_ss_divider =
+					info.spread_percentage_divider;
+
+				if (info.type.CENTER_MODE == 0) {
+					/* Currently for DP Reference clock we
+					 * need only SS percentage for
+					 * downspread */
+					dc110->gpu_pll_ss_percentage =
+						info.spread_spectrum_percentage;
+				}
+			}
+
+		}
+	}
+
+	return true;
+}
+
+/*****************************************************************************
+ * public functions
+ *****************************************************************************/
+
+struct display_clock *dal_display_clock_dce110_create(
+	struct dc_context *ctx,
+	struct adapter_service *as)
+{
+	struct display_clock_dce110 *dc110;
+
+	dc110 = dm_alloc(ctx, sizeof(struct display_clock_dce110));
+
+	if (dc110 == NULL)
+		return NULL;
+
+	if (dal_display_clock_dce110_construct(dc110, ctx, as))
+		return &dc110->disp_clk_base;
+
+	dm_free(ctx, dc110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
new file mode 100644
index 000000000000..0cdc7b52a09f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_DISPLAY_CLOCK_DCE110_H__
+#define __DAL_DISPLAY_CLOCK_DCE110_H__
+
+#include "gpu/display_clock.h"
+
+struct display_clock_dce110 {
+	struct display_clock disp_clk_base;
+	/* Max display block clocks state*/
+	enum clocks_state max_clks_state;
+	bool use_max_disp_clk;
+	uint32_t dentist_vco_freq_khz;
+	/* Cache the status of DFS-bypass feature*/
+	bool dfs_bypass_enabled;
+	/* GPU PLL SS percentage (if down-spread enabled) */
+	uint32_t gpu_pll_ss_percentage;
+	/* GPU PLL SS percentage Divider (100 or 1000) */
+	uint32_t gpu_pll_ss_divider;
+	/* Flag for Enabled SS on GPU PLL */
+	bool ss_on_gpu_pll;
+	/* Cache the display clock returned by VBIOS if DFS-bypass is enabled.
+	 * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */
+	uint32_t dfs_bypass_disp_clk;
+	struct display_clock_state clock_state;
+};
+
+#define DCLCK110_FROM_BASE(dc_base) \
+	container_of(dc_base, struct display_clock_dce110, disp_clk_base)
+
+#endif /* __DAL_DISPLAY_CLOCK_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
new file mode 100644
index 000000000000..13192484a3ba
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "display_clock.h"
+
+#include "adapter_service_interface.h"
+
+void dal_display_clock_base_set_dp_ref_clock_source(
+	struct display_clock *disp_clk,
+	enum clock_source_id clk_src)
+{/*must be implemented in derived*/
+
+}
+
+void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk,
+	struct display_clock_state clk_state)
+{
+	/*Implemented only in DCE81*/
+}
+struct display_clock_state dal_display_clock_base_get_clock_state(
+	struct display_clock *disp_clk)
+{
+	/*Implemented only in DCE81*/
+	struct display_clock_state state = {0};
+	return state;
+}
+uint32_t dal_display_clock_base_get_dfs_bypass_threshold(
+	struct display_clock *disp_clk)
+{
+	/*Implemented only in DCE81*/
+	return 0;
+}
+
+bool dal_display_clock_construct_base(
+	struct display_clock *base,
+	struct dc_context *ctx,
+	struct adapter_service *as)
+{
+	base->ctx = ctx;
+	base->id = CLOCK_SOURCE_ID_DCPLL;
+	base->min_display_clk_threshold_khz = 0;
+	base->as = as;
+
+/* Initially set current min clocks state to invalid since we
+ * cannot make any assumption about PPLIB's initial state. This will be updated
+ * by HWSS via SetMinClocksState() on first mode set prior to programming
+ * state dependent clocks.*/
+	base->cur_min_clks_state = CLOCKS_STATE_INVALID;
+
+	return true;
+}
+
+void dal_display_clock_destroy(struct display_clock **disp_clk)
+{
+	if (!disp_clk || !*disp_clk) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*disp_clk)->funcs->destroy(disp_clk);
+
+	*disp_clk = NULL;
+}
+
+bool dal_display_clock_validate(
+	struct display_clock *disp_clk,
+	struct min_clock_params *params)
+{
+	return disp_clk->funcs->validate(disp_clk, params);
+}
+
+uint32_t dal_display_clock_calculate_min_clock(
+	struct display_clock *disp_clk,
+	uint32_t path_num,
+	struct min_clock_params *params)
+{
+	return disp_clk->funcs->calculate_min_clock(disp_clk, path_num, params);
+}
+
+uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_validation_clock(disp_clk);
+}
+
+void dal_display_clock_set_clock(
+	struct display_clock *disp_clk,
+	uint32_t requested_clock_khz)
+{
+	disp_clk->funcs->set_clock(disp_clk, requested_clock_khz);
+}
+
+uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_clock(disp_clk);
+}
+
+enum clocks_state dal_display_clock_get_min_clocks_state(
+	struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_min_clocks_state(disp_clk);
+}
+
+enum clocks_state dal_display_clock_get_required_clocks_state(
+	struct display_clock *disp_clk,
+	struct state_dependent_clocks *req_clocks)
+{
+	return disp_clk->funcs->get_required_clocks_state(disp_clk, req_clocks);
+}
+
+bool dal_display_clock_set_min_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state clocks_state)
+{
+	return disp_clk->funcs->set_min_clocks_state(disp_clk, clocks_state);
+}
+
+uint32_t dal_display_clock_get_dp_ref_clk_frequency(
+	struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_dp_ref_clk_frequency(disp_clk);
+}
+
+/*the second parameter of "switchreferenceclock" is
+ * a dummy argument for all pre dce 6.0 versions*/
+
+void dal_display_clock_switch_reference_clock(
+	struct display_clock *disp_clk,
+	bool use_external_ref_clk,
+	uint32_t requested_clk_khz)
+{
+	/* TODO: requires Asic Control*/
+	/*
+	struct ac_pixel_clk_params params;
+	struct asic_control *ac =
+		dal_adapter_service_get_asic_control(disp_clk->as);
+	dc_service_memset(&params, 0, sizeof(struct ac_pixel_clk_params));
+
+	params.tgt_pixel_clk_khz = requested_clk_khz;
+	params.flags.SET_EXTERNAL_REF_DIV_SRC = use_external_ref_clk;
+	params.pll_id = disp_clk->id;
+	dal_asic_control_program_display_engine_pll(ac, &params);
+	*/
+}
+
+void dal_display_clock_set_dp_ref_clock_source(
+	struct display_clock *disp_clk,
+	enum clock_source_id clk_src)
+{
+	disp_clk->funcs->set_dp_ref_clock_source(disp_clk, clk_src);
+}
+
+void dal_display_clock_store_max_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state max_clocks_state)
+{
+	disp_clk->funcs->store_max_clocks_state(disp_clk, max_clocks_state);
+}
+
+void dal_display_clock_set_clock_state(
+	struct display_clock *disp_clk,
+	struct display_clock_state clk_state)
+{
+	disp_clk->funcs->set_clock_state(disp_clk, clk_state);
+}
+
+struct display_clock_state dal_display_clock_get_clock_state(
+	struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_clock_state(disp_clk);
+}
+
+uint32_t dal_display_clock_get_dfs_bypass_threshold(
+	struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_dfs_bypass_threshold(disp_clk);
+}
+
+void dal_display_clock_invalid_clock_state(
+	struct display_clock *disp_clk)
+{
+	disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
new file mode 100644
index 000000000000..845393b7ecb6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DISPLAY_CLOCK_H__
+#define __DAL_DISPLAY_CLOCK_H__
+
+#include "include/display_clock_interface.h"
+
+struct display_clock_funcs {
+	void (*destroy)(struct display_clock **to_destroy);
+	bool (*validate)(struct display_clock *disp_clk,
+		struct min_clock_params *params);
+	uint32_t (*calculate_min_clock)(struct display_clock *disp_clk,
+		uint32_t path_num, struct min_clock_params *params);
+	uint32_t (*get_validation_clock)(struct display_clock *disp_clk);
+	void (*set_clock)(struct display_clock *disp_clk,
+		uint32_t requested_clock_khz);
+	uint32_t (*get_clock)(struct display_clock *disp_clk);
+	enum clocks_state (*get_min_clocks_state)(
+		struct display_clock *disp_clk);
+	enum clocks_state (*get_required_clocks_state)(
+		struct display_clock *disp_clk,
+		struct state_dependent_clocks *req_clocks);
+	bool (*set_min_clocks_state)(struct display_clock *disp_clk,
+		enum clocks_state clocks_state);
+	uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk);
+	void (*set_dp_ref_clock_source)(struct display_clock *disp_clk,
+		enum clock_source_id clk_src);
+	void (*store_max_clocks_state)(struct display_clock *disp_clk,
+		enum clocks_state max_clocks_state);
+	void (*set_clock_state)(struct display_clock *disp_clk,
+		struct display_clock_state clk_state);
+	struct display_clock_state (*get_clock_state)(
+		struct display_clock *disp_clk);
+	uint32_t (*get_dfs_bypass_threshold)(struct display_clock *disp_clk);
+};
+
+struct display_clock {
+	struct dc_context *ctx;
+	const struct display_clock_funcs *funcs;
+	uint32_t min_display_clk_threshold_khz;
+	enum clock_source_id id;
+	struct adapter_service *as;
+
+	enum clocks_state cur_min_clks_state;
+};
+void dal_display_clock_base_set_dp_ref_clock_source(
+	struct display_clock *disp_clk,
+	enum clock_source_id clk_src);
+struct display_clock_state dal_display_clock_base_get_clock_state(
+	struct display_clock *disp_clk);
+uint32_t dal_display_clock_base_get_dfs_bypass_threshold(
+	struct display_clock *disp_clk);
+void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk,
+	struct display_clock_state clk_state);
+bool dal_display_clock_construct_base(
+	struct display_clock *base,
+	struct dc_context *ctx,
+	struct adapter_service *as);
+#endif /* __DAL_DISPLAY_CLOCK_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
new file mode 100644
index 000000000000..59d44004411b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "divider_range.h"
+
+bool dal_divider_range_construct(
+	struct divider_range *div_range,
+	uint32_t range_start,
+	uint32_t range_step,
+	uint32_t did_min,
+	uint32_t did_max)
+{
+	div_range->div_range_start = range_start;
+	div_range->div_range_step = range_step;
+	div_range->did_min = did_min;
+	div_range->did_max = did_max;
+
+	if (div_range->div_range_step == 0) {
+		div_range->div_range_step = 1;
+		/*div_range_step cannot be zero*/
+		BREAK_TO_DEBUGGER();
+	}
+	/* Calculate this based on the other inputs.*/
+	/* See DividerRange.h for explanation of */
+	/* the relationship between divider id (DID) and a divider.*/
+	/* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/
+	/* Maximum divider identified in this range =
+	 * (Number of Divider IDs)*Step size between dividers
+	 *  + The start of this range.*/
+	div_range->div_range_end = (did_max - did_min) * range_step
+		+ range_start;
+	return true;
+}
+
+static uint32_t dal_divider_range_calc_divider(
+	struct divider_range *div_range,
+	uint32_t did)
+{
+	/* Is this DID within our range?*/
+	if ((did < div_range->did_min) || (did >= div_range->did_max))
+		return INVALID_DIVIDER;
+
+	return ((did - div_range->did_min) * div_range->div_range_step)
+			+ div_range->div_range_start;
+
+}
+
+static uint32_t dal_divider_range_calc_did(
+	struct divider_range *div_range,
+	uint32_t div)
+{
+	uint32_t did;
+	/* Check before dividing.*/
+	if (div_range->div_range_step == 0) {
+		div_range->div_range_step = 1;
+		/*div_range_step cannot be zero*/
+		BREAK_TO_DEBUGGER();
+	}
+	/* Is this divider within our range?*/
+	if ((div < div_range->div_range_start)
+		|| (div >= div_range->div_range_end))
+		return INVALID_DID;
+/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/
+	did = div - div_range->div_range_start;
+	did += div_range->div_range_step - 1;
+	did /= div_range->div_range_step;
+	did += div_range->did_min;
+	return did;
+}
+
+uint32_t dal_divider_range_get_divider(
+	struct divider_range *div_range,
+	uint32_t ranges_num,
+	uint32_t did)
+{
+	uint32_t div = INVALID_DIVIDER;
+	uint32_t i;
+
+	for (i = 0; i < ranges_num; i++) {
+		/* Calculate divider with given divider ID*/
+		div = dal_divider_range_calc_divider(&div_range[i], did);
+		/* Found a valid return divider*/
+		if (div != INVALID_DIVIDER)
+			break;
+	}
+	return div;
+}
+uint32_t dal_divider_range_get_did(
+	struct divider_range *div_range,
+	uint32_t ranges_num,
+	uint32_t divider)
+{
+	uint32_t did = INVALID_DID;
+	uint32_t i;
+
+	for (i = 0; i < ranges_num; i++) {
+		/*  CalcDid returns InvalidDid if a divider ID isn't found*/
+		did = dal_divider_range_calc_did(&div_range[i], divider);
+		/* Found a valid return did*/
+		if (did != INVALID_DID)
+			break;
+	}
+	return did;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h
new file mode 100644
index 000000000000..2ec1034035ad
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DIVIDER_RANGE_H__
+#define __DAL_DIVIDER_RANGE_H__
+
+enum divider_error_types {
+	INVALID_DID = 0,
+	INVALID_DIVIDER = 1
+};
+
+struct divider_range {
+	uint32_t div_range_start;
+	/* The end of this range of dividers.*/
+	uint32_t div_range_end;
+	/* The distance between each divider in this range.*/
+	uint32_t div_range_step;
+	/* The divider id for the lowest divider.*/
+	uint32_t did_min;
+	/* The divider id for the highest divider.*/
+	uint32_t did_max;
+};
+
+bool dal_divider_range_construct(
+	struct divider_range *div_range,
+	uint32_t range_start,
+	uint32_t range_step,
+	uint32_t did_min,
+	uint32_t did_max);
+
+uint32_t dal_divider_range_get_divider(
+	struct divider_range *div_range,
+	uint32_t ranges_num,
+	uint32_t did);
+uint32_t dal_divider_range_get_did(
+	struct divider_range *div_range,
+	uint32_t ranges_num,
+	uint32_t divider);
+
+
+#endif /* __DAL_DIVIDER_RANGE_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 11/29] drm/amd/dal: Audio
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (9 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 10/29] drm/amd/dal: GPU Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 12/29] drm/amd/dal: Bandwidth calculations Harry Wentland
                   ` (21 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Responsible for programming the audio encoder in the display path.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/audio/Makefile          |   22 +
 drivers/gpu/drm/amd/dal/dc/audio/audio.h           |  195 ++
 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c      |  470 +++++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c |  453 +++++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h |   42 +
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c  | 1930 ++++++++++++++++++++
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h  |   47 +
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c    |  771 ++++++++
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h    |  285 +++
 9 files changed, 4215 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h

diff --git a/drivers/gpu/drm/amd/dal/dc/audio/Makefile b/drivers/gpu/drm/amd/dal/dc/audio/Makefile
new file mode 100644
index 000000000000..0999372cecf0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the 'audio' sub-component of DAL.
+# It provides the control and status of HW adapter resources,
+# that are global for the ASIC and sharable between pipes.
+
+AUDIO = audio_base.o hw_ctx_audio.o
+
+AMD_DAL_AUDIO = $(addprefix $(AMDDALPATH)/dc/audio/,$(AUDIO))
+
+AMD_DAL_FILES += $(AMD_DAL_AUDIO)
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+AUDIO_DCE11 = audio_dce110.o hw_ctx_audio_dce110.o
+
+AMD_DAL_AUDIO_DCE11 = $(addprefix $(AMDDALPATH)/dc/audio/dce110/,$(AUDIO_DCE11))
+
+AMD_DAL_FILES += $(AMD_DAL_AUDIO_DCE11)
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/audio.h b/drivers/gpu/drm/amd/dal/dc/audio/audio.h
new file mode 100644
index 000000000000..ad2dc18ef37b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/audio.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUDIO_H__
+#define __DAL_AUDIO_H__
+
+#include "include/audio_interface.h"
+#include "hw_ctx_audio.h"
+#include "include/link_service_types.h"
+
+/***** only for hook functions  *****/
+/**
+ *which will be overwritten by derived audio object.
+ *audio hw context object is independent object
+ */
+
+struct audio;
+
+struct audio_funcs {
+	/*
+	 *get_object_id
+	 *get_object_type
+	 *enumerate_input_signals
+	 *enumerate_output_signals
+	 *is_input_signal_supported
+	 *is_output_signal_supported
+	 *set_object_properties
+	 *get_object_properties
+	 */
+
+	void (*destroy)(struct audio **audio);
+	/*power_up
+	 *power_down
+	 *release_hw_base
+	 */
+
+	/* setup audio */
+	enum audio_result (*setup)(
+		struct audio *audio,
+		struct audio_output *output,
+		struct audio_info *info);
+
+	enum audio_result (*enable_output)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	enum audio_result (*disable_output)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	/*enable_azalia_audio_jack_presence
+	 * disable_azalia_audio_jack_presence
+	 */
+
+	enum audio_result (*unmute)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	enum audio_result (*mute)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	/* SW initialization that cannot be done in constructor. This will
+	 * be done is audio_power_up but is not in audio_interface. It is only
+	 * called by power_up
+	 */
+	enum audio_result (*initialize)(
+		struct audio *audio);
+
+	/* enable channel splitting mapping */
+	void (*enable_channel_splitting_mapping)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal,
+		const struct audio_channel_associate_info *audio_mapping,
+		bool enable);
+
+	/* get current multi channel split. */
+	enum audio_result (*get_channel_splitting_mapping)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		struct audio_channel_associate_info *audio_mapping);
+
+	/* set payload value for the unsolicited response */
+	void (*set_unsolicited_response_payload)(
+		struct audio *audio,
+		enum audio_payload payload);
+
+	/* Update audio wall clock source */
+	void (*setup_audio_wall_dto)(
+		struct audio *audio,
+		enum signal_type signal,
+		const struct audio_crtc_info *crtc_info,
+		const struct audio_pll_info *pll_info);
+
+	/* options and features supported by Audio */
+	struct audio_feature_support (*get_supported_features)(
+		struct audio *audio);
+
+	/*
+	 *check_audio_bandwidth
+	 *write_reg
+	 *read_reg
+	 *enable_gtc_embedding_with_group
+	 *disable_gtc_embedding
+	 *register_interrupt
+	 *unregister_interrupt
+	 *process_interrupt
+	 *create_hw_ctx
+	 *getHwCtx
+	 *setHwCtx
+	 *handle_interrupt
+	 */
+};
+
+struct audio {
+	/* hook functions. they will be overwritten by specific ASIC */
+	const struct audio_funcs *funcs;
+	/* TODO: static struct audio_funcs funcs;*/
+
+	/*external structures - get service from external*/
+	struct graphics_object_id id;
+	struct adapter_service *adapter_service;
+	/* audio HW context */
+	struct hw_ctx_audio *hw_ctx;
+	struct dc_context *ctx;
+	/* audio supports input and output signals */
+	uint32_t input_signals;
+	uint32_t output_signals;
+};
+
+/* - functions defined by audio.h will be used by audio component only.
+ *   but audio.c also implements some function defined by dal\include
+ */
+
+/* graphics_object_base implemention
+ * 1.input_signals and output_signals are moved
+ * into audio object.
+ *
+ * 2.Get the Graphics Object ID
+ *
+ * Outside audio:
+ * use dal_graphics_object_id_get_audio_id
+ * Within audio:
+ *	use audio->go_base.id
+ *
+ * 3. Get the Graphics Object Type
+ *
+ *  use object_id.type
+ *  not function implemented.
+ * 4. Common Graphics Object Properties
+ * use object id ->go_properties.multi_path
+ * not function implemented.
+ */
+
+bool dal_audio_construct_base(
+	struct audio *audio,
+	const struct audio_init_data *init_data);
+
+void dal_audio_destruct_base(
+	struct audio *audio);
+
+void dal_audio_release_hw_base(
+	struct audio *audio);
+
+#endif  /* __DAL_AUDIO__ */
+
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
new file mode 100644
index 000000000000..bfd6725d9b91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "audio.h"
+#include "hw_ctx_audio.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/audio_dce110.h"
+#include "dce110/hw_ctx_audio_dce110.h"
+#endif
+
+/***** static function : only used within audio.c *****/
+
+/* stub for hook functions */
+static void destroy(
+	struct audio **audio)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+static enum audio_result setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result initialize(
+	struct audio *audio)
+{
+	/*DCE specific, must be implemented in derived. Implemeentaion of
+	 *initialize will create audio hw context. create_hw_ctx
+	 */
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static void enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* get current multi channel split. */
+static enum audio_result get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+/* set payload value for the unsolicited response */
+static void set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* update audio wall clock source */
+static void setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+static struct audio_feature_support get_supported_features(struct audio *audio)
+{
+	/*DCE specific, must be implemented in derived*/
+	struct audio_feature_support features;
+
+	dm_memset(&features, 0, sizeof(features));
+
+	features.ENGINE_DIGA = 1;
+	features.ENGINE_DIGB = 1;
+
+	return features;
+}
+
+static const struct audio_funcs audio_funcs = {
+	.destroy = destroy,
+	.setup = setup,
+	.enable_output = enable_output,
+	.disable_output = disable_output,
+	.unmute = unmute,
+	.mute = mute,
+	.initialize = initialize,
+	.enable_channel_splitting_mapping =
+		enable_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.setup_audio_wall_dto = setup_audio_wall_dto,
+	.get_supported_features = get_supported_features,
+};
+
+/***** SCOPE : declare in audio.h. use within dal-audio. *****/
+
+bool dal_audio_construct_base(
+	struct audio *audio,
+	const struct audio_init_data *init_data)
+{
+	enum signal_type signals = SIGNAL_TYPE_HDMI_TYPE_A;
+
+	ASSERT(init_data->as != NULL);
+
+	/* base hook functions */
+	audio->funcs = &audio_funcs;
+
+	/*setup pointers to get service from dal service compoenents*/
+	audio->adapter_service = init_data->as;
+
+	audio->ctx = init_data->ctx;
+
+	/* save audio endpoint number to identify object creating */
+	audio->id = init_data->audio_stream_id;
+
+	/* Fill supported signals. !!! be aware that android definition is
+	 * already shift to vector.
+	 */
+	signals |= SIGNAL_TYPE_DISPLAY_PORT;
+	signals |= SIGNAL_TYPE_DISPLAY_PORT_MST;
+	signals |= SIGNAL_TYPE_EDP;
+	signals |= SIGNAL_TYPE_DISPLAY_PORT;
+	signals |= SIGNAL_TYPE_WIRELESS;
+
+	/* Audio supports same set for input and output signals */
+	audio->input_signals = signals;
+	audio->output_signals = signals;
+
+	return true;
+}
+
+/* except hw_ctx, no other hw need reset. so do nothing */
+void dal_audio_destruct_base(
+	struct audio *audio)
+{
+}
+
+/* Enumerate Graphics Object supported Input/Output Signal Types */
+uint32_t dal_audio_enumerate_input_signals(
+	struct audio *audio)
+{
+	return audio->input_signals;
+}
+
+uint32_t dal_audio_enumerate_output_signals(
+	struct audio *audio)
+{
+	return audio->output_signals;
+}
+
+/*  Check if signal supported by GraphicsObject  */
+bool dal_audio_is_input_signal_supported(
+	struct audio *audio,
+	enum signal_type signal)
+{
+	return (signal & audio->output_signals) != 0;
+}
+
+bool dal_audio_is_output_signal_supported(
+	struct audio *audio,
+	enum signal_type signal)
+{
+	return (signal & audio->input_signals) != 0;
+}
+
+/***** SCOPE : declare in dal\include  *****/
+
+/* audio object creator triage. memory allocate and release will be
+ * done within dal_audio_create_dcexx
+ */
+struct audio *dal_audio_create(
+	const struct audio_init_data *init_data)
+{
+	struct adapter_service *as;
+
+	if (init_data->as == NULL)
+		return NULL;
+
+	as = init_data->as;
+	switch (dal_adapter_service_get_dce_version(as)) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dal_audio_create_dce110(init_data);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dal_audio_create_dce110(init_data);
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	return NULL;
+}
+
+/* audio object creator triage.
+ * memory for "struct audio   dal_audio_create_dce8x" allocate
+ * will happens within dal_audio_dce8x. memory allocate is done
+ * with dal_audio_create_dce8x. memory release is initiated by
+ * dal_audio_destroy. It will call hook function which will finially
+ * used destroy() of dal_audio_dce8x. therefore, no memroy allocate
+ *and release happen physcially at audio base object.
+ */
+void dal_audio_destroy(
+	struct audio **audio)
+{
+	if (!audio || !*audio) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*audio)->funcs->destroy(audio);
+
+	*audio = NULL;
+}
+
+const struct graphics_object_id dal_audio_get_graphics_object_id(
+	const struct audio *audio)
+{
+	return audio->id;
+}
+
+/* enable azalia audio endpoint. This function call hw_ctx directly
+ *not overwitten at audio level.
+ */
+enum audio_result dal_audio_enable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id)
+{
+	audio->hw_ctx->funcs->enable_azalia_audio(audio->hw_ctx, engine_id);
+	return AUDIO_RESULT_OK;
+}
+
+/* disable azalia audio endpoint. This function call hw_ctx directly
+ *not overwitten at audio level.
+ */
+enum audio_result dal_audio_disable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id)
+{
+	audio->hw_ctx->funcs->disable_azalia_audio(audio->hw_ctx, engine_id);
+	return AUDIO_RESULT_OK;
+}
+
+/* get audio bandwidth information. This function call hw_ctx directly
+ *not overwitten at audio level.
+ */
+void dal_audio_check_audio_bandwidth(
+	struct audio *audio,
+	const struct audio_crtc_info *info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates)
+{
+	dal_hw_ctx_audio_check_audio_bandwidth(
+		audio->hw_ctx, info, channel_count, signal, sample_rates);
+}
+
+/* DP Audio register write access. This function call hw_ctx directly
+ * not overwitten at audio level.
+ */
+
+/*assign GTC group and enable GTC value embedding*/
+void dal_audio_enable_gtc_embedding_with_group(
+	struct audio *audio,
+	uint32_t group_num,
+	uint32_t audio_latency)
+{
+	audio->hw_ctx->funcs->enable_gtc_embedding_with_group(
+		audio->hw_ctx, group_num, audio_latency);
+}
+
+/* disable GTC value embedding */
+void dal_audio_disable_gtc_embedding(
+	struct audio *audio)
+{
+	audio->hw_ctx->funcs->disable_gtc_embedding(audio->hw_ctx);
+}
+
+/* perform power up sequence (boot up, resume, recovery) */
+enum audio_result dal_audio_power_up(
+	struct audio *audio)
+{
+	return audio->funcs->initialize(audio);
+}
+
+/* perform power down (shut down, stand by) */
+enum audio_result dal_audio_power_down(
+	struct audio *audio)
+{
+	return AUDIO_RESULT_OK;
+}
+
+/* setup audio */
+enum audio_result dal_audio_setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info)
+{
+	return audio->funcs->setup(audio, output, info);
+}
+
+/* enable audio */
+enum audio_result dal_audio_enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->enable_output(audio, engine_id, signal);
+}
+
+/* disable audio */
+enum audio_result dal_audio_disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->disable_output(audio, engine_id, signal);
+}
+
+/* unmute audio */
+enum audio_result dal_audio_unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->unmute(audio, engine_id, signal);
+}
+
+/* mute audio */
+enum audio_result dal_audio_mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->mute(audio, engine_id, signal);
+}
+
+/* Enable multi channel split */
+void dal_audio_enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	audio->funcs->enable_channel_splitting_mapping(
+		audio, engine_id, signal, audio_mapping, enable);
+}
+
+/* get current multi channel split. */
+enum audio_result dal_audio_get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	return audio->funcs->get_channel_splitting_mapping(
+		audio, engine_id, audio_mapping);
+}
+
+/* set payload value for the unsolicited response */
+void dal_audio_set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload)
+{
+	audio->funcs->set_unsolicited_response_payload(audio, payload);
+}
+
+/* update audio wall clock source */
+void dal_audio_setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	audio->funcs->setup_audio_wall_dto(audio, signal, crtc_info, pll_info);
+}
+
+struct audio_feature_support dal_audio_get_supported_features(
+	struct audio *audio)
+{
+	return audio->funcs->get_supported_features(audio);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
new file mode 100644
index 000000000000..1aa0c1e61b32
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "audio_dce110.h"
+
+/***** static functions  *****/
+
+static void destruct(struct audio_dce110 *audio)
+{
+	/*release memory allocated for hw_ctx -- allocated is initiated
+	 *by audio_dce110 power_up
+	 *audio->base->hw_ctx = NULL is done within hw-ctx->destroy
+	 */
+	if (audio->base.hw_ctx)
+		audio->base.hw_ctx->funcs->destroy(&(audio->base.hw_ctx));
+
+	/* reset base_audio_block */
+	dal_audio_destruct_base(&audio->base);
+}
+
+static void destroy(struct audio **ptr)
+{
+	struct audio_dce110 *audio = NULL;
+
+	audio = container_of(*ptr, struct audio_dce110, base);
+
+	destruct(audio);
+
+	/* release memory allocated for audio_dce110*/
+	dm_free((*ptr)->ctx, audio);
+	*ptr = NULL;
+}
+
+
+/* The inital call of hook function comes from audio object level.
+ *The passing object handle "struct audio *audio" point to base object
+ *already.There is not need to get base object from audio_dce110.
+ */
+
+/**
+* setup
+*
+* @brief
+*  setup Audio HW block, to be called by dal_audio_setup
+*
+*/
+static enum audio_result setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info)
+{
+	switch (output->signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		/*setup HDMI audio engine*/
+		audio->hw_ctx->funcs->enable_afmt_clock(
+			audio->hw_ctx,
+			output->engine_id,
+			true);
+		audio->hw_ctx->funcs->setup_hdmi_audio(
+			audio->hw_ctx, output->engine_id, &output->crtc_info);
+
+		audio->hw_ctx->funcs->setup_azalia(
+			audio->hw_ctx,
+			output->engine_id,
+			output->signal,
+			&output->crtc_info,
+			&output->pll_info,
+			info);
+		break;
+
+	case SIGNAL_TYPE_WIRELESS:
+		/* setup Azalia block for Wireless Display - This
+			is different than for wired
+			displays because there is no
+			DIG to program.*/
+		/*TODO:
+		audio->hw_ctx->funcs->setup_azalia_for_vce(
+			audio->hw_ctx,
+			audio->signal,
+			audio->crtc_info,
+			info);
+		*/
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		/* setup DP audio engine will be done at enable output */
+
+		/* setup Azalia block*/
+		audio->hw_ctx->funcs->setup_azalia(
+			audio->hw_ctx,
+			output->engine_id,
+			output->signal,
+			&output->crtc_info,
+			&output->pll_info,
+			info);
+
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* enable_output
+*
+* @brief
+*  enable Audio HW block, to be called by dal_audio_enable_output
+*/
+static enum audio_result enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/* enable audio output */
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP: {
+			/* enable AFMT clock before enable audio*/
+			audio->hw_ctx->funcs->enable_afmt_clock(
+				audio->hw_ctx, engine_id, true);
+			/* setup DP audio engine */
+			audio->hw_ctx->funcs->setup_dp_audio(
+				audio->hw_ctx, engine_id);
+			/* enabl DP audio packets will be done at unblank */
+			audio->hw_ctx->funcs->enable_dp_audio(
+				audio->hw_ctx, engine_id);
+		}
+		break;
+	case SIGNAL_TYPE_WIRELESS:
+		/* route audio to VCE block */
+		audio->hw_ctx->funcs->setup_vce_audio(audio->hw_ctx);
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* disable_output
+*
+* @brief
+*  disable Audio HW block, to be called by dal_audio_disable_output
+*
+*/
+static enum audio_result disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_WIRELESS:
+		/* disable HDMI audio */
+		audio->hw_ctx->
+			funcs->disable_azalia_audio(
+					audio->hw_ctx, engine_id);
+		audio->hw_ctx->
+			funcs->enable_afmt_clock(
+					audio->hw_ctx, engine_id,
+					false);
+
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP: {
+			/* disable DP audio */
+			audio->hw_ctx->funcs->disable_dp_audio(
+				audio->hw_ctx, engine_id);
+			audio->hw_ctx->funcs->disable_azalia_audio(
+				audio->hw_ctx, engine_id);
+			audio->hw_ctx->funcs->enable_afmt_clock(
+				audio->hw_ctx, engine_id, false);
+		}
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* unmute
+*
+* @brief
+*  unmute audio, to be called by dal_audio_unmute
+*
+*/
+static enum audio_result unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		/* unmute Azalia audio */
+		audio->hw_ctx->funcs->unmute_azalia_audio(
+				audio->hw_ctx, engine_id);
+		break;
+	case SIGNAL_TYPE_WIRELESS:
+		/*Do nothing for wireless display*/
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* mute
+*
+* @brief
+*  mute audio, to be called  by dal_audio_nmute
+*
+*/
+static enum audio_result mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		/* mute Azalia audio */
+		audio->hw_ctx->funcs->mute_azalia_audio(
+				audio->hw_ctx, engine_id);
+		break;
+	case SIGNAL_TYPE_WIRELESS:
+		/*Do nothing for wireless display*/
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* initialize
+*
+* @brief
+*  Perform SW initialization - create audio hw context. Then do HW
+*  initialization. this function is called at dal_audio_power_up.
+*
+*/
+static enum audio_result initialize(
+	struct audio *audio)
+{
+	uint8_t audio_endpoint_enum_id = 0;
+
+	audio_endpoint_enum_id = audio->id.enum_id;
+
+	/* HW CTX already create*/
+	if (audio->hw_ctx != NULL)
+		return AUDIO_RESULT_OK;
+
+	audio->hw_ctx = dal_hw_ctx_audio_dce110_create(
+			audio->ctx,
+			audio_endpoint_enum_id);
+
+	if (audio->hw_ctx == NULL)
+		return AUDIO_RESULT_ERROR;
+
+	/* override HW default settings */
+	audio->hw_ctx->funcs->hw_initialize(audio->hw_ctx);
+
+	return AUDIO_RESULT_OK;
+}
+
+/* enable multi channel split */
+static void enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	audio->hw_ctx->funcs->setup_channel_splitting_mapping(
+		audio->hw_ctx,
+		engine_id,
+		signal,
+		audio_mapping, enable);
+}
+
+/* get current multi channel split. */
+static enum audio_result get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	if (audio->hw_ctx->funcs->get_channel_splitting_mapping(
+		audio->hw_ctx, engine_id, audio_mapping)) {
+		return AUDIO_RESULT_OK;
+	} else {
+		return AUDIO_RESULT_ERROR;
+	}
+}
+
+/**
+* set_unsolicited_response_payload
+*
+* @brief
+*  Set payload value for the unsolicited response
+*/
+static void set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload)
+{
+	audio->hw_ctx->funcs->set_unsolicited_response_payload(
+			audio->hw_ctx, payload);
+}
+
+/**
+* setup_audio_wall_dto
+*
+* @brief
+*  Update audio source clock from hardware context.
+*
+*/
+static void setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	audio->hw_ctx->funcs->setup_audio_wall_dto(
+		audio->hw_ctx, signal, crtc_info, pll_info);
+}
+
+/**
+* get_supported_features
+*
+* @brief
+*  options and features supported by Audio
+*  returns supported engines, signals.
+*  features are reported for HW audio/Azalia block rather then Audio object
+*  itself the difference for DCE6.x is that MultiStream Audio is now supported
+*
+*/
+static struct audio_feature_support get_supported_features(struct audio *audio)
+{
+	struct audio_feature_support afs = {0};
+
+	afs.ENGINE_DIGA = 1;
+	afs.ENGINE_DIGB = 1;
+	afs.ENGINE_DIGC = 1;
+	afs.MULTISTREAM_AUDIO = 1;
+
+	return afs;
+}
+
+static const struct audio_funcs funcs = {
+	.destroy = destroy,
+	.setup = setup,
+	.enable_output = enable_output,
+	.disable_output = disable_output,
+	.unmute = unmute,
+	.mute = mute,
+	.initialize = initialize,
+	.enable_channel_splitting_mapping =
+		enable_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.setup_audio_wall_dto = setup_audio_wall_dto,
+	.get_supported_features = get_supported_features,
+};
+
+static bool construct(
+	struct audio_dce110 *audio,
+	const struct audio_init_data *init_data)
+{
+	struct audio *base = &audio->base;
+
+	/* base audio construct*/
+	if (!dal_audio_construct_base(base, init_data))
+		return false;
+
+	/*vtable methods*/
+	base->funcs = &funcs;
+	return true;
+}
+
+
+/* --- audio scope functions  --- */
+
+struct audio *dal_audio_create_dce110(
+	const struct audio_init_data *init_data)
+{
+	/*allocate memory for audio_dce110 */
+	struct audio_dce110 *audio = dm_alloc(init_data->ctx, sizeof(*audio));
+
+	if (audio == NULL) {
+		ASSERT_CRITICAL(audio);
+		return NULL;
+	}
+	/*pointer to base_audio_block of audio_dce110 ==> audio base object */
+	if (construct(audio, init_data))
+		return &audio->base;
+
+	dal_logger_write(
+		init_data->ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_AUDIO,
+		"Failed to create audio object for DCE11\n");
+
+	 /*release memory allocated if fail */
+	dm_free(init_data->ctx, audio);
+	return NULL;
+}
+
+/* Do not need expose construct_dce110 and destruct_dce110 becuase there is
+ *derived object after dce110
+ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
new file mode 100644
index 000000000000..e5ff823368b3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_AUDIO_DCE_110_H__
+#define __DAL_AUDIO_DCE_110_H__
+
+#include "audio/audio.h"
+#include "audio/hw_ctx_audio.h"
+#include "audio/dce110/hw_ctx_audio_dce110.h"
+
+
+
+struct audio_dce110 {
+	struct audio base;
+	/* dce-specific members are following */
+	/* none */
+};
+
+struct audio *dal_audio_create_dce110(const struct audio_init_data *init_data);
+
+#endif   /*__DAL_AUDIO_DCE_110_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
new file mode 100644
index 000000000000..f24b964bdd8d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
@@ -0,0 +1,1930 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+#include "../hw_ctx_audio.h"
+#include "hw_ctx_audio_dce110.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#define FROM_BASE(ptr) \
+	container_of((ptr), struct hw_ctx_audio_dce110, base)
+
+#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000
+#define DP_AUDIO_DTO_MODULE_WITHOUT_SS 360
+#define DP_AUDIO_DTO_PHASE_WITHOUT_SS 24
+
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUDIO_FRONT_END 0
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__REGISTER_PROGRAMMABLE 2
+
+#define FIRST_AUDIO_STREAM_ID 1
+
+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_AUDIO, \
+			"Audio:%s()\n", __func__)
+
+static const uint32_t engine_offset[] = {
+	0,
+	mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL,
+	mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL,
+	mmDIG3_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL
+};
+
+static void destruct(
+	struct hw_ctx_audio_dce110 *hw_ctx_dce110)
+{
+	dal_audio_destruct_hw_ctx_audio(&hw_ctx_dce110->base);
+}
+
+static void destroy(
+	struct hw_ctx_audio **ptr)
+{
+	struct hw_ctx_audio_dce110 *hw_ctx_dce110;
+
+	hw_ctx_dce110 = container_of(
+		*ptr, struct hw_ctx_audio_dce110, base);
+
+	destruct(hw_ctx_dce110);
+	/* release memory allocated for struct hw_ctx_audio_dce110 */
+	dm_free((*ptr)->ctx, hw_ctx_dce110);
+
+	*ptr = NULL;
+}
+
+/* ---  helpers --- */
+static void write_indirect_azalia_reg(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t reg_index,
+	uint32_t reg_data)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	/* AZALIA_F0_CODEC_ENDPOINT_INDEX  endpoint index  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index;
+
+		set_reg_field_value(value, reg_index,
+			AZALIA_F0_CODEC_ENDPOINT_INDEX,
+			AZALIA_ENDPOINT_REG_INDEX);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AZALIA_F0_CODEC_ENDPOINT_DATA  endpoint data  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data;
+
+		value = 0;
+		set_reg_field_value(value, reg_data,
+			AZALIA_F0_CODEC_ENDPOINT_DATA,
+			AZALIA_ENDPOINT_REG_DATA);
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	dal_logger_write(
+		hw_ctx->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_AUDIO,
+		"AUDIO:write_indirect_azalia_reg: index: %u  data: %u\n",
+		reg_index, reg_data);
+}
+
+static uint32_t read_indirect_azalia_reg(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t reg_index)
+{
+	uint32_t ret_val = 0;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+
+	/* AZALIA_F0_CODEC_ENDPOINT_INDEX  endpoint index  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index;
+
+		set_reg_field_value(value, reg_index,
+			AZALIA_F0_CODEC_ENDPOINT_INDEX,
+			AZALIA_ENDPOINT_REG_INDEX);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AZALIA_F0_CODEC_ENDPOINT_DATA  endpoint data  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		ret_val = value;
+	}
+
+	dal_logger_write(
+		hw_ctx->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_AUDIO,
+		"AUDIO:read_indirect_azalia_reg: index: %u  data: %u\n",
+		reg_index, ret_val);
+
+	return ret_val;
+}
+
+/* expose/not expose HBR capability to Audio driver */
+static void set_high_bit_rate_capable(
+	const struct hw_ctx_audio *hw_ctx,
+	bool capable)
+{
+	uint32_t value = 0;
+
+	/* set high bit rate audio capable*/
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR);
+
+	set_reg_field_value(value, capable,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR,
+		HBR_CAPABLE);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR,
+		value);
+}
+
+/* set HBR channnel count *
+static void set_hbr_channel_count(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t hbr_channel_count)
+{
+	uint32_t value = 0;
+
+	if (hbr_channel_count > 7)
+		return;
+
+	value = dal_read_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL);
+
+	set_reg_field_value(value, hbr_channel_count,
+		AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL,
+		HBR_CHANNEL_COUNT);
+
+	dal_write_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, value);
+
+}
+
+*set compressed audio channel count *
+static void set_compressed_audio_channel_count(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t compressed_audio_ch_count)
+{
+	uint32_t value = 0;
+	if (compressed_audio_ch_count > 7)
+		return;
+
+	value = dal_read_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL);
+
+	set_reg_field_value(value, compressed_audio_ch_count,
+		AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL,
+		COMPRESSED_CHANNEL_COUNT);
+
+	dal_write_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL,
+		value);
+
+}
+*/
+/* set video latency in in ms/2+1 */
+static void set_video_latency(
+	const struct hw_ctx_audio *hw_ctx,
+	int latency_in_ms)
+{
+	uint32_t value = 0;
+
+	if ((latency_in_ms < 0) || (latency_in_ms > 255))
+		return;
+
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
+
+	set_reg_field_value(value, latency_in_ms,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		VIDEO_LIPSYNC);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		value);
+
+}
+
+/* set audio latency in in ms/2+1 */
+static void set_audio_latency(
+	const struct hw_ctx_audio *hw_ctx,
+	int latency_in_ms)
+{
+	uint32_t value = 0;
+
+	if (latency_in_ms < 0)
+		latency_in_ms = 0;
+
+	if (latency_in_ms > 255)
+		latency_in_ms = 255;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
+
+	set_reg_field_value(value, latency_in_ms,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		AUDIO_LIPSYNC);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		value);
+
+}
+
+/* enable HW/SW Sync */
+/*static void enable_hw_sw_sync(
+	const struct hw_ctx_audio *hw_ctx)
+{
+		union AZALIA_CYCLIC_BUFFER_SYNC value;
+
+	value = dal_read_reg(mmAZALIA_CYCLIC_BUFFER_SYNC);
+	value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 1;
+	dal_write_reg(mmAZALIA_CYCLIC_BUFFER_SYNC, value);
+}*/
+
+/* disable HW/SW Sync */
+/*static void disable_hw_sw_sync(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	union AZALIA_CYCLIC_BUFFER_SYNC value;
+
+	value = dal_read_reg(
+		mmAZALIA_CYCLIC_BUFFER_SYNC);
+	value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 0;
+	dal_write_reg(
+		mmAZALIA_CYCLIC_BUFFER_SYNC, value);
+}*/
+
+/* update hardware with software's current position in cyclic buffer */
+/*static void update_sw_write_ptr(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t offset)
+{
+		union AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER value;
+
+	value = dal_read_reg(
+		mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER);
+	value.bits.APPLICATION_POSITION_IN_CYCLIC_BUFFER = offset;
+	dal_write_reg(
+		mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER,
+		value);
+}*/
+
+/* update Audio/Video association */
+/*static void update_av_association(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	uint32_t displayId)
+{
+
+}*/
+
+/* ---  hook functions --- */
+static bool get_azalia_clock_info_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct azalia_clock_info *azalia_clock_info);
+
+static bool get_azalia_clock_info_dp(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t requested_pixel_clock_in_khz,
+	const struct audio_pll_info *pll_info,
+	struct azalia_clock_info *azalia_clock_info);
+
+static void setup_audio_wall_dto(
+	const struct hw_ctx_audio *hw_ctx,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	struct azalia_clock_info clock_info = { 0 };
+
+	uint32_t value = dm_read_reg(hw_ctx->ctx, mmDCCG_AUDIO_DTO_SOURCE);
+
+	/* TODO: GraphicsObject\inc\GraphicsObjectDefs.hpp(131):
+	 *inline bool isHdmiSignal(SignalType signal)
+	 *if (Signals::isHdmiSignal(signal))
+	 */
+	if (dc_is_hdmi_signal(signal)) {
+		/*DTO0 Programming goal:
+		-generate 24MHz, 128*Fs from 24MHz
+		-use DTO0 when an active HDMI port is connected
+		(optionally a DP is connected) */
+
+		/* calculate DTO settings */
+		get_azalia_clock_info_hdmi(
+			hw_ctx,
+			crtc_info->requested_pixel_clock,
+			crtc_info->calculated_pixel_clock,
+			&clock_info);
+
+		/* On TN/SI, Program DTO source select and DTO select before
+		programming DTO modulo and DTO phase. These bits must be
+		programmed first, otherwise there will be no HDMI audio at boot
+		up. This is a HW sequence change (different from old ASICs).
+		Caution when changing this programming sequence.
+
+		HDMI enabled, using DTO0
+		program master CRTC for DTO0 */
+		{
+			set_reg_field_value(value,
+				pll_info->dto_source - DTO_SOURCE_ID0,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO0_SOURCE_SEL);
+
+			set_reg_field_value(value,
+				0,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO_SEL);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO_SOURCE, value);
+		}
+
+		/* module */
+		{
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_MODULE);
+			set_reg_field_value(value,
+				clock_info.audio_dto_module,
+				DCCG_AUDIO_DTO0_MODULE,
+				DCCG_AUDIO_DTO0_MODULE);
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_MODULE, value);
+		}
+
+		/* phase */
+		{
+			value = 0;
+
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_PHASE);
+			set_reg_field_value(value,
+				clock_info.audio_dto_phase,
+				DCCG_AUDIO_DTO0_PHASE,
+				DCCG_AUDIO_DTO0_PHASE);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_PHASE, value);
+		}
+
+	} else {
+		/*DTO1 Programming goal:
+		-generate 24MHz, 512*Fs, 128*Fs from 24MHz
+		-default is to used DTO1, and switch to DTO0 when an audio
+		master HDMI port is connected
+		-use as default for DP
+
+		calculate DTO settings */
+		get_azalia_clock_info_dp(
+			hw_ctx,
+			crtc_info->requested_pixel_clock,
+			pll_info,
+			&clock_info);
+
+		/* Program DTO select before programming DTO modulo and DTO
+		phase. default to use DTO1 */
+
+		{
+			set_reg_field_value(value, 1,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO_SEL);
+			/*dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value)*/
+
+			/* Select 512fs for DP TODO: web register definition
+			does not match register header file
+			set_reg_field_value(value, 1,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO2_USE_512FBR_DTO);
+			*/
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO_SOURCE, value);
+		}
+
+		/* module */
+		{
+			value = 0;
+
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_MODULE);
+
+			set_reg_field_value(value,
+				clock_info.audio_dto_module,
+				DCCG_AUDIO_DTO1_MODULE,
+				DCCG_AUDIO_DTO1_MODULE);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_MODULE, value);
+		}
+
+		/* phase */
+		{
+			value = 0;
+
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_PHASE);
+
+			set_reg_field_value(value,
+				clock_info.audio_dto_phase,
+				DCCG_AUDIO_DTO1_PHASE,
+				DCCG_AUDIO_DTO1_PHASE);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_PHASE, value);
+		}
+
+		/* DAL2 code separate DCCG_AUDIO_DTO_SEL and
+		DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different
+		location. merge together should not hurt */
+		/*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1;
+		dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/
+	}
+}
+
+/* setup HDMI audio */
+static void setup_hdmi_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	const struct audio_crtc_info *crtc_info)
+{
+	struct audio_clock_info audio_clock_info = {0};
+	uint32_t max_packets_per_line;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* For now still do calculation, although this field is ignored when
+	above HDMI_PACKET_GEN_VERSION set to 1 */
+	max_packets_per_line =
+		dal_audio_hw_ctx_calc_max_audio_packets_per_line(
+			hw_ctx,
+			crtc_info);
+
+	/* HDMI_AUDIO_PACKET_CONTROL */
+	{
+		addr =
+			mmHDMI_AUDIO_PACKET_CONTROL + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, max_packets_per_line,
+			HDMI_AUDIO_PACKET_CONTROL,
+			HDMI_AUDIO_PACKETS_PER_LINE);
+		/* still apply RS600's default setting which is 1. */
+		set_reg_field_value(value, 1,
+			HDMI_AUDIO_PACKET_CONTROL,
+			HDMI_AUDIO_DELAY_EN);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_AUDIO_PACKET_CONTROL */
+	{
+		addr = mmAFMT_AUDIO_PACKET_CONTROL + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 1,
+			AFMT_AUDIO_PACKET_CONTROL,
+			AFMT_60958_CS_UPDATE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_AUDIO_PACKET_CONTROL2 */
+	{
+		addr = mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 0,
+				AFMT_AUDIO_PACKET_CONTROL2,
+				AFMT_AUDIO_LAYOUT_OVRD);
+
+		/*Register field changed.*/
+		set_reg_field_value(value, 0,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_60958_OSF_OVRD);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* HDMI_ACR_PACKET_CONTROL */
+	{
+		addr = mmHDMI_ACR_PACKET_CONTROL + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 1,
+			HDMI_ACR_PACKET_CONTROL,
+			HDMI_ACR_AUTO_SEND);
+
+		/* Set HDMI_ACR_SOURCE to 0, to use hardwre
+		 *  computed CTS values.*/
+		set_reg_field_value(value, 0,
+			HDMI_ACR_PACKET_CONTROL,
+			HDMI_ACR_SOURCE);
+
+		/* For now clear HDMI_ACR_AUDIO_PRIORITY =>ACR packet has
+		higher priority over Audio Sample */
+		set_reg_field_value(value, 0,
+			HDMI_ACR_PACKET_CONTROL,
+			HDMI_ACR_AUDIO_PRIORITY);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* Program audio clock sample/regeneration parameters */
+	if (dal_audio_hw_ctx_get_audio_clock_info(
+		hw_ctx,
+		crtc_info->color_depth,
+		crtc_info->requested_pixel_clock,
+		crtc_info->calculated_pixel_clock,
+		&audio_clock_info)) {
+
+		/* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */
+		{
+			addr = mmHDMI_ACR_32_0 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+
+			set_reg_field_value(value, audio_clock_info.cts_32khz,
+				HDMI_ACR_32_0,
+				HDMI_ACR_CTS_32);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */
+		{
+			addr = mmHDMI_ACR_32_1 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.n_32khz,
+				HDMI_ACR_32_1,
+				HDMI_ACR_N_32);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */
+		{
+			addr = mmHDMI_ACR_44_0 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.cts_44khz,
+				HDMI_ACR_44_0,
+				HDMI_ACR_CTS_44);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */
+		{
+			addr = mmHDMI_ACR_44_1 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.n_44khz,
+				HDMI_ACR_44_1,
+				HDMI_ACR_N_44);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */
+		{
+			addr = mmHDMI_ACR_48_0 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.cts_48khz,
+				HDMI_ACR_48_0,
+				HDMI_ACR_CTS_48);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */
+		{
+			addr = mmHDMI_ACR_48_1 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.n_48khz,
+				HDMI_ACR_48_1,
+				HDMI_ACR_N_48);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* Video driver cannot know in advance which sample rate will
+		be used by HD Audio driver
+		HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is
+		programmed below in interruppt callback */
+	} /* if */
+
+	/* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK &
+	AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */
+	{
+		addr = mmAFMT_60958_0 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 1,
+			AFMT_60958_0,
+			AFMT_60958_CS_CHANNEL_NUMBER_L);
+
+		 /*HW default */
+		set_reg_field_value(value, 0,
+			AFMT_60958_0,
+			AFMT_60958_CS_CLOCK_ACCURACY);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */
+	{
+		addr = mmAFMT_60958_1 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 2,
+			AFMT_60958_1,
+			AFMT_60958_CS_CHANNEL_NUMBER_R);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/*AFMT_60958_2 now keep this settings until
+	 *  Programming guide comes out*/
+	{
+		addr = mmAFMT_60958_2 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 3,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_2);
+
+		set_reg_field_value(value, 4,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_3);
+
+		set_reg_field_value(value, 5,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_4);
+
+		set_reg_field_value(value, 6,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_5);
+
+		set_reg_field_value(value, 7,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_6);
+
+		set_reg_field_value(value, 8,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_7);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+}
+
+ /* setup DP audio */
+static void setup_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/* --- DP Audio packet configurations --- */
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* ATP Configuration */
+	{
+		addr = mmDP_SEC_AUD_N + engine_offset[engine_id];
+
+		set_reg_field_value(value,
+			DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT,
+			DP_SEC_AUD_N,
+			DP_SEC_AUD_N);
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* Async/auto-calc timestamp mode */
+	{
+		addr = mmDP_SEC_TIMESTAMP +
+			engine_offset[engine_id];
+
+		value = 0;
+
+		set_reg_field_value(value,
+			DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC,
+			DP_SEC_TIMESTAMP,
+			DP_SEC_TIMESTAMP_MODE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* --- The following are the registers
+	 *  copied from the SetupHDMI --- */
+
+
+	/* AFMT_AUDIO_PACKET_CONTROL */
+	{
+		addr = mmAFMT_AUDIO_PACKET_CONTROL +
+			engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value,
+			1,
+			AFMT_AUDIO_PACKET_CONTROL,
+			AFMT_60958_CS_UPDATE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_AUDIO_PACKET_CONTROL2 */
+	{
+		addr =
+			mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value,
+			0,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_AUDIO_LAYOUT_OVRD);
+
+		set_reg_field_value(value,
+			0,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_60958_OSF_OVRD);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_INFOFRAME_CONTROL0 */
+	{
+		addr =
+			mmAFMT_INFOFRAME_CONTROL0 + engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value,
+			1,
+			AFMT_INFOFRAME_CONTROL0,
+			AFMT_AUDIO_INFO_UPDATE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */
+	{
+		addr = mmAFMT_60958_0 + engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value,
+			0,
+			AFMT_60958_0,
+			AFMT_60958_CS_CLOCK_ACCURACY);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+}
+
+ /* setup VCE audio */
+static void setup_vce_audio(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	struct dc_context *ctx = hw_ctx->ctx;
+
+	NOT_IMPLEMENTED();
+
+	/*TODO:
+	const uint32_t addr = mmDOUT_DCE_VCE_CONTROL;
+	uint32_t value = 0;
+
+	value = dal_read_reg(hw_ctx->ctx,
+			addr);
+
+	set_reg_field_value(value,
+		FROM_BASE(hw_ctx)->azalia_stream_id - 1,
+		DOUT_DCE_VCE_CONTROL,
+		DC_VCE_AUDIO_STREAM_SELECT);
+
+	dal_write_reg(hw_ctx->ctx,
+			addr, value);*/
+}
+
+static void enable_afmt_clock(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	bool enable_flag)
+{
+	uint32_t engine_offs = engine_offset[engine_id];
+	uint32_t value;
+	uint32_t count = 0;
+	uint32_t enable = enable_flag ? 1:0;
+
+	/* Enable Audio packets*/
+	value = dm_read_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs);
+
+	/*enable AFMT clock*/
+	set_reg_field_value(value, enable,
+		AFMT_CNTL, AFMT_AUDIO_CLOCK_EN);
+	dm_write_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs, value);
+
+	/*wait for AFMT clock to turn on,
+	 * the expectation is that this
+	 * should complete in 1-2 reads)
+	 */
+	do {
+		/* Wait for 1us between subsequent register reads.*/
+		dm_delay_in_microseconds(hw_ctx->ctx, 1);
+		value = dm_read_reg(hw_ctx->ctx,
+				mmAFMT_CNTL + engine_offs);
+	} while (get_reg_field_value(value,
+				AFMT_CNTL, AFMT_AUDIO_CLOCK_ON) !=
+						enable && count++ < 10);
+}
+
+/* enable Azalia audio */
+static void enable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	uint32_t value;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
+
+	if (get_reg_field_value(value,
+			AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+			AUDIO_ENABLED) != 1)
+		set_reg_field_value(value, 1,
+			AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+			AUDIO_ENABLED);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+		value);
+}
+
+/* disable Azalia audio */
+static void disable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	uint32_t value;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
+
+	set_reg_field_value(value, 0,
+		AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+		AUDIO_ENABLED);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+		value);
+}
+
+/* enable DP audio */
+static void enable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id];
+
+	uint32_t value;
+
+	/* Enable Audio packets */
+	value = dm_read_reg(hw_ctx->ctx, addr);
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_ASP_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+
+	/* Program the ATP and AIP next */
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_ATP_ENABLE);
+
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_AIP_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+
+	/* Program STREAM_ENABLE after all the other enables. */
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+/* disable DP audio */
+static void disable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id];
+
+	uint32_t value;
+
+	/* Disable Audio packets */
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_ASP_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_ATP_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_AIP_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_ACM_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_STREAM_ENABLE);
+
+	/* This register shared with encoder info frame. Therefore we need to
+	keep master enabled if at least on of the fields is not 0 */
+	if (value != 0)
+		set_reg_field_value(value, 1,
+			DP_SEC_CNTL,
+			DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+static void configure_azalia(
+	const struct hw_ctx_audio *hw_ctx,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_info *audio_info)
+{
+	uint32_t speakers = audio_info->flags.info.ALLSPEAKERS;
+	uint32_t value;
+	uint32_t field = 0;
+	enum audio_format_code audio_format_code;
+	uint32_t format_index;
+	uint32_t index;
+	bool is_ac3_supported = false;
+	bool is_audio_format_supported = false;
+	union audio_sample_rates sample_rate;
+	uint32_t strlen = 0;
+
+	/* Speaker Allocation */
+	/*
+	uint32_t value;
+	uint32_t field = 0;*/
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
+
+	set_reg_field_value(value,
+		speakers,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		SPEAKER_ALLOCATION);
+
+	/* LFE_PLAYBACK_LEVEL = LFEPBL
+	 * LFEPBL = 0 : Unknown or refer to other information
+	 * LFEPBL = 1 : 0dB playback
+	 * LFEPBL = 2 : +10dB playback
+	 * LFE_BL = 3 : Reserved
+	 */
+	set_reg_field_value(value,
+		0,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		LFE_PLAYBACK_LEVEL);
+
+	set_reg_field_value(value,
+		0,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		HDMI_CONNECTION);
+
+	set_reg_field_value(value,
+		0,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		DP_CONNECTION);
+
+	field = get_reg_field_value(value,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			EXTRA_CONNECTION_INFO);
+
+	field &= ~0x1;
+
+	set_reg_field_value(value,
+		field,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		EXTRA_CONNECTION_INFO);
+
+	/* set audio for output signal */
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		set_reg_field_value(value,
+			1,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			HDMI_CONNECTION);
+
+		break;
+	case SIGNAL_TYPE_WIRELESS: {
+		/*LSB used for "is wireless" flag */
+		field = 0;
+		field = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		EXTRA_CONNECTION_INFO);
+		field |= 0x1;
+		set_reg_field_value(value,
+			field,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			EXTRA_CONNECTION_INFO);
+
+		set_reg_field_value(value,
+			1,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			HDMI_CONNECTION);
+
+		}
+		break;
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		set_reg_field_value(value,
+			1,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			DP_CONNECTION);
+
+		break;
+	default:
+		break;
+	}
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		value);
+
+	/* Wireless Display identification */
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION);
+
+	set_reg_field_value(value,
+		signal == SIGNAL_TYPE_WIRELESS ? 1 : 0,
+		AZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION,
+		WIRELESS_DISPLAY_IDENTIFICATION);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION,
+		value);
+
+	/*  Audio Descriptors   */
+	/* pass through all formats */
+	for (format_index = 0; format_index < AUDIO_FORMAT_CODE_COUNT;
+			format_index++) {
+		audio_format_code =
+			(AUDIO_FORMAT_CODE_FIRST + format_index);
+
+		/* those are unsupported, skip programming */
+		if (audio_format_code == AUDIO_FORMAT_CODE_1BITAUDIO ||
+			audio_format_code == AUDIO_FORMAT_CODE_DST)
+			continue;
+
+		value = 0;
+
+		/* check if supported */
+		is_audio_format_supported =
+			dal_audio_hw_ctx_is_audio_format_supported(
+				hw_ctx,
+				audio_info,
+				audio_format_code, &index);
+
+		if (is_audio_format_supported) {
+			const struct audio_mode *audio_mode =
+					&audio_info->modes[index];
+			union audio_sample_rates sample_rates =
+					audio_mode->sample_rates;
+			uint8_t byte2 = audio_mode->max_bit_rate;
+
+			/* adjust specific properties */
+			switch (audio_format_code) {
+			case AUDIO_FORMAT_CODE_LINEARPCM: {
+				dal_hw_ctx_audio_check_audio_bandwidth(
+					hw_ctx,
+					crtc_info,
+					audio_mode->channel_count,
+					signal,
+					&sample_rates);
+
+				byte2 = audio_mode->sample_size;
+
+				set_reg_field_value(value,
+				sample_rates.all,
+		AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+				SUPPORTED_FREQUENCIES_STEREO);
+
+				}
+				break;
+			case AUDIO_FORMAT_CODE_AC3:
+				is_ac3_supported = true;
+				break;
+			case AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS:
+			case AUDIO_FORMAT_CODE_DTS_HD:
+			case AUDIO_FORMAT_CODE_MAT_MLP:
+			case AUDIO_FORMAT_CODE_DST:
+			case AUDIO_FORMAT_CODE_WMAPRO:
+				byte2 = audio_mode->vendor_specific;
+				break;
+			default:
+				break;
+			}
+
+			/* fill audio format data */
+			set_reg_field_value(value,
+			audio_mode->channel_count - 1,
+			AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+			MAX_CHANNELS);
+
+			set_reg_field_value(value,
+			sample_rates.all,
+			AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+			SUPPORTED_FREQUENCIES);
+
+			set_reg_field_value(value,
+			byte2,
+			AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+			DESCRIPTOR_BYTE_2);
+
+		} /* if */
+
+		write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 +
+		format_index,
+		value);
+	} /* for */
+
+	if (is_ac3_supported)
+		dm_write_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS,
+		0x05);
+
+	/* check for 192khz/8-Ch support for HBR requirements */
+	sample_rate.all = 0;
+	sample_rate.rate.RATE_192 = 1;
+	dal_hw_ctx_audio_check_audio_bandwidth(
+		hw_ctx,
+		crtc_info,
+		8,
+		signal,
+		&sample_rate);
+
+	set_high_bit_rate_capable(hw_ctx, sample_rate.rate.RATE_192);
+
+	/* Audio and Video Lipsync */
+	set_video_latency(hw_ctx, audio_info->video_latency);
+	set_audio_latency(hw_ctx, audio_info->audio_latency);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->manufacture_id,
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
+		MANUFACTURER_ID);
+
+	set_reg_field_value(value, audio_info->product_id,
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
+		PRODUCT_ID);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
+		value);
+
+
+	value = 0;
+
+	/*get display name string length */
+	while (audio_info->display_name[strlen++] != '\0') {
+		if (strlen >=
+		MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS)
+			break;
+		}
+	set_reg_field_value(value, strlen,
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1,
+		SINK_DESCRIPTION_LEN);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1,
+		value);
+
+
+	/*
+	*write the port ID:
+	*PORT_ID0 = display index
+	*PORT_ID1 = 16bit BDF
+	*(format MSB->LSB: 8bit Bus, 5bit Device, 3bit Function)
+	*/
+
+	value = 0;
+
+	set_reg_field_value(value, audio_info->port_id[0],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2,
+		PORT_ID0);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2,
+		value);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->port_id[1],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3,
+		PORT_ID1);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3,
+		value);
+
+	/*write the 18 char monitor string */
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[0],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION0);
+
+	set_reg_field_value(value, audio_info->display_name[1],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION1);
+
+	set_reg_field_value(value, audio_info->display_name[2],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION2);
+
+	set_reg_field_value(value, audio_info->display_name[3],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION3);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		value);
+
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[4],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION4);
+
+	set_reg_field_value(value, audio_info->display_name[5],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION5);
+
+	set_reg_field_value(value, audio_info->display_name[6],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION6);
+
+	set_reg_field_value(value, audio_info->display_name[7],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION7);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		value);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[8],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION8);
+
+	set_reg_field_value(value, audio_info->display_name[9],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION9);
+
+	set_reg_field_value(value, audio_info->display_name[10],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION10);
+
+	set_reg_field_value(value, audio_info->display_name[11],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION11);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		value);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[12],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION12);
+
+	set_reg_field_value(value, audio_info->display_name[13],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION13);
+
+	set_reg_field_value(value, audio_info->display_name[14],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION14);
+
+	set_reg_field_value(value, audio_info->display_name[15],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION15);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		value);
+
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[16],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
+		DESCRIPTION16);
+
+	set_reg_field_value(value, audio_info->display_name[17],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
+		DESCRIPTION17);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
+		value);
+
+}
+
+/* setup Azalia HW block */
+static void setup_azalia(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info,
+	const struct audio_info *audio_info)
+{
+	uint32_t speakers = 0;
+	uint32_t channels = 0;
+
+	if (audio_info == NULL)
+		/* This should not happen.it does so we don't get BSOD*/
+		return;
+
+	speakers = audio_info->flags.info.ALLSPEAKERS;
+	channels = dal_audio_hw_ctx_speakers_to_channels(
+		hw_ctx,
+		audio_info->flags.speaker_flags).all;
+
+	/* setup the audio stream source select (audio -> dig mapping) */
+	{
+		const uint32_t addr =
+			mmAFMT_AUDIO_SRC_CONTROL + engine_offset[engine_id];
+
+		uint32_t value = 0;
+		/*convert one-based index to zero-based */
+		set_reg_field_value(value,
+			FROM_BASE(hw_ctx)->azalia_stream_id - 1,
+			AFMT_AUDIO_SRC_CONTROL,
+			AFMT_AUDIO_SRC_SELECT);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* Channel allocation */
+	{
+		const uint32_t addr =
+			mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
+		uint32_t value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value,
+			channels,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_AUDIO_CHANNEL_ENABLE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	configure_azalia(hw_ctx, signal, crtc_info, audio_info);
+}
+
+/* unmute audio */
+static void unmute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL +
+		engine_offset[engine_id];
+
+	uint32_t value = 0;
+
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	set_reg_field_value(value, 1,
+		AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+/* mute audio */
+static void mute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL +
+		engine_offset[engine_id];
+
+	uint32_t value = 0;
+
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	set_reg_field_value(value, 0,
+		AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+/* enable channel splitting mapping */
+static void setup_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	uint32_t value = 0;
+
+	if ((audio_mapping == NULL || audio_mapping->u32all == 0) && enable)
+		return;
+
+
+	value = audio_mapping->u32all;
+
+	if (enable == false)
+		/*0xFFFFFFFF;*/
+		value = MULTI_CHANNEL_SPLIT_NO_ASSO_INFO;
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO,
+		value);
+}
+
+/* get current channel spliting */
+static bool get_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	uint32_t value = 0;
+
+	if (audio_mapping == NULL)
+		return false;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO);
+
+	/*0xFFFFFFFF*/
+	if (get_reg_field_value(value,
+			AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO,
+			ASSOCIATION_INFO) !=
+			MULTI_CHANNEL_SPLIT_NO_ASSO_INFO) {
+		uint32_t multi_channel01_enable = 0;
+		uint32_t multi_channel23_enable = 0;
+		uint32_t multi_channel45_enable = 0;
+		uint32_t multi_channel67_enable = 0;
+		/* get the one we set.*/
+		audio_mapping->u32all = value;
+
+		/* check each enable status*/
+		value = read_indirect_azalia_reg(
+			hw_ctx,
+			ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE);
+
+		multi_channel01_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL01_ENABLE);
+
+		multi_channel23_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL23_ENABLE);
+
+		multi_channel45_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL45_ENABLE);
+
+		multi_channel67_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL67_ENABLE);
+
+		if (multi_channel01_enable == 0 &&
+			multi_channel23_enable == 0 &&
+			multi_channel45_enable == 0 &&
+			multi_channel67_enable == 0)
+			dal_logger_write(hw_ctx->ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_COMPONENT_AUDIO,
+				"Audio driver did not enable multi-channel\n");
+
+		return true;
+	}
+
+	return false;
+}
+
+/* set the payload value for the unsolicited response */
+static void set_unsolicited_response_payload(
+	const struct hw_ctx_audio *hw_ctx,
+	enum audio_payload payload)
+{
+	/* set the payload value for the unsolicited response
+	 Jack presence is not required to be enabled */
+	uint32_t value = 0;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE);
+
+	set_reg_field_value(value, payload,
+		AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE,
+		UNSOLICITED_RESPONSE_PAYLOAD);
+
+	set_reg_field_value(value, 1,
+		AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE,
+		UNSOLICITED_RESPONSE_FORCE);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE,
+		value);
+}
+
+/* initialize HW state */
+static void hw_initialize(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	uint32_t stream_id = FROM_BASE(hw_ctx)->azalia_stream_id;
+	uint32_t addr;
+
+	/* we only need to program the following registers once, so we only do
+	it for the first audio stream.*/
+	if (stream_id != FIRST_AUDIO_STREAM_ID)
+		return;
+
+	/* Suport R5 - 32khz
+	 * Suport R6 - 44.1khz
+	 * Suport R7 - 48khz
+	 */
+	addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES;
+	{
+		uint32_t value;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 0x70,
+		AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES,
+		AUDIO_RATE_CAPABILITIES);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/*Keep alive bit to verify HW block in BU. */
+	addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES;
+	{
+		uint32_t value;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 1,
+		AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
+		CLKSTOP);
+
+		set_reg_field_value(value, 1,
+		AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
+		EPSS);
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+}
+
+/* Assign GTC group and enable GTC value embedding */
+static void enable_gtc_embedding_with_group(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t group_num,
+	uint32_t audio_latency)
+{
+	/*need to replace the static number with variable */
+	if (group_num <= 6) {
+		uint32_t value = read_indirect_azalia_reg(
+			hw_ctx,
+			ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING);
+
+		set_reg_field_value(
+			value,
+			group_num,
+			AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+			PRESENTATION_TIME_EMBEDDING_GROUP);
+
+		set_reg_field_value(
+			value,
+			1,
+			AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+			PRESENTATION_TIME_EMBEDDING_ENABLE);
+
+		write_indirect_azalia_reg(
+			hw_ctx,
+			ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+			value);
+
+		/*update audio latency to LIPSYNC*/
+		set_audio_latency(hw_ctx, audio_latency);
+	} else {
+		dal_logger_write(
+			hw_ctx->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_COMPONENT_AUDIO,
+			"GTC group number %d is too big",
+			group_num);
+	}
+}
+
+ /* Disable GTC value embedding */
+static void disable_gtc_embedding(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	uint32_t value = 0;
+
+	value = read_indirect_azalia_reg(
+	hw_ctx,
+	ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING);
+
+	set_reg_field_value(value, 0,
+	AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+	PRESENTATION_TIME_EMBEDDING_ENABLE);
+
+	set_reg_field_value(value, 0,
+	AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+	PRESENTATION_TIME_EMBEDDING_GROUP);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+		value);
+}
+
+/* search pixel clock value for Azalia HDMI Audio */
+static bool get_azalia_clock_info_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	if (azalia_clock_info == NULL)
+		return false;
+
+	/* audio_dto_phase= 24 * 10,000;
+	 *   24MHz in [100Hz] units */
+	azalia_clock_info->audio_dto_phase =
+			24 * 10000;
+
+	/* audio_dto_module = PCLKFrequency * 10,000;
+	 *  [khz] -> [100Hz] */
+	azalia_clock_info->audio_dto_module =
+			actual_pixel_clock_in_khz * 10;
+
+	return true;
+}
+
+/* search pixel clock value for Azalia DP Audio */
+static bool get_azalia_clock_info_dp(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t requested_pixel_clock_in_khz,
+	const struct audio_pll_info *pll_info,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	if (pll_info == NULL || azalia_clock_info == NULL)
+		return false;
+
+	/* Reported dpDtoSourceClockInkhz value for
+	 * DCE8 already adjusted for SS, do not need any
+	 * adjustment here anymore
+	 */
+
+	/*audio_dto_phase = 24 * 10,000;
+	 * 24MHz in [100Hz] units */
+	azalia_clock_info->audio_dto_phase = 24 * 10000;
+
+	/*audio_dto_module = dpDtoSourceClockInkhz * 10,000;
+	 *  [khz] ->[100Hz] */
+	azalia_clock_info->audio_dto_module =
+		pll_info->dp_dto_source_clock_in_khz * 10;
+
+	return true;
+}
+
+static const struct hw_ctx_audio_funcs funcs = {
+	.destroy = destroy,
+	.setup_audio_wall_dto =
+		setup_audio_wall_dto,
+	.setup_hdmi_audio =
+		setup_hdmi_audio,
+	.setup_dp_audio = setup_dp_audio,
+	.setup_vce_audio = setup_vce_audio,
+	.enable_azalia_audio =
+		enable_azalia_audio,
+	.disable_azalia_audio =
+		disable_azalia_audio,
+	.enable_dp_audio =
+		enable_dp_audio,
+	.disable_dp_audio =
+		disable_dp_audio,
+	.setup_azalia =
+		setup_azalia,
+	.disable_az_clock_gating = NULL,
+	.unmute_azalia_audio =
+		unmute_azalia_audio,
+	.mute_azalia_audio =
+		mute_azalia_audio,
+	.setup_channel_splitting_mapping =
+		setup_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.hw_initialize =
+		hw_initialize,
+	.enable_gtc_embedding_with_group =
+		enable_gtc_embedding_with_group,
+	.disable_gtc_embedding =
+		disable_gtc_embedding,
+	.get_azalia_clock_info_hdmi =
+		get_azalia_clock_info_hdmi,
+	.get_azalia_clock_info_dp =
+		get_azalia_clock_info_dp,
+	.enable_afmt_clock = enable_afmt_clock
+};
+
+static bool construct(
+	struct hw_ctx_audio_dce110 *hw_ctx,
+	uint8_t azalia_stream_id,
+	struct dc_context *ctx)
+{
+	struct hw_ctx_audio *base = &hw_ctx->base;
+
+	if (!dal_audio_construct_hw_ctx_audio(base))
+		return false;
+
+	base->funcs = &funcs;
+
+	/* save audio endpoint or dig front for current dce110 audio object */
+	hw_ctx->azalia_stream_id = azalia_stream_id;
+	hw_ctx->base.ctx = ctx;
+
+	/* azalia audio endpoints register offsets. azalia is associated with
+	DIG front. save AUDIO register offset */
+	switch (azalia_stream_id) {
+	case 1: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	case 2: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	case 3: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	case 4: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	default:
+		dal_logger_write(
+			hw_ctx->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_AUDIO,
+			"Invalid Azalia stream ID!");
+		break;
+	}
+
+	return true;
+}
+
+/* audio_dce110 is derived from audio directly, not via dce80  */
+struct hw_ctx_audio *dal_hw_ctx_audio_dce110_create(
+	struct dc_context *ctx,
+	uint32_t azalia_stream_id)
+{
+	/* allocate memory for struc hw_ctx_audio_dce110 */
+	struct hw_ctx_audio_dce110 *hw_ctx_dce110 =
+			dm_alloc(ctx, sizeof(struct hw_ctx_audio_dce110));
+
+	if (!hw_ctx_dce110) {
+		ASSERT_CRITICAL(hw_ctx_dce110);
+		return NULL;
+	}
+
+	/*return pointer to hw_ctx_audio back to caller  -- audio object */
+	if (construct(
+			hw_ctx_dce110, azalia_stream_id, ctx))
+		return &hw_ctx_dce110->base;
+
+	dal_logger_write(
+		ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_AUDIO,
+		"Failed to create hw_ctx_audio for DCE11\n");
+
+
+	dm_free(ctx, hw_ctx_dce110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
new file mode 100644
index 000000000000..1ad3826aeb9f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_AUDIO_DCE110_H__
+#define __DAL_HW_CTX_AUDIO_DCE110_H__
+
+#include "audio/hw_ctx_audio.h"
+
+struct hw_ctx_audio_dce110 {
+	struct hw_ctx_audio base;
+
+	/* azalia stream id 1 based indexing, corresponding to audio GO enumId*/
+	uint32_t azalia_stream_id;
+
+	/* azalia stream endpoint register offsets */
+	struct azalia_reg_offsets az_mm_reg_offsets;
+
+	/* audio encoder block MM register offset -- associate with DIG FRONT */
+};
+
+struct hw_ctx_audio *dal_hw_ctx_audio_dce110_create(
+	struct dc_context *ctx,
+	uint32_t azalia_stream_id);
+
+#endif  /* __DAL_HW_CTX_AUDIO_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
new file mode 100644
index 000000000000..58207f53bff1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "hw_ctx_audio.h"
+
+/* 25.2MHz/1.001*/
+/* 25.2MHz/1.001*/
+/* 25.2MHz*/
+/* 27MHz */
+/* 27MHz*1.001*/
+/* 27MHz*1.001*/
+/* 54MHz*/
+/* 54MHz*1.001*/
+/* 74.25MHz/1.001*/
+/* 74.25MHz*/
+/* 148.5MHz/1.001*/
+/* 148.5MHz*/
+
+static const struct audio_clock_info audio_clock_info_table[12] = {
+	{2517, 4576, 28125, 7007, 31250, 6864, 28125},
+	{2518, 4576, 28125, 7007, 31250, 6864, 28125},
+	{2520, 4096, 25200, 6272, 28000, 6144, 25200},
+	{2700, 4096, 27000, 6272, 30000, 6144, 27000},
+	{2702, 4096, 27027, 6272, 30030, 6144, 27027},
+	{2703, 4096, 27027, 6272, 30030, 6144, 27027},
+	{5400, 4096, 54000, 6272, 60000, 6144, 54000},
+	{5405, 4096, 54054, 6272, 60060, 6144, 54054},
+	{7417, 11648, 210937, 17836, 234375, 11648, 140625},
+	{7425, 4096, 74250, 6272, 82500, 6144, 74250},
+	{14835, 11648, 421875, 8918, 234375, 5824, 140625},
+	{14850, 4096, 148500, 6272, 165000, 6144, 148500}
+};
+
+static const struct audio_clock_info audio_clock_info_table_36bpc[12] = {
+	{2517, 9152, 84375, 7007, 48875, 9152, 56250},
+	{2518, 9152, 84375, 7007, 48875, 9152, 56250},
+	{2520, 4096, 37800, 6272, 42000, 6144, 37800},
+	{2700, 4096, 40500, 6272, 45000, 6144, 40500},
+	{2702, 8192, 81081, 6272, 45045, 8192, 54054},
+	{2703, 8192, 81081, 6272, 45045, 8192, 54054},
+	{5400, 4096, 81000, 6272, 90000, 6144, 81000},
+	{5405, 4096, 81081, 6272, 90090, 6144, 81081},
+	{7417, 11648, 316406, 17836, 351562, 11648, 210937},
+	{7425, 4096, 111375, 6272, 123750, 6144, 111375},
+	{14835, 11648, 632812, 17836, 703125, 11648, 421875},
+	{14850, 4096, 222750, 6272, 247500, 6144, 222750}
+};
+
+static const struct audio_clock_info audio_clock_info_table_48bpc[12] = {
+	{2517, 4576, 56250, 7007, 62500, 6864, 56250},
+	{2518, 4576, 56250, 7007, 62500, 6864, 56250},
+	{2520, 4096, 50400, 6272, 56000, 6144, 50400},
+	{2700, 4096, 54000, 6272, 60000, 6144, 54000},
+	{2702, 4096, 54054, 6267, 60060, 8192, 54054},
+	{2703, 4096, 54054, 6272, 60060, 8192, 54054},
+	{5400, 4096, 108000, 6272, 120000, 6144, 108000},
+	{5405, 4096, 108108, 6272, 120120, 6144, 108108},
+	{7417, 11648, 421875, 17836, 468750, 11648, 281250},
+	{7425, 4096, 148500, 6272, 165000, 6144, 148500},
+	{14835, 11648, 843750, 8918, 468750, 11648, 281250},
+	{14850, 4096, 297000, 6272, 330000, 6144, 297000}
+};
+
+
+/***** static function *****/
+
+/*
+ * except of HW context create function, caller will access other functions of
+ * hw ctx via handle hw_ctx. Memory allocation for struct hw_ctx_audio_dce8x
+ * will happen in hw_ctx_audio_dce8x. Memory allocation is done with
+ * dal_audio_create_hw_ctx_audio_dce8x. Memory release is done by caller
+ * via hw_ctx->functions.destroy(). It will finally use destroy() of
+ * hw_ctx_audio_dce8x. Therefore, no memory allocate and release happen
+ * physically at hw ctx base object.
+ */
+static void destroy(
+	struct hw_ctx_audio **ptr)
+{
+	/* Attention!
+	 * You must override this method in derived class */
+}
+
+static void setup_audio_wall_dto(
+	const struct hw_ctx_audio *hw_ctx,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* setup HDMI audio */
+static void setup_hdmi_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	const struct audio_crtc_info *crtc_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+ /* setup DP audio */
+static void setup_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+ /* setup VCE audio */
+static void setup_vce_audio(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* enable Azalia audio */
+static void enable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* disable Azalia audio */
+static void disable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* enable DP audio */
+static void enable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* disable DP audio */
+static void disable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* setup Azalia HW block */
+static void setup_azalia(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info,
+	const struct audio_info *audio_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* unmute audio */
+static void unmute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* mute audio */
+static void mute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* enable channel splitting mapping */
+static void setup_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* get current channel spliting */
+static bool get_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+/* set the payload value for the unsolicited response */
+static void set_unsolicited_response_payload(
+	const struct hw_ctx_audio *hw_ctx,
+	enum audio_payload payload)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* initialize HW state */
+static void hw_initialize(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* Assign GTC group and enable GTC value embedding */
+static void enable_gtc_embedding_with_group(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t groupNum,
+	uint32_t audioLatency)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* Disable GTC value embedding */
+static void disable_gtc_embedding(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* Disable Azalia Clock Gating Feature */
+static void disable_az_clock_gating(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* search pixel clock value for Azalia HDMI Audio */
+static bool get_azalia_clock_info_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+/* search pixel clock value for Azalia DP Audio */
+static bool get_azalia_clock_info_dp(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t requested_pixel_clock_in_khz,
+	const struct audio_pll_info *pll_info,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+
+
+
+
+
+
+
+
+/*****SCOPE : within audio hw context dal-audio-hw-ctx *****/
+
+
+/* check whether specified sample rates can fit into a given timing */
+void dal_hw_ctx_audio_check_audio_bandwidth(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		dal_audio_hw_ctx_check_audio_bandwidth_hdmi(
+			hw_ctx, crtc_info, channel_count, sample_rates);
+		break;
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+		dal_audio_hw_ctx_check_audio_bandwidth_dpsst(
+			hw_ctx, crtc_info, channel_count, sample_rates);
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		dal_audio_hw_ctx_check_audio_bandwidth_dpmst(
+			hw_ctx,  crtc_info, channel_count, sample_rates);
+		break;
+	default:
+		break;
+	}
+}
+
+/*For HDMI, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates)
+{
+	uint32_t samples;
+	uint32_t  h_blank;
+	bool limit_freq_to_48_khz = false;
+	bool limit_freq_to_88_2_khz = false;
+	bool limit_freq_to_96_khz = false;
+	bool limit_freq_to_174_4_khz = false;
+
+	/* For two channels supported return whatever sink support,unmodified*/
+	if (channel_count > 2) {
+
+		/* Based on HDMI spec 1.3 Table 7.5 */
+		if ((crtc_info->requested_pixel_clock <= 27000) &&
+		(crtc_info->v_active <= 576) &&
+		!(crtc_info->interlaced) &&
+		!(crtc_info->pixel_repetition == 2 ||
+		crtc_info->pixel_repetition == 4)) {
+			limit_freq_to_48_khz = true;
+
+		} else if ((crtc_info->requested_pixel_clock <= 27000) &&
+				(crtc_info->v_active <= 576) &&
+				(crtc_info->interlaced) &&
+				(crtc_info->pixel_repetition == 2)) {
+			limit_freq_to_88_2_khz = true;
+
+		} else if ((crtc_info->requested_pixel_clock <= 54000) &&
+				(crtc_info->v_active <= 576) &&
+				!(crtc_info->interlaced)) {
+			limit_freq_to_174_4_khz = true;
+		}
+	}
+
+	/* Also do some calculation for the available Audio Bandwidth for the
+	 * 8 ch (i.e. for the Layout 1 => ch > 2)
+	 */
+	h_blank = crtc_info->h_total - crtc_info->h_active;
+
+	if (crtc_info->pixel_repetition)
+		h_blank *= crtc_info->pixel_repetition;
+
+	/*based on HDMI spec 1.3 Table 7.5 */
+	h_blank -= 58;
+	/*for Control Period */
+	h_blank -= 16;
+
+	samples = h_blank * 10;
+	/* Number of Audio Packets (multiplied by 10) per Line (for 8 ch number
+	 * of Audio samples per line multiplied by 10 - Layout 1)
+	 */
+	 samples /= 32;
+	 samples *= crtc_info->v_active;
+	 /*Number of samples multiplied by 10, per second */
+	 samples *= crtc_info->refresh_rate;
+	 /*Number of Audio samples per second */
+	 samples /= 10;
+
+	 /* @todo do it after deep color is implemented
+	  * 8xx - deep color bandwidth scaling
+	  * Extra bandwidth is avaliable in deep color b/c link runs faster than
+	  * pixel rate. This has the effect of allowing more tmds characters to
+	  * be transmitted during blank
+	  */
+
+	switch (crtc_info->color_depth) {
+	case COLOR_DEPTH_888:
+		samples *= 4;
+		break;
+	case COLOR_DEPTH_101010:
+		samples *= 5;
+		break;
+	case COLOR_DEPTH_121212:
+		samples *= 6;
+		break;
+	default:
+		samples *= 4;
+		break;
+	}
+
+	samples /= 4;
+
+	/*check limitation*/
+	if (samples < 88200)
+		limit_freq_to_48_khz = true;
+	else if (samples < 96000)
+		limit_freq_to_88_2_khz = true;
+	else if (samples < 176400)
+		limit_freq_to_96_khz = true;
+	else if (samples < 192000)
+		limit_freq_to_174_4_khz = true;
+
+	if (sample_rates != NULL) {
+		/* limit frequencies */
+		if (limit_freq_to_174_4_khz)
+			sample_rates->rate.RATE_192 = 0;
+
+		if (limit_freq_to_96_khz) {
+			sample_rates->rate.RATE_192 = 0;
+			sample_rates->rate.RATE_176_4 = 0;
+		}
+		if (limit_freq_to_88_2_khz) {
+			sample_rates->rate.RATE_192 = 0;
+			sample_rates->rate.RATE_176_4 = 0;
+			sample_rates->rate.RATE_96 = 0;
+		}
+		if (limit_freq_to_48_khz) {
+			sample_rates->rate.RATE_192 = 0;
+			sample_rates->rate.RATE_176_4 = 0;
+			sample_rates->rate.RATE_96 = 0;
+			sample_rates->rate.RATE_88_2 = 0;
+		}
+	}
+}
+
+/*For DP SST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpsst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates)
+{
+	/* do nothing */
+}
+
+/*For DP MST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpmst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates)
+{
+	/* do nothing  */
+}
+
+/* calculate max number of Audio packets per line */
+uint32_t dal_audio_hw_ctx_calc_max_audio_packets_per_line(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info)
+{
+	uint32_t max_packets_per_line;
+
+	max_packets_per_line =
+		crtc_info->h_total - crtc_info->h_active;
+
+	if (crtc_info->pixel_repetition)
+		max_packets_per_line *= crtc_info->pixel_repetition;
+
+	/* for other hdmi features */
+	max_packets_per_line -= 58;
+	/* for Control Period */
+	max_packets_per_line -= 16;
+	/* Number of Audio Packets per Line */
+	max_packets_per_line /= 32;
+
+	return max_packets_per_line;
+}
+
+/**
+* speakersToChannels
+*
+* @brief
+*  translate speakers to channels
+*
+*  FL  - Front Left
+*  FR  - Front Right
+*  RL  - Rear Left
+*  RR  - Rear Right
+*  RC  - Rear Center
+*  FC  - Front Center
+*  FLC - Front Left Center
+*  FRC - Front Right Center
+*  RLC - Rear Left Center
+*  RRC - Rear Right Center
+*  LFE - Low Freq Effect
+*
+*               FC
+*          FLC      FRC
+*    FL                    FR
+*
+*                    LFE
+*              ()
+*
+*
+*    RL                    RR
+*          RLC      RRC
+*               RC
+*
+*             ch  8   7   6   5   4   3   2   1
+* 0b00000011      -   -   -   -   -   -   FR  FL
+* 0b00000111      -   -   -   -   -   LFE FR  FL
+* 0b00001011      -   -   -   -   FC  -   FR  FL
+* 0b00001111      -   -   -   -   FC  LFE FR  FL
+* 0b00010011      -   -   -   RC  -   -   FR  FL
+* 0b00010111      -   -   -   RC  -   LFE FR  FL
+* 0b00011011      -   -   -   RC  FC  -   FR  FL
+* 0b00011111      -   -   -   RC  FC  LFE FR  FL
+* 0b00110011      -   -   RR  RL  -   -   FR  FL
+* 0b00110111      -   -   RR  RL  -   LFE FR  FL
+* 0b00111011      -   -   RR  RL  FC  -   FR  FL
+* 0b00111111      -   -   RR  RL  FC  LFE FR  FL
+* 0b01110011      -   RC  RR  RL  -   -   FR  FL
+* 0b01110111      -   RC  RR  RL  -   LFE FR  FL
+* 0b01111011      -   RC  RR  RL  FC  -   FR  FL
+* 0b01111111      -   RC  RR  RL  FC  LFE FR  FL
+* 0b11110011      RRC RLC RR  RL  -   -   FR  FL
+* 0b11110111      RRC RLC RR  RL  -   LFE FR  FL
+* 0b11111011      RRC RLC RR  RL  FC  -   FR  FL
+* 0b11111111      RRC RLC RR  RL  FC  LFE FR  FL
+* 0b11000011      FRC FLC -   -   -   -   FR  FL
+* 0b11000111      FRC FLC -   -   -   LFE FR  FL
+* 0b11001011      FRC FLC -   -   FC  -   FR  FL
+* 0b11001111      FRC FLC -   -   FC  LFE FR  FL
+* 0b11010011      FRC FLC -   RC  -   -   FR  FL
+* 0b11010111      FRC FLC -   RC  -   LFE FR  FL
+* 0b11011011      FRC FLC -   RC  FC  -   FR  FL
+* 0b11011111      FRC FLC -   RC  FC  LFE FR  FL
+* 0b11110011      FRC FLC RR  RL  -   -   FR  FL
+* 0b11110111      FRC FLC RR  RL  -   LFE FR  FL
+* 0b11111011      FRC FLC RR  RL  FC  -   FR  FL
+* 0b11111111      FRC FLC RR  RL  FC  LFE FR  FL
+*
+* @param
+*  speakers - speaker information as it comes from CEA audio block
+*/
+/* translate speakers to channels */
+union audio_cea_channels dal_audio_hw_ctx_speakers_to_channels(
+	const struct hw_ctx_audio *hw_ctx,
+	struct audio_speaker_flags speaker_flags)
+{
+	union audio_cea_channels cea_channels = {0};
+
+	/* these are one to one */
+	cea_channels.channels.FL = speaker_flags.FL_FR;
+	cea_channels.channels.FR = speaker_flags.FL_FR;
+	cea_channels.channels.LFE = speaker_flags.LFE;
+	cea_channels.channels.FC = speaker_flags.FC;
+
+	/* if Rear Left and Right exist move RC speaker to channel 7
+	 * otherwise to channel 5
+	 */
+	if (speaker_flags.RL_RR) {
+		cea_channels.channels.RL_RC = speaker_flags.RL_RR;
+		cea_channels.channels.RR = speaker_flags.RL_RR;
+		cea_channels.channels.RC_RLC_FLC = speaker_flags.RC;
+	} else {
+		cea_channels.channels.RL_RC = speaker_flags.RC;
+	}
+
+	/* FRONT Left Right Center and REAR Left Right Center are exclusive */
+	if (speaker_flags.FLC_FRC) {
+		cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC;
+		cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC;
+	} else {
+		cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC;
+		cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC;
+	}
+
+	return cea_channels;
+}
+
+/* check whether specified audio format supported */
+bool dal_audio_hw_ctx_is_audio_format_supported(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_info *audio_info,
+	enum audio_format_code audio_format_code,
+	uint32_t *format_index)
+{
+	uint32_t index;
+	uint32_t max_channe_index = 0;
+	bool found = false;
+
+	if (audio_info == NULL)
+		return found;
+
+	/* pass through whole array */
+	for (index = 0; index < audio_info->mode_count; index++) {
+		if (audio_info->modes[index].format_code == audio_format_code) {
+			if (found) {
+				/* format has multiply entries, choose one with
+				 *  highst number of channels */
+				if (audio_info->modes[index].channel_count >
+		audio_info->modes[max_channe_index].channel_count) {
+					max_channe_index = index;
+				}
+			} else {
+				/* format found, save it's index */
+				found = true;
+				max_channe_index = index;
+			}
+		}
+	}
+
+	/* return index */
+	if (found && format_index != NULL)
+		*format_index = max_channe_index;
+
+	return found;
+}
+
+/* search pixel clock value for HDMI */
+bool dal_audio_hw_ctx_get_audio_clock_info(
+	const struct hw_ctx_audio *hw_ctx,
+	enum dc_color_depth color_depth,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct audio_clock_info *audio_clock_info)
+{
+	const struct audio_clock_info *clock_info;
+	uint32_t index;
+	uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_in_khz / 10;
+	uint32_t audio_array_size;
+
+	if (audio_clock_info == NULL)
+		return false; /* should not happen */
+
+	switch (color_depth) {
+	case COLOR_DEPTH_161616:
+		clock_info = audio_clock_info_table_48bpc;
+		audio_array_size = ARRAY_SIZE(
+				audio_clock_info_table_48bpc);
+		break;
+	case COLOR_DEPTH_121212:
+		clock_info = audio_clock_info_table_36bpc;
+		audio_array_size = ARRAY_SIZE(
+				audio_clock_info_table_36bpc);
+		break;
+	default:
+		clock_info = audio_clock_info_table;
+		audio_array_size = ARRAY_SIZE(
+				audio_clock_info_table);
+		break;
+	}
+
+	if (clock_info != NULL) {
+		/* search for exact pixel clock in table */
+		for (index = 0; index < audio_array_size; index++) {
+			if (clock_info[index].pixel_clock_in_10khz >
+				crtc_pixel_clock_in_10khz)
+				break;  /* not match */
+			else if (clock_info[index].pixel_clock_in_10khz ==
+					crtc_pixel_clock_in_10khz) {
+				/* match found */
+				if (audio_clock_info != NULL) {
+					*audio_clock_info = clock_info[index];
+					return true;
+				}
+			}
+		}
+	}
+
+
+	/* not found */
+	if (actual_pixel_clock_in_khz == 0)
+		actual_pixel_clock_in_khz = crtc_pixel_clock_in_khz;
+
+	/* See HDMI spec  the table entry under
+	 *  pixel clock of "Other". */
+	audio_clock_info->pixel_clock_in_10khz =
+			actual_pixel_clock_in_khz / 10;
+	audio_clock_info->cts_32khz = actual_pixel_clock_in_khz;
+	audio_clock_info->cts_44khz = actual_pixel_clock_in_khz;
+	audio_clock_info->cts_48khz = actual_pixel_clock_in_khz;
+
+	audio_clock_info->n_32khz = 4096;
+	audio_clock_info->n_44khz = 6272;
+	audio_clock_info->n_48khz = 6144;
+
+	return true;
+}
+
+static const struct hw_ctx_audio_funcs funcs = {
+	.destroy = destroy,
+	.setup_audio_wall_dto =
+		setup_audio_wall_dto,
+	.setup_hdmi_audio =
+		setup_hdmi_audio,
+	.setup_dp_audio = setup_dp_audio,
+	.setup_vce_audio = setup_vce_audio,
+	.enable_azalia_audio =
+		enable_azalia_audio,
+	.disable_azalia_audio =
+		disable_azalia_audio,
+	.enable_dp_audio =
+		enable_dp_audio,
+	.disable_dp_audio =
+		disable_dp_audio,
+	.setup_azalia =
+		setup_azalia,
+	.disable_az_clock_gating =
+		disable_az_clock_gating,
+	.unmute_azalia_audio =
+		unmute_azalia_audio,
+	.mute_azalia_audio =
+		mute_azalia_audio,
+	.setup_channel_splitting_mapping =
+		setup_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.hw_initialize =
+		hw_initialize,
+	.enable_gtc_embedding_with_group =
+		enable_gtc_embedding_with_group,
+	.disable_gtc_embedding =
+		disable_gtc_embedding,
+	.get_azalia_clock_info_hdmi =
+		get_azalia_clock_info_hdmi,
+	.get_azalia_clock_info_dp =
+		get_azalia_clock_info_dp,
+};
+/* --- object creator, destroy, construct, destruct --- */
+
+bool dal_audio_construct_hw_ctx_audio(
+	struct hw_ctx_audio *ctx)
+{
+	ctx->funcs = &funcs;
+
+	/* internal variables */
+
+	return true;
+}
+
+void dal_audio_destruct_hw_ctx_audio(
+	struct hw_ctx_audio *ctx)
+{
+	/* nothing to do */
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
new file mode 100644
index 000000000000..8ab2e5851f91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_AUDIO_H__
+#define __DAL_HW_CTX_AUDIO_H__
+
+#include "include/audio_interface.h"
+#include "include/link_service_types.h"
+
+struct hw_ctx_audio;
+
+
+struct azalia_reg_offsets {
+	uint32_t azf0endpointx_azalia_f0_codec_endpoint_index;
+	uint32_t azf0endpointx_azalia_f0_codec_endpoint_data;
+};
+
+/***** hook functions *****/
+
+struct hw_ctx_audio_funcs {
+
+	/* functions for hw_ctx creation */
+	void (*destroy)(
+		struct hw_ctx_audio **ptr);
+
+	/***** from dal2 hwcontextaudio.hpp *****/
+
+	void (*setup_audio_wall_dto)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum signal_type signal,
+		const struct audio_crtc_info *crtc_info,
+		const struct audio_pll_info *pll_info);
+
+	/* MM register access  read_register  write_register */
+
+	/***** from dal2 hwcontextaudio_hal.hpp *****/
+
+	/* setup HDMI audio */
+	void (*setup_hdmi_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		const struct audio_crtc_info *crtc_info);
+
+	/* setup DP audio */
+	void (*setup_dp_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* setup VCE audio */
+	void (*setup_vce_audio)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* enable Azalia audio */
+	void (*enable_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* disable Azalia audio */
+	void (*disable_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* enable DP audio */
+	void (*enable_dp_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* disable DP audio */
+	void (*disable_dp_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* setup Azalia HW block */
+	void (*setup_azalia)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		enum signal_type signal,
+		const struct audio_crtc_info *crtc_info,
+		const struct audio_pll_info *pll_info,
+		const struct audio_info *audio_info);
+
+	/* unmute audio */
+	void (*unmute_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* mute audio */
+	void (*mute_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* enable channel splitting mapping */
+	void (*setup_channel_splitting_mapping)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		enum signal_type signal,
+		const struct audio_channel_associate_info *audio_mapping,
+		bool enable);
+
+	/* get current channel spliting */
+	bool (*get_channel_splitting_mapping)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		struct audio_channel_associate_info *audio_mapping);
+
+	/* set the payload value for the unsolicited response */
+	void (*set_unsolicited_response_payload)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum audio_payload payload);
+
+	/* initialize HW state */
+	void (*hw_initialize)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* check_audio_bandwidth */
+
+	/* Assign GTC group and enable GTC value embedding */
+	void (*enable_gtc_embedding_with_group)(
+		const struct hw_ctx_audio *hw_ctx,
+		uint32_t groupNum,
+		uint32_t audioLatency);
+
+	/* Disable GTC value embedding */
+	void (*disable_gtc_embedding)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* Disable Azalia Clock Gating Feature */
+	void (*disable_az_clock_gating)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* ~~~~  protected: ~~~~*/
+
+	/* calc_max_audio_packets_per_line */
+	/* speakers_to_channels */
+	/* is_audio_format_supported */
+	/* get_audio_clock_info */
+
+	/* search pixel clock value for Azalia HDMI Audio */
+	bool (*get_azalia_clock_info_hdmi)(
+		const struct hw_ctx_audio *hw_ctx,
+		uint32_t crtc_pixel_clock_in_khz,
+		uint32_t actual_pixel_clock_in_khz,
+		struct azalia_clock_info *azalia_clock_info);
+
+	/* search pixel clock value for Azalia DP Audio */
+	bool (*get_azalia_clock_info_dp)(
+		const struct hw_ctx_audio *hw_ctx,
+		uint32_t requested_pixel_clock_in_khz,
+		const struct audio_pll_info *pll_info,
+		struct azalia_clock_info *azalia_clock_info);
+
+	void (*enable_afmt_clock)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		bool enable);
+
+	/* @@@@   private:  @@@@  */
+
+	/* check_audio_bandwidth_hdmi  */
+	/* check_audio_bandwidth_dpsst */
+	/* check_audio_bandwidth_dpmst */
+
+};
+
+
+struct hw_ctx_audio {
+	const struct hw_ctx_audio_funcs *funcs;
+	struct dc_context *ctx;
+
+	/*audio_clock_infoTable[12];
+	 *audio_clock_infoTable_36bpc[12];
+	 *audio_clock_infoTable_48bpc[12];
+	 *used by hw_ctx_audio.c file only. Will declare as static array
+	 *azaliaclockinfoTable[12]  -- not used
+	 *BusNumberMask;   BusNumberShift; DeviceNumberMask;
+	 *not used by dce6 and after
+	 */
+};
+
+
+
+/* --- object construct, destruct --- */
+
+/*
+ *called by derived audio object for specific ASIC. In case no derived object,
+ *these two functions do not need exposed.
+ */
+bool dal_audio_construct_hw_ctx_audio(
+	struct hw_ctx_audio *hw_ctx);
+
+void dal_audio_destruct_hw_ctx_audio(
+	struct hw_ctx_audio *hw_ctx);
+
+/*
+ *creator of audio HW context will be implemented by specific ASIC object only.
+ *Top base or interface object does not have implementation of creator.
+ */
+
+
+/* --- functions called by audio hw context itself --- */
+
+/* MM register access */
+/*read_register  - dal_read_reg */
+/*write_register - dal_write_reg*/
+
+
+/*check whether specified sample rates can fit into a given timing */
+void dal_hw_ctx_audio_check_audio_bandwidth(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates);
+
+/*For HDMI, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates);
+
+/*For DPSST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpsst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates);
+
+/*For DPMST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpmst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates);
+
+/* calculate max number of Audio packets per line */
+uint32_t dal_audio_hw_ctx_calc_max_audio_packets_per_line(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info);
+
+/* translate speakers to channels */
+union audio_cea_channels dal_audio_hw_ctx_speakers_to_channels(
+	const struct hw_ctx_audio *hw_ctx,
+	struct audio_speaker_flags speaker_flags);
+
+/* check whether specified audio format supported */
+bool dal_audio_hw_ctx_is_audio_format_supported(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_info *audio_info,
+	enum audio_format_code audio_format_code,
+	uint32_t *format_index);
+
+/* search pixel clock value for HDMI */
+bool dal_audio_hw_ctx_get_audio_clock_info(
+	const struct hw_ctx_audio *hw_ctx,
+	enum dc_color_depth color_depth,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct audio_clock_info *audio_clock_info);
+
+
+#endif  /* __DAL_HW_CTX_AUDIO_H__ */
+
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 12/29] drm/amd/dal: Bandwidth calculations
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (10 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 11/29] drm/amd/dal: Audio Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 13/29] drm/amd/dal: Add encoder HW programming Harry Wentland
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/calcs/Makefile          |   10 +
 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 3941 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c        |  300 ++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c   | 1992 ++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h   |   74 +
 5 files changed, 6317 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h

diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/Makefile b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile
new file mode 100644
index 000000000000..7f1916b79b88
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the 'calcs' sub-component of DAL.
+# It calculates Bandwidth and Watermarks values for HW programming
+#
+
+BW_CALCS = bandwidth_calcs.o bw_fixed.o scaler_filter.o
+
+AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS))
+
+AMD_DAL_FILES += $(AMD_DAL_BW_CALCS)
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
new file mode 100644
index 000000000000..8faabbc12fd3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
@@ -0,0 +1,3941 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "bandwidth_calcs.h"
+
+/*******************************************************************************
+ * Private Functions
+ ******************************************************************************/
+
+static void calculate_bandwidth(
+	const struct bw_calcs_dceip *dceip,
+	const struct bw_calcs_vbios *vbios,
+	const struct bw_calcs_mode_data_internal *mode_data,
+	struct bw_calcs_results *results)
+
+{
+	const int32_t pixels_per_chunk = 512;
+	const int32_t max_chunks_non_fbc_mode = 16;
+	const int32_t high = 2;
+	const int32_t mid = 1;
+	const int32_t low = 0;
+
+	int32_t i, j, k;
+	struct bw_fixed yclk[3];
+	struct bw_fixed sclk[3];
+	bool d0_underlay_enable;
+	bool d1_underlay_enable;
+	enum bw_defines sclk_message;
+	enum bw_defines yclk_message;
+	enum bw_defines v_filter_init_mode[maximum_number_of_surfaces];
+	enum bw_defines tiling_mode[maximum_number_of_surfaces];
+	enum bw_defines stereo_mode[maximum_number_of_surfaces];
+	enum bw_defines surface_type[maximum_number_of_surfaces];
+	enum bw_defines voltage;
+	enum bw_defines pipe_check;
+	enum bw_defines hsr_check;
+	enum bw_defines vsr_check;
+	enum bw_defines lb_size_check;
+	enum bw_defines fbc_check;
+	enum bw_defines rotation_check;
+	enum bw_defines mode_check;
+
+	yclk[low] = vbios->low_yclk;
+	yclk[mid] = vbios->high_yclk;
+	yclk[high] = vbios->high_yclk;
+	sclk[low] = vbios->low_sclk;
+	sclk[mid] = vbios->mid_sclk;
+	sclk[high] = vbios->high_sclk;
+	/* surface assignment:*/
+	/* 0: d0 underlay or underlay luma*/
+	/* 1: d0 underlay chroma*/
+	/* 2: d1 underlay or underlay luma*/
+	/* 3: d1 underlay chroma*/
+	/* 4: d0 graphics*/
+	/* 5: d1 graphics*/
+	/* 6: d2 graphics*/
+	/* 7: d3 graphics, same mode as d2*/
+	/* 8: d4 graphics, same mode as d2*/
+	/* 9: d5 graphics, same mode as d2*/
+	/* ...*/
+	/* maximum_number_of_surfaces-2: d1 display_write_back420 luma*/
+	/* maximum_number_of_surfaces-1: d1 display_write_back420 chroma*/
+	/* underlay luma and chroma surface parameters from spreadsheet*/
+	if (mode_data->d0_underlay_mode == bw_def_none) {
+		d0_underlay_enable = 0;
+	} else {
+		d0_underlay_enable = 1;
+	}
+	if (mode_data->d1_underlay_mode == bw_def_none) {
+		d1_underlay_enable = 0;
+	} else {
+		d1_underlay_enable = 1;
+	}
+	results->number_of_underlay_surfaces = d0_underlay_enable
+		+ d1_underlay_enable;
+	switch (mode_data->underlay_surface_type) {
+	case bw_def_420:
+		surface_type[0] = bw_def_underlay420_luma;
+		surface_type[2] = bw_def_underlay420_luma;
+		results->bytes_per_pixel[0] = 1;
+		results->bytes_per_pixel[2] = 1;
+		surface_type[1] = bw_def_underlay420_chroma;
+		surface_type[3] = bw_def_underlay420_chroma;
+		results->bytes_per_pixel[1] = 2;
+		results->bytes_per_pixel[3] = 2;
+		results->lb_size_per_component[0] =
+			dceip->underlay420_luma_lb_size_per_component;
+		results->lb_size_per_component[1] =
+			dceip->underlay420_chroma_lb_size_per_component;
+		results->lb_size_per_component[2] =
+			dceip->underlay420_luma_lb_size_per_component;
+		results->lb_size_per_component[3] =
+			dceip->underlay420_chroma_lb_size_per_component;
+		break;
+	case bw_def_422:
+		surface_type[0] = bw_def_underlay422;
+		surface_type[2] = bw_def_underlay422;
+		results->bytes_per_pixel[0] = 2;
+		results->bytes_per_pixel[2] = 2;
+		results->lb_size_per_component[0] =
+			dceip->underlay422_lb_size_per_component;
+		results->lb_size_per_component[2] =
+			dceip->underlay422_lb_size_per_component;
+		break;
+	default:
+		surface_type[0] = bw_def_underlay444;
+		surface_type[2] = bw_def_underlay444;
+		results->bytes_per_pixel[0] = 4;
+		results->bytes_per_pixel[2] = 4;
+		results->lb_size_per_component[0] =
+			dceip->lb_size_per_component444;
+		results->lb_size_per_component[2] =
+			dceip->lb_size_per_component444;
+		break;
+	}
+	if (d0_underlay_enable) {
+		switch (mode_data->underlay_surface_type) {
+		case bw_def_420:
+			results->enable[0] = 1;
+			results->enable[1] = 1;
+			break;
+		default:
+			results->enable[0] = 1;
+			results->enable[1] = 0;
+			break;
+		}
+	} else {
+		results->enable[0] = 0;
+		results->enable[1] = 0;
+	}
+	if (d1_underlay_enable) {
+		switch (mode_data->underlay_surface_type) {
+		case bw_def_420:
+			results->enable[2] = 1;
+			results->enable[3] = 1;
+			break;
+		default:
+			results->enable[2] = 1;
+			results->enable[3] = 0;
+			break;
+		}
+	} else {
+		results->enable[2] = 0;
+		results->enable[3] = 0;
+	}
+	results->use_alpha[0] = 0;
+	results->use_alpha[1] = 0;
+	results->use_alpha[2] = 0;
+	results->use_alpha[3] = 0;
+	results->scatter_gather_enable_for_pipe[0] =
+		vbios->scatter_gather_enable;
+	results->scatter_gather_enable_for_pipe[1] =
+		vbios->scatter_gather_enable;
+	results->scatter_gather_enable_for_pipe[2] =
+		vbios->scatter_gather_enable;
+	results->scatter_gather_enable_for_pipe[3] =
+		vbios->scatter_gather_enable;
+	results->interlace_mode[0] = mode_data->graphics_interlace_mode;
+	results->interlace_mode[1] = mode_data->graphics_interlace_mode;
+	results->interlace_mode[2] = mode_data->graphics_interlace_mode;
+	results->interlace_mode[3] = mode_data->graphics_interlace_mode;
+	results->h_total[0] = bw_int_to_fixed(mode_data->d0_htotal);
+	results->h_total[1] = bw_int_to_fixed(mode_data->d0_htotal);
+	results->h_total[2] = bw_int_to_fixed(mode_data->d1_htotal);
+	results->h_total[3] = bw_int_to_fixed(mode_data->d1_htotal);
+	results->pixel_rate[0] = mode_data->d0_pixel_rate;
+	results->pixel_rate[1] = mode_data->d0_pixel_rate;
+	results->pixel_rate[2] = mode_data->d1_pixel_rate;
+	results->pixel_rate[3] = mode_data->d1_pixel_rate;
+	results->src_width[0] = bw_int_to_fixed(mode_data->underlay_src_width);
+	results->src_width[1] = bw_int_to_fixed(mode_data->underlay_src_width);
+	results->src_width[2] = bw_int_to_fixed(mode_data->underlay_src_width);
+	results->src_width[3] = bw_int_to_fixed(mode_data->underlay_src_width);
+	results->src_height[0] = bw_int_to_fixed(
+		mode_data->underlay_src_height);
+	results->src_height[1] = bw_int_to_fixed(
+		mode_data->underlay_src_height);
+	results->src_height[2] = bw_int_to_fixed(
+		mode_data->underlay_src_height);
+	results->src_height[3] = bw_int_to_fixed(
+		mode_data->underlay_src_height);
+	results->pitch_in_pixels[0] = bw_int_to_fixed(
+		mode_data->underlay_pitch_in_pixels);
+	results->pitch_in_pixels[1] = bw_int_to_fixed(
+		mode_data->underlay_pitch_in_pixels);
+	results->pitch_in_pixels[2] = bw_int_to_fixed(
+		mode_data->underlay_pitch_in_pixels);
+	results->pitch_in_pixels[3] = bw_int_to_fixed(
+		mode_data->underlay_pitch_in_pixels);
+	results->scale_ratio[0] = mode_data->d0_underlay_scale_ratio;
+	results->scale_ratio[1] = mode_data->d0_underlay_scale_ratio;
+	results->scale_ratio[2] = mode_data->d1_underlay_scale_ratio;
+	results->scale_ratio[3] = mode_data->d1_underlay_scale_ratio;
+	results->h_taps[0] = bw_int_to_fixed(mode_data->underlay_htaps);
+	results->h_taps[1] = bw_int_to_fixed(mode_data->underlay_htaps);
+	results->h_taps[2] = bw_int_to_fixed(mode_data->underlay_htaps);
+	results->h_taps[3] = bw_int_to_fixed(mode_data->underlay_htaps);
+	results->v_taps[0] = bw_int_to_fixed(mode_data->underlay_vtaps);
+	results->v_taps[1] = bw_int_to_fixed(mode_data->underlay_vtaps);
+	results->v_taps[2] = bw_int_to_fixed(mode_data->underlay_vtaps);
+	results->v_taps[3] = bw_int_to_fixed(mode_data->underlay_vtaps);
+	results->rotation_angle[0] = bw_int_to_fixed(
+		mode_data->underlay_rotation_angle);
+	results->rotation_angle[1] = bw_int_to_fixed(
+		mode_data->underlay_rotation_angle);
+	results->rotation_angle[2] = bw_int_to_fixed(
+		mode_data->underlay_rotation_angle);
+	results->rotation_angle[3] = bw_int_to_fixed(
+		mode_data->underlay_rotation_angle);
+	if (mode_data->underlay_tiling_mode == bw_def_linear) {
+		tiling_mode[0] = bw_def_linear;
+		tiling_mode[1] = bw_def_linear;
+		tiling_mode[2] = bw_def_linear;
+		tiling_mode[3] = bw_def_linear;
+	} else {
+		tiling_mode[0] = bw_def_landscape;
+		tiling_mode[1] = bw_def_landscape;
+		tiling_mode[2] = bw_def_landscape;
+		tiling_mode[3] = bw_def_landscape;
+	}
+	stereo_mode[0] = mode_data->underlay_stereo_mode;
+	stereo_mode[1] = mode_data->underlay_stereo_mode;
+	stereo_mode[2] = mode_data->underlay_stereo_mode;
+	stereo_mode[3] = mode_data->underlay_stereo_mode;
+	results->lb_bpc[0] = mode_data->underlay_lb_bpc;
+	results->lb_bpc[1] = mode_data->underlay_lb_bpc;
+	results->lb_bpc[2] = mode_data->underlay_lb_bpc;
+	results->lb_bpc[3] = mode_data->underlay_lb_bpc;
+	results->compression_rate[0] = bw_int_to_fixed(1);
+	results->compression_rate[1] = bw_int_to_fixed(1);
+	results->compression_rate[2] = bw_int_to_fixed(1);
+	results->compression_rate[3] = bw_int_to_fixed(1);
+	results->access_one_channel_only[0] = 0;
+	results->access_one_channel_only[1] = 0;
+	results->access_one_channel_only[2] = 0;
+	results->access_one_channel_only[3] = 0;
+	results->cursor_width_pixels[0] = bw_int_to_fixed(0);
+	results->cursor_width_pixels[1] = bw_int_to_fixed(0);
+	results->cursor_width_pixels[2] = bw_int_to_fixed(0);
+	results->cursor_width_pixels[3] = bw_int_to_fixed(0);
+	/* graphics surface parameters from spreadsheet*/
+	for (i = 4; i <= maximum_number_of_surfaces - 3; i++) {
+		if (i < mode_data->number_of_displays + 4) {
+			if (i == 4
+				&& mode_data->d0_underlay_mode
+					== bw_def_underlay_only) {
+				results->enable[i] = 0;
+				results->use_alpha[i] = 0;
+			} else if (i == 4
+				&& mode_data->d0_underlay_mode
+					== bw_def_blend) {
+				results->enable[i] = 1;
+				results->use_alpha[i] = 1;
+			} else if (i == 4) {
+				results->enable[i] = 1;
+				results->use_alpha[i] = 0;
+			} else if (i == 5
+				&& mode_data->d1_underlay_mode
+					== bw_def_underlay_only) {
+				results->enable[i] = 0;
+				results->use_alpha[i] = 0;
+			} else if (i == 5
+				&& mode_data->d1_underlay_mode
+					== bw_def_blend) {
+				results->enable[i] = 1;
+				results->use_alpha[i] = 1;
+			} else {
+				results->enable[i] = 1;
+				results->use_alpha[i] = 0;
+			}
+		} else {
+			results->enable[i] = 0;
+			results->use_alpha[i] = 0;
+		}
+		results->scatter_gather_enable_for_pipe[i] =
+			vbios->scatter_gather_enable;
+		surface_type[i] = bw_def_graphics;
+		results->lb_size_per_component[i] =
+			dceip->lb_size_per_component444;
+		results->bytes_per_pixel[i] =
+			mode_data->graphics_bytes_per_pixel;
+		results->interlace_mode[i] = mode_data->graphics_interlace_mode;
+		results->h_taps[i] = bw_int_to_fixed(mode_data->graphics_htaps);
+		results->v_taps[i] = bw_int_to_fixed(mode_data->graphics_vtaps);
+		results->rotation_angle[i] = bw_int_to_fixed(
+			mode_data->graphics_rotation_angle);
+		if (mode_data->graphics_tiling_mode == bw_def_linear) {
+			tiling_mode[i] = bw_def_linear;
+		} else if (mode_data->graphics_rotation_angle == 0
+			|| mode_data->graphics_rotation_angle == 180) {
+			tiling_mode[i] = bw_def_landscape;
+		} else {
+			tiling_mode[i] = bw_def_portrait;
+		}
+		results->lb_bpc[i] = mode_data->graphics_lb_bpc;
+		if (i == 4) {
+			if (mode_data->d0_fbc_enable
+				&& (dceip->argb_compression_support
+					|| mode_data->d0_underlay_mode
+						!= bw_def_blended)) {
+				results->compression_rate[i] = bw_int_to_fixed(
+					vbios->average_compression_rate);
+				results->access_one_channel_only[i] =
+					mode_data->d0_lpt_enable;
+			} else {
+				results->compression_rate[i] = bw_int_to_fixed(
+					1);
+				results->access_one_channel_only[i] = 0;
+			}
+			results->h_total[i] = bw_int_to_fixed(
+				mode_data->d0_htotal);
+			results->pixel_rate[i] = mode_data->d0_pixel_rate;
+			results->src_width[i] = bw_int_to_fixed(
+				mode_data->d0_graphics_src_width);
+			results->src_height[i] = bw_int_to_fixed(
+				mode_data->d0_graphics_src_height);
+			results->pitch_in_pixels[i] = bw_int_to_fixed(
+				mode_data->d0_graphics_src_width);
+			results->scale_ratio[i] =
+				mode_data->d0_graphics_scale_ratio;
+			stereo_mode[i] = mode_data->d0_graphics_stereo_mode;
+		} else if (i == 5) {
+			results->compression_rate[i] = bw_int_to_fixed(1);
+			results->access_one_channel_only[i] = 0;
+			results->h_total[i] = bw_int_to_fixed(
+				mode_data->d1_htotal);
+			results->pixel_rate[i] = mode_data->d1_pixel_rate;
+			results->src_width[i] = bw_int_to_fixed(
+				mode_data->d1_graphics_src_width);
+			results->src_height[i] = bw_int_to_fixed(
+				mode_data->d1_graphics_src_height);
+			results->pitch_in_pixels[i] = bw_int_to_fixed(
+				mode_data->d1_graphics_src_width);
+			results->scale_ratio[i] =
+				mode_data->d1_graphics_scale_ratio;
+			stereo_mode[i] = mode_data->d1_graphics_stereo_mode;
+		} else {
+			results->compression_rate[i] = bw_int_to_fixed(1);
+			results->access_one_channel_only[i] = 0;
+			results->h_total[i] = bw_int_to_fixed(
+				mode_data->d2_htotal);
+			results->pixel_rate[i] = mode_data->d2_pixel_rate;
+			results->src_width[i] = bw_int_to_fixed(
+				mode_data->d2_graphics_src_width);
+			results->src_height[i] = bw_int_to_fixed(
+				mode_data->d2_graphics_src_height);
+			results->pitch_in_pixels[i] = bw_int_to_fixed(
+				mode_data->d2_graphics_src_width);
+			results->scale_ratio[i] =
+				mode_data->d2_graphics_scale_ratio;
+			stereo_mode[i] = mode_data->d2_graphics_stereo_mode;
+		}
+		results->cursor_width_pixels[i] = bw_int_to_fixed(
+			vbios->cursor_width);
+	}
+	/* display_write_back420*/
+	results->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 2] =
+		0;
+	results->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 1] =
+		0;
+	if (mode_data->d1_display_write_back_dwb_enable == 1) {
+		results->enable[maximum_number_of_surfaces - 2] = 1;
+		results->enable[maximum_number_of_surfaces - 1] = 1;
+	} else {
+		results->enable[maximum_number_of_surfaces - 2] = 0;
+		results->enable[maximum_number_of_surfaces - 1] = 0;
+	}
+	surface_type[maximum_number_of_surfaces - 2] =
+		bw_def_display_write_back420_luma;
+	surface_type[maximum_number_of_surfaces - 1] =
+		bw_def_display_write_back420_chroma;
+	results->lb_size_per_component[maximum_number_of_surfaces - 2] =
+		dceip->underlay420_luma_lb_size_per_component;
+	results->lb_size_per_component[maximum_number_of_surfaces - 1] =
+		dceip->underlay420_chroma_lb_size_per_component;
+	results->bytes_per_pixel[maximum_number_of_surfaces - 2] = 1;
+	results->bytes_per_pixel[maximum_number_of_surfaces - 1] = 2;
+	results->interlace_mode[maximum_number_of_surfaces - 2] =
+		mode_data->graphics_interlace_mode;
+	results->interlace_mode[maximum_number_of_surfaces - 1] =
+		mode_data->graphics_interlace_mode;
+	results->h_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
+	results->h_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
+	results->v_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
+	results->v_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
+	results->rotation_angle[maximum_number_of_surfaces - 2] =
+		bw_int_to_fixed(0);
+	results->rotation_angle[maximum_number_of_surfaces - 1] =
+		bw_int_to_fixed(0);
+	tiling_mode[maximum_number_of_surfaces - 2] = bw_def_linear;
+	tiling_mode[maximum_number_of_surfaces - 1] = bw_def_linear;
+	results->lb_bpc[maximum_number_of_surfaces - 2] = 8;
+	results->lb_bpc[maximum_number_of_surfaces - 1] = 8;
+	results->compression_rate[maximum_number_of_surfaces - 2] =
+		bw_int_to_fixed(1);
+	results->compression_rate[maximum_number_of_surfaces - 1] =
+		bw_int_to_fixed(1);
+	results->access_one_channel_only[maximum_number_of_surfaces - 2] = 0;
+	results->access_one_channel_only[maximum_number_of_surfaces - 1] = 0;
+	results->h_total[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+		mode_data->d1_htotal);
+	results->h_total[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+		mode_data->d1_htotal);
+	results->pixel_rate[maximum_number_of_surfaces - 2] =
+		mode_data->d1_pixel_rate;
+	results->pixel_rate[maximum_number_of_surfaces - 1] =
+		mode_data->d1_pixel_rate;
+	results->src_width[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+		mode_data->d1_graphics_src_width);
+	results->src_width[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+		mode_data->d1_graphics_src_width);
+	results->src_height[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+		mode_data->d1_graphics_src_height);
+	results->src_height[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+		mode_data->d1_graphics_src_height);
+	results->pitch_in_pixels[maximum_number_of_surfaces - 2] =
+		bw_int_to_fixed(mode_data->d1_graphics_src_width);
+	results->pitch_in_pixels[maximum_number_of_surfaces - 1] =
+		bw_int_to_fixed(mode_data->d1_graphics_src_width);
+	results->scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+		1);
+	results->scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+		1);
+	stereo_mode[maximum_number_of_surfaces - 2] = bw_def_mono;
+	stereo_mode[maximum_number_of_surfaces - 1] = bw_def_mono;
+	results->cursor_width_pixels[maximum_number_of_surfaces - 2] =
+		bw_int_to_fixed(0);
+	results->cursor_width_pixels[maximum_number_of_surfaces - 1] =
+		bw_int_to_fixed(0);
+	results->use_alpha[maximum_number_of_surfaces - 2] = 0;
+	results->use_alpha[maximum_number_of_surfaces - 1] = 0;
+	/*mode check calculations:*/
+	/* mode within dce ip capabilities*/
+	/* fbc*/
+	/* hsr*/
+	/* vsr*/
+	/* lb size*/
+	/*effective scaling source and ratios:*/
+	/*for graphics, non-stereo, non-interlace surfaces when the size of the source and destination are the same, only one tap is used*/
+	/*420 chroma has half the width, height, horizontal and vertical scaling ratios than luma*/
+	/*rotating an underlay surface swaps the width, height, horizontal and vertical scaling ratios*/
+	/*in top-bottom stereo mode there is 2:1 vertical downscaling for each eye*/
+	/*in side-by-side stereo mode there is 2:1 horizontal downscaling for each eye*/
+	/*in interlace mode there is 2:1 vertical downscaling for each field*/
+	/*in panning or bezel adjustment mode the source width has an extra 128 pixels*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_equ(results->scale_ratio[i], bw_int_to_fixed(1))
+				&& surface_type[i] == bw_def_graphics
+				&& stereo_mode[i] == bw_def_mono
+				&& results->interlace_mode[i] == 0) {
+				results->h_taps[i] = bw_int_to_fixed(1);
+				results->v_taps[i] = bw_int_to_fixed(1);
+			}
+			if (surface_type[i]
+				== bw_def_display_write_back420_chroma
+				|| surface_type[i]
+					== bw_def_underlay420_chroma) {
+				results->pitch_in_pixels_after_surface_type[i] =
+					bw_div(
+						results->pitch_in_pixels[i],
+						bw_int_to_fixed(2));
+				results->src_width_after_surface_type = bw_div(
+					results->src_width[i],
+					bw_int_to_fixed(2));
+				results->src_height_after_surface_type = bw_div(
+					results->src_height[i],
+					bw_int_to_fixed(2));
+				results->hsr_after_surface_type = bw_div(
+					results->scale_ratio[i],
+					bw_int_to_fixed(2));
+				results->vsr_after_surface_type = bw_div(
+					results->scale_ratio[i],
+					bw_int_to_fixed(2));
+			} else {
+				results->pitch_in_pixels_after_surface_type[i] =
+					results->pitch_in_pixels[i];
+				results->src_width_after_surface_type =
+					results->src_width[i];
+				results->src_height_after_surface_type =
+					results->src_height[i];
+				results->hsr_after_surface_type =
+					results->scale_ratio[i];
+				results->vsr_after_surface_type =
+					results->scale_ratio[i];
+			}
+			if ((bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(90))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(270)))
+				&& surface_type[i] != bw_def_graphics) {
+				results->src_width_after_rotation =
+					results->src_height_after_surface_type;
+				results->src_height_after_rotation =
+					results->src_width_after_surface_type;
+				results->hsr_after_rotation =
+					results->vsr_after_surface_type;
+				results->vsr_after_rotation =
+					results->hsr_after_surface_type;
+			} else {
+				results->src_width_after_rotation =
+					results->src_width_after_surface_type;
+				results->src_height_after_rotation =
+					results->src_height_after_surface_type;
+				results->hsr_after_rotation =
+					results->hsr_after_surface_type;
+				results->vsr_after_rotation =
+					results->vsr_after_surface_type;
+			}
+			switch (stereo_mode[i]) {
+			case bw_def_top_bottom:
+				results->source_width_pixels[i] =
+					results->src_width_after_rotation;
+				results->source_height_pixels = bw_mul(
+					bw_int_to_fixed(2),
+					results->src_height_after_rotation);
+				results->hsr_after_stereo =
+					results->hsr_after_rotation;
+				results->vsr_after_stereo = bw_mul(
+					bw_int_to_fixed(1),
+					results->vsr_after_rotation);
+				break;
+			case bw_def_side_by_side:
+				results->source_width_pixels[i] = bw_mul(
+					bw_int_to_fixed(2),
+					results->src_width_after_rotation);
+				results->source_height_pixels =
+					results->src_height_after_rotation;
+				results->hsr_after_stereo = bw_mul(
+					bw_int_to_fixed(1),
+					results->hsr_after_rotation);
+				results->vsr_after_stereo =
+					results->vsr_after_rotation;
+				break;
+			default:
+				results->source_width_pixels[i] =
+					results->src_width_after_rotation;
+				results->source_height_pixels =
+					results->src_height_after_rotation;
+				results->hsr_after_stereo =
+					results->hsr_after_rotation;
+				results->vsr_after_stereo =
+					results->vsr_after_rotation;
+				break;
+			}
+			results->hsr[i] = results->hsr_after_stereo;
+			if (results->interlace_mode[i]) {
+				results->vsr[i] = bw_mul(
+					results->vsr_after_stereo,
+					bw_int_to_fixed(2));
+			} else {
+				results->vsr[i] = results->vsr_after_stereo;
+			}
+			if (mode_data->panning_and_bezel_adjustment
+				!= bw_def_none) {
+				results->source_width_rounded_up_to_chunks[i] =
+					bw_add(
+						bw_floor2(
+							bw_sub(
+								results->source_width_pixels[i],
+								bw_int_to_fixed(
+									1)),
+							bw_int_to_fixed(128)),
+						bw_int_to_fixed(256));
+			} else {
+				results->source_width_rounded_up_to_chunks[i] =
+					bw_ceil2(
+						results->source_width_pixels[i],
+						bw_int_to_fixed(128));
+			}
+			results->source_height_rounded_up_to_chunks[i] =
+				results->source_height_pixels;
+		}
+	}
+	/*mode support checks:*/
+	/*the number of graphics and underlay pipes is limited by the ip support*/
+	/*maximum horizontal and vertical scale ratio is 4, and should not exceed the number of taps*/
+	/*for downscaling with the pre-downscaler, the horizontal scale ratio must be more than the ceiling of one quarter of the number of taps*/
+	/*the pre-downscaler reduces the line buffer source by the horizontal scale ratio*/
+	/*the number of lines in the line buffer has to exceed the number of vertical taps*/
+	/*the size of the line in the line buffer is the product of the source width and the bits per component, rounded up to a multiple of 48*/
+	/*the size of the line in the line buffer in the case of 10 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/
+	/*the size of the line in the line buffer in the case of 8 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/
+	/*frame buffer compression is not supported with stereo mode, rotation, or non- 888 formats*/
+	/*rotation is not supported with linear of stereo modes*/
+	if (dceip->number_of_graphics_pipes >= mode_data->number_of_displays
+		&& dceip->number_of_underlay_pipes
+			>= results->number_of_underlay_surfaces
+		&& !(dceip->display_write_back_supported == 0
+			&& mode_data->d1_display_write_back_dwb_enable == 1)) {
+		pipe_check = bw_def_ok;
+	} else {
+		pipe_check = bw_def_notok;
+	}
+	hsr_check = bw_def_ok;
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_neq(results->hsr[i], bw_int_to_fixed(1))) {
+				if (bw_mtn(
+					results->hsr[i],
+					bw_int_to_fixed(4))) {
+					hsr_check = bw_def_hsr_mtn_4;
+				} else {
+					if (bw_mtn(
+						results->hsr[i],
+						results->h_taps[i])) {
+						hsr_check =
+							bw_def_hsr_mtn_h_taps;
+					} else {
+						if (dceip->pre_downscaler_enabled
+							== 1
+							&& bw_mtn(
+								results->hsr[i],
+								bw_int_to_fixed(
+									1))
+							&& bw_leq(
+								results->hsr[i],
+								bw_ceil2(
+									bw_div(
+										results->h_taps[i],
+										bw_int_to_fixed(
+											4)),
+									bw_int_to_fixed(
+										1)))) {
+							hsr_check =
+								bw_def_ceiling__h_taps_div_4___meq_hsr;
+						}
+					}
+				}
+			}
+		}
+	}
+	vsr_check = bw_def_ok;
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_neq(results->vsr[i], bw_int_to_fixed(1))) {
+				if (bw_mtn(
+					results->vsr[i],
+					bw_int_to_fixed(4))) {
+					vsr_check = bw_def_vsr_mtn_4;
+				} else {
+					if (bw_mtn(
+						results->vsr[i],
+						results->v_taps[i])) {
+						vsr_check =
+							bw_def_vsr_mtn_v_taps;
+					}
+				}
+			}
+		}
+	}
+	lb_size_check = bw_def_ok;
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if ((dceip->pre_downscaler_enabled
+				&& bw_mtn(results->hsr[i], bw_int_to_fixed(1)))) {
+				results->source_width_in_lb = bw_div(
+					results->source_width_pixels[i],
+					results->hsr[i]);
+			} else {
+				results->source_width_in_lb =
+					results->source_width_pixels[i];
+			}
+			switch (results->lb_bpc[i]) {
+			case 8:
+				results->lb_line_pitch =
+					bw_ceil2(
+						bw_mul(
+							bw_div(
+								bw_frc_to_fixed(
+									2401171875ULL,
+									100000000),
+								bw_int_to_fixed(
+									3)),
+							bw_ceil2(
+								results->source_width_in_lb,
+								bw_int_to_fixed(
+									8))),
+						bw_int_to_fixed(48));
+				break;
+			case 10:
+				results->lb_line_pitch =
+					bw_ceil2(
+						bw_mul(
+							bw_div(
+								bw_frc_to_fixed(
+									300234375,
+									10000000),
+								bw_int_to_fixed(
+									3)),
+							bw_ceil2(
+								results->source_width_in_lb,
+								bw_int_to_fixed(
+									8))),
+						bw_int_to_fixed(48));
+				break;
+			default:
+				results->lb_line_pitch = bw_ceil2(
+					bw_mul(
+						bw_int_to_fixed(
+							results->lb_bpc[i]),
+						results->source_width_in_lb),
+					bw_int_to_fixed(48));
+				break;
+			}
+			results->lb_partitions[i] = bw_floor2(
+				bw_div(
+					results->lb_size_per_component[i],
+					results->lb_line_pitch),
+				bw_int_to_fixed(1));
+			/*clamp the partitions to the maxium number supported by the lb*/
+			if ((surface_type[i] != bw_def_graphics
+				|| dceip->graphics_lb_nodownscaling_multi_line_prefetching
+					== 1)) {
+				results->lb_partitions_max[i] = bw_int_to_fixed(
+					10);
+			} else {
+				results->lb_partitions_max[i] = bw_int_to_fixed(
+					7);
+			}
+			results->lb_partitions[i] = bw_min2(
+				results->lb_partitions_max[i],
+				results->lb_partitions[i]);
+			if (bw_mtn(
+				bw_add(results->v_taps[i], bw_int_to_fixed(1)),
+				results->lb_partitions[i])) {
+				lb_size_check = bw_def_notok;
+			}
+		}
+	}
+	if (mode_data->d0_fbc_enable
+		&& (mode_data->graphics_rotation_angle == 90
+			|| mode_data->graphics_rotation_angle == 270
+			|| mode_data->d0_graphics_stereo_mode != bw_def_mono
+			|| mode_data->graphics_bytes_per_pixel != 4)) {
+		fbc_check = bw_def_invalid_rotation_or_bpp_or_stereo;
+	} else {
+		fbc_check = bw_def_ok;
+	}
+	rotation_check = bw_def_ok;
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if ((bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(90))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(270)))
+				&& (tiling_mode[i] == bw_def_linear
+					|| stereo_mode[i] != bw_def_mono)) {
+				rotation_check =
+					bw_def_invalid_linear_or_stereo_mode;
+			}
+		}
+	}
+	if (pipe_check == bw_def_ok && hsr_check == bw_def_ok
+		&& vsr_check == bw_def_ok && lb_size_check == bw_def_ok
+		&& fbc_check == bw_def_ok && rotation_check == bw_def_ok) {
+		mode_check = bw_def_ok;
+	} else {
+		mode_check = bw_def_notok;
+	}
+	/*memory request size and latency hiding:*/
+	/*request size is normally 64 byte, 2-line interleaved, with full latency hiding*/
+	/*the display write-back requests are single line*/
+	/*for tiled graphics surfaces, or undelay surfaces with width higher than the maximum size for full efficiency, request size is 32 byte in 8 and 16 bpp or if the rotation is orthogonal to the tiling grain. only half is useful of the bytes in the request size in 8 bpp or in 32 bpp if the rotation is orthogonal to the tiling grain.*/
+	/*for undelay surfaces with width lower than the maximum size for full efficiency, requests are 4-line interleaved in 16bpp if the rotation is parallel to the tiling grain, and 8-line interleaved with 4-line latency hiding in 8bpp or if the rotation is orthogonal to the tiling grain.*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if ((bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(90))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(270)))) {
+				if ((tiling_mode[i] == bw_def_portrait)) {
+					results->orthogonal_rotation[i] = 0;
+				} else {
+					results->orthogonal_rotation[i] = 1;
+				}
+			} else {
+				if ((tiling_mode[i] == bw_def_portrait)) {
+					results->orthogonal_rotation[i] = 1;
+				} else {
+					results->orthogonal_rotation[i] = 0;
+				}
+			}
+			if (bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(90))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(270))) {
+				results->underlay_maximum_source_efficient_for_tiling =
+					dceip->underlay_maximum_height_efficient_for_tiling;
+			} else {
+				results->underlay_maximum_source_efficient_for_tiling =
+					dceip->underlay_maximum_width_efficient_for_tiling;
+			}
+			if (bw_equ(
+				dceip->de_tiling_buffer,
+				bw_int_to_fixed(0))) {
+				if (surface_type[i]
+					== bw_def_display_write_back420_luma
+					|| surface_type[i]
+						== bw_def_display_write_back420_chroma) {
+					results->bytes_per_request[i] =
+						bw_int_to_fixed(64);
+					results->useful_bytes_per_request[i] =
+						bw_int_to_fixed(64);
+					results->lines_interleaved_in_mem_access[i] =
+						bw_int_to_fixed(1);
+					results->latency_hiding_lines[i] =
+						bw_int_to_fixed(1);
+				} else if (tiling_mode[i] == bw_def_linear) {
+					results->bytes_per_request[i] =
+						bw_int_to_fixed(64);
+					results->useful_bytes_per_request[i] =
+						bw_int_to_fixed(64);
+					results->lines_interleaved_in_mem_access[i] =
+						bw_int_to_fixed(2);
+					results->latency_hiding_lines[i] =
+						bw_int_to_fixed(2);
+				} else {
+					if (surface_type[i] == bw_def_graphics
+						|| (bw_mtn(
+							results->source_width_rounded_up_to_chunks[i],
+							bw_ceil2(
+								results->underlay_maximum_source_efficient_for_tiling,
+								bw_int_to_fixed(
+									256))))) {
+						switch (results->bytes_per_pixel[i]) {
+						case 8:
+							results->lines_interleaved_in_mem_access[i] =
+								bw_int_to_fixed(
+									2);
+							results->latency_hiding_lines[i] =
+								bw_int_to_fixed(
+									2);
+							if (results->orthogonal_rotation[i]) {
+								results->bytes_per_request[i] =
+									bw_int_to_fixed(
+										32);
+								results->useful_bytes_per_request[i] =
+									bw_int_to_fixed(
+										32);
+							} else {
+								results->bytes_per_request[i] =
+									bw_int_to_fixed(
+										64);
+								results->useful_bytes_per_request[i] =
+									bw_int_to_fixed(
+										64);
+							}
+							break;
+						case 4:
+							if (results->orthogonal_rotation[i]) {
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										2);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										2);
+								results->bytes_per_request[i] =
+									bw_int_to_fixed(
+										32);
+								results->useful_bytes_per_request[i] =
+									bw_int_to_fixed(
+										16);
+							} else {
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										2);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										2);
+								results->bytes_per_request[i] =
+									bw_int_to_fixed(
+										64);
+								results->useful_bytes_per_request[i] =
+									bw_int_to_fixed(
+										64);
+							}
+							break;
+						case 2:
+							results->lines_interleaved_in_mem_access[i] =
+								bw_int_to_fixed(
+									2);
+							results->latency_hiding_lines[i] =
+								bw_int_to_fixed(
+									2);
+							results->bytes_per_request[i] =
+								bw_int_to_fixed(
+									32);
+							results->useful_bytes_per_request[i] =
+								bw_int_to_fixed(
+									32);
+							break;
+						default:
+							results->lines_interleaved_in_mem_access[i] =
+								bw_int_to_fixed(
+									2);
+							results->latency_hiding_lines[i] =
+								bw_int_to_fixed(
+									2);
+							results->bytes_per_request[i] =
+								bw_int_to_fixed(
+									32);
+							results->useful_bytes_per_request[i] =
+								bw_int_to_fixed(
+									16);
+							break;
+						}
+					} else {
+						results->bytes_per_request[i] =
+							bw_int_to_fixed(64);
+						results->useful_bytes_per_request[i] =
+							bw_int_to_fixed(64);
+						if (results->orthogonal_rotation[i]) {
+							results->lines_interleaved_in_mem_access[i] =
+								bw_int_to_fixed(
+									8);
+							results->latency_hiding_lines[i] =
+								bw_int_to_fixed(
+									4);
+						} else {
+							switch (results->bytes_per_pixel[i]) {
+							case 4:
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										2);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										2);
+								break;
+							case 2:
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										4);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										4);
+								break;
+							default:
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										8);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										4);
+								break;
+							}
+						}
+					}
+				}
+			} else {
+				results->bytes_per_request[i] = bw_int_to_fixed(
+					256);
+				results->useful_bytes_per_request[i] =
+					bw_int_to_fixed(256);
+				results->lines_interleaved_in_mem_access[i] =
+					bw_int_to_fixed(4);
+				results->latency_hiding_lines[i] =
+					bw_int_to_fixed(4);
+			}
+		}
+	}
+	/*requested peak bandwidth:*/
+	/*the peak request-per-second bandwidth is the product of the maximum source lines in per line out in the beginning and in the middle of the frame, the ratio of the source width to the line time, the ratio of line interleaving in memory to lines of latency hiding, and the ratio of bytes per pixel to useful bytes per request.*/
+	/*the peak bandwidth is the peak request-per-second bandwidth times the request size.*/
+	/*the line buffer lines in per line out in the beginning of the frame is the vertical filter initialization value rounded up to even and divided by the line times for initialization, which is normally three.*/
+	/*the line buffer lines in per line out in the middle of the frame is at least one, or the vertical scale ratio, rounded up to line pairs if not doing line buffer prefetching.*/
+	/*the non-prefetching rounding up of the vertical scale ratio can also be done up to 1 (for a 0,2 pattern), 4/3 (for a 0,2,2 pattern), 6/4 (for a 0,2,2,2 pattern), or 3 (for a 2,4 pattern).*/
+	/*the scaler vertical filter initialization value is calculated by the hardware as the floor of the average of the vertical scale ratio and the number of vertical taps increased by one.  add one more for possible odd line panning/bezel adjustment mode.*/
+	/*for the bottom interlace field an extra 50% of the vertical scale ratio is considered for this calculation.*/
+	/*in top-bottom stereo mode software has to set the filter initialization value manually and explicitly limit it to 4.  further, there is only one line time for initialization.*/
+	/*line buffer prefetching is done when the number of lines in the line buffer exceeds the number of taps plus the ceiling of the vertical scale ratio.*/
+	/*line buffer prefetching is not done when downscaling in the graphics pipe or for possible odd line panning/bezel adjustment mode.*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->v_filter_init[i] =
+				bw_floor2(
+					bw_div(
+						(bw_add(
+							bw_add(
+								bw_add(
+									bw_int_to_fixed(
+										1),
+									results->v_taps[i]),
+								results->vsr[i]),
+							bw_mul(
+								bw_mul(
+									bw_int_to_fixed(
+										results->interlace_mode[i]),
+									bw_frc_to_fixed(
+										5,
+										10)),
+								results->vsr[i]))),
+						bw_int_to_fixed(2)),
+					bw_int_to_fixed(1));
+			if (mode_data->panning_and_bezel_adjustment
+				== bw_def_any_lines) {
+				results->v_filter_init[i] = bw_add(
+					results->v_filter_init[i],
+					bw_int_to_fixed(1));
+			}
+			if (stereo_mode[i] == bw_def_top_bottom) {
+				v_filter_init_mode[i] = bw_def_manual;
+				results->v_filter_init[i] = bw_min2(
+					results->v_filter_init[i],
+					bw_int_to_fixed(4));
+			} else {
+				v_filter_init_mode[i] = bw_def_auto;
+			}
+			if (stereo_mode[i] == bw_def_top_bottom) {
+				results->num_lines_at_frame_start =
+					bw_int_to_fixed(1);
+			} else {
+				results->num_lines_at_frame_start =
+					bw_int_to_fixed(3);
+			}
+			if ((bw_mtn(results->vsr[i], bw_int_to_fixed(1))
+				&& surface_type[i] == bw_def_graphics)
+				|| mode_data->panning_and_bezel_adjustment
+					== bw_def_any_lines) {
+				results->line_buffer_prefetch[i] = 0;
+			} else if ((((dceip->underlay_downscale_prefetch_enabled
+				== 1 && surface_type[i] != bw_def_graphics)
+				|| surface_type[i] == bw_def_graphics)
+				&& (bw_mtn(
+					results->lb_partitions[i],
+					bw_add(
+						results->v_taps[i],
+						bw_ceil2(
+							results->vsr[i],
+							bw_int_to_fixed(1))))))) {
+				results->line_buffer_prefetch[i] = 1;
+			} else {
+				results->line_buffer_prefetch[i] = 0;
+			}
+			results->lb_lines_in_per_line_out_in_beginning_of_frame[i] =
+				bw_div(
+					bw_ceil2(
+						results->v_filter_init[i],
+						bw_int_to_fixed(
+							dceip->lines_interleaved_into_lb)),
+					results->num_lines_at_frame_start);
+			if (results->line_buffer_prefetch[i] == 1) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_max2(
+						bw_int_to_fixed(1),
+						results->vsr[i]);
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(1))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_int_to_fixed(1);
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(4 / 3))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_div(
+						bw_int_to_fixed(4),
+						bw_int_to_fixed(3));
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(6 / 4))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_div(
+						bw_int_to_fixed(6),
+						bw_int_to_fixed(4));
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(2))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_int_to_fixed(2);
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(3))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_int_to_fixed(3);
+			} else {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_int_to_fixed(4);
+			}
+			if (results->line_buffer_prefetch[i] == 1
+				|| bw_equ(
+					results->lb_lines_in_per_line_out_in_middle_of_frame[i],
+					bw_int_to_fixed(2))
+				|| bw_equ(
+					results->lb_lines_in_per_line_out_in_middle_of_frame[i],
+					bw_int_to_fixed(4))) {
+				results->horizontal_blank_and_chunk_granularity_factor[i] =
+					bw_int_to_fixed(1);
+			} else {
+				results->horizontal_blank_and_chunk_granularity_factor[i] =
+					bw_div(
+						results->h_total[i],
+						(bw_div(
+							(bw_add(
+								results->h_total[i],
+								bw_div(
+									(bw_sub(
+										results->source_width_pixels[i],
+										bw_int_to_fixed(
+											dceip->chunk_width))),
+									results->hsr[i]))),
+							bw_int_to_fixed(2))));
+			}
+			results->request_bandwidth[i] =
+				bw_div(
+					bw_mul(
+						bw_div(
+							bw_mul(
+								bw_div(
+									bw_mul(
+										bw_max2(
+											results->lb_lines_in_per_line_out_in_beginning_of_frame[i],
+											results->lb_lines_in_per_line_out_in_middle_of_frame[i]),
+										results->source_width_rounded_up_to_chunks[i]),
+									(bw_div(
+										results->h_total[i],
+										results->pixel_rate[i]))),
+								bw_int_to_fixed(
+									results->bytes_per_pixel[i])),
+							results->useful_bytes_per_request[i]),
+						results->lines_interleaved_in_mem_access[i]),
+					results->latency_hiding_lines[i]);
+			results->display_bandwidth[i] = bw_mul(
+				results->request_bandwidth[i],
+				results->bytes_per_request[i]);
+		}
+	}
+	/*outstanding chunk request limit*/
+	/*if underlay buffer sharing is enabled, the data buffer size for underlay in 422 or 444 is the sum of the luma and chroma data buffer sizes.*/
+	/*underlay buffer sharing mode is only permitted in orthogonal rotation modes.*/
+	/*if there is only one display enabled, the data buffer size for graphics is doubled.*/
+	/*the memory chunk size in bytes is 1024 for the writeback, and 256 times the memory line interleaving and the bytes per pixel for graphics*/
+	/*and underlay.*/
+	/*the pipe chunk size uses 2 for line interleaving, except for the write back, in which case it is 1.*/
+	/*graphics and underlay data buffer size is adjusted (limited) using the outstanding chunk request limit if there is more than one*/
+	/*display enabled or if the dmif request buffer is not large enough for the total data buffer size.*/
+	/*the outstanding chunk request limit is the ceiling of the adjusted data buffer size divided by the chunk size in bytes*/
+	/*the adjusted data buffer size is the product of the display bandwidth and the minimum effective data buffer size in terms of time,*/
+	/*rounded up to the chunk size in bytes, but should not exceed the original data buffer size*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			switch (surface_type[i]) {
+			case bw_def_display_write_back420_luma:
+				results->data_buffer_size[i] =
+					bw_int_to_fixed(
+						dceip->display_write_back420_luma_mcifwr_buffer_size);
+				break;
+			case bw_def_display_write_back420_chroma:
+				results->data_buffer_size[i] =
+					bw_int_to_fixed(
+						dceip->display_write_back420_chroma_mcifwr_buffer_size);
+				break;
+			case bw_def_underlay420_luma:
+				results->data_buffer_size[i] = bw_int_to_fixed(
+					dceip->underlay_luma_dmif_size);
+				break;
+			case bw_def_underlay420_chroma:
+				results->data_buffer_size[i] =
+					bw_div(
+						bw_int_to_fixed(
+							dceip->underlay_chroma_dmif_size),
+						bw_int_to_fixed(2));
+				break;
+			case bw_def_underlay422:
+			case bw_def_underlay444:
+				if (results->orthogonal_rotation[i] == 0) {
+					results->data_buffer_size[i] =
+						bw_int_to_fixed(
+							dceip->underlay_luma_dmif_size);
+				} else {
+					results->data_buffer_size[i] =
+						bw_add(
+							bw_int_to_fixed(
+								dceip->underlay_luma_dmif_size),
+							bw_int_to_fixed(
+								dceip->underlay_chroma_dmif_size));
+				}
+				break;
+			default:
+				if (mode_data->number_of_displays == 1
+					&& bw_equ(
+						dceip->de_tiling_buffer,
+						bw_int_to_fixed(0))) {
+					if (mode_data->d0_fbc_enable) {
+						results->data_buffer_size[i] =
+							bw_mul(
+								bw_int_to_fixed(
+									dceip->max_dmif_buffer_allocated),
+								bw_int_to_fixed(
+									dceip->graphics_dmif_size));
+					} else {
+						/*the effective dmif buffer size in non-fbc mode is limited by the 16 entry chunk tracker*/
+						results->data_buffer_size[i] =
+							bw_mul(
+								bw_mul(
+									bw_int_to_fixed(
+										max_chunks_non_fbc_mode),
+									bw_int_to_fixed(
+										pixels_per_chunk)),
+								bw_int_to_fixed(
+									results->bytes_per_pixel[i]));
+					}
+				} else {
+					results->data_buffer_size[i] =
+						bw_int_to_fixed(
+							dceip->graphics_dmif_size);
+				}
+				break;
+			}
+			if (surface_type[i] == bw_def_display_write_back420_luma
+				|| surface_type[i]
+					== bw_def_display_write_back420_chroma) {
+				results->memory_chunk_size_in_bytes[i] =
+					bw_int_to_fixed(1024);
+				results->pipe_chunk_size_in_bytes[i] =
+					bw_int_to_fixed(1024);
+			} else {
+				results->memory_chunk_size_in_bytes[i] =
+					bw_mul(
+						bw_mul(
+							bw_int_to_fixed(
+								dceip->chunk_width),
+							results->lines_interleaved_in_mem_access[i]),
+						bw_int_to_fixed(
+							results->bytes_per_pixel[i]));
+				results->pipe_chunk_size_in_bytes[i] =
+					bw_mul(
+						bw_mul(
+							bw_int_to_fixed(
+								dceip->chunk_width),
+							bw_int_to_fixed(
+								dceip->lines_interleaved_into_lb)),
+						bw_int_to_fixed(
+							results->bytes_per_pixel[i]));
+			}
+		}
+	}
+	results->min_dmif_size_in_time = bw_int_to_fixed(9999);
+	results->min_mcifwr_size_in_time = bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				if (bw_ltn(
+					bw_div(
+						bw_div(
+							bw_mul(
+								results->data_buffer_size[i],
+								results->bytes_per_request[i]),
+							results->useful_bytes_per_request[i]),
+						results->display_bandwidth[i]),
+					results->min_dmif_size_in_time)) {
+					results->min_dmif_size_in_time =
+						bw_div(
+							bw_div(
+								bw_mul(
+									results->data_buffer_size[i],
+									results->bytes_per_request[i]),
+								results->useful_bytes_per_request[i]),
+							results->display_bandwidth[i]);
+				}
+			} else {
+				if (bw_ltn(
+					bw_div(
+						bw_div(
+							bw_mul(
+								results->data_buffer_size[i],
+								results->bytes_per_request[i]),
+							results->useful_bytes_per_request[i]),
+						results->display_bandwidth[i]),
+					results->min_mcifwr_size_in_time)) {
+					results->min_mcifwr_size_in_time =
+						bw_div(
+							bw_div(
+								bw_mul(
+									results->data_buffer_size[i],
+									results->bytes_per_request[i]),
+								results->useful_bytes_per_request[i]),
+							results->display_bandwidth[i]);
+				}
+			}
+		}
+	}
+	results->total_requests_for_dmif_size = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]
+			&& surface_type[i] != bw_def_display_write_back420_luma
+			&& surface_type[i]
+				!= bw_def_display_write_back420_chroma) {
+			results->total_requests_for_dmif_size = bw_add(
+				results->total_requests_for_dmif_size,
+				bw_div(
+					results->data_buffer_size[i],
+					results->useful_bytes_per_request[i]));
+		}
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma
+				&& dceip->limit_excessive_outstanding_dmif_requests
+				&& (mode_data->number_of_displays > 1
+					|| bw_mtn(
+						results->total_requests_for_dmif_size,
+						dceip->dmif_request_buffer_size))) {
+				results->adjusted_data_buffer_size[i] =
+					bw_min2(
+						results->data_buffer_size[i],
+						bw_ceil2(
+							bw_mul(
+								results->min_dmif_size_in_time,
+								results->display_bandwidth[i]),
+							results->memory_chunk_size_in_bytes[i]));
+			} else {
+				results->adjusted_data_buffer_size[i] =
+					results->data_buffer_size[i];
+			}
+		}
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if ((mode_data->number_of_displays == 1
+				&& results->number_of_underlay_surfaces == 0)) {
+				/*set maximum chunk limit if only one graphic pipe is enabled*/
+				results->outstanding_chunk_request_limit[i] =
+					bw_int_to_fixed(255);
+			} else {
+				results->outstanding_chunk_request_limit[i] =
+					bw_ceil2(
+						bw_div(
+							results->adjusted_data_buffer_size[i],
+							results->pipe_chunk_size_in_bytes[i]),
+						bw_int_to_fixed(1));
+			}
+		}
+	}
+	/*outstanding pte request limit*/
+	/*in tiling mode with no rotation the sg pte requests are 8 useful pt_es, the sg row height is the page height and the sg page width x height is 64x64 for 8bpp, 64x32 for 16 bpp, 32x32 for 32 bpp*/
+	/*in tiling mode with rotation the sg pte requests are only one useful pte, and the sg row height is also the page height, but the sg page width and height are swapped*/
+	/*in linear mode the pte requests are 8 useful pt_es, the sg page width is 4096 divided by the bytes per pixel, the sg page height is 1, but there is just one row whose height is the lines of pte prefetching*/
+	/*the outstanding pte request limit is obtained by multiplying the outstanding chunk request limit by the peak pte request to eviction limiting ratio, rounding up to integer, multiplying by the pte requests per chunk, and rounding up to integer again*/
+	/*if not using peak pte request to eviction limiting, the outstanding pte request limit is the pte requests in the vblank*/
+	/*the pte requests in the vblank is the product of the number of pte request rows times the number of pte requests in a row*/
+	/*the number of pte requests in a row is the quotient of the source width divided by 256, multiplied by the pte requests per chunk, rounded up to even, multiplied by the scatter-gather row height and divided by the scatter-gather page height*/
+	/*the pte requests per chunk is 256 divided by the scatter-gather page width and the useful pt_es per pte request*/
+	if (mode_data->number_of_displays > 1
+		|| (mode_data->graphics_rotation_angle != 0
+			&& mode_data->graphics_rotation_angle != 180)) {
+		results->peak_pte_request_to_eviction_ratio_limiting =
+			dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display;
+	} else {
+		results->peak_pte_request_to_eviction_ratio_limiting =
+			dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation;
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]
+			&& results->scatter_gather_enable_for_pipe[i] == 1) {
+			if (tiling_mode[i] == bw_def_linear) {
+				results->useful_pte_per_pte_request =
+					bw_int_to_fixed(8);
+				results->scatter_gather_page_width[i] = bw_div(
+					bw_int_to_fixed(4096),
+					bw_int_to_fixed(
+						results->bytes_per_pixel[i]));
+				results->scatter_gather_page_height[i] =
+					bw_int_to_fixed(1);
+				results->scatter_gather_pte_request_rows =
+					bw_int_to_fixed(1);
+				results->scatter_gather_row_height =
+					bw_int_to_fixed(
+						dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode);
+			} else if (bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(0))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(180))) {
+				results->useful_pte_per_pte_request =
+					bw_int_to_fixed(8);
+				switch (results->bytes_per_pixel[i]) {
+				case 4:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(32);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(32);
+					break;
+				case 2:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(64);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(32);
+					break;
+				default:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(64);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(64);
+					break;
+				}
+				results->scatter_gather_pte_request_rows =
+					bw_int_to_fixed(
+						dceip->scatter_gather_pte_request_rows_in_tiling_mode);
+				results->scatter_gather_row_height =
+					results->scatter_gather_page_height[i];
+			} else {
+				results->useful_pte_per_pte_request =
+					bw_int_to_fixed(1);
+				switch (results->bytes_per_pixel[i]) {
+				case 4:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(32);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(32);
+					break;
+				case 2:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(32);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(64);
+					break;
+				default:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(64);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(64);
+					break;
+				}
+				results->scatter_gather_pte_request_rows =
+					bw_int_to_fixed(
+						dceip->scatter_gather_pte_request_rows_in_tiling_mode);
+				results->scatter_gather_row_height =
+					results->scatter_gather_page_height[i];
+			}
+			results->pte_request_per_chunk[i] = bw_div(
+				bw_div(
+					bw_int_to_fixed(dceip->chunk_width),
+					results->scatter_gather_page_width[i]),
+				results->useful_pte_per_pte_request);
+			results->scatter_gather_pte_requests_in_row[i] =
+				bw_div(
+					bw_mul(
+						bw_ceil2(
+							bw_mul(
+								bw_div(
+									results->source_width_rounded_up_to_chunks[i],
+									bw_int_to_fixed(
+										dceip->chunk_width)),
+								results->pte_request_per_chunk[i]),
+							bw_int_to_fixed(1)),
+						results->scatter_gather_row_height),
+					results->scatter_gather_page_height[i]);
+			results->scatter_gather_pte_requests_in_vblank = bw_mul(
+				results->scatter_gather_pte_request_rows,
+				results->scatter_gather_pte_requests_in_row[i]);
+			if (bw_equ(
+				results->peak_pte_request_to_eviction_ratio_limiting,
+				bw_int_to_fixed(0))) {
+				results->scatter_gather_pte_request_limit[i] =
+					results->scatter_gather_pte_requests_in_vblank;
+			} else {
+				results->scatter_gather_pte_request_limit[i] =
+					bw_max2(
+						dceip->minimum_outstanding_pte_request_limit,
+						bw_min2(
+							results->scatter_gather_pte_requests_in_vblank,
+							bw_ceil2(
+								bw_mul(
+									bw_mul(
+										bw_div(
+											bw_ceil2(
+												results->adjusted_data_buffer_size[i],
+												results->memory_chunk_size_in_bytes[i]),
+											results->memory_chunk_size_in_bytes[i]),
+										results->pte_request_per_chunk[i]),
+									results->peak_pte_request_to_eviction_ratio_limiting),
+								bw_int_to_fixed(
+									1))));
+			}
+		}
+	}
+	/*pitch padding recommended for efficiency in linear mode*/
+	/*in linear mode graphics or underlay with scatter gather, a pitch that is a multiple of the channel interleave (256 bytes) times the channel-bank rotation is not efficient*/
+	/*if that is the case it is recommended to pad the pitch by at least 256 pixels*/
+	results->inefficient_linear_pitch_in_bytes = bw_mul(
+		bw_mul(
+			bw_int_to_fixed(256),
+			bw_int_to_fixed(vbios->number_of_dram_banks)),
+		bw_int_to_fixed(vbios->number_of_dram_channels));
+	switch (mode_data->underlay_surface_type) {
+	case bw_def_420:
+		results->inefficient_underlay_pitch_in_pixels =
+			results->inefficient_linear_pitch_in_bytes;
+		break;
+	case bw_def_422:
+		results->inefficient_underlay_pitch_in_pixels = bw_div(
+			results->inefficient_linear_pitch_in_bytes,
+			bw_int_to_fixed(2));
+		break;
+	default:
+		results->inefficient_underlay_pitch_in_pixels = bw_div(
+			results->inefficient_linear_pitch_in_bytes,
+			bw_int_to_fixed(4));
+		break;
+	}
+	if (mode_data->underlay_tiling_mode == bw_def_linear
+		&& vbios->scatter_gather_enable == 1
+		&& bw_equ(
+			bw_mod(
+				bw_int_to_fixed(
+					mode_data->underlay_pitch_in_pixels),
+				results->inefficient_underlay_pitch_in_pixels),
+			bw_int_to_fixed(0))) {
+		results->minimum_underlay_pitch_padding_recommended_for_efficiency =
+			bw_int_to_fixed(256);
+	} else {
+		results->minimum_underlay_pitch_padding_recommended_for_efficiency =
+			bw_int_to_fixed(0);
+	}
+	/*pixel transfer time*/
+	/*the dmif and mcifwr yclk(pclk) required is the one that allows the transfer of all pipe's data buffer size in memory in the time for data transfer*/
+	/*for dmif, pte and cursor requests have to be included.*/
+	/*the dram data requirement is doubled when the data request size in bytes is less than the dram channel width times the burst size (8)*/
+	/*the dram data requirement is also multiplied by the number of channels in the case of low power tiling*/
+	/*the page close-open time is determined by trc and the number of page close-opens*/
+	/*in tiled mode graphics or underlay with scatter-gather enabled the bytes per page close-open is the product of the memory line interleave times the maximum of the scatter-gather page width and the product of the tile width (8 pixels) times the number of channels times the number of banks.*/
+	/*in linear mode graphics or underlay with scatter-gather enabled and inefficient pitch, the bytes per page close-open is the line request alternation slice, because different lines are in completely different 4k address bases.*/
+	/*otherwise, the bytes page close-open is the chunk size because that is the arbitration slice.*/
+	/*pte requests are grouped by pte requests per chunk if that is more than 1. each group costs a page close-open time for dmif reads*/
+	/*cursor requests outstanding are limited to a group of two source lines. each group costs a page close-open time for dmif reads*/
+	/*the display reads and writes time for data transfer is the minimum data or cursor buffer size in time minus the mc urgent latency*/
+	/*the mc urgent latency is experienced more than one time if the number of dmif requests in the data buffer exceeds the request buffer size plus the request slots reserved for dmif in the dram channel arbiter queues*/
+	/*the dispclk required is the maximum for all surfaces of the maximum of the source pixels for first output pixel times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, and the source pixels for last output pixel, times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, plus the active time.*/
+	/*the data burst time is the maximum of the total page close-open time, total dmif/mcifwr buffer size in memory divided by the dram bandwidth, and the total dmif/mcifwr buffer size in memory divided by the 32 byte sclk data bus bandwidth, each multiplied by its efficiency.*/
+	/*the source line transfer time is the maximum for all surfaces of the maximum of the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the fist pixel, and the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the last pixel plus the active time.*/
+	/*the source pixels for the first output pixel is 512 if the scaler vertical filter initialization value is greater than 2, and it is 4 times the source width if it is greater than 4.*/
+	/*the source pixels for the last output pixel is the source width times the scaler vertical filter initialization value rounded up to even*/
+	/*the source data for these pixels is the number of pixels times the bytes per pixel times the bytes per request divided by the useful bytes per request.*/
+	results->cursor_total_data = bw_int_to_fixed(0);
+	results->cursor_total_request_groups = bw_int_to_fixed(0);
+	results->scatter_gather_total_pte_requests = bw_int_to_fixed(0);
+	results->scatter_gather_total_pte_request_groups = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->cursor_total_data =
+				bw_add(
+					results->cursor_total_data,
+					bw_mul(
+						bw_mul(
+							bw_int_to_fixed(2),
+							results->cursor_width_pixels[i]),
+						bw_int_to_fixed(4)));
+			results->cursor_total_request_groups = bw_add(
+				results->cursor_total_request_groups,
+				bw_ceil2(
+					bw_div(
+						results->cursor_width_pixels[i],
+						dceip->cursor_chunk_width),
+					bw_int_to_fixed(1)));
+			if (results->scatter_gather_enable_for_pipe[i]) {
+				results->scatter_gather_total_pte_requests =
+					bw_add(
+						results->scatter_gather_total_pte_requests,
+						results->scatter_gather_pte_request_limit[i]);
+				results->scatter_gather_total_pte_request_groups =
+					bw_add(
+						results->scatter_gather_total_pte_request_groups,
+						bw_ceil2(
+							bw_div(
+								results->scatter_gather_pte_request_limit[i],
+								bw_ceil2(
+									results->pte_request_per_chunk[i],
+									bw_int_to_fixed(
+										1))),
+							bw_int_to_fixed(1)));
+			}
+		}
+	}
+	results->tile_width_in_pixels = bw_int_to_fixed(8);
+	results->dmif_total_number_of_data_request_page_close_open =
+		bw_int_to_fixed(0);
+	results->mcifwr_total_number_of_data_request_page_close_open =
+		bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (results->scatter_gather_enable_for_pipe[i] == 1
+				&& tiling_mode[i] != bw_def_linear) {
+				results->bytes_per_page_close_open =
+					bw_mul(
+						results->lines_interleaved_in_mem_access[i],
+						bw_max2(
+							bw_mul(
+								bw_mul(
+									bw_mul(
+										bw_int_to_fixed(
+											results->bytes_per_pixel[i]),
+										results->tile_width_in_pixels),
+									bw_int_to_fixed(
+										vbios->number_of_dram_banks)),
+								bw_int_to_fixed(
+									vbios->number_of_dram_channels)),
+							bw_mul(
+								bw_int_to_fixed(
+									results->bytes_per_pixel[i]),
+								results->scatter_gather_page_width[i])));
+			} else if (results->scatter_gather_enable_for_pipe[i]
+				== 1 && tiling_mode[i] == bw_def_linear
+				&& bw_equ(
+					bw_mod(
+						(bw_mul(
+							results->pitch_in_pixels_after_surface_type[i],
+							bw_int_to_fixed(
+								results->bytes_per_pixel[i]))),
+						results->inefficient_linear_pitch_in_bytes),
+					bw_int_to_fixed(0))) {
+				results->bytes_per_page_close_open =
+					dceip->linear_mode_line_request_alternation_slice;
+			} else {
+				results->bytes_per_page_close_open =
+					results->memory_chunk_size_in_bytes[i];
+			}
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->dmif_total_number_of_data_request_page_close_open =
+					bw_add(
+						results->dmif_total_number_of_data_request_page_close_open,
+						bw_div(
+							bw_ceil2(
+								results->adjusted_data_buffer_size[i],
+								results->memory_chunk_size_in_bytes[i]),
+							results->bytes_per_page_close_open));
+			} else {
+				results->mcifwr_total_number_of_data_request_page_close_open =
+					bw_add(
+						results->mcifwr_total_number_of_data_request_page_close_open,
+						bw_div(
+							bw_ceil2(
+								results->adjusted_data_buffer_size[i],
+								results->memory_chunk_size_in_bytes[i]),
+							results->bytes_per_page_close_open));
+			}
+		}
+	}
+	results->dmif_total_page_close_open_time =
+		bw_div(
+			bw_mul(
+				(bw_add(
+					bw_add(
+						results->dmif_total_number_of_data_request_page_close_open,
+						results->scatter_gather_total_pte_request_groups),
+					results->cursor_total_request_groups)),
+				vbios->trc),
+			bw_int_to_fixed(1000));
+	results->mcifwr_total_page_close_open_time =
+		bw_div(
+			bw_mul(
+				results->mcifwr_total_number_of_data_request_page_close_open,
+				vbios->trc),
+			bw_int_to_fixed(1000));
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->adjusted_data_buffer_size_in_memory[i] =
+				bw_div(
+					bw_mul(
+						results->adjusted_data_buffer_size[i],
+						results->bytes_per_request[i]),
+					results->useful_bytes_per_request[i]);
+		}
+	}
+	results->total_requests_for_adjusted_dmif_size = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->total_requests_for_adjusted_dmif_size =
+					bw_add(
+						results->total_requests_for_adjusted_dmif_size,
+						bw_div(
+							results->adjusted_data_buffer_size[i],
+							results->useful_bytes_per_request[i]));
+			}
+		}
+	}
+	if (dceip->dcfclk_request_generation == 1) {
+		results->total_dmifmc_urgent_trips = bw_int_to_fixed(1);
+	} else {
+		results->total_dmifmc_urgent_trips =
+			bw_ceil2(
+				bw_div(
+					results->total_requests_for_adjusted_dmif_size,
+					(bw_add(
+						dceip->dmif_request_buffer_size,
+						bw_int_to_fixed(
+							vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel
+								* vbios->number_of_dram_channels)))),
+				bw_int_to_fixed(1));
+	}
+	results->total_dmifmc_urgent_latency = bw_mul(
+		vbios->dmifmc_urgent_latency,
+		results->total_dmifmc_urgent_trips);
+	results->total_display_reads_required_data = bw_int_to_fixed(0);
+	results->total_display_reads_required_dram_access_data =
+		bw_int_to_fixed(0);
+	results->total_display_writes_required_data = bw_int_to_fixed(0);
+	results->total_display_writes_required_dram_access_data =
+		bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->display_reads_required_data =
+					results->adjusted_data_buffer_size_in_memory[i];
+				results->display_reads_required_dram_access_data =
+					bw_mul(
+						results->adjusted_data_buffer_size_in_memory[i],
+						bw_ceil2(
+							bw_div(
+								bw_int_to_fixed(
+									vbios->dram_channel_width_in_bits),
+								results->bytes_per_request[i]),
+							bw_int_to_fixed(1)));
+				if (results->access_one_channel_only[i]) {
+					results->display_reads_required_dram_access_data =
+						bw_mul(
+							results->display_reads_required_dram_access_data,
+							bw_int_to_fixed(
+								vbios->number_of_dram_channels));
+				}
+				results->total_display_reads_required_data =
+					bw_add(
+						results->total_display_reads_required_data,
+						results->display_reads_required_data);
+				results->total_display_reads_required_dram_access_data =
+					bw_add(
+						results->total_display_reads_required_dram_access_data,
+						results->display_reads_required_dram_access_data);
+			} else {
+				results->total_display_writes_required_data =
+					bw_add(
+						results->total_display_writes_required_data,
+						results->adjusted_data_buffer_size_in_memory[i]);
+				results->total_display_writes_required_dram_access_data =
+					bw_add(
+						results->total_display_writes_required_dram_access_data,
+						bw_mul(
+							results->adjusted_data_buffer_size_in_memory[i],
+							bw_ceil2(
+								bw_div(
+									bw_int_to_fixed(
+										vbios->dram_channel_width_in_bits),
+									results->bytes_per_request[i]),
+								bw_int_to_fixed(
+									1))));
+			}
+		}
+	}
+	results->total_display_reads_required_data = bw_add(
+		bw_add(
+			results->total_display_reads_required_data,
+			results->cursor_total_data),
+		bw_mul(
+			results->scatter_gather_total_pte_requests,
+			bw_int_to_fixed(64)));
+	results->total_display_reads_required_dram_access_data = bw_add(
+		bw_add(
+			results->total_display_reads_required_dram_access_data,
+			results->cursor_total_data),
+		bw_mul(
+			results->scatter_gather_total_pte_requests,
+			bw_int_to_fixed(64)));
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_mtn(
+				results->v_filter_init[i],
+				bw_int_to_fixed(4))) {
+				results->src_pixels_for_first_output_pixel[i] =
+					bw_mul(
+						bw_int_to_fixed(4),
+						results->source_width_rounded_up_to_chunks[i]);
+			} else {
+				if (bw_mtn(
+					results->v_filter_init[i],
+					bw_int_to_fixed(2))) {
+					results->src_pixels_for_first_output_pixel[i] =
+						bw_int_to_fixed(512);
+				} else {
+					results->src_pixels_for_first_output_pixel[i] =
+						bw_int_to_fixed(0);
+				}
+			}
+			results->src_data_for_first_output_pixel[i] =
+				bw_div(
+					bw_mul(
+						bw_mul(
+							results->src_pixels_for_first_output_pixel[i],
+							bw_int_to_fixed(
+								results->bytes_per_pixel[i])),
+						results->bytes_per_request[i]),
+					results->useful_bytes_per_request[i]);
+			results->src_pixels_for_last_output_pixel[i] =
+				bw_mul(
+					results->source_width_rounded_up_to_chunks[i],
+					bw_max2(
+						bw_ceil2(
+							results->v_filter_init[i],
+							bw_int_to_fixed(
+								dceip->lines_interleaved_into_lb)),
+						bw_mul(
+							bw_ceil2(
+								results->vsr[i],
+								bw_int_to_fixed(
+									dceip->lines_interleaved_into_lb)),
+							results->horizontal_blank_and_chunk_granularity_factor[i])));
+			results->src_data_for_last_output_pixel[i] =
+				bw_div(
+					bw_mul(
+						bw_mul(
+							bw_mul(
+								results->source_width_rounded_up_to_chunks[i],
+								bw_max2(
+									bw_ceil2(
+										results->v_filter_init[i],
+										bw_int_to_fixed(
+											dceip->lines_interleaved_into_lb)),
+									results->lines_interleaved_in_mem_access[i])),
+							bw_int_to_fixed(
+								results->bytes_per_pixel[i])),
+						results->bytes_per_request[i]),
+					results->useful_bytes_per_request[i]);
+			results->active_time[i] =
+				bw_div(
+					bw_div(
+						results->source_width_rounded_up_to_chunks[i],
+						results->hsr[i]),
+					results->pixel_rate[i]);
+		}
+	}
+	for (i = 0; i <= 2; i++) {
+		for (j = 0; j <= 2; j++) {
+			results->dmif_burst_time[i][j] =
+				bw_max3(
+					results->dmif_total_page_close_open_time,
+					bw_div(
+						results->total_display_reads_required_dram_access_data,
+						(bw_mul(
+							bw_div(
+								bw_mul(
+									yclk[i],
+									bw_int_to_fixed(
+										vbios->dram_channel_width_in_bits)),
+								bw_int_to_fixed(
+									8)),
+							bw_int_to_fixed(
+								vbios->number_of_dram_channels)))),
+					bw_div(
+						results->total_display_reads_required_data,
+						(bw_mul(
+							sclk[j],
+							vbios->data_return_bus_width))));
+			if (mode_data->d1_display_write_back_dwb_enable == 1) {
+				results->mcifwr_burst_time[i][j] =
+					bw_max3(
+						results->mcifwr_total_page_close_open_time,
+						bw_div(
+							results->total_display_writes_required_dram_access_data,
+							(bw_mul(
+								bw_div(
+									bw_mul(
+										yclk[i],
+										bw_int_to_fixed(
+											vbios->dram_channel_width_in_bits)),
+									bw_int_to_fixed(
+										8)),
+								bw_int_to_fixed(
+									vbios->number_of_dram_channels)))),
+						bw_div(
+							results->total_display_writes_required_data,
+							(bw_mul(
+								sclk[j],
+								vbios->data_return_bus_width))));
+			}
+		}
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		for (j = 0; j <= 2; j++) {
+			for (k = 0; k <= 2; k++) {
+				if (results->enable[i]) {
+					if (surface_type[i]
+						!= bw_def_display_write_back420_luma
+						&& surface_type[i]
+							!= bw_def_display_write_back420_chroma) {
+						results->line_source_transfer_time[i][j][k] =
+							bw_max2(
+								bw_mul(
+									(bw_add(
+										results->total_dmifmc_urgent_latency,
+										results->dmif_burst_time[j][k])),
+									bw_floor2(
+										bw_div(
+											results->src_data_for_first_output_pixel[i],
+											results->adjusted_data_buffer_size_in_memory[i]),
+										bw_int_to_fixed(
+											1))),
+								bw_sub(
+									bw_mul(
+										(bw_add(
+											results->total_dmifmc_urgent_latency,
+											results->dmif_burst_time[j][k])),
+										bw_floor2(
+											bw_div(
+												results->src_data_for_last_output_pixel[i],
+												results->adjusted_data_buffer_size_in_memory[i]),
+											bw_int_to_fixed(
+												1))),
+									results->active_time[i]));
+					} else {
+						results->line_source_transfer_time[i][j][k] =
+							bw_max2(
+								bw_mul(
+									(bw_add(
+										vbios->mcifwrmc_urgent_latency,
+										results->mcifwr_burst_time[j][k])),
+									bw_floor2(
+										bw_div(
+											results->src_data_for_first_output_pixel[i],
+											results->adjusted_data_buffer_size_in_memory[i]),
+										bw_int_to_fixed(
+											1))),
+								bw_sub(
+									bw_mul(
+										(bw_add(
+											vbios->mcifwrmc_urgent_latency,
+											results->mcifwr_burst_time[j][k])),
+										bw_floor2(
+											bw_div(
+												results->src_data_for_last_output_pixel[i],
+												results->adjusted_data_buffer_size_in_memory[i]),
+											bw_int_to_fixed(
+												1))),
+									results->active_time[i]));
+					}
+				}
+			}
+		}
+	}
+	/*cpu c-state and p-state change enable*/
+	/*for cpu p-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration*/
+	/*for cpu c-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration and recovery*/
+	/*condition for the blackout duration:*/
+	/* minimum latency hiding > blackout duration + dmif burst time + line source transfer time*/
+	/*condition for the blackout recovery:*/
+	/* recovery time >  dmif burst time + 2 * urgent latency*/
+	/* recovery time > (display bw * blackout duration  + (2 * urgent latency + dmif burst time)*dispclk - dmif size )*/
+	/*                  / (dispclk - display bw)*/
+	/*the minimum latency hiding is the minimum for all pipes of one screen line time, plus one more line time if doing lb prefetch, plus the dmif data buffer size equivalent in time, minus the urgent latency.*/
+	/*the minimum latency hiding is  further limited by the cursor.  the cursor latency hiding is the number of lines of the cursor buffer, minus one if the downscaling is less than two, or minus three if it is more*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_equ(
+				dceip->stutter_and_dram_clock_state_change_gated_before_cursor,
+				bw_int_to_fixed(0))
+				&& bw_mtn(
+					results->cursor_width_pixels[i],
+					bw_int_to_fixed(0))) {
+				if (bw_ltn(
+					results->vsr[i],
+					bw_int_to_fixed(2))) {
+					results->cursor_latency_hiding[i] =
+						bw_div(
+							bw_div(
+								bw_mul(
+									(bw_sub(
+										dceip->cursor_dcp_buffer_lines,
+										bw_int_to_fixed(
+											1))),
+									results->h_total[i]),
+								results->vsr[i]),
+							results->pixel_rate[i]);
+				} else {
+					results->cursor_latency_hiding[i] =
+						bw_div(
+							bw_div(
+								bw_mul(
+									(bw_sub(
+										dceip->cursor_dcp_buffer_lines,
+										bw_int_to_fixed(
+											3))),
+									results->h_total[i]),
+								results->vsr[i]),
+							results->pixel_rate[i]);
+				}
+			} else {
+				results->cursor_latency_hiding[i] =
+					bw_int_to_fixed(9999);
+			}
+		}
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (dceip->graphics_lb_nodownscaling_multi_line_prefetching
+				== 1
+				&& (bw_equ(results->vsr[i], bw_int_to_fixed(1))
+					|| (bw_leq(
+						results->vsr[i],
+						bw_frc_to_fixed(8, 10))
+						&& bw_leq(
+							results->v_taps[i],
+							bw_int_to_fixed(2))
+						&& results->lb_bpc[i] == 8))
+				&& surface_type[i] == bw_def_graphics) {
+				results->minimum_latency_hiding[i] =
+					bw_sub(
+						bw_div(
+							bw_mul(
+								bw_div(
+									(bw_add(
+										bw_sub(
+											results->lb_partitions[i],
+											bw_int_to_fixed(
+												1)),
+										bw_div(
+											bw_div(
+												results->data_buffer_size[i],
+												bw_int_to_fixed(
+													results->bytes_per_pixel[i])),
+											results->source_width_pixels[i]))),
+									results->vsr[i]),
+								results->h_total[i]),
+							results->pixel_rate[i]),
+						results->total_dmifmc_urgent_latency);
+			} else {
+				results->minimum_latency_hiding[i] =
+					bw_sub(
+						bw_div(
+							bw_mul(
+								(bw_add(
+									bw_int_to_fixed(
+										1
+											+ results->line_buffer_prefetch[i]),
+									bw_div(
+										bw_div(
+											bw_div(
+												results->data_buffer_size[i],
+												bw_int_to_fixed(
+													results->bytes_per_pixel[i])),
+											results->source_width_pixels[i]),
+										results->vsr[i]))),
+								results->h_total[i]),
+							results->pixel_rate[i]),
+						results->total_dmifmc_urgent_latency);
+			}
+			results->minimum_latency_hiding_with_cursor[i] =
+				bw_min2(
+					results->minimum_latency_hiding[i],
+					results->cursor_latency_hiding[i]);
+		}
+	}
+	for (i = 0; i <= 2; i++) {
+		for (j = 0; j <= 2; j++) {
+			results->blackout_duration_margin[i][j] =
+				bw_int_to_fixed(9999);
+			results->dispclk_required_for_blackout_duration[i][j] =
+				bw_int_to_fixed(0);
+			results->dispclk_required_for_blackout_recovery[i][j] =
+				bw_int_to_fixed(0);
+			for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+				if (results->enable[k]
+					&& bw_mtn(
+						vbios->blackout_duration,
+						bw_int_to_fixed(0))) {
+					if (surface_type[k]
+						!= bw_def_display_write_back420_luma
+						&& surface_type[k]
+							!= bw_def_display_write_back420_chroma) {
+						results->blackout_duration_margin[i][j] =
+							bw_min2(
+								results->blackout_duration_margin[i][j],
+								bw_sub(
+									bw_sub(
+										bw_sub(
+											results->minimum_latency_hiding_with_cursor[k],
+											vbios->blackout_duration),
+										results->dmif_burst_time[i][j]),
+									results->line_source_transfer_time[k][i][j]));
+						results->dispclk_required_for_blackout_duration[i][j] =
+							bw_max3(
+								results->dispclk_required_for_blackout_duration[i][j],
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_first_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_sub(
+										bw_sub(
+											results->minimum_latency_hiding_with_cursor[k],
+											vbios->blackout_duration),
+										results->dmif_burst_time[i][j]))),
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_last_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_add(
+										bw_sub(
+											bw_sub(
+												results->minimum_latency_hiding_with_cursor[k],
+												vbios->blackout_duration),
+											results->dmif_burst_time[i][j]),
+										results->active_time[k]))));
+						if (bw_leq(
+							vbios->maximum_blackout_recovery_time,
+							bw_add(
+								bw_mul(
+									bw_int_to_fixed(
+										2),
+									results->total_dmifmc_urgent_latency),
+								results->dmif_burst_time[i][j]))) {
+							results->dispclk_required_for_blackout_recovery[i][j] =
+								bw_int_to_fixed(
+									9999);
+						} else if (bw_ltn(
+							results->adjusted_data_buffer_size[k],
+							bw_mul(
+								bw_div(
+									bw_mul(
+										results->display_bandwidth[k],
+										results->useful_bytes_per_request[k]),
+									results->bytes_per_request[k]),
+								(bw_add(
+									vbios->blackout_duration,
+									bw_add(
+										bw_mul(
+											bw_int_to_fixed(
+												2),
+											results->total_dmifmc_urgent_latency),
+										results->dmif_burst_time[i][j])))))) {
+							results->dispclk_required_for_blackout_recovery[i][j] =
+								bw_max2(
+									results->dispclk_required_for_blackout_recovery[i][j],
+									bw_div(
+										bw_mul(
+											bw_div(
+												bw_div(
+													(bw_sub(
+														bw_mul(
+															bw_div(
+																bw_mul(
+																	results->display_bandwidth[k],
+																	results->useful_bytes_per_request[k]),
+																results->bytes_per_request[k]),
+															(bw_add(
+																vbios->blackout_duration,
+																vbios->maximum_blackout_recovery_time))),
+														results->adjusted_data_buffer_size[k])),
+													bw_int_to_fixed(
+														results->bytes_per_pixel[k])),
+												(bw_sub(
+													vbios->maximum_blackout_recovery_time,
+													bw_sub(
+														bw_mul(
+															bw_int_to_fixed(
+																2),
+															results->total_dmifmc_urgent_latency),
+														results->dmif_burst_time[i][j])))),
+											results->latency_hiding_lines[k]),
+										results->lines_interleaved_in_mem_access[k]));
+						}
+					} else {
+						results->blackout_duration_margin[i][j] =
+							bw_min2(
+								results->blackout_duration_margin[i][j],
+								bw_sub(
+									bw_sub(
+										bw_sub(
+											bw_sub(
+												results->minimum_latency_hiding_with_cursor[k],
+												vbios->blackout_duration),
+											results->dmif_burst_time[i][j]),
+										results->mcifwr_burst_time[i][j]),
+									results->line_source_transfer_time[k][i][j]));
+						results->dispclk_required_for_blackout_duration[i][j] =
+							bw_max3(
+								results->dispclk_required_for_blackout_duration[i][j],
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_first_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_sub(
+										bw_sub(
+											bw_sub(
+												results->minimum_latency_hiding_with_cursor[k],
+												vbios->blackout_duration),
+											results->dmif_burst_time[i][j]),
+										results->mcifwr_burst_time[i][j]))),
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_last_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_add(
+										bw_sub(
+											bw_sub(
+												bw_sub(
+													results->minimum_latency_hiding_with_cursor[k],
+													vbios->blackout_duration),
+												results->dmif_burst_time[i][j]),
+											results->mcifwr_burst_time[i][j]),
+										results->active_time[k]))));
+						if (bw_ltn(
+							vbios->maximum_blackout_recovery_time,
+							bw_add(
+								bw_add(
+									bw_mul(
+										bw_int_to_fixed(
+											2),
+										vbios->mcifwrmc_urgent_latency),
+									results->dmif_burst_time[i][j]),
+								results->mcifwr_burst_time[i][j]))) {
+							results->dispclk_required_for_blackout_recovery[i][j] =
+								bw_int_to_fixed(
+									9999);
+						} else if (bw_ltn(
+							results->adjusted_data_buffer_size[k],
+							bw_mul(
+								bw_div(
+									bw_mul(
+										results->display_bandwidth[k],
+										results->useful_bytes_per_request[k]),
+									results->bytes_per_request[k]),
+								(bw_add(
+									vbios->blackout_duration,
+									bw_add(
+										bw_mul(
+											bw_int_to_fixed(
+												2),
+											results->total_dmifmc_urgent_latency),
+										results->dmif_burst_time[i][j])))))) {
+							results->dispclk_required_for_blackout_recovery[i][j] =
+								bw_max2(
+									results->dispclk_required_for_blackout_recovery[i][j],
+									bw_div(
+										bw_mul(
+											bw_div(
+												bw_div(
+													(bw_sub(
+														bw_mul(
+															bw_div(
+																bw_mul(
+																	results->display_bandwidth[k],
+																	results->useful_bytes_per_request[k]),
+																results->bytes_per_request[k]),
+															(bw_add(
+																vbios->blackout_duration,
+																vbios->maximum_blackout_recovery_time))),
+														results->adjusted_data_buffer_size[k])),
+													bw_int_to_fixed(
+														results->bytes_per_pixel[k])),
+												(bw_sub(
+													vbios->maximum_blackout_recovery_time,
+													(bw_add(
+														bw_mul(
+															bw_int_to_fixed(
+																2),
+															results->total_dmifmc_urgent_latency),
+														results->dmif_burst_time[i][j]))))),
+											results->latency_hiding_lines[k]),
+										results->lines_interleaved_in_mem_access[k]));
+						}
+					}
+				}
+			}
+		}
+	}
+	if (bw_mtn(
+		results->blackout_duration_margin[high][high],
+		bw_int_to_fixed(0))
+		&& bw_ltn(
+			results->dispclk_required_for_blackout_duration[high][high],
+			vbios->high_voltage_max_dispclk)) {
+		results->cpup_state_change_enable = bw_def_yes;
+		if (bw_ltn(
+			results->dispclk_required_for_blackout_recovery[high][high],
+			vbios->high_voltage_max_dispclk)) {
+			results->cpuc_state_change_enable = bw_def_yes;
+		} else {
+			results->cpuc_state_change_enable = bw_def_no;
+		}
+	} else {
+		results->cpup_state_change_enable = bw_def_no;
+		results->cpuc_state_change_enable = bw_def_no;
+	}
+	/*nb p-state change enable*/
+	/*for dram speed/p-state change to be possible for a yclk(pclk) and sclk level there has to be positive margin and the dispclk required has to be below the maximum.*/
+	/*the dram speed/p-state change margin is the minimum for all surfaces of the maximum latency hiding minus the dram speed/p-state change latency, minus the dmif burst time, minus the source line transfer time*/
+	/*the maximum latency hiding is the minimum latency hiding plus one source line used for de-tiling in the line buffer, plus half the urgent latency*/
+	/*if stutter and dram clock state change are gated before cursor then the cursor latency hiding does not limit stutter or dram clock state change*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (mode_data->number_of_displays <= 1
+				|| mode_data->display_synchronization_enabled
+					== bw_def_yes) {
+				results->maximum_latency_hiding[i] =
+					bw_int_to_fixed(450);
+			} else {
+				results->maximum_latency_hiding[i] =
+					bw_add(
+						results->minimum_latency_hiding[i],
+						bw_add(
+							bw_div(
+								bw_mul(
+									bw_div(
+										bw_int_to_fixed(
+											1),
+										results->vsr[i]),
+									results->h_total[i]),
+								results->pixel_rate[i]),
+							bw_mul(
+								bw_frc_to_fixed(
+									5,
+									10),
+								results->total_dmifmc_urgent_latency)));
+			}
+			results->maximum_latency_hiding_with_cursor[i] =
+				bw_min2(
+					results->maximum_latency_hiding[i],
+					results->cursor_latency_hiding[i]);
+		}
+	}
+	for (i = 0; i <= 2; i++) {
+		for (j = 0; j <= 2; j++) {
+			results->dram_speed_change_margin[i][j] =
+				bw_int_to_fixed(9999);
+			results->dispclk_required_for_dram_speed_change[i][j] =
+				bw_int_to_fixed(0);
+			for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+				if (results->enable[k]) {
+					if (surface_type[k]
+						!= bw_def_display_write_back420_luma
+						&& surface_type[k]
+							!= bw_def_display_write_back420_chroma) {
+						results->dram_speed_change_margin[i][j] =
+							bw_min2(
+								results->dram_speed_change_margin[i][j],
+								bw_sub(
+									bw_sub(
+										bw_sub(
+											results->maximum_latency_hiding_with_cursor[k],
+											vbios->nbp_state_change_latency),
+										results->dmif_burst_time[i][j]),
+									results->line_source_transfer_time[k][i][j]));
+						results->dispclk_required_for_dram_speed_change[i][j] =
+							bw_max3(
+								results->dispclk_required_for_dram_speed_change[i][j],
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_first_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_sub(
+										bw_sub(
+											results->maximum_latency_hiding_with_cursor[k],
+											vbios->nbp_state_change_latency),
+										results->dmif_burst_time[i][j]))),
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_last_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_add(
+										bw_sub(
+											bw_sub(
+												results->maximum_latency_hiding_with_cursor[k],
+												vbios->nbp_state_change_latency),
+											results->dmif_burst_time[i][j]),
+										results->active_time[k]))));
+					} else {
+						results->dram_speed_change_margin[i][j] =
+							bw_min2(
+								results->dram_speed_change_margin[i][j],
+								bw_sub(
+									bw_sub(
+										bw_sub(
+											bw_sub(
+												results->maximum_latency_hiding_with_cursor[k],
+												vbios->nbp_state_change_latency),
+											results->dmif_burst_time[i][j]),
+										results->mcifwr_burst_time[i][j]),
+									results->line_source_transfer_time[k][i][j]));
+						results->dispclk_required_for_dram_speed_change[i][j] =
+							bw_max3(
+								results->dispclk_required_for_dram_speed_change[i][j],
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_first_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_sub(
+										bw_sub(
+											bw_sub(
+												results->maximum_latency_hiding_with_cursor[k],
+												vbios->nbp_state_change_latency),
+											results->dmif_burst_time[i][j]),
+										results->mcifwr_burst_time[i][j]))),
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_last_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_add(
+										bw_sub(
+											bw_sub(
+												bw_sub(
+													results->maximum_latency_hiding_with_cursor[k],
+													vbios->nbp_state_change_latency),
+												results->dmif_burst_time[i][j]),
+											results->mcifwr_burst_time[i][j]),
+										results->active_time[k]))));
+					}
+				}
+			}
+		}
+	}
+	if (bw_mtn(
+		results->dram_speed_change_margin[high][high],
+		bw_int_to_fixed(0))
+		&& bw_ltn(
+			results->dispclk_required_for_dram_speed_change[high][high],
+			vbios->high_voltage_max_dispclk)) {
+		results->nbp_state_change_enable = bw_def_yes;
+	} else {
+		results->nbp_state_change_enable = bw_def_no;
+	}
+	/*required yclk(pclk)*/
+	/*yclk requirement only makes sense if the dmif and mcifwr data total page close-open time is less than the time for data transfer and the total pte requests fit in the scatter-gather saw queque size*/
+	/*if that is the case, the yclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/low yclk(pclk) is chosen accordingly*/
+	/*high yclk(pclk) has to be selected when dram speed/p-state change is not possible.*/
+	results->min_cursor_memory_interface_buffer_size_in_time =
+		bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_mtn(
+				results->cursor_width_pixels[i],
+				bw_int_to_fixed(0))) {
+				results->min_cursor_memory_interface_buffer_size_in_time =
+					bw_min2(
+						results->min_cursor_memory_interface_buffer_size_in_time,
+						bw_div(
+							bw_mul(
+								bw_div(
+									bw_div(
+										dceip->cursor_memory_interface_buffer_pixels,
+										results->cursor_width_pixels[i]),
+									results->vsr[i]),
+								results->h_total[i]),
+							results->pixel_rate[i]));
+			}
+		}
+	}
+	results->min_read_buffer_size_in_time = bw_min2(
+		results->min_cursor_memory_interface_buffer_size_in_time,
+		results->min_dmif_size_in_time);
+	results->display_reads_time_for_data_transfer = bw_sub(
+		results->min_read_buffer_size_in_time,
+		results->total_dmifmc_urgent_latency);
+	results->display_writes_time_for_data_transfer = bw_sub(
+		results->min_mcifwr_size_in_time,
+		vbios->mcifwrmc_urgent_latency);
+	results->dmif_required_dram_bandwidth = bw_div(
+		results->total_display_reads_required_dram_access_data,
+		results->display_reads_time_for_data_transfer);
+	results->mcifwr_required_dram_bandwidth = bw_div(
+		results->total_display_writes_required_dram_access_data,
+		results->display_writes_time_for_data_transfer);
+	results->required_dmifmc_urgent_latency_for_page_close_open = bw_div(
+		(bw_sub(
+			results->min_read_buffer_size_in_time,
+			results->dmif_total_page_close_open_time)),
+		results->total_dmifmc_urgent_trips);
+	results->required_mcifmcwr_urgent_latency = bw_sub(
+		results->min_mcifwr_size_in_time,
+		results->mcifwr_total_page_close_open_time);
+	if (bw_mtn(
+		results->scatter_gather_total_pte_requests,
+		dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) {
+		results->required_dram_bandwidth_gbyte_per_second =
+			bw_int_to_fixed(9999);
+		yclk_message =
+			bw_def_exceeded_allowed_outstanding_pte_req_queue_size;
+		results->y_clk_level = high;
+		results->dram_bandwidth =
+			bw_mul(
+				bw_div(
+					bw_mul(
+						yclk[high],
+						bw_int_to_fixed(
+							vbios->dram_channel_width_in_bits)),
+					bw_int_to_fixed(8)),
+				bw_int_to_fixed(
+					vbios->number_of_dram_channels));
+	} else if (bw_mtn(
+		vbios->dmifmc_urgent_latency,
+		results->required_dmifmc_urgent_latency_for_page_close_open)
+		|| bw_mtn(
+			vbios->mcifwrmc_urgent_latency,
+			results->required_mcifmcwr_urgent_latency)) {
+		results->required_dram_bandwidth_gbyte_per_second =
+			bw_int_to_fixed(9999);
+		yclk_message = bw_def_exceeded_allowed_page_close_open;
+		results->y_clk_level = high;
+		results->dram_bandwidth =
+			bw_mul(
+				bw_div(
+					bw_mul(
+						yclk[high],
+						bw_int_to_fixed(
+							vbios->dram_channel_width_in_bits)),
+					bw_int_to_fixed(8)),
+				bw_int_to_fixed(
+					vbios->number_of_dram_channels));
+	} else {
+		results->required_dram_bandwidth_gbyte_per_second = bw_div(
+			bw_max2(
+				results->dmif_required_dram_bandwidth,
+				results->mcifwr_required_dram_bandwidth),
+			bw_int_to_fixed(1000));
+		if (bw_ltn(
+			bw_mul(
+				results->required_dram_bandwidth_gbyte_per_second,
+				bw_int_to_fixed(1000)),
+			bw_mul(
+				bw_div(
+					bw_mul(
+						yclk[low],
+						bw_int_to_fixed(
+							vbios->dram_channel_width_in_bits)),
+					bw_int_to_fixed(8)),
+				bw_int_to_fixed(
+					vbios->number_of_dram_channels)))
+			&& (results->cpup_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[low][high],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[low][high],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->cpuc_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[low][high],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[low][high],
+						vbios->high_voltage_max_dispclk)
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_recovery[low][high],
+						vbios->high_voltage_max_dispclk)))
+			&& bw_mtn(
+				results->dram_speed_change_margin[low][high],
+				bw_int_to_fixed(0))
+			&& bw_ltn(
+				results->dispclk_required_for_dram_speed_change[low][high],
+				vbios->high_voltage_max_dispclk)) {
+			yclk_message = bw_def_low;
+			results->y_clk_level = low;
+			results->dram_bandwidth =
+				bw_mul(
+					bw_div(
+						bw_mul(
+							yclk[low],
+							bw_int_to_fixed(
+								vbios->dram_channel_width_in_bits)),
+						bw_int_to_fixed(8)),
+					bw_int_to_fixed(
+						vbios->number_of_dram_channels));
+		} else if (bw_ltn(
+			bw_mul(
+				results->required_dram_bandwidth_gbyte_per_second,
+				bw_int_to_fixed(1000)),
+			bw_mul(
+				bw_div(
+					bw_mul(
+						yclk[high],
+						bw_int_to_fixed(
+							vbios->dram_channel_width_in_bits)),
+					bw_int_to_fixed(8)),
+				bw_int_to_fixed(
+					vbios->number_of_dram_channels)))) {
+			yclk_message = bw_def_high;
+			results->y_clk_level = high;
+			results->dram_bandwidth =
+				bw_mul(
+					bw_div(
+						bw_mul(
+							yclk[high],
+							bw_int_to_fixed(
+								vbios->dram_channel_width_in_bits)),
+						bw_int_to_fixed(8)),
+					bw_int_to_fixed(
+						vbios->number_of_dram_channels));
+		} else {
+			yclk_message = bw_def_exceeded_allowed_maximum_bw;
+			results->y_clk_level = high;
+			results->dram_bandwidth =
+				bw_mul(
+					bw_div(
+						bw_mul(
+							yclk[high],
+							bw_int_to_fixed(
+								vbios->dram_channel_width_in_bits)),
+						bw_int_to_fixed(8)),
+					bw_int_to_fixed(
+						vbios->number_of_dram_channels));
+		}
+	}
+	/*required sclk*/
+	/*sclk requirement only makes sense if the total pte requests fit in the scatter-gather saw queque size*/
+	/*if that is the case, the sclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/mid/low sclk is chosen accordingly, unless that choice results in foresaking dram speed/nb p-state change.*/
+	/*the dmif and mcifwr sclk required is the one that allows the transfer of all pipe's data buffer size through the sclk bus in the time for data transfer*/
+	/*for dmif, pte and cursor requests have to be included.*/
+	results->dmif_required_sclk = bw_div(
+		bw_div(
+			results->total_display_reads_required_data,
+			results->display_reads_time_for_data_transfer),
+		vbios->data_return_bus_width);
+	results->mcifwr_required_sclk = bw_div(
+		bw_div(
+			results->total_display_writes_required_data,
+			results->display_writes_time_for_data_transfer),
+		vbios->data_return_bus_width);
+	if (bw_mtn(
+		results->scatter_gather_total_pte_requests,
+		dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) {
+		results->required_sclk = bw_int_to_fixed(9999);
+		sclk_message =
+			bw_def_exceeded_allowed_outstanding_pte_req_queue_size;
+		results->sclk_level = high;
+	} else if (bw_mtn(
+		vbios->dmifmc_urgent_latency,
+		results->required_dmifmc_urgent_latency_for_page_close_open)
+		|| bw_mtn(
+			vbios->mcifwrmc_urgent_latency,
+			results->required_mcifmcwr_urgent_latency)) {
+		results->required_sclk = bw_int_to_fixed(9999);
+		sclk_message = bw_def_exceeded_allowed_page_close_open;
+		results->sclk_level = high;
+	} else {
+		results->required_sclk = bw_max2(
+			results->dmif_required_sclk,
+			results->mcifwr_required_sclk);
+		if (bw_ltn(results->required_sclk, sclk[low])
+			&& (results->cpup_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[results->y_clk_level][low],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[results->y_clk_level][low],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->cpuc_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[results->y_clk_level][low],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[results->y_clk_level][low],
+						vbios->high_voltage_max_dispclk)
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_recovery[results->y_clk_level][low],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->nbp_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->dram_speed_change_margin[results->y_clk_level][low],
+					bw_int_to_fixed(0))
+					&& bw_leq(
+						results->dispclk_required_for_dram_speed_change[results->y_clk_level][low],
+						vbios->high_voltage_max_dispclk)))) {
+			sclk_message = bw_def_low;
+			results->sclk_level = low;
+		} else if (bw_ltn(results->required_sclk, sclk[mid])
+			&& (results->cpup_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[results->y_clk_level][mid],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[results->y_clk_level][mid],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->cpuc_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[results->y_clk_level][mid],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[results->y_clk_level][mid],
+						vbios->high_voltage_max_dispclk)
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_recovery[results->y_clk_level][mid],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->nbp_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->dram_speed_change_margin[results->y_clk_level][mid],
+					bw_int_to_fixed(0))
+					&& bw_leq(
+						results->dispclk_required_for_dram_speed_change[results->y_clk_level][mid],
+						vbios->high_voltage_max_dispclk)))) {
+			sclk_message = bw_def_mid;
+			results->sclk_level = mid;
+		} else if (bw_ltn(results->required_sclk, sclk[high])) {
+			sclk_message = bw_def_high;
+			results->sclk_level = high;
+		} else {
+			sclk_message = bw_def_exceeded_allowed_maximum_sclk;
+			results->sclk_level = high;
+		}
+	}
+	/*dispclk*/
+	/*if dispclk is set to the maximum, ramping is not required.  dispclk required without ramping is less than the dispclk required with ramping.*/
+	/*if dispclk required without ramping is more than the maximum dispclk, that is the dispclk required, and the mode is not supported*/
+	/*if that does not happen, but dispclk required with ramping is more than the maximum dispclk, dispclk required is just the maximum dispclk*/
+	/*if that does not happen either, dispclk required is the dispclk required with ramping.*/
+	/*dispclk required without ramping is the maximum of the one required for display pipe pixel throughput, for scaler throughput, for total read request thrrougput and for dram/np p-state change if enabled.*/
+	/*the display pipe pixel throughput is the maximum of lines in per line out in the beginning of the frame and lines in per line out in the middle of the frame multiplied by the horizontal blank and chunk granularity factor, altogether multiplied by the ratio of the source width to the line time, divided by the line buffer pixels per dispclk throughput, and multiplied by the display pipe throughput factor.*/
+	/*the horizontal blank and chunk granularity factor is the ratio of the line time divided by the line time minus half the horizontal blank and chunk time.  it applies when the lines in per line out is not 2 or 4.*/
+	/*the dispclk required for scaler throughput is the product of the pixel rate and the scaling limits factor.*/
+	/*the dispclk required for total read request throughput is the product of the peak request-per-second bandwidth and the dispclk cycles per request, divided by the request efficiency.*/
+	/*for the dispclk required with ramping, instead of multiplying just the pipe throughput by the display pipe throughput factor, we multiply the scaler and pipe throughput by the ramping factor.*/
+	/*the scaling limits factor is the product of the horizontal scale ratio, and the ratio of the vertical taps divided by the scaler efficiency clamped to at least 1.*/
+	/*the scaling limits factor itself it also clamped to at least 1*/
+	/*if doing downscaling with the pre-downscaler enabled, the horizontal scale ratio should not be considered above (use "1")*/
+	results->downspread_factor = bw_add(
+		bw_int_to_fixed(1),
+		bw_div(vbios->down_spread_percentage, bw_int_to_fixed(100)));
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] == bw_def_graphics) {
+				switch (results->lb_bpc[i]) {
+				case 6:
+					results->v_scaler_efficiency =
+						dceip->graphics_vscaler_efficiency6_bit_per_component;
+					break;
+				case 8:
+					results->v_scaler_efficiency =
+						dceip->graphics_vscaler_efficiency8_bit_per_component;
+					break;
+				case 10:
+					results->v_scaler_efficiency =
+						dceip->graphics_vscaler_efficiency10_bit_per_component;
+					break;
+				default:
+					results->v_scaler_efficiency =
+						dceip->graphics_vscaler_efficiency12_bit_per_component;
+					break;
+				}
+				if (results->use_alpha[i] == 1) {
+					results->v_scaler_efficiency =
+						bw_min2(
+							results->v_scaler_efficiency,
+							dceip->alpha_vscaler_efficiency);
+				}
+			} else {
+				switch (results->lb_bpc[i]) {
+				case 6:
+					results->v_scaler_efficiency =
+						dceip->underlay_vscaler_efficiency6_bit_per_component;
+					break;
+				case 8:
+					results->v_scaler_efficiency =
+						dceip->underlay_vscaler_efficiency8_bit_per_component;
+					break;
+				case 10:
+					results->v_scaler_efficiency =
+						dceip->underlay_vscaler_efficiency10_bit_per_component;
+					break;
+				default:
+					results->v_scaler_efficiency =
+						dceip->underlay_vscaler_efficiency12_bit_per_component;
+					break;
+				}
+			}
+			if (dceip->pre_downscaler_enabled
+				&& bw_mtn(
+					results->hsr[i],
+					bw_int_to_fixed(1))) {
+				results->scaler_limits_factor =
+					bw_max2(
+						bw_div(
+							results->v_taps[i],
+							results->v_scaler_efficiency),
+						bw_div(
+							results->source_width_rounded_up_to_chunks[i],
+							results->h_total[i]));
+			} else {
+				results->scaler_limits_factor =
+					bw_max3(
+						bw_int_to_fixed(1),
+						bw_ceil2(
+							bw_div(
+								results->h_taps[i],
+								bw_int_to_fixed(
+									4)),
+							bw_int_to_fixed(1)),
+						bw_mul(
+							results->hsr[i],
+							bw_max2(
+								bw_div(
+									results->v_taps[i],
+									results->v_scaler_efficiency),
+								bw_int_to_fixed(
+									1))));
+			}
+			results->display_pipe_pixel_throughput =
+				bw_div(
+					bw_div(
+						bw_mul(
+							bw_max2(
+								results->lb_lines_in_per_line_out_in_beginning_of_frame[i],
+								bw_mul(
+									results->lb_lines_in_per_line_out_in_middle_of_frame[i],
+									results->horizontal_blank_and_chunk_granularity_factor[i])),
+							results->source_width_rounded_up_to_chunks[i]),
+						(bw_div(
+							results->h_total[i],
+							results->pixel_rate[i]))),
+					dceip->lb_write_pixels_per_dispclk);
+			results->dispclk_required_without_ramping[i] =
+				bw_mul(
+					results->downspread_factor,
+					bw_max2(
+						bw_mul(
+							results->pixel_rate[i],
+							results->scaler_limits_factor),
+						bw_mul(
+							dceip->display_pipe_throughput_factor,
+							results->display_pipe_pixel_throughput)));
+			results->dispclk_required_with_ramping[i] =
+				bw_mul(
+					dceip->dispclk_ramping_factor,
+					bw_max2(
+						bw_mul(
+							results->pixel_rate[i],
+							results->scaler_limits_factor),
+						results->display_pipe_pixel_throughput));
+		}
+	}
+	results->total_dispclk_required_with_ramping = bw_int_to_fixed(0);
+	results->total_dispclk_required_without_ramping = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_ltn(
+				results->total_dispclk_required_with_ramping,
+				results->dispclk_required_with_ramping[i])) {
+				results->total_dispclk_required_with_ramping =
+					results->dispclk_required_with_ramping[i];
+			}
+			if (bw_ltn(
+				results->total_dispclk_required_without_ramping,
+				results->dispclk_required_without_ramping[i])) {
+				results->total_dispclk_required_without_ramping =
+					results->dispclk_required_without_ramping[i];
+			}
+		}
+	}
+	results->total_read_request_bandwidth = bw_int_to_fixed(0);
+	results->total_write_request_bandwidth = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->total_read_request_bandwidth = bw_add(
+					results->total_read_request_bandwidth,
+					results->request_bandwidth[i]);
+			} else {
+				results->total_write_request_bandwidth = bw_add(
+					results->total_write_request_bandwidth,
+					results->request_bandwidth[i]);
+			}
+		}
+	}
+	results->dispclk_required_for_total_read_request_bandwidth = bw_div(
+		bw_mul(
+			results->total_read_request_bandwidth,
+			dceip->dispclk_per_request),
+		dceip->request_efficiency);
+	if (dceip->dcfclk_request_generation == 0) {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_with_ramping,
+				results->dispclk_required_for_total_read_request_bandwidth);
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_without_ramping,
+				results->dispclk_required_for_total_read_request_bandwidth);
+	} else {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			results->total_dispclk_required_with_ramping;
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			results->total_dispclk_required_without_ramping;
+	}
+	if (results->cpuc_state_change_enable == bw_def_yes) {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			bw_max3(
+				results->total_dispclk_required_with_ramping_with_request_bandwidth,
+				results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level],
+				results->dispclk_required_for_blackout_recovery[results->y_clk_level][results->sclk_level]);
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			bw_max3(
+				results->total_dispclk_required_without_ramping_with_request_bandwidth,
+				results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level],
+				results->dispclk_required_for_blackout_recovery[results->y_clk_level][results->sclk_level]);
+	}
+	if (results->cpup_state_change_enable == bw_def_yes) {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_with_ramping_with_request_bandwidth,
+				results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level]);
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_without_ramping_with_request_bandwidth,
+				results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level]);
+	}
+	if (results->nbp_state_change_enable == bw_def_yes) {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_with_ramping_with_request_bandwidth,
+				results->dispclk_required_for_dram_speed_change[results->y_clk_level][results->sclk_level]);
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_without_ramping_with_request_bandwidth,
+				results->dispclk_required_for_dram_speed_change[results->y_clk_level][results->sclk_level]);
+	}
+	if (bw_ltn(
+		results->total_dispclk_required_with_ramping_with_request_bandwidth,
+		vbios->high_voltage_max_dispclk)) {
+		results->dispclk =
+			results->total_dispclk_required_with_ramping_with_request_bandwidth;
+	} else if (bw_ltn(
+		results->total_dispclk_required_without_ramping_with_request_bandwidth,
+		vbios->high_voltage_max_dispclk)) {
+		results->dispclk = vbios->high_voltage_max_dispclk;
+	} else {
+		results->dispclk =
+			results->total_dispclk_required_without_ramping_with_request_bandwidth;
+	}
+	/* required core voltage*/
+	/* the core voltage required is low if sclk, yclk(pclk)and dispclk are within the low limits*/
+	/* otherwise, the core voltage required is medium if yclk (pclk) is within the low limit and sclk and dispclk are within the medium limit*/
+	/* otherwise, the core voltage required is high if the three clocks are within the high limits*/
+	/* otherwise, or if the mode is not supported, core voltage requirement is not applicable*/
+	if (pipe_check == bw_def_notok) {
+		voltage = bw_def_na;
+	} else if (mode_check == bw_def_notok) {
+		voltage = bw_def_notok;
+	} else if (yclk_message == bw_def_low && sclk_message == bw_def_low
+		&& bw_ltn(results->dispclk, vbios->low_voltage_max_dispclk)) {
+		voltage = bw_def_low;
+	} else if (yclk_message == bw_def_low
+		&& (sclk_message == bw_def_low || sclk_message == bw_def_mid)
+		&& bw_ltn(results->dispclk, vbios->mid_voltage_max_dispclk)) {
+		voltage = bw_def_mid;
+	} else if ((yclk_message == bw_def_low || yclk_message == bw_def_high)
+		&& (sclk_message == bw_def_low || sclk_message == bw_def_mid
+			|| sclk_message == bw_def_high)
+		&& bw_leq(results->dispclk, vbios->high_voltage_max_dispclk)) {
+		if (results->nbp_state_change_enable == bw_def_yes) {
+			voltage = bw_def_high;
+		} else {
+			voltage = bw_def_high_no_nbp_state_change;
+		}
+	} else {
+		voltage = bw_def_notok;
+	}
+	/*required blackout recovery time*/
+	results->blackout_recovery_time = bw_int_to_fixed(0);
+	for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+		if (results->enable[k]
+			&& bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0))
+			&& results->cpup_state_change_enable == bw_def_yes) {
+			if (surface_type[k] != bw_def_display_write_back420_luma
+				&& surface_type[k]
+					!= bw_def_display_write_back420_chroma) {
+				results->blackout_recovery_time =
+					bw_max2(
+						results->blackout_recovery_time,
+						bw_add(
+							bw_mul(
+								bw_int_to_fixed(
+									2),
+								results->total_dmifmc_urgent_latency),
+							results->dmif_burst_time[results->y_clk_level][results->sclk_level]));
+				if (bw_ltn(
+					results->adjusted_data_buffer_size[k],
+					bw_mul(
+						bw_div(
+							bw_mul(
+								results->display_bandwidth[k],
+								results->useful_bytes_per_request[k]),
+							results->bytes_per_request[k]),
+						(bw_add(
+							vbios->blackout_duration,
+							bw_add(
+								bw_mul(
+									bw_int_to_fixed(
+										2),
+									results->total_dmifmc_urgent_latency),
+								results->dmif_burst_time[results->y_clk_level][results->sclk_level])))))) {
+					results->blackout_recovery_time =
+						bw_max2(
+							results->blackout_recovery_time,
+							bw_div(
+								(bw_add(
+									bw_mul(
+										bw_div(
+											bw_mul(
+												results->display_bandwidth[k],
+												results->useful_bytes_per_request[k]),
+											results->bytes_per_request[k]),
+										vbios->blackout_duration),
+									bw_sub(
+										bw_div(
+											bw_mul(
+												bw_mul(
+													bw_mul(
+														(bw_add(
+															bw_mul(
+																bw_int_to_fixed(
+																	2),
+																results->total_dmifmc_urgent_latency),
+															results->dmif_burst_time[results->y_clk_level][results->sclk_level])),
+														results->dispclk),
+													bw_int_to_fixed(
+														results->bytes_per_pixel[k])),
+												results->lines_interleaved_in_mem_access[k]),
+											results->latency_hiding_lines[k]),
+										results->adjusted_data_buffer_size[k]))),
+								(bw_sub(
+									bw_div(
+										bw_mul(
+											bw_mul(
+												results->dispclk,
+												bw_int_to_fixed(
+													results->bytes_per_pixel[k])),
+											results->lines_interleaved_in_mem_access[k]),
+										results->latency_hiding_lines[k]),
+									bw_div(
+										bw_mul(
+											results->display_bandwidth[k],
+											results->useful_bytes_per_request[k]),
+										results->bytes_per_request[k])))));
+				}
+			} else {
+				results->blackout_recovery_time =
+					bw_max2(
+						results->blackout_recovery_time,
+						bw_add(
+							bw_mul(
+								bw_int_to_fixed(
+									2),
+								vbios->mcifwrmc_urgent_latency),
+							results->mcifwr_burst_time[results->y_clk_level][results->sclk_level]));
+				if (bw_ltn(
+					results->adjusted_data_buffer_size[k],
+					bw_mul(
+						bw_div(
+							bw_mul(
+								results->display_bandwidth[k],
+								results->useful_bytes_per_request[k]),
+							results->bytes_per_request[k]),
+						(bw_add(
+							vbios->blackout_duration,
+							bw_add(
+								bw_mul(
+									bw_int_to_fixed(
+										2),
+									vbios->mcifwrmc_urgent_latency),
+								results->mcifwr_burst_time[results->y_clk_level][results->sclk_level])))))) {
+					results->blackout_recovery_time =
+						bw_max2(
+							results->blackout_recovery_time,
+							bw_div(
+								(bw_add(
+									bw_mul(
+										bw_div(
+											bw_mul(
+												results->display_bandwidth[k],
+												results->useful_bytes_per_request[k]),
+											results->bytes_per_request[k]),
+										vbios->blackout_duration),
+									bw_sub(
+										bw_div(
+											bw_mul(
+												bw_mul(
+													bw_mul(
+														(bw_add(
+															bw_add(
+																bw_mul(
+																	bw_int_to_fixed(
+																		2),
+																	vbios->mcifwrmc_urgent_latency),
+																results->dmif_burst_time[i][j]),
+															results->mcifwr_burst_time[results->y_clk_level][results->sclk_level])),
+														results->dispclk),
+													bw_int_to_fixed(
+														results->bytes_per_pixel[k])),
+												results->lines_interleaved_in_mem_access[k]),
+											results->latency_hiding_lines[k]),
+										results->adjusted_data_buffer_size[k]))),
+								(bw_sub(
+									bw_div(
+										bw_mul(
+											bw_mul(
+												results->dispclk,
+												bw_int_to_fixed(
+													results->bytes_per_pixel[k])),
+											results->lines_interleaved_in_mem_access[k]),
+										results->latency_hiding_lines[k]),
+									bw_div(
+										bw_mul(
+											results->display_bandwidth[k],
+											results->useful_bytes_per_request[k]),
+										results->bytes_per_request[k])))));
+				}
+			}
+		}
+	}
+	/*sclk deep sleep*/
+	/*during self-refresh, sclk can be reduced to dispclk divided by the minimum pixels in the data fifo entry, with 15% margin, but shoudl not be set to less than the request bandwidth.*/
+	/*the data fifo entry is 16 pixels for the writeback, 64 bytes/bytes_per_pixel for the graphics, 16 pixels for the parallel rotation underlay,*/
+	/*and 16 bytes/bytes_per_pixel for the orthogonal rotation underlay.*/
+	/*in parallel mode (underlay pipe), the data read from the dmifv buffer is variable and based on the pixel depth (8bbp - 16 bytes, 16 bpp - 32 bytes, 32 bpp - 64 bytes)*/
+	/*in orthogonal mode (underlay pipe), the data read from the dmifv buffer is fixed at 16 bytes.*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] == bw_def_display_write_back420_luma
+				|| surface_type[i]
+					== bw_def_display_write_back420_chroma) {
+				results->pixels_per_data_fifo_entry[i] =
+					bw_int_to_fixed(16);
+			} else if (surface_type[i] == bw_def_graphics) {
+				results->pixels_per_data_fifo_entry[i] = bw_div(
+					bw_int_to_fixed(64),
+					bw_int_to_fixed(
+						results->bytes_per_pixel[i]));
+			} else if (results->orthogonal_rotation[i] == 0) {
+				results->pixels_per_data_fifo_entry[i] =
+					bw_int_to_fixed(16);
+			} else {
+				results->pixels_per_data_fifo_entry[i] = bw_div(
+					bw_int_to_fixed(16),
+					bw_int_to_fixed(
+						results->bytes_per_pixel[i]));
+			}
+		}
+	}
+	results->min_pixels_per_data_fifo_entry = bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_mtn(
+				results->min_pixels_per_data_fifo_entry,
+				results->pixels_per_data_fifo_entry[i])) {
+				results->min_pixels_per_data_fifo_entry =
+					results->pixels_per_data_fifo_entry[i];
+			}
+		}
+	}
+	results->sclk_deep_sleep = bw_max2(
+		bw_div(
+			bw_mul(results->dispclk, bw_frc_to_fixed(115, 100)),
+			results->min_pixels_per_data_fifo_entry),
+		results->total_read_request_bandwidth);
+	/*urgent, stutter and nb-p_state watermark*/
+	/*the urgent watermark is the maximum of the urgent trip time plus the pixel transfer time, the urgent trip times to get data for the first pixel, and the urgent trip times to get data for the last pixel.*/
+	/*the stutter exit watermark is the self refresh exit time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel.  it does not apply to the writeback.*/
+	/*the nb p-state change watermark is the dram speed/p-state change time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel.*/
+	/*the pixel transfer time is the maximum of the time to transfer the source pixels required for the first output pixel, and the time to transfer the pixels for the last output pixel minus the active line time.*/
+	/*blackout_duration is added to the urgent watermark*/
+	results->chunk_request_time = bw_int_to_fixed(0);
+	results->cursor_request_time = bw_int_to_fixed(0);
+	/*compute total time to request one chunk from each active display pipe*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->chunk_request_time =
+				bw_add(
+					results->chunk_request_time,
+					(bw_div(
+						(bw_div(
+							bw_int_to_fixed(
+								pixels_per_chunk
+									* results->bytes_per_pixel[i]),
+							results->useful_bytes_per_request[i])),
+						bw_min2(
+							sclk[results->sclk_level],
+							bw_div(
+								results->dispclk,
+								bw_int_to_fixed(
+									2))))));
+		}
+	}
+	/*compute total time to request cursor data*/
+	results->cursor_request_time = (bw_div(
+		results->cursor_total_data,
+		(bw_mul(bw_int_to_fixed(32), sclk[results->sclk_level]))));
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->line_source_pixels_transfer_time =
+				bw_max2(
+					bw_div(
+						bw_div(
+							results->src_pixels_for_first_output_pixel[i],
+							dceip->lb_write_pixels_per_dispclk),
+						(bw_div(
+							results->dispclk,
+							dceip->display_pipe_throughput_factor))),
+					bw_sub(
+						bw_div(
+							bw_div(
+								results->src_pixels_for_last_output_pixel[i],
+								dceip->lb_write_pixels_per_dispclk),
+							(bw_div(
+								results->dispclk,
+								dceip->display_pipe_throughput_factor))),
+						results->active_time[i]));
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->urgent_watermark[i] =
+					bw_add(
+						bw_add(
+							bw_add(
+								bw_add(
+									bw_add(
+										results->total_dmifmc_urgent_latency,
+										results->dmif_burst_time[results->y_clk_level][results->sclk_level]),
+									bw_max2(
+										results->line_source_pixels_transfer_time,
+										results->line_source_transfer_time[i][results->y_clk_level][results->sclk_level])),
+								vbios->blackout_duration),
+							results->chunk_request_time),
+						results->cursor_request_time);
+				results->stutter_exit_watermark[i] =
+					bw_add(
+						bw_sub(
+							vbios->stutter_self_refresh_exit_latency,
+							results->total_dmifmc_urgent_latency),
+						results->urgent_watermark[i]);
+				/*unconditionally remove black out time from the nb p_state watermark*/
+				results->nbp_state_change_watermark[i] =
+					bw_sub(
+						bw_add(
+							bw_sub(
+								vbios->nbp_state_change_latency,
+								results->total_dmifmc_urgent_latency),
+							results->urgent_watermark[i]),
+						vbios->blackout_duration);
+			} else {
+				results->urgent_watermark[i] =
+					bw_add(
+						bw_add(
+							bw_add(
+								bw_add(
+									bw_add(
+										vbios->mcifwrmc_urgent_latency,
+										results->mcifwr_burst_time[results->y_clk_level][results->sclk_level]),
+									bw_max2(
+										results->line_source_pixels_transfer_time,
+										results->line_source_transfer_time[i][results->y_clk_level][results->sclk_level])),
+								vbios->blackout_duration),
+							results->chunk_request_time),
+						results->cursor_request_time);
+				results->stutter_exit_watermark[i] =
+					bw_int_to_fixed(0);
+				results->nbp_state_change_watermark[i] =
+					bw_add(
+						bw_sub(
+							bw_add(
+								vbios->nbp_state_change_latency,
+								results->dmif_burst_time[results->y_clk_level][results->sclk_level]),
+							vbios->mcifwrmc_urgent_latency),
+						results->urgent_watermark[i]);
+			}
+		}
+	}
+	/*stutter mode enable*/
+	/*in the multi-display case the stutter exit watermark cannot exceed the cursor dcp buffer size*/
+	results->stutter_mode_enable = results->cpuc_state_change_enable;
+	if (mode_data->number_of_displays > 1) {
+		for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+			if (results->enable[i]) {
+				if (bw_mtn(
+					results->stutter_exit_watermark[i],
+					results->cursor_latency_hiding[i])) {
+					results->stutter_mode_enable =
+						bw_def_no;
+				}
+			}
+		}
+	}
+	/*performance metrics*/
+	/* display read access efficiency (%)*/
+	/* display write back access efficiency (%)*/
+	/* stutter efficiency (%)*/
+	/* extra underlay pitch recommended for efficiency (pixels)*/
+	/* immediate flip time (us)*/
+	/* latency for other clients due to urgent display read (us)*/
+	/* latency for other clients due to urgent display write (us)*/
+	/* average bandwidth consumed by display (no compression) (gb/s)*/
+	/* required dram  bandwidth (gb/s)*/
+	/* required sclk (m_hz)*/
+	/* required rd urgent latency (us)*/
+	/* nb p-state change margin (us)*/
+	/*dmif and mcifwr dram access efficiency*/
+	/*is the ratio between the ideal dram access time (which is the data buffer size in memory divided by the dram bandwidth), and the actual time which is the total page close-open time.  but it cannot exceed the dram efficiency provided by the memory subsystem*/
+	results->dmifdram_access_efficiency =
+		bw_min2(
+			bw_div(
+				bw_div(
+					results->total_display_reads_required_dram_access_data,
+					results->dram_bandwidth),
+				results->dmif_total_page_close_open_time),
+			bw_int_to_fixed(1));
+	if (bw_mtn(
+		results->total_display_writes_required_dram_access_data,
+		bw_int_to_fixed(0))) {
+		results->mcifwrdram_access_efficiency =
+			bw_min2(
+				bw_div(
+					bw_div(
+						results->total_display_writes_required_dram_access_data,
+						results->dram_bandwidth),
+					results->mcifwr_total_page_close_open_time),
+				bw_int_to_fixed(1));
+	} else {
+		results->mcifwrdram_access_efficiency = bw_int_to_fixed(0);
+	}
+	/*average bandwidth*/
+	/*the average bandwidth with no compression is the vertical active time is the source width times the bytes per pixel divided by the line time, multiplied by the vertical scale ratio and the ratio of bytes per request divided by the useful bytes per request.*/
+	/*the average bandwidth with compression is the same, divided by the compression ratio*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->average_bandwidth_no_compression[i] =
+				bw_div(
+					bw_mul(
+						bw_mul(
+							bw_div(
+								bw_mul(
+									results->source_width_rounded_up_to_chunks[i],
+									bw_int_to_fixed(
+										results->bytes_per_pixel[i])),
+								(bw_div(
+									results->h_total[i],
+									results->pixel_rate[i]))),
+							results->vsr[i]),
+						results->bytes_per_request[i]),
+					results->useful_bytes_per_request[i]);
+			results->average_bandwidth[i] = bw_div(
+				results->average_bandwidth_no_compression[i],
+				results->compression_rate[i]);
+		}
+	}
+	results->total_average_bandwidth_no_compression = bw_int_to_fixed(0);
+	results->total_average_bandwidth = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->total_average_bandwidth_no_compression =
+				bw_add(
+					results->total_average_bandwidth_no_compression,
+					results->average_bandwidth_no_compression[i]);
+			results->total_average_bandwidth = bw_add(
+				results->total_average_bandwidth,
+				results->average_bandwidth[i]);
+		}
+	}
+	/*stutter efficiency*/
+	/*the stutter efficiency is the frame-average time in self-refresh divided by the frame-average stutter cycle duration.  only applies if the display write-back is not enabled.*/
+	/*the frame-average stutter cycle used is the minimum for all pipes of the frame-average data buffer size in time, times the compression rate*/
+	/*the frame-average time in self-refresh is the stutter cycle minus the self refresh exit latency and the burst time*/
+	/*the stutter cycle is the dmif buffer size reduced by the excess of the stutter exit watermark over the lb size in time.*/
+	/*the burst time is the data needed during the stutter cycle divided by the available bandwidth*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->stutter_cycle_duration[i] =
+				bw_sub(
+					bw_mul(
+						bw_div(
+							bw_div(
+								bw_mul(
+									bw_div(
+										bw_div(
+											results->adjusted_data_buffer_size[i],
+											bw_int_to_fixed(
+												results->bytes_per_pixel[i])),
+										results->source_width_rounded_up_to_chunks[i]),
+									results->h_total[i]),
+								results->vsr[i]),
+							results->pixel_rate[i]),
+						results->compression_rate[i]),
+					bw_max2(
+						bw_int_to_fixed(0),
+						bw_sub(
+							results->stutter_exit_watermark[i],
+							bw_div(
+								bw_mul(
+									bw_int_to_fixed(
+										(2
+											+ results->line_buffer_prefetch[i])),
+									results->h_total[i]),
+								results->pixel_rate[i]))));
+		}
+	}
+	results->total_stutter_cycle_duration = bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_mtn(
+				results->total_stutter_cycle_duration,
+				results->stutter_cycle_duration[i])) {
+				results->total_stutter_cycle_duration =
+					results->stutter_cycle_duration[i];
+			}
+		}
+	}
+	results->stutter_burst_time = bw_div(
+		bw_mul(
+			results->total_stutter_cycle_duration,
+			results->total_average_bandwidth),
+		bw_min2(
+			(bw_mul(
+				results->dram_bandwidth,
+				results->dmifdram_access_efficiency)),
+			bw_mul(
+				sclk[results->sclk_level],
+				vbios->data_return_bus_width)));
+	results->time_in_self_refresh = bw_sub(
+		bw_sub(
+			results->total_stutter_cycle_duration,
+			vbios->stutter_self_refresh_exit_latency),
+		results->stutter_burst_time);
+	if (mode_data->d1_display_write_back_dwb_enable == 1) {
+		results->stutter_efficiency = bw_int_to_fixed(0);
+	} else if (bw_ltn(results->time_in_self_refresh, bw_int_to_fixed(0))) {
+		results->stutter_efficiency = bw_int_to_fixed(0);
+	} else {
+		results->stutter_efficiency = bw_mul(
+			bw_div(
+				results->time_in_self_refresh,
+				results->total_stutter_cycle_duration),
+			bw_int_to_fixed(100));
+	}
+	/*immediate flip time*/
+	/*if scatter gather is enabled, the immediate flip takes a number of urgent memory trips equivalent to the pte requests in a row divided by the pte request limit.*/
+	/*otherwise, it may take just one urgenr memory trip*/
+	results->worst_number_of_trips_to_memory = bw_int_to_fixed(1);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]
+			&& results->scatter_gather_enable_for_pipe[i] == 1) {
+			results->number_of_trips_to_memory_for_getting_apte_row[i] =
+				bw_ceil2(
+					bw_div(
+						results->scatter_gather_pte_requests_in_row[i],
+						results->scatter_gather_pte_request_limit[i]),
+					bw_int_to_fixed(1));
+			if (bw_ltn(
+				results->worst_number_of_trips_to_memory,
+				results->number_of_trips_to_memory_for_getting_apte_row[i])) {
+				results->worst_number_of_trips_to_memory =
+					results->number_of_trips_to_memory_for_getting_apte_row[i];
+			}
+		}
+	}
+	results->immediate_flip_time = bw_mul(
+		results->worst_number_of_trips_to_memory,
+		results->total_dmifmc_urgent_latency);
+	/*worst latency for other clients*/
+	/*it is the urgent latency plus the urgent burst time*/
+	results->latency_for_non_dmif_clients =
+		bw_add(
+			results->total_dmifmc_urgent_latency,
+			results->dmif_burst_time[results->y_clk_level][results->sclk_level]);
+	if (mode_data->d1_display_write_back_dwb_enable == 1) {
+		results->latency_for_non_mcifwr_clients = bw_add(
+			vbios->mcifwrmc_urgent_latency,
+			dceip->mcifwr_all_surfaces_burst_time);
+	} else {
+		results->latency_for_non_mcifwr_clients = bw_int_to_fixed(0);
+	}
+	/*dmif mc urgent latency suppported in high sclk and yclk*/
+	results->dmifmc_urgent_latency_supported_in_high_sclk_and_yclk = bw_div(
+		(bw_sub(
+			results->min_read_buffer_size_in_time,
+			results->dmif_burst_time[high][high])),
+		results->total_dmifmc_urgent_trips);
+	/*dram speed/p-state change margin*/
+	/*in the multi-display case the nb p-state change watermark cannot exceed the average lb size plus the dmif size or the cursor dcp buffer size*/
+	results->nbp_state_dram_speed_change_margin = bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->nbp_state_dram_speed_change_margin =
+				bw_min2(
+					results->nbp_state_dram_speed_change_margin,
+					bw_sub(
+						results->maximum_latency_hiding_with_cursor[i],
+						results->nbp_state_change_watermark[i]));
+		}
+	}
+	/*sclk required vs urgent latency*/
+	for (i = 1; i <= 5; i++) {
+		results->display_reads_time_for_data_transfer_and_urgent_latency =
+			bw_sub(
+				results->min_read_buffer_size_in_time,
+				bw_mul(
+					results->total_dmifmc_urgent_trips,
+					bw_int_to_fixed(i)));
+		if (pipe_check == bw_def_ok
+			&& (bw_mtn(
+				results->display_reads_time_for_data_transfer_and_urgent_latency,
+				results->dmif_total_page_close_open_time))) {
+			results->dmif_required_sclk_for_urgent_latency[i] =
+				bw_div(
+					bw_div(
+						results->total_display_reads_required_data,
+						results->display_reads_time_for_data_transfer_and_urgent_latency),
+					vbios->data_return_bus_width);
+		} else {
+			results->dmif_required_sclk_for_urgent_latency[i] =
+				bw_int_to_fixed(bw_def_na);
+		}
+	}
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+void bw_calcs_init(struct bw_calcs_dceip *bw_dceip,
+	struct bw_calcs_vbios *bw_vbios)
+{
+	struct bw_calcs_dceip dceip = {{ 0 }};
+	struct bw_calcs_vbios vbios = { 0 };
+
+	vbios.number_of_dram_channels = 2;
+	vbios.dram_channel_width_in_bits = 64;
+	vbios.number_of_dram_banks = 8;
+	vbios.high_yclk = bw_int_to_fixed(1600);
+	vbios.mid_yclk = bw_int_to_fixed(1600);
+	vbios.low_yclk = bw_frc_to_fixed(66666, 100);
+	vbios.low_sclk = bw_int_to_fixed(200);
+	vbios.mid_sclk = bw_int_to_fixed(300);
+	vbios.high_sclk = bw_frc_to_fixed(62609, 100);
+	vbios.low_voltage_max_dispclk = bw_int_to_fixed(352);
+	vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467);
+	vbios.high_voltage_max_dispclk = bw_int_to_fixed(643);
+	vbios.data_return_bus_width = bw_int_to_fixed(32);
+	vbios.trc = bw_int_to_fixed(50);
+	vbios.dmifmc_urgent_latency = bw_int_to_fixed(4);
+	vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(153, 10);
+	vbios.nbp_state_change_latency = bw_frc_to_fixed(19649, 1000);
+	vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10);
+	vbios.scatter_gather_enable = true;
+	vbios.down_spread_percentage = bw_frc_to_fixed(5, 10);
+	vbios.cursor_width = 32;
+	vbios.average_compression_rate = 4;
+	vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256;
+	vbios.blackout_duration = bw_int_to_fixed(18); /* us */
+	vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20);
+
+
+	dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
+	dceip.de_tiling_buffer = bw_int_to_fixed(0);
+	dceip.dcfclk_request_generation = 0;
+	dceip.lines_interleaved_into_lb = 2;
+	dceip.chunk_width = 256;
+	dceip.number_of_graphics_pipes = 3;
+	dceip.number_of_underlay_pipes = 1;
+	dceip.display_write_back_supported = false;
+	dceip.argb_compression_support = false;
+	dceip.underlay_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(
+		35556, 10000);
+	dceip.underlay_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(
+		34286, 10000);
+	dceip.underlay_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32,
+		10);
+	dceip.underlay_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3);
+	dceip.graphics_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35,
+		10);
+	dceip.graphics_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(
+		34286, 10000);
+	dceip.graphics_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32,
+		10);
+	dceip.graphics_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3);
+	dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3);
+	dceip.max_dmif_buffer_allocated = 2;
+	dceip.graphics_dmif_size = 12288;
+	dceip.underlay_luma_dmif_size = 19456;
+	dceip.underlay_chroma_dmif_size = 23552;
+	dceip.pre_downscaler_enabled = true;
+	dceip.underlay_downscale_prefetch_enabled = true;
+	dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1);
+	dceip.lb_size_per_component444 = bw_int_to_fixed(82176);
+	dceip.graphics_lb_nodownscaling_multi_line_prefetching = false;
+	dceip.stutter_and_dram_clock_state_change_gated_before_cursor =
+		bw_int_to_fixed(0);
+	dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed(82176);
+	dceip.underlay420_chroma_lb_size_per_component = bw_int_to_fixed(164352);
+	dceip.underlay422_lb_size_per_component = bw_int_to_fixed(82176);
+	dceip.cursor_chunk_width = bw_int_to_fixed(64);
+	dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4);
+	dceip.cursor_memory_interface_buffer_pixels = bw_int_to_fixed(64);
+	dceip.underlay_maximum_width_efficient_for_tiling = bw_int_to_fixed(1920);
+	dceip.underlay_maximum_height_efficient_for_tiling = bw_int_to_fixed(1080);
+	dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display =
+		bw_frc_to_fixed(3, 10);
+	dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation =
+		bw_int_to_fixed(25);
+	dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed(2);
+	dceip.maximum_total_outstanding_pte_requests_allowed_by_saw =
+		bw_int_to_fixed(128);
+	dceip.limit_excessive_outstanding_dmif_requests = true;
+	dceip.linear_mode_line_request_alternation_slice = bw_int_to_fixed(64);
+	dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = 32;
+	dceip.display_write_back420_luma_mcifwr_buffer_size = 12288;
+	dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192;
+	dceip.request_efficiency = bw_frc_to_fixed(8, 10);
+	dceip.dispclk_per_request = bw_int_to_fixed(2);
+	dceip.dispclk_ramping_factor = bw_frc_to_fixed(11, 10);
+	dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100);
+	dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2;
+	dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: this is a bug*/
+
+	*bw_dceip = dceip;
+	*bw_vbios = vbios;
+}
+
+/**
+ * Compare calculated (required) clocks against the clocks available at
+ * maximum voltage (max Performance Level).
+ */
+static bool is_display_configuration_supported(
+	const struct bw_calcs_vbios *vbios,
+	const struct bw_calcs_output *calcs_output)
+{
+	uint32_t int_max_clk;
+
+	int_max_clk = bw_fixed_to_int(vbios->high_voltage_max_dispclk);
+	int_max_clk *= 1000; /* MHz to kHz */
+	if (calcs_output->dispclk_khz > int_max_clk)
+		return false;
+
+	int_max_clk = bw_fixed_to_int(vbios->high_sclk);
+	int_max_clk *= 1000; /* MHz to kHz */
+	if (calcs_output->required_sclk > int_max_clk)
+		return false;
+
+	return true;
+}
+
+/**
+ * Return:
+ *	true -	Display(s) configuration supported.
+ *		In this case 'calcs_output' contains data for HW programming
+ *	false - Display(s) configuration not supported (not enough bandwidth).
+ */
+
+bool bw_calcs(struct dc_context *ctx, const struct bw_calcs_dceip *dceip,
+	const struct bw_calcs_vbios *vbios,
+	const struct bw_calcs_mode_data *mode_data,
+	struct bw_calcs_output *calcs_output)
+{
+	struct bw_calcs_results *bw_results_internal = dm_alloc(
+				ctx, sizeof(struct bw_calcs_results));
+	struct bw_calcs_mode_data_internal *bw_data_internal =
+		dm_alloc(
+			ctx, sizeof(struct bw_calcs_mode_data_internal));
+	switch (mode_data->number_of_displays) {
+	case (3):
+		bw_data_internal->d2_htotal =
+			mode_data->displays_data[2].h_total;
+		bw_data_internal->d2_pixel_rate =
+			mode_data->displays_data[2].pixel_rate;
+		bw_data_internal->d2_graphics_src_width =
+			mode_data->displays_data[2].graphics_src_width;
+		bw_data_internal->d2_graphics_src_height =
+			mode_data->displays_data[2].graphics_src_height;
+		bw_data_internal->d2_graphics_scale_ratio =
+			mode_data->displays_data[2].graphics_scale_ratio;
+		bw_data_internal->d2_graphics_stereo_mode =
+			mode_data->displays_data[2].graphics_stereo_mode;
+	case (2):
+		bw_data_internal->d1_display_write_back_dwb_enable = false;
+		bw_data_internal->d1_underlay_mode = bw_def_none;
+		bw_data_internal->d1_underlay_scale_ratio = bw_int_to_fixed(0);
+		bw_data_internal->d1_htotal =
+			mode_data->displays_data[1].h_total;
+		bw_data_internal->d1_pixel_rate =
+			mode_data->displays_data[1].pixel_rate;
+		bw_data_internal->d1_graphics_src_width =
+			mode_data->displays_data[1].graphics_src_width;
+		bw_data_internal->d1_graphics_src_height =
+			mode_data->displays_data[1].graphics_src_height;
+		bw_data_internal->d1_graphics_scale_ratio =
+			mode_data->displays_data[1].graphics_scale_ratio;
+		bw_data_internal->d1_graphics_stereo_mode =
+			mode_data->displays_data[1].graphics_stereo_mode;
+
+	case (1):
+		bw_data_internal->d0_fbc_enable =
+			mode_data->displays_data[0].fbc_enable;
+		bw_data_internal->d0_lpt_enable =
+			mode_data->displays_data[0].lpt_enable;
+		bw_data_internal->d0_underlay_mode =
+			mode_data->displays_data[0].underlay_mode;
+		bw_data_internal->d0_underlay_scale_ratio = bw_int_to_fixed(0);
+		bw_data_internal->d0_htotal =
+			mode_data->displays_data[0].h_total;
+		bw_data_internal->d0_pixel_rate =
+			mode_data->displays_data[0].pixel_rate;
+		bw_data_internal->d0_graphics_src_width =
+			mode_data->displays_data[0].graphics_src_width;
+		bw_data_internal->d0_graphics_src_height =
+			mode_data->displays_data[0].graphics_src_height;
+		bw_data_internal->d0_graphics_scale_ratio =
+			mode_data->displays_data[0].graphics_scale_ratio;
+		bw_data_internal->d0_graphics_stereo_mode =
+			mode_data->displays_data[0].graphics_stereo_mode;
+
+	default:
+		/* data for all displays */
+		bw_data_internal->number_of_displays =
+			mode_data->number_of_displays;
+		bw_data_internal->graphics_rotation_angle =
+			mode_data->displays_data[0].graphics_rotation_angle;
+		bw_data_internal->underlay_rotation_angle =
+			mode_data->displays_data[0].underlay_rotation_angle;
+		bw_data_internal->underlay_surface_type =
+			mode_data->displays_data[0].underlay_surface_type;
+		bw_data_internal->panning_and_bezel_adjustment =
+			mode_data->displays_data[0].panning_and_bezel_adjustment;
+		bw_data_internal->graphics_tiling_mode =
+			mode_data->displays_data[0].graphics_tiling_mode;
+		bw_data_internal->graphics_interlace_mode =
+			mode_data->displays_data[0].graphics_interlace_mode;
+		bw_data_internal->graphics_bytes_per_pixel =
+			mode_data->displays_data[0].graphics_bytes_per_pixel;
+		bw_data_internal->graphics_htaps =
+			mode_data->displays_data[0].graphics_h_taps;
+		bw_data_internal->graphics_vtaps =
+			mode_data->displays_data[0].graphics_v_taps;
+		bw_data_internal->graphics_lb_bpc =
+			mode_data->displays_data[0].graphics_lb_bpc;
+		bw_data_internal->underlay_lb_bpc =
+			mode_data->displays_data[0].underlay_lb_bpc;
+		bw_data_internal->underlay_tiling_mode =
+			mode_data->displays_data[0].underlay_tiling_mode;
+		bw_data_internal->underlay_htaps =
+			mode_data->displays_data[0].underlay_h_taps;
+		bw_data_internal->underlay_vtaps =
+			mode_data->displays_data[0].underlay_v_taps;
+		bw_data_internal->underlay_src_width =
+			mode_data->displays_data[0].underlay_src_width;
+		bw_data_internal->underlay_src_height =
+			mode_data->displays_data[0].underlay_src_height;
+		bw_data_internal->underlay_pitch_in_pixels =
+			mode_data->displays_data[0].underlay_pitch_in_pixels;
+		bw_data_internal->underlay_stereo_mode =
+			mode_data->displays_data[0].underlay_stereo_mode;
+		bw_data_internal->display_synchronization_enabled =
+			mode_data->display_synchronization_enabled;
+	}
+
+	if (bw_data_internal->number_of_displays != 0) {
+		uint8_t yclk_lvl, sclk_lvl;
+		struct bw_fixed high_sclk = vbios->high_sclk;
+		struct bw_fixed mid_sclk = vbios->mid_sclk;
+		struct bw_fixed low_sclk = vbios->low_sclk;
+		struct bw_fixed high_yclk = vbios->high_yclk;
+		struct bw_fixed mid_yclk = vbios->mid_yclk;
+		struct bw_fixed low_yclk = vbios->low_yclk;
+
+		calculate_bandwidth(dceip, vbios, bw_data_internal,
+							bw_results_internal);
+
+		yclk_lvl = bw_results_internal->y_clk_level;
+		sclk_lvl = bw_results_internal->sclk_level;
+
+		calcs_output->all_displays_in_sync =
+			mode_data->display_synchronization_enabled;
+		calcs_output->nbp_state_change_enable =
+			bw_results_internal->nbp_state_change_enable;
+		calcs_output->cpuc_state_change_enable =
+				bw_results_internal->cpuc_state_change_enable;
+		calcs_output->cpup_state_change_enable =
+				bw_results_internal->cpup_state_change_enable;
+		calcs_output->stutter_mode_enable =
+				bw_results_internal->stutter_mode_enable;
+		calcs_output->dispclk_khz =
+			bw_fixed_to_int(bw_mul(bw_results_internal->dispclk,
+					bw_int_to_fixed(1000)));
+		calcs_output->required_blackout_duration_us =
+			bw_fixed_to_int(bw_add(bw_results_internal->
+				blackout_duration_margin[yclk_lvl][sclk_lvl],
+				vbios->blackout_duration));
+		calcs_output->required_sclk =
+			bw_fixed_to_int(bw_mul(bw_results_internal->required_sclk,
+					bw_int_to_fixed(1000)));
+		calcs_output->required_sclk_deep_sleep =
+			bw_fixed_to_int(bw_mul(bw_results_internal->sclk_deep_sleep,
+					bw_int_to_fixed(1000)));
+		if (yclk_lvl == 0)
+			calcs_output->required_yclk = bw_fixed_to_int(
+				bw_mul(low_yclk, bw_int_to_fixed(1000)));
+		else if (yclk_lvl == 1)
+			calcs_output->required_yclk = bw_fixed_to_int(
+				bw_mul(mid_yclk, bw_int_to_fixed(1000)));
+		else
+			calcs_output->required_yclk = bw_fixed_to_int(
+				bw_mul(high_yclk, bw_int_to_fixed(1000)));
+
+		/* units: nanosecond, 16bit storage. */
+		calcs_output->nbp_state_change_wm_ns[0].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[4],bw_int_to_fixed(1000)));
+		calcs_output->nbp_state_change_wm_ns[1].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->nbp_state_change_wm_ns[2].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[6], bw_int_to_fixed(1000)));
+
+		calcs_output->stutter_exit_wm_ns[0].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->stutter_exit_wm_ns[1].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->stutter_exit_wm_ns[2].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[6], bw_int_to_fixed(1000)));
+
+		calcs_output->urgent_wm_ns[0].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->urgent_wm_ns[1].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->urgent_wm_ns[2].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[6], bw_int_to_fixed(1000)));
+
+		((struct bw_calcs_vbios *)vbios)->low_yclk = high_yclk;
+		((struct bw_calcs_vbios *)vbios)->mid_yclk = high_yclk;
+		((struct bw_calcs_vbios *)vbios)->low_sclk = high_sclk;
+		((struct bw_calcs_vbios *)vbios)->mid_sclk = high_sclk;
+
+		calculate_bandwidth(dceip, vbios, bw_data_internal,
+							bw_results_internal);
+
+		calcs_output->nbp_state_change_wm_ns[0].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->nbp_state_change_wm_ns[1].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->nbp_state_change_wm_ns[2].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[6], bw_int_to_fixed(1000)));
+
+		calcs_output->stutter_exit_wm_ns[0].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->stutter_exit_wm_ns[1].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->stutter_exit_wm_ns[2].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[6], bw_int_to_fixed(1000)));
+
+		calcs_output->urgent_wm_ns[0].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->urgent_wm_ns[1].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->urgent_wm_ns[2].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[6], bw_int_to_fixed(1000)));
+
+		((struct bw_calcs_vbios *)vbios)->low_yclk = low_yclk;
+		((struct bw_calcs_vbios *)vbios)->mid_yclk = mid_yclk;
+		((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk;
+		((struct bw_calcs_vbios *)vbios)->mid_sclk = mid_sclk;
+	} else {
+		calcs_output->nbp_state_change_enable = true;
+		calcs_output->cpuc_state_change_enable = true;
+		calcs_output->cpup_state_change_enable = true;
+		calcs_output->stutter_mode_enable = true;
+		calcs_output->dispclk_khz = 0;
+		calcs_output->required_sclk = 0;
+	}
+
+	dm_free(ctx, bw_data_internal);
+	dm_free(ctx, bw_results_internal);
+
+	return is_display_configuration_supported(vbios, calcs_output);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
new file mode 100644
index 000000000000..8a7a4c99fb5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "bw_fixed.h"
+
+
+#define BITS_PER_FRACTIONAL_PART 24
+
+#define MIN_I32 \
+	(int64_t)(-(1LL << (63 - BITS_PER_FRACTIONAL_PART)))
+
+#define MAX_I32 \
+	(int64_t)((1ULL << (63 - BITS_PER_FRACTIONAL_PART)) - 1)
+
+#define MIN_I64 \
+	(int64_t)(-(1LL << 63))
+
+#define MAX_I64 \
+	(int64_t)((1ULL << 63) - 1)
+
+
+#define FRACTIONAL_PART_MASK \
+	((1ULL << BITS_PER_FRACTIONAL_PART) - 1)
+
+#define GET_INTEGER_PART(x) \
+	((x) >> BITS_PER_FRACTIONAL_PART)
+
+#define GET_FRACTIONAL_PART(x) \
+	(FRACTIONAL_PART_MASK & (x))
+
+static uint64_t abs_i64(int64_t arg)
+{
+	if (arg >= 0)
+		return (uint64_t)(arg);
+	else
+		return (uint64_t)(-arg);
+}
+
+struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3)
+{
+	return bw_min2(bw_min2(v1, v2), v3);
+}
+
+struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3)
+{
+	return bw_max2(bw_max2(v1, v2), v3);
+}
+
+struct bw_fixed bw_int_to_fixed(int64_t value)
+{
+	struct bw_fixed res;
+	ASSERT(value < MAX_I32 && value > MIN_I32);
+	res.value = value << BITS_PER_FRACTIONAL_PART;
+	return res;
+}
+
+int32_t bw_fixed_to_int(struct bw_fixed value)
+{
+	return GET_INTEGER_PART(value.value);
+}
+
+struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator)
+{
+	struct bw_fixed res;
+	bool arg1_negative = numerator < 0;
+	bool arg2_negative = denominator < 0;
+	uint64_t arg1_value;
+	uint64_t arg2_value;
+	uint64_t remainder;
+
+	/* determine integer part */
+	uint64_t res_value;
+
+	ASSERT(denominator != 0);
+
+	arg1_value = (uint64_t)abs_i64(numerator);
+	arg2_value = (uint64_t)abs_i64(denominator);
+	res_value = div64_u64_rem(arg1_value, arg2_value, &remainder);
+
+	ASSERT(res_value <= MAX_I32);
+
+	/* determine fractional part */
+	{
+		uint32_t i = BITS_PER_FRACTIONAL_PART;
+
+		do
+		{
+			remainder <<= 1;
+
+			res_value <<= 1;
+
+			if (remainder >= arg2_value)
+			{
+				res_value |= 1;
+				remainder -= arg2_value;
+			}
+		} while (--i != 0);
+	}
+
+	/* round up LSB */
+	{
+		uint64_t summand = (remainder << 1) >= arg2_value;
+
+		ASSERT(res_value <= MAX_I64 - summand);
+
+		res_value += summand;
+	}
+
+	res.value = (int64_t)(res_value);
+
+	if (arg1_negative ^ arg2_negative)
+		res.value = -res.value;
+	return res;
+}
+
+struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return (arg1.value <= arg2.value) ? arg1 : arg2;
+}
+
+struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return (arg2.value <= arg1.value) ? arg1 : arg2;
+}
+
+struct bw_fixed bw_floor2(
+	const struct bw_fixed arg,
+	const struct bw_fixed significance)
+{
+	struct bw_fixed result;
+	int64_t multiplicand;
+	multiplicand = div64_s64(arg.value, abs_i64(significance.value));
+	result.value = abs_i64(significance.value) * multiplicand;
+	ASSERT(abs_i64(result.value) <= abs_i64(arg.value));
+	return result;
+}
+
+struct bw_fixed bw_ceil2(
+	const struct bw_fixed arg,
+	const struct bw_fixed significance)
+{
+	struct bw_fixed result;
+	int64_t multiplicand;
+
+	multiplicand = div64_s64(arg.value, abs_i64(significance.value));
+	result.value = abs_i64(significance.value) * multiplicand;
+	if (abs_i64(result.value) < abs_i64(arg.value)) {
+		if (arg.value < 0)
+			result.value -= abs_i64(significance.value);
+		else
+			result.value += abs_i64(significance.value);
+	}
+	return result;
+}
+
+struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res;
+
+	res.value = arg1.value + arg2.value;
+
+	return res;
+}
+
+struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res;
+
+	res.value = arg1.value - arg2.value;
+
+	return res;
+}
+
+struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res;
+
+	bool arg1_negative = arg1.value < 0;
+	bool arg2_negative = arg2.value < 0;
+
+	uint64_t arg1_value = abs_i64(arg1.value);
+	uint64_t arg2_value = abs_i64(arg2.value);
+
+	uint64_t arg1_int = GET_INTEGER_PART(arg1_value);
+	uint64_t arg2_int = GET_INTEGER_PART(arg2_value);
+
+	uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
+	uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
+
+	uint64_t tmp;
+
+	res.value = arg1_int * arg2_int;
+
+	ASSERT(res.value <= MAX_I32);
+
+	res.value <<= BITS_PER_FRACTIONAL_PART;
+
+	tmp = arg1_int * arg2_fra;
+
+	ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
+
+	res.value += tmp;
+
+	tmp = arg2_int * arg1_fra;
+
+	ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
+
+	res.value += tmp;
+
+	tmp = arg1_fra * arg2_fra;
+
+	tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
+		(tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value));
+
+	ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
+
+	res.value += tmp;
+
+	if (arg1_negative ^ arg2_negative)
+		res.value = -res.value;
+	return res;
+}
+
+struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res = bw_frc_to_fixed(arg1.value, arg2.value);
+	return res;
+}
+
+struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res;
+	div64_u64_rem(arg1.value, arg2.value, &res.value);
+	return res;
+}
+struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw)
+{
+	struct bw_fixed result = { 0 };
+
+	if (raw < 0) {
+		raw = -raw;
+		result.value = -(raw >> (32 - BITS_PER_FRACTIONAL_PART));
+	} else {
+		result.value = raw >> (32 - BITS_PER_FRACTIONAL_PART);
+	}
+
+	return result;
+}
+
+bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value == arg2.value;
+}
+
+bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value != arg2.value;
+}
+
+bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value <= arg2.value;
+}
+
+bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value >= arg2.value;
+}
+
+bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value < arg2.value;
+}
+
+bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value > arg2.value;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
new file mode 100644
index 000000000000..64ca20328315
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
@@ -0,0 +1,1992 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/fixed31_32.h"
+
+#include "scaler_filter.h"
+
+enum {
+	DOWN_DB_SCALES = 8,
+	DOWN_DB_POINTS = 11,
+
+	UP_DB_SCALES = 1,
+	UP_DB_POINTS = 7,
+
+	MIN_SHARPNESS = -50,
+	MAX_SHARPNESS = 50,
+
+	CONST_DIVIDER = 10000000,
+
+	MAX_HOR_DOWNSCALE = 1666000, /* 1:6  */
+	MAX_VER_DOWNSCALE = 1666000, /* 1:6  */
+
+	MAX_HOR_UPSCALE = 160000000, /* 16:1 */
+	MAX_VER_UPSCALE = 160000000, /* 16:1 */
+
+	THRESHOLDRATIOLOW = 8000000, /* 0.8 */
+	THRESHOLDRATIOUP = 10000000, /* 1.0 */
+
+	DOWN_DB_FUZZY = -120411996, /* -12.041200 */
+	DOWN_DB_FLAT = -60205998, /* -6.020600 */
+	DOWN_DB_SHARP = -10000000, /* -1.000000 */
+
+	UP_DB_FUZZY = -60205998, /* -6.020600 */
+	UP_DB_FLAT = 0,
+	UP_DB_SHARP = 60205998 /* 6.020600 */
+};
+
+static inline struct fixed31_32 max_hor_downscale(void)
+{
+	return dal_fixed31_32_from_fraction(MAX_HOR_DOWNSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 max_ver_downscale(void)
+{
+	return dal_fixed31_32_from_fraction(MAX_VER_DOWNSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 max_hor_upscale(void)
+{
+	return dal_fixed31_32_from_fraction(MAX_HOR_UPSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 max_ver_upscale(void)
+{
+	return dal_fixed31_32_from_fraction(MAX_VER_UPSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 threshold_ratio_low(void)
+{
+	return dal_fixed31_32_from_fraction(THRESHOLDRATIOLOW, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 threshold_ratio_up(void)
+{
+	return dal_fixed31_32_from_fraction(THRESHOLDRATIOUP, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 down_db_fuzzy(void)
+{
+	return dal_fixed31_32_from_fraction(DOWN_DB_FUZZY, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 down_db_flat(void)
+{
+	return dal_fixed31_32_from_fraction(DOWN_DB_FLAT, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 down_db_sharp(void)
+{
+	return dal_fixed31_32_from_fraction(DOWN_DB_SHARP, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 up_db_fuzzy(void)
+{
+	return dal_fixed31_32_from_fraction(UP_DB_FUZZY, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 up_db_flat(void)
+{
+	return dal_fixed31_32_from_fraction(UP_DB_FLAT, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 up_db_sharp(void)
+{
+	return dal_fixed31_32_from_fraction(UP_DB_SHARP, CONST_DIVIDER);
+}
+
+static const int32_t
+	downscaling_db_table[][DOWN_DB_SCALES + 1][DOWN_DB_POINTS] = {
+	/* 3 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			14302719,	14302719,	14302719,
+			10000000,	99999,		99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14302339,	14302339,	14302339,
+			10000000,	4452010,	99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14302760,	14302760,	14302760,
+			10000000,	7826979,	5258399,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14302819,	14302819,	14302819,
+			10000000,	8669400,	7414469,
+			4422729,	99999,		99999,
+			99999,		99999
+		},
+		{
+			14302730,	14302730,	12791190,
+			10000000,	9045640,	8180170,
+			6477950,	4599249,	2019010,
+			99999,		99999
+		},
+		{
+			14302699,	14302699,	12067849,
+			10000000,	9236029,	8541280,
+			7252740,	6021010,	4820120,
+			3511950,	1769340
+		},
+		{
+			14302710,	14302710,	11783510,
+			10000000,	9325690,	8704419,
+			7595670,	6583020,	5652850,
+			4749999,	3847680
+		},
+		{
+			14302920,	14302920,	11709250,
+			10000000,	9345560,	8754609,
+			7692559,	6738259,	5878239,
+			5057529,	4264070
+		}
+	},
+	/* 4 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			14308999,	14308999,	14308999,
+			10000000,	99999,		99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14308999,	14308999,	14308999,
+			10000000,	6311039,	99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14308999,	14308999,	14308999,
+			10000000,	8526669,	6832849,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14308999,	14308999,	12110630,
+			10000000,	9117940,	8230940,
+			6320130,	3719770,	99999,
+			99999,		99999
+		},
+		{
+			14308999,	14308999,	11474980,
+			10000000,	9370139,	8771979,
+			7601270,	6440780,	5249999,
+			3887520,	2039040
+		},
+		{
+			14308999,	13084859,	11179579,
+			10000000,	9495180,	9016919,
+			8134520,	7311699,	6560329,
+			5845720,	5155519
+		},
+		{
+			14308999,	12576600,	11048669,
+			10000000,	9550499,	9132360,
+			8368729,	7679399,	7073119,
+			6520900,	6015530
+		},
+		{
+			14308999,	12448530,	11007410,
+			10000000,	9566799,	9165279,
+			8435800,	7785279,	7215780,
+			6701470,	6240640
+		}
+	},
+	/* 5 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			8971139,	8971139,	8971139,
+			10000000,	99999,		99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			9466379,	9466379,	9466379,
+			10000000,	5648760,	3834280,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			15000000,	15000000,	14550110,
+			10000000,	7121120,	5994579,
+			4314630,	2606149,	99999,
+			99999,		99999
+		},
+		{
+			15000000,	15000000,	13047469,
+			10000000,	8368809,	7343569,
+			5970299,	4924620,	4029389,
+			3171139,	2276369
+		},
+		{
+			15000000,	14157199,	11897679,
+			10000000,	9166659,	8444600,
+			7287240,	6374719,	5615460,
+			4949580,	4350199
+		},
+		{
+			15000000,	12877819,	11224579,
+			10000000,	9488620,	9016109,
+			8203780,	7500000,	6883730,
+			6326839,	5818459
+		},
+		{
+			14733040,	12233200,	10939040,
+			10000000,	9608929,	9250000,
+			8623390,	8076940,	7606369,
+			7177749,	6785169
+		},
+		{
+			14627330,	12046170,	10862360,
+			10000000,	9639260,	9312710,
+			8737679,	8242470,	7815709,
+			7432209,	7082970
+		}
+	},
+	/* 6 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			8231559,	8231559,	8231559,
+			10000000,	99999,		99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			8353310,	8353310,	8353310,
+			10000000,	5504879,	4310710,
+			870359,		99999,		99999,
+			99999,		99999
+		},
+		{
+			8643479,	8643479,	8643479,
+			10000000,	6483510,	5768150,
+			4630779,	3580690,	2501940,
+			1015309,	99999
+		},
+		{
+			15000000,	15000000,	13493930,
+			10000000,	7516040,	6802409,
+			5824409,	5080109,	4454280,
+			3896749,	3386510
+		},
+		{
+			15000000,	14055930,	12321079,
+			10000000,	8872389,	8090410,
+			7035570,	6281229,	5676810,
+			5165010,	4717260
+		},
+		{
+			15000000,	12915290,	11311399,
+			10000000,	9460610,	8988440,
+			8202149,	7548679,	6999999,
+			6510639,	6065719
+		},
+		{
+			14310129,	12140829,	10901659,
+			10000000,	9635019,	9307180,
+			8740929,	8263260,	7858849,
+			7499330,	7170130
+		},
+		{
+			13815449,	11911309,	10801299,
+			10000000,	9669629,	9380580,
+			8878319,	8452050,	8097199,
+			7785030,	7504299
+		}
+	},
+	/* 7 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10616660,	10616660,	10616660,
+			10000000,	2646020,	99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	4936839,	4112670,
+			2729740,	896539,		99999,
+			99999,		99999
+		},
+		{
+			8345860,	8345860,	8345860,
+			10000000,	6034079,	5371739,
+			4466759,	3763799,	3155870,
+			2588019,	2026730
+		},
+		{
+			9298499,	9298499,	13768420,
+			10000000,	7174239,	6524270,
+			5670250,	5052099,	4549089,
+			4115279,	3722150
+		},
+		{
+			15000000,	14116940,	12563209,
+			10000000,	8542140,	7782419,
+			6865050,	6239479,	5758860,
+			5351870,	4992800
+		},
+		{
+			15000000,	12913750,	11306079,
+			10000000,	9452580,	8969209,
+			8168810,	7538409,	7029479,
+			6603180,	6227809
+		},
+		{
+			14390859,	11862809,	10757420,
+			10000000,	9688709,	9404249,
+			8904439,	8472480,	8099079,
+			7765330,	7459110
+		},
+		{
+			13752900,	11554559,	10637769,
+			10000000,	9736120,	9499999,
+			9079759,	8718389,	8408790,
+			8134469,	7886120
+		}
+	},
+	/* 8 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			11277090,	11277090,	11277090,
+			10000000,	2949059,	99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			11196039,	11196039,	11196039,
+			10000000,	4627540,	4018869,
+			3018769,	2000000,	250770,
+			99999,		99999
+		},
+		{
+			10878369,	10878369,	10878369,
+			10000000,	5657230,	5118110,
+			4372630,	3809120,	3337709,
+			2919510,	2535369
+		},
+		{
+			9090089,	9090089,	13961290,
+			10000000,	6929969,	6334999,
+			5569829,	5019649,	4584150,
+			4208610,	3876540
+		},
+		{
+			15000000,	14173229,	12732659,
+			10000000,	8267070,	7575380,
+			6764540,	6218209,	5803539,
+			5454990,	5146239
+		},
+		{
+			15000000,	12928279,	11292259,
+			10000000,	9447429,	8954229,
+			8141599,	7516989,	7039459,
+			6649519,	6316819
+		},
+		{
+			14661350,	11638879,	10665880,
+			10000000,	9722669,	9464690,
+			9013469,	8613470,	8266339,
+			7949870,	7663450
+		},
+		{
+			13861900,	11311980,	10543940,
+			10000000,	9772019,	9565100,
+			9198870,	8881340,	8609200,
+			8365769,	8147500
+		}
+	},
+	/* 9 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{	10099999,	10099999,	10099999,
+			10000000,	2939159,	1526470,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			11726609,	11726609,	11726609,
+			10000000,	4329420,	3805609,
+			3030480,	2363760,	1732099,
+			980139,		99999
+		},
+		{
+			10949269,	10949269,	10949269,
+			10000000,	5452589,	4946640,
+			4277969,	3790729,	3392640,
+			3048950,	2750000
+		},
+		{
+			8830279,	8830279,	14084529,
+			10000000,	6743149,	6182519,
+			5482980,	5000000,	4622060,
+			4303340,	4022600
+		},
+		{
+			9709150,	14111399,	12800760,
+			10000000,	7989749,	7445629,
+			6741260,	6241980,	5857459,
+			5534989,	5255370
+		},
+		{
+			15000000,	12830289,	11489900,
+			10000000,	9302089,	8767340,
+			8025540,	7500000,	7100800,
+			6768149,	6481850
+		},
+		{
+			14873609,	11576000,	10650579,
+			10000000,	9731360,	9483649,
+			9054650,	8680559,	8358049,
+			8066400,	7802420
+		},
+		{
+			12981410,	11185950,	10491620,
+			10000000,	9795730,	9611030,
+			9286710,	9007279,	8768100,
+			8553469,	8361340
+		}
+	},
+	/* 10 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			8993279,	8993279,	8993279,
+			10000000,	2921360,	1905619,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			9064850,	9064850,	9064850,
+			10000000,	4095619,	3655839,
+			3021000,	2500000,	2031680,
+			1566990,	1055440
+		},
+		{
+			11043460,	11043460,	11043460,
+			10000000,	5287479,	4816150,
+			4208439,	3769229,	3418970,
+			3117449,	2850320
+		},
+		{
+			8651900,	8651900,	14169909,
+			10000000,	6596950,	6071490,
+			5423219,	4980779,	4644620,
+			4362219,	4114899
+		},
+		{
+			9246050,	14055370,	12832759,
+			10000000,	7831320,	7369570,
+			6731680,	6262450,	5897690,
+			5592269,	5328789
+		},
+		{
+			15000000,	12770450,	11642129,
+			10000000,	9120929,	8601920,
+			7946630,	7490440,	7140589,
+			6847490,	6593719
+		},
+		{
+			14062479,	11541219,	10644329,
+			10000000,	9736120,	9495139,
+			9080520,	8724340,	8419489,
+			8146359,	7899820
+		},
+		{
+			12507469,	11102950,	10457479,
+			10000000,	9811149,	9641249,
+			9344969,	9090980,	8875219,
+			8684499,	8513180
+		}
+	},
+	/* 11 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10099509,	10099509,	10099509,
+			10000000,	2788810,	2054850,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			8872069,	8872069,	8872069,
+			10000000,	3929649,	3522840,
+			2963230,	2527720,	2157579,
+			1823610,	1500000
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	5155599,	4712319,
+			4154500,	3759450,	3448629,
+			3183139,	2948490
+		},
+		{
+			10511649,	10511649,	14216580,
+			10000000,	6445930,	5988820,
+			5401239,	4988409,	4673399,
+			4410479,	4181599
+		},
+		{
+			9170889,	14003310,	12949769,
+			10000000,	7684900,	7250000,
+			6670129,	6255810,	5934680,
+			5664110,	5427970
+		},
+		{
+			15000000,	12763030,	11734730,
+			10000000,	8958870,	8478559,
+			7893459,	7489529,	7179200,
+			6917790,	6688359
+		},
+		{
+			14634610,	11491880,	10619130,
+			10000000,	9744859,	9509819,
+			9102900,	8760340,	8463050,
+			8202620,	7968729
+		},
+		{
+			12415319,	10980290,	10405089,
+			10000000,	9831910,	9680110,
+			9413710,	9184579,	8987190,
+			8813819,	8655819
+		}
+	},
+	/* 12 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10832400,	10832400,	10832400,
+			10000000,	2700819,	2115820,
+			750000,		99999,		99999,
+			99999,		99999
+		},
+		{
+			10747549,	10747549,	10747549,
+			10000000,	3781630,	3415020,
+			2914879,	2537429,	2221180,
+			1943199,	1688420
+		},
+		{
+			11630790,	11630790,	11630790,
+			10000000,	5047429,	4631519,
+			4113860,	3750000,	3469760,
+			3229379,	3016360
+		},
+		{
+			10780229,	10780229,	10780229,
+			10000000,	6340010,	5935009,
+			5387600,	4995940,	4695929,
+			4446829,	4231610
+		},
+		{
+			9055669,	13968739,	13037070,
+			10000000,	7556660,	7149490,
+			6625509,	6250000,	5958870,
+			5713790,	5500869
+		},
+		{
+			14614900,	12760740,	11806739,
+			10000000,	8824530,	8388419,
+			7857400,	7489010,	7206150,
+			6968010,	6759889
+		},
+		{
+			14894100,	11451840,	10598870,
+			10000000,	9750000,	9521099,
+			9122239,	8784019,	8494700,
+			8243309,	8018680
+		},
+		{
+			12298769,	10886880,	10367530,
+			10000000,	9846829,	9708030,
+			9464049,	9252949,	9072539,
+			8910980,	8766649
+		}
+	},
+	/* 13 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	2574490,	2099110,
+			1194889,	99999,		99999,
+			99999,		99999
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	3679780,	3332070,
+			2869139,	2530030,	2251899,
+			2010450,	1793050
+		},
+		{
+			9306690,	9306690,	9306690,
+			10000000,	4964010,	4573009,
+			4082309,	3742089,	3481810,
+			3262990,	3070969
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	6217889,	5843269,
+			5353810,	5000000,	4730190,
+			4499999,	4301390
+		},
+		{
+			8819990,	13964320,	13098440,
+			10000000,	7454770,	7075160,
+			6591439,	6250000,	5983970,
+			5760229,	5564339
+		},
+		{
+			14432849,	12727780,	11847709,
+			10000000,	8695709,	8322049,
+			7842620,	7500000,	7234820,
+			7010849,	6814730
+		},
+		{
+			15000000,	11440130,	10620100,
+			10000000,	9742270,	9508739,
+			9110010,	8782560,	8510140,
+			8276290,	8069980
+		},
+		{
+			12039999,	10825289,	10341939,
+			10000000,	9858080,	9729740,
+			9505100,	9310669,	9144560,
+			8996559,	8862569
+		}
+	},
+	/* 14 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			9289590,	9289590,	9289590,
+			10000000,	2485270,	2084970,
+			1362659,	250000,		99999,
+			99999,		99999
+		},
+		{
+			9484500,	9484500,	9484500,
+			10000000,	3593840,	3263100,
+			2833609,	2519409,	2267650,
+			2050379,	1856749
+		},
+		{
+			9237130,	9237130,	9237130,
+			10000000,	4898909,	4527629,
+			4057880,	3734529,	3490320,
+			3287230,	3111050
+		},
+		{
+			9543399,	9543399,	9543399,
+			10000000,	6110230,	5772359,
+			5328080,	5007240,	4757330,
+			4545379,	4359109
+		},
+		{
+			9032660,	9032660,	9032660,
+			10000000,	7373520,	7016940,
+			6565740,	6250000,	6002650,
+			5794939,	5610830
+		},
+		{
+			14351329,	12697319,	11875350,
+			10000000,	8606730,	8275989,
+			7833449,	7510430,	7257339,
+			7043970,	6857690
+		},
+		{
+			13286800,	11436090,	10643019,
+			10000000,	9729470,	9491149,
+			9096930,	8778640,	8519319,
+			8299450,	8104829
+		},
+		{
+			11838380,	10778709,	10322740,
+			10000000,	9866499,	9746059,
+			9535790,	9354810,	9200339,
+			9063839,	8940430
+		}
+	},
+	/* 15 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			9193199,	9193199,	9193199,
+			10000000,	2400999,	2042409,
+			1450179,	789309,		99999,
+			99999,		99999
+		},
+		{
+			10755189,	10755189,	10755189,
+			10000000,	3532319,	3212479,
+			2803660,	2510200,	2278629,
+			2078720,	1899970
+		},
+		{
+			8732669,	8732669,	8732669,
+			10000000,	4821290,	4483030,
+			4045079,	3737959,	3505080,
+			3311960,	3143329
+		},
+		{
+			9450280,	9450280,	9450280,
+			10000000,	6040880,	5718960,
+			5302609,	5004199,	4771710,
+			4575310,	4404180
+		},
+		{
+			10520930,	10520930,	10520930,
+			10000000,	7298259,	6975160,
+			6552690,	6250000,	6018469,
+			5822089,	5648869
+		},
+		{
+			14320160,	12683949,	11917040,
+			10000000,	8541300,	8228710,
+			7812070,	7509459,	7272909,
+			7072560,	6895729
+		},
+		{
+			15000000,	11434819,	10650700,
+			10000000,	9723110,	9480339,
+			9083300,	8771640,	8524850,
+			8317480,	8135899
+		},
+		{
+			11750520,	10722860,	10299190,
+			10000000,	9875990,	9763770,
+			9567070,	9397709,	9252669,
+			9124029,	9008929
+		}
+	},
+	/* 16 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10612260,	10612260,	10612260,
+			10000000,	2308720,	1999289,
+			1495770,	1009820,	315460,
+			99999,		99999
+		},
+		{
+			9394969,	9394969,	9394969,
+			10000000,	3462660,	3162190,
+			2780120,	2508420,	2295179,
+			2109449,	1943989
+		},
+		{
+			10609409,	10609409,	10609409,
+			10000000,	4749999,	4447000,
+			4039109,	3746300,	3522360,
+			3336620,	3177059
+		},
+		{
+			9435039,	9435039,	9435039,
+			10000000,	5978109,	5675160,
+			5282300,	5000000,	4782429,
+			4598149,	4438050
+		},
+		{
+			10592620,	10592620,	10592620,
+			10000000,	7244589,	6940630,
+			6537730,	6250000,	6027920,
+			5842260,	5680159
+		},
+		{
+			14282959,	12678509,	11963449,
+			10000000,	8484349,	8181620,
+			7785459,	7500000,	7281309,
+			7095699,	6932809
+		},
+		{
+			15000000,	11434919,	10673819,
+			10000000,	9708179,	9456859,
+			9060000,	8760929,	8529940,
+			8338279,	8172209
+		},
+		{
+			11690390,	10668220,	10277210,
+			10000000,	9884750,	9780330,
+			9597110,	9439319,	9304260,
+			9183580,	9075019
+		}
+	}
+};
+
+static const int32_t upscaling_db_table[][UP_DB_SCALES+1][UP_DB_POINTS] = {
+	/* 3 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			14302920,	14302920,	11709250,
+			10000000,
+			8754609,	7692559,	6738259
+		}
+	},
+	/*	4 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			14308999,	12448530,	11007410,
+			10000000,	9165279,	8435800,
+			7785279
+		}
+	},
+	/* 5 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			14627330,	12046170,	10862360,
+			10000000,
+			9312710,	8737679,	8242470
+		}
+	},
+	/* 6 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			13815449,	11911309,	10801299,
+			10000000,
+			9380580,	8878319,	8452050
+		}
+	},
+	/* 7 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			13752900,	11554559,	10637769,
+			10000000,
+			9499999,	9079759,	8718389
+		}
+	},
+	/* 8 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			13861900,	11311980,	10543940,
+			10000000,
+			9565100,	9198870,	8881340
+		}
+	},
+	/* 9 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12981410,	11185950,	10491620,
+			10000000,
+			9611030,	9286710,	9007279
+		}
+	},
+	/* 10 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12507469,	11102950,	10457479,
+			10000000,
+			9641249,	9344969,	9090980
+		}
+	},
+	/* 11 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12415319,	10980290,	10405089,
+			10000000,
+			9680110,	9413710,	9184579
+		}
+	},
+	/* 12 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12298769,	10886880,	10367530,
+			10000000,
+			9708030,	9464049,	9252949
+		}
+	},
+	/* 13 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12039999,	10825289,	10341939,
+			10000000,
+			9729740,	9505100,	9310669
+		}
+	},
+	/* 14 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			11838380,	10778709,	10322740,
+			10000000,
+			9746059,	9535790,	9354810
+		}
+	},
+	/* 15 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			11750520,	10722860,	10299190,
+			10000000,
+			9763770,	9567070,	9397709
+		}
+	},
+	/* 16 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			11690390,	10668220,	10277210,
+			10000000,
+			9780330,	9597110,	9439319
+		}
+	}
+};
+
+static bool allocate_3d_storage(
+	struct dc_context *ctx,
+	struct fixed31_32 ****ptr,
+	int32_t numberof_tables,
+	int32_t numberof_rows,
+	int32_t numberof_columns)
+{
+	int32_t indexof_table = 0;
+	int32_t indexof_row = 0;
+
+	struct fixed31_32 ***tables = dm_alloc(
+		ctx,
+		numberof_tables * sizeof(struct fixed31_32 **));
+
+	if (!tables) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	while (indexof_table != numberof_tables) {
+		struct fixed31_32 **rows = dm_alloc(
+			ctx,
+			numberof_rows * sizeof(struct fixed31_32 *));
+
+		if (!rows) {
+			BREAK_TO_DEBUGGER();
+			--indexof_table;
+			goto failure;
+		}
+
+		tables[indexof_table] = rows;
+
+		while (indexof_row != numberof_rows) {
+			struct fixed31_32 *columns = dm_alloc(
+				ctx,
+				numberof_columns * sizeof(struct fixed31_32));
+
+			if (!columns) {
+				BREAK_TO_DEBUGGER();
+				--indexof_row;
+				goto failure;
+			}
+
+			rows[indexof_row] = columns;
+
+			++indexof_row;
+		}
+
+		indexof_row = 0;
+
+		++indexof_table;
+	}
+
+	*ptr = tables;
+
+	return true;
+
+failure:
+
+	while (indexof_table >= 0) {
+		while (indexof_row >= 0) {
+			dm_free(ctx, tables[indexof_table][indexof_row]);
+
+			--indexof_row;
+		}
+
+		indexof_row = numberof_rows - 1;
+
+		dm_free(ctx, tables[indexof_table]);
+
+		--indexof_table;
+	}
+
+	dm_free(ctx, tables);
+
+	return false;
+}
+
+static void destroy_3d_storage(
+	struct dc_context *ctx,
+	struct fixed31_32 ****ptr,
+	uint32_t numberof_tables,
+	uint32_t numberof_rows)
+{
+	struct fixed31_32 ***tables = *ptr;
+
+	uint32_t indexof_table = 0;
+
+	if (!tables)
+		return;
+
+	while (indexof_table != numberof_tables) {
+		uint32_t indexof_row = 0;
+
+		while (indexof_row != numberof_rows) {
+			dm_free(
+				ctx, tables[indexof_table][indexof_row]);
+
+			++indexof_row;
+		};
+
+		dm_free(ctx, tables[indexof_table]);
+
+		++indexof_table;
+	};
+
+	dm_free(ctx, tables);
+
+	*ptr = NULL;
+}
+
+static bool create_downscaling_table(
+	struct scaler_filter *filter)
+{
+	const int32_t numberof_tables =
+		ARRAY_SIZE(downscaling_db_table);
+	const int32_t numberof_rows =
+		ARRAY_SIZE(downscaling_db_table[0]);
+	const int32_t numberof_columns =
+		ARRAY_SIZE(downscaling_db_table[0][0]);
+
+	int32_t indexof_table = 0;
+
+	if (!allocate_3d_storage(filter->ctx, &filter->downscaling_table,
+		numberof_tables, numberof_rows, numberof_columns)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	while (indexof_table != numberof_tables) {
+		struct fixed31_32 **table =
+			filter->downscaling_table[indexof_table];
+
+		int32_t indexof_row = 0;
+
+		while (indexof_row != numberof_rows) {
+			struct fixed31_32 *row = table[indexof_row];
+
+			int32_t indexof_column = 0;
+
+			while (indexof_column != numberof_columns) {
+				row[indexof_column] =
+dal_fixed31_32_from_fraction(
+	downscaling_db_table[indexof_table][indexof_row][indexof_column],
+	CONST_DIVIDER);
+
+				++indexof_column;
+			}
+
+			++indexof_row;
+		}
+
+		++indexof_table;
+	}
+
+	return true;
+}
+
+static inline void destroy_downscaling_table(
+	struct scaler_filter *filter)
+{
+	destroy_3d_storage(
+		filter->ctx,
+		&filter->downscaling_table,
+		ARRAY_SIZE(downscaling_db_table),
+		ARRAY_SIZE(downscaling_db_table[0]));
+}
+
+static bool create_upscaling_table(
+	struct scaler_filter *filter)
+{
+	const int32_t numberof_tables =
+		ARRAY_SIZE(upscaling_db_table);
+	const int32_t numberof_rows =
+		ARRAY_SIZE(upscaling_db_table[0]);
+	const int32_t numberof_columns =
+		ARRAY_SIZE(upscaling_db_table[0][0]);
+
+	int32_t indexof_table = 0;
+
+	if (!allocate_3d_storage(filter->ctx, &filter->upscaling_table,
+		numberof_tables, numberof_rows, numberof_columns)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	while (indexof_table != numberof_tables) {
+		struct fixed31_32 **table =
+			filter->upscaling_table[indexof_table];
+
+		int32_t indexof_row = 0;
+
+		while (indexof_row != numberof_rows) {
+			struct fixed31_32 *row = table[indexof_row];
+
+			int32_t indexof_column = 0;
+
+			while (indexof_column != numberof_columns) {
+				row[indexof_column] =
+dal_fixed31_32_from_fraction(
+	upscaling_db_table[indexof_table][indexof_row][indexof_column],
+	CONST_DIVIDER);
+
+				++indexof_column;
+			}
+
+			++indexof_row;
+		}
+
+		++indexof_table;
+	}
+
+	return true;
+}
+
+static inline void destroy_upscaling_table(
+	struct scaler_filter *filter)
+{
+	destroy_3d_storage(
+		filter->ctx,
+		&filter->upscaling_table,
+		ARRAY_SIZE(upscaling_db_table),
+		ARRAY_SIZE(upscaling_db_table[0]));
+}
+
+static bool same_filter_required(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	uint32_t src_size,
+	uint32_t dst_size)
+{
+	if (!filter->src_size)
+		return false;
+	if (!filter->dst_size)
+		return false;
+	if (filter->src_size != src_size)
+		return false;
+	if (filter->dst_size != dst_size)
+		return false;
+	if (filter->params.taps != params->taps)
+		return false;
+	if (filter->params.phases != params->phases)
+		return false;
+	if (filter->params.sharpness != params->sharpness)
+		return false;
+
+	return true;
+}
+
+/*
+ * @brief
+ *                                            (scale_max - scale_min)
+ * result = scale_min + (value - value_min) * -----------------------
+ *                                            (value_max - value_min)
+ */
+
+static struct fixed31_32 interpolate(
+	struct fixed31_32 value,
+	struct fixed31_32 value_min,
+	struct fixed31_32 value_max,
+	struct fixed31_32 scale_min,
+	struct fixed31_32 scale_max)
+{
+	return dal_fixed31_32_add(
+		scale_min,
+		dal_fixed31_32_div(
+			dal_fixed31_32_mul(
+				dal_fixed31_32_sub(
+					value,
+					value_min),
+				dal_fixed31_32_sub(
+					scale_max,
+					scale_min)),
+			dal_fixed31_32_sub(
+				value_max,
+				value_min)));
+}
+
+static bool map_sharpness(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	uint32_t src_size,
+	uint32_t dst_size,
+	struct fixed31_32 *attenuation,
+	struct fixed31_32 *decibels_at_nyquist)
+{
+	struct fixed31_32 ratio = dal_fixed31_32_from_fraction(
+		dst_size,
+		src_size);
+
+	const struct fixed31_32 sharp_flat =
+		dal_fixed31_32_from_fraction(MIN_SHARPNESS + MAX_SHARPNESS, 2);
+
+	struct fixed31_32 sharp_max =
+		dal_fixed31_32_from_int(MAX_SHARPNESS);
+	struct fixed31_32 sharp_min =
+		dal_fixed31_32_from_int(MIN_SHARPNESS);
+
+	uint32_t index = params->taps - 3;
+
+	struct fixed31_32 ratio_low;
+	struct fixed31_32 ratio_up;
+
+	struct fixed31_32 db_min;
+	struct fixed31_32 db_flat;
+	struct fixed31_32 db_max;
+	struct fixed31_32 db_value;
+
+	uint32_t i0;
+	uint32_t i1;
+	uint32_t row0;
+	uint32_t row1;
+
+	int32_t sharp = params->sharpness;
+
+	if (sharp < MIN_SHARPNESS)
+		sharp = MIN_SHARPNESS;
+	else if (sharp > MAX_SHARPNESS)
+		sharp = MAX_SHARPNESS;
+
+	if (params->flags.bits.HORIZONTAL) {
+		if (dal_fixed31_32_lt(ratio, max_hor_downscale())) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		} else if (dal_fixed31_32_lt(
+			max_hor_upscale(), ratio)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+	} else {
+		if (dal_fixed31_32_lt(ratio, max_ver_downscale())) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		} else if (dal_fixed31_32_lt(
+			max_ver_upscale(), ratio)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+	}
+
+	if (dst_size >= src_size) {
+		if (sharp < 0) {
+			db_max = up_db_flat();
+			db_min = up_db_fuzzy();
+
+			sharp_max = sharp_flat;
+		} else {
+			db_max = up_db_sharp();
+			db_min = up_db_flat();
+
+			sharp_min = sharp_flat;
+		}
+
+		db_value = interpolate(
+			dal_fixed31_32_from_int(sharp),
+			sharp_min, sharp_max,
+			db_min, db_max);
+
+		i0 = 0;
+
+		while (dal_fixed31_32_lt(
+			db_value, filter->upscaling_table[index][0][i0]) &&
+			(i0 < UP_DB_POINTS - 1))
+			++i0;
+
+		i1 = i0 + 1;
+
+		if (i0 == UP_DB_POINTS - 1)
+			i1 = i0--;
+
+		sharp_max = filter->upscaling_table[index][1][i0];
+		sharp_min = filter->upscaling_table[index][1][i1];
+
+		db_max = filter->upscaling_table[index][0][i0];
+		db_min = filter->upscaling_table[index][0][i1];
+
+		*attenuation = interpolate(
+			db_value,
+			db_max, db_min,
+			sharp_max, sharp_min);
+
+		*decibels_at_nyquist = db_value;
+
+		return true;
+	} else if ((5 * dst_size) < (src_size << 2)) {
+		if (sharp < 0) {
+			db_max = down_db_flat();
+			db_min = down_db_fuzzy();
+
+			sharp_max = sharp_flat;
+		} else {
+			db_max = down_db_sharp();
+			db_min = down_db_flat();
+
+			sharp_min = sharp_flat;
+		}
+
+		db_value = interpolate(
+			dal_fixed31_32_from_int(sharp),
+			sharp_min, sharp_max,
+			db_min, db_max);
+	} else {
+		struct fixed31_32 db_value_min =
+			filter->downscaling_table[index][0][0];
+
+		struct fixed31_32 db_value_max =
+			filter->downscaling_table[index][0][DOWN_DB_POINTS - 1];
+
+		db_min = interpolate(
+			ratio,
+			threshold_ratio_low(), threshold_ratio_up(),
+			down_db_fuzzy(), up_db_fuzzy());
+
+		db_flat = interpolate(
+			ratio,
+			threshold_ratio_low(), threshold_ratio_up(),
+			down_db_flat(), up_db_flat());
+
+		db_max = interpolate(
+			ratio,
+			threshold_ratio_low(), threshold_ratio_up(),
+			down_db_sharp(), up_db_sharp());
+
+		if (sharp < 0) {
+			db_max = db_flat;
+
+			db_value = interpolate(
+				dal_fixed31_32_from_int(sharp),
+				sharp_min, dal_fixed31_32_zero,
+				db_min, db_max);
+		} else {
+			db_min = db_flat;
+
+			db_value = interpolate(
+				dal_fixed31_32_from_int(sharp),
+				dal_fixed31_32_zero, sharp_max,
+				db_min, db_max);
+		}
+
+		if (dal_fixed31_32_lt(db_value_min, db_value))
+			db_value = db_value_min;
+		else if (dal_fixed31_32_lt(db_value, db_value_max))
+			db_value = db_value_max;
+	}
+
+	i1 = 0;
+
+	while (dal_fixed31_32_lt(db_value,
+		filter->downscaling_table[index][0][i1]) &&
+		(i1 < DOWN_DB_POINTS - 1))
+		++i1;
+
+	if (i1 == 0)
+		i0 = i1++;
+	else
+		i0 = i1 - 1;
+
+	row0 = dal_fixed31_32_round(
+		dal_fixed31_32_mul_int(ratio, DOWN_DB_SCALES));
+
+	if (dal_fixed31_32_lt(
+		dal_fixed31_32_from_fraction(row0, DOWN_DB_SCALES), ratio)) {
+		row1 = row0 + 1;
+
+		if (row1 > DOWN_DB_SCALES) {
+			row1 = DOWN_DB_SCALES;
+			row0 = row1 - 1;
+		}
+	} else {
+		row1 = row0--;
+
+		if (row0 < 1) {
+			row0 = 1;
+			row1 = 2;
+		}
+	}
+
+	ratio_low = dal_fixed31_32_from_fraction(row0, DOWN_DB_SCALES);
+	ratio_up = dal_fixed31_32_from_fraction(row1, DOWN_DB_SCALES);
+
+	sharp_max = interpolate(
+		ratio,
+		ratio_low, ratio_up,
+		filter->downscaling_table[index][row0][i0],
+		filter->downscaling_table[index][row1][i0]);
+
+	sharp_min = interpolate(
+		ratio,
+		ratio_low, ratio_up,
+		filter->downscaling_table[index][row0][i1],
+		filter->downscaling_table[index][row1][i1]);
+
+	db_max = filter->downscaling_table[index][0][i0];
+	db_min = filter->downscaling_table[index][0][i1];
+
+	*attenuation = interpolate(
+		db_value,
+		db_max, db_min,
+		sharp_max, sharp_min);
+
+	*decibels_at_nyquist = db_value;
+
+	return true;
+}
+
+static inline struct fixed31_32 lanczos(
+	struct fixed31_32 x,
+	struct fixed31_32 a2)
+{
+	return dal_fixed31_32_mul(
+		dal_fixed31_32_sinc(x),
+		dal_fixed31_32_sinc(
+			dal_fixed31_32_mul(x, a2)));
+}
+
+static bool generate_filter(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	struct fixed31_32 attenuation,
+	struct fixed31_32 *ringing)
+{
+	uint32_t n = params->phases * params->taps;
+
+	uint32_t coefficients_quantity = n;
+	uint32_t coefficients_sum_quantity = params->phases;
+
+	uint32_t i;
+	uint32_t i_limit;
+	uint32_t j;
+	uint32_t m;
+
+	struct fixed31_32 attenby2;
+
+	struct fixed31_32 a_max = dal_fixed31_32_zero;
+	struct fixed31_32 a_min = dal_fixed31_32_zero;
+
+	if (filter->coefficients_quantity < coefficients_quantity) {
+		if (filter->coefficients) {
+			dm_free(filter->ctx, filter->coefficients);
+
+			filter->coefficients = NULL;
+			filter->coefficients_quantity = 0;
+		}
+
+		filter->coefficients = dm_alloc(
+			filter->ctx,
+			coefficients_quantity * sizeof(struct fixed31_32));
+
+		if (!filter->coefficients) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		filter->coefficients_quantity = coefficients_quantity;
+	}
+
+	i = 0;
+
+	while (i != filter->coefficients_quantity) {
+		filter->coefficients[i] = dal_fixed31_32_zero;
+
+		++i;
+	}
+
+	if (filter->coefficients_sum_quantity < coefficients_sum_quantity) {
+		if (filter->coefficients_sum) {
+			dm_free(filter->ctx, filter->coefficients_sum);
+
+			filter->coefficients_sum = NULL;
+			filter->coefficients_sum_quantity = 0;
+		}
+
+		filter->coefficients_sum = dm_alloc(
+			filter->ctx,
+			coefficients_sum_quantity * sizeof(struct fixed31_32));
+
+		if (!filter->coefficients_sum) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		filter->coefficients_sum_quantity = coefficients_sum_quantity;
+	}
+
+	i = 0;
+
+	while (i != filter->coefficients_sum_quantity) {
+		filter->coefficients_sum[i] = dal_fixed31_32_zero;
+
+		++i;
+	}
+
+	m = 0;
+
+	attenby2 = dal_fixed31_32_div_int(
+		dal_fixed31_32_mul_int(attenuation, params->taps), 2);
+
+	i = 1;
+
+	while (i <= params->taps) {
+		j = 0;
+
+		while (j != params->phases) {
+			struct fixed31_32 x = dal_fixed31_32_mul(
+				dal_fixed31_32_pi,
+				dal_fixed31_32_from_fraction(
+					(int64_t)(m << 1) - n, n));
+
+			uint32_t index =
+				(params->taps - i) * params->phases + j;
+
+			filter->coefficients[index] = lanczos(x, attenby2);
+
+			++m;
+
+			++j;
+		}
+
+		++i;
+	}
+
+	i = 0;
+
+	while (i != params->phases) {
+		filter->coefficients_sum[i] = dal_fixed31_32_zero;
+
+		m = i;
+
+		j = 0;
+
+		while (j != params->taps) {
+			filter->coefficients_sum[i] =
+				dal_fixed31_32_add(
+					filter->coefficients_sum[i],
+					filter->coefficients[m]);
+
+			m += params->phases;
+
+			++j;
+		}
+
+		++i;
+	}
+
+	i = 0;
+
+	while (i != params->phases) {
+		m = i;
+
+		j = 0;
+
+		while (j != params->taps) {
+			filter->coefficients[m] =
+				dal_fixed31_32_div(
+					filter->coefficients[m],
+					filter->coefficients_sum[i]);
+
+			m += params->phases;
+
+			++j;
+		}
+
+		++i;
+	}
+
+	i = 0;
+	i_limit = (params->phases >> 1) + 1;
+
+	while (i != i_limit) {
+		m = i;
+
+		j = 0;
+
+		while (j != params->taps) {
+			struct fixed31_32 tmp = filter->coefficients[m];
+
+			filter->filter[i * params->taps + j] = tmp;
+
+			if (dal_fixed31_32_lt(
+				tmp, dal_fixed31_32_zero) &&
+				dal_fixed31_32_lt(tmp, a_min))
+				a_min = tmp;
+			else if (dal_fixed31_32_lt(
+				dal_fixed31_32_zero, tmp) &&
+				dal_fixed31_32_lt(a_max, tmp))
+				a_max = tmp;
+
+			m += params->phases;
+
+			++j;
+		}
+
+		++i;
+	}
+
+	if (dal_fixed31_32_eq(a_min, dal_fixed31_32_zero))
+		*ringing = dal_fixed31_32_from_int(100);
+	else
+		*ringing = dal_fixed31_32_min(
+			dal_fixed31_32_abs(
+				dal_fixed31_32_div(a_max, a_min)),
+			dal_fixed31_32_from_int(100));
+
+	return true;
+}
+
+static bool construct_scaler_filter(
+	struct dc_context *ctx,
+	struct scaler_filter *filter)
+{
+	filter->src_size = 0;
+	filter->dst_size = 0;
+	filter->filter = NULL;
+	filter->integer_filter = NULL;
+	filter->filter_size_allocated = 0;
+	filter->filter_size_effective = 0;
+	filter->coefficients = NULL;
+	filter->coefficients_quantity = 0;
+	filter->coefficients_sum = NULL;
+	filter->coefficients_sum_quantity = 0;
+	filter->downscaling_table = NULL;
+	filter->upscaling_table = NULL;
+	filter->ctx = ctx;
+
+	if (!create_downscaling_table(filter)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!create_upscaling_table(filter)) {
+		BREAK_TO_DEBUGGER();
+		destroy_downscaling_table(filter);
+		return false;
+	}
+
+	return true;
+}
+
+static void destruct_scaler_filter(
+	struct scaler_filter *filter)
+{
+	if (filter->coefficients_sum)
+		dm_free(filter->ctx, filter->coefficients_sum);
+
+	if (filter->coefficients)
+		dm_free(filter->ctx, filter->coefficients);
+
+	if (filter->integer_filter)
+		dm_free(filter->ctx, filter->integer_filter);
+
+	if (filter->filter)
+		dm_free(filter->ctx, filter->filter);
+
+	destroy_upscaling_table(filter);
+
+	destroy_downscaling_table(filter);
+}
+
+struct scaler_filter *dal_scaler_filter_create(struct dc_context *ctx)
+{
+	struct scaler_filter *filter =
+		dm_alloc(ctx, sizeof(struct scaler_filter));
+
+	if (!filter) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (construct_scaler_filter(ctx, filter))
+		return filter;
+
+	BREAK_TO_DEBUGGER();
+
+	dm_free(ctx, filter);
+
+	return NULL;
+}
+
+bool dal_scaler_filter_generate(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	uint32_t src_size,
+	uint32_t dst_size)
+{
+	uint32_t filter_size_required;
+
+	struct fixed31_32 attenuation;
+	struct fixed31_32 decibels_at_nyquist;
+	struct fixed31_32 ringing;
+
+	if (!params) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if ((params->taps < 3) || (params->taps > 16)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!src_size || !dst_size) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (same_filter_required(filter, params, src_size, dst_size))
+		return true;
+
+	filter_size_required =
+		params->taps * ((params->phases >> 1) + 1);
+
+	if (filter_size_required > filter->filter_size_allocated) {
+		if (filter->filter) {
+			dm_free(filter->ctx, filter->filter);
+
+			filter->filter = 0;
+			filter->filter_size_allocated = 0;
+		}
+
+		filter->filter = dm_alloc(
+			filter->ctx,
+			filter_size_required * sizeof(struct fixed31_32));
+
+		if (!filter->filter) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (filter->integer_filter) {
+			dm_free(filter->ctx, filter->integer_filter);
+
+			filter->integer_filter = 0;
+		}
+
+		filter->integer_filter = dm_alloc(
+			filter->ctx,
+			filter_size_required * sizeof(uint32_t));
+
+		if (!filter->integer_filter) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		filter->filter_size_allocated = filter_size_required;
+	}
+
+	filter->filter_size_effective = filter_size_required;
+
+	if (!map_sharpness(filter, params, src_size, dst_size,
+		&attenuation, &decibels_at_nyquist)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!generate_filter(filter, params, attenuation, &ringing)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	filter->params = *params;
+	filter->src_size = src_size;
+	filter->dst_size = dst_size;
+
+	return true;
+}
+
+const struct fixed31_32 *dal_scaler_filter_get(
+	const struct scaler_filter *filter,
+	uint32_t **data,
+	uint32_t *number)
+{
+	if (!number) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (!data) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	*number = filter->filter_size_effective;
+	*data = filter->integer_filter;
+
+	return filter->filter;
+}
+
+void dal_scaler_filter_destroy(
+	struct scaler_filter **filter)
+{
+	if (!filter || !*filter) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct_scaler_filter(*filter);
+
+	dm_free((*filter)->ctx, *filter);
+
+	*filter = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
new file mode 100644
index 000000000000..668691d6c6e6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
@@ -0,0 +1,74 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SCALER_FILTER_H__
+#define __DAL_SCALER_FILTER_H__
+
+struct scaler_filter_params {
+	uint32_t taps; /* 3...16 */
+	uint32_t phases;
+	int32_t sharpness; /* -50...50 */
+	union {
+		struct {
+			uint32_t HORIZONTAL:1;
+			uint32_t RESERVED:31;
+		} bits;
+		uint32_t value;
+	} flags;
+};
+
+struct q31_32;
+
+struct scaler_filter {
+	struct scaler_filter_params params;
+	uint32_t src_size;
+	uint32_t dst_size;
+	struct fixed31_32 *filter;
+	uint32_t *integer_filter;
+	uint32_t filter_size_allocated;
+	uint32_t filter_size_effective;
+	struct fixed31_32 *coefficients;
+	uint32_t coefficients_quantity;
+	struct fixed31_32 *coefficients_sum;
+	uint32_t coefficients_sum_quantity;
+	struct fixed31_32 ***downscaling_table;
+	struct fixed31_32 ***upscaling_table;
+	struct dc_context *ctx;
+};
+
+struct scaler_filter *dal_scaler_filter_create(struct dc_context *ctx);
+void dal_scaler_filter_destroy(struct scaler_filter **ptr);
+
+bool dal_scaler_filter_generate(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	uint32_t src_size,
+	uint32_t dst_size);
+
+const struct fixed31_32 *dal_scaler_filter_get(
+	const struct scaler_filter *filter,
+	uint32_t **data,
+	uint32_t *number);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 13/29] drm/amd/dal: Add encoder HW programming
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (11 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 12/29] drm/amd/dal: Bandwidth calculations Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 14/29] drm/amd/dal: Add clock source " Harry Wentland
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Responsible for programming back-end of display path, such as DIG,
UNIPHY, DP, DAC, and DVO.
Supports:
- DisplayPort (single stream)
- HDMI
- DVI
- eDP

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.c    | 1927 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.h    |  156 ++
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.c  | 1123 ++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.h  |  122 ++
 4 files changed, 3328 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
new file mode 100644
index 000000000000..f714215c0dd5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
@@ -0,0 +1,1927 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "core_types.h"
+#include "link_encoder.h"
+#include "stream_encoder.h"
+#include "dce110_link_encoder.h"
+
+#include "i2caux_interface.h"
+#include "dc_bios_types.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dce/dce_11_0_enum.h"
+
+#define LINK_REG(reg)\
+	(enc110->link_regs->reg)
+
+#define AUX_REG(reg)\
+	(enc110->aux_regs->reg)
+
+#define BL_REG(reg)\
+	(enc110->bl_regs->reg)
+
+/* For current ASICs pixel clock - 600MHz */
+#define MAX_ENCODER_CLK 600000
+
+#define DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ 600000
+
+#define DEFAULT_AUX_MAX_DATA_SIZE 16
+#define AUX_MAX_DEFER_WRITE_RETRY 20
+/*
+ * @brief
+ * Trigger Source Select
+ * ASIC-dependent, actual values for register programming
+ */
+#define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x0
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x1
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x2
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x4
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x08
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x10
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20
+
+/* all values are in milliseconds */
+/* For eDP, after power-up/power/down,
+ * 300/500 msec max. delay from LCDVCC to black video generation */
+#define PANEL_POWER_UP_TIMEOUT 300
+#define PANEL_POWER_DOWN_TIMEOUT 500
+#define HPD_CHECK_INTERVAL 10
+
+/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */
+#define TMDS_MIN_PIXEL_CLOCK 25000
+/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */
+#define TMDS_MAX_PIXEL_CLOCK 165000
+/* For current ASICs pixel clock - 600MHz */
+#define MAX_ENCODER_CLOCK 600000
+
+enum {
+	DP_MST_UPDATE_MAX_RETRY = 50
+};
+
+#define DIG_REG(reg)\
+	(reg + enc110->offsets.dig)
+
+#define DP_REG(reg)\
+	(reg + enc110->offsets.dp)
+
+static struct link_encoder_funcs dce110_lnk_enc_funcs = {
+	.validate_output_with_stream =
+		dce110_link_encoder_validate_output_with_stream,
+	.hw_init = dce110_link_encoder_hw_init,
+	.setup = dce110_link_encoder_setup,
+	.enable_tmds_output = dce110_link_encoder_enable_tmds_output,
+	.enable_dp_output = dce110_link_encoder_enable_dp_output,
+	.enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,
+	.disable_output = dce110_link_encoder_disable_output,
+	.dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
+	.dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
+	.update_mst_stream_allocation_table =
+		dce110_link_encoder_update_mst_stream_allocation_table,
+	.set_lcd_backlight_level = dce110_link_encoder_set_lcd_backlight_level,
+	.backlight_control = dce110_link_encoder_edp_backlight_control,
+	.power_control = dce110_link_encoder_edp_power_control,
+	.connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe
+};
+
+static enum bp_result link_transmitter_control(
+	struct dce110_link_encoder *enc110,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result;
+	struct dc_bios *bp = dal_adapter_service_get_bios_parser(
+					enc110->base.adapter_service);
+
+	result = bp->funcs->transmitter_control(bp, cntl);
+
+	return result;
+}
+
+static void enable_phy_bypass_mode(
+	struct dce110_link_encoder *enc110,
+	bool enable)
+{
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	const uint32_t addr = LINK_REG(DP_DPHY_CNTL);
+
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, enable, DP_DPHY_CNTL, DPHY_BYPASS);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void disable_prbs_symbols(
+	struct dce110_link_encoder *enc110,
+	bool disable)
+{
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	const uint32_t addr = LINK_REG(DP_DPHY_CNTL);
+
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, disable,
+			DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0);
+
+	set_reg_field_value(value, disable,
+			DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1);
+
+	set_reg_field_value(value, disable,
+			DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2);
+
+	set_reg_field_value(value, disable,
+			DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void disable_prbs_mode(
+	struct dce110_link_encoder *enc110)
+{
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	const uint32_t addr = LINK_REG(DP_DPHY_PRBS_CNTL);
+	uint32_t value;
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, 0, DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void program_pattern_symbols(
+	struct dce110_link_encoder *enc110,
+	uint16_t pattern_symbols[8])
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+
+	addr = LINK_REG(DP_DPHY_SYM0);
+
+	value = 0;
+	set_reg_field_value(value, pattern_symbols[0],
+			DP_DPHY_SYM0, DPHY_SYM1);
+	set_reg_field_value(value, pattern_symbols[1],
+			DP_DPHY_SYM0, DPHY_SYM2);
+	set_reg_field_value(value, pattern_symbols[2],
+			DP_DPHY_SYM0, DPHY_SYM3);
+	dm_write_reg(ctx, addr, value);
+
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+
+	addr = LINK_REG(DP_DPHY_SYM1);
+
+	value = 0;
+	set_reg_field_value(value, pattern_symbols[3],
+			DP_DPHY_SYM1, DPHY_SYM4);
+	set_reg_field_value(value, pattern_symbols[4],
+			DP_DPHY_SYM1, DPHY_SYM5);
+	set_reg_field_value(value, pattern_symbols[5],
+			DP_DPHY_SYM1, DPHY_SYM6);
+	dm_write_reg(ctx, addr, value);
+
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	addr = LINK_REG(DP_DPHY_SYM2);
+	value = 0;
+	set_reg_field_value(value, pattern_symbols[6],
+			DP_DPHY_SYM2, DPHY_SYM7);
+	set_reg_field_value(value, pattern_symbols[6],
+			DP_DPHY_SYM2, DPHY_SYM8);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_dp_phy_pattern_d102(
+	struct dce110_link_encoder *enc110)
+{
+	/* Disable PHY Bypass mode to setup the test pattern */
+	enable_phy_bypass_mode(enc110, false);
+
+	/* For 10-bit PRBS or debug symbols
+	 * please use the following sequence: */
+
+	/* Enable debug symbols on the lanes */
+
+	disable_prbs_symbols(enc110, true);
+
+	/* Disable PRBS mode,
+	 * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */
+
+	disable_prbs_mode(enc110);
+
+	/* Program debug symbols to be output */
+	{
+		uint16_t pattern_symbols[8] = {
+			0x2AA, 0x2AA, 0x2AA, 0x2AA,
+			0x2AA, 0x2AA, 0x2AA, 0x2AA
+		};
+
+		program_pattern_symbols(enc110, pattern_symbols);
+	}
+
+	/* Enable phy bypass mode to enable the test pattern */
+
+	enable_phy_bypass_mode(enc110, true);
+}
+
+static void set_link_training_complete(
+	struct dce110_link_encoder *enc110,
+	bool complete)
+{
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	struct dc_context *ctx = enc110->base.ctx;
+	const uint32_t addr = LINK_REG(DP_LINK_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, complete,
+			DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_dp_phy_pattern_training_pattern(
+	struct dce110_link_encoder *enc110,
+	uint32_t index)
+{
+	/* Write Training Pattern */
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DP_DPHY_TRAINING_PATTERN_SEL);
+
+	dm_write_reg(ctx, addr, index);
+
+	/* Set HW Register Training Complete to false */
+
+	set_link_training_complete(enc110, false);
+
+	/* Disable PHY Bypass mode to output Training Pattern */
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* Disable PRBS mode,
+	 * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */
+
+	disable_prbs_mode(enc110);
+}
+
+static void set_dp_phy_pattern_symbol_error(
+	struct dce110_link_encoder *enc110)
+{
+	/* Disable PHY Bypass mode to setup the test pattern */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* program correct panel mode*/
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_INTERNAL_CTRL);
+		uint32_t value = 0x0;
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* A PRBS23 pattern is used for most DP electrical measurements. */
+
+	/* Enable PRBS symbols on the lanes */
+
+	disable_prbs_symbols(enc110, false);
+
+	/* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_PRBS_CNTL);
+		uint32_t value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(value, 1,
+				DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL);
+		set_reg_field_value(value, 1,
+				DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN);
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* Enable phy bypass mode to enable the test pattern */
+
+	enable_phy_bypass_mode(enc110, true);
+}
+
+static void set_dp_phy_pattern_prbs7(
+	struct dce110_link_encoder *enc110)
+{
+	/* Disable PHY Bypass mode to setup the test pattern */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* A PRBS7 pattern is used for most DP electrical measurements. */
+
+	/* Enable PRBS symbols on the lanes */
+
+	disable_prbs_symbols(enc110, false);
+
+	/* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_PRBS_CNTL);
+
+		uint32_t value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(value, 0,
+				DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL);
+
+		set_reg_field_value(value, 1,
+				DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* Enable phy bypass mode to enable the test pattern */
+
+	enable_phy_bypass_mode(enc110, true);
+}
+
+static void set_dp_phy_pattern_80bit_custom(
+	struct dce110_link_encoder *enc110,
+	const uint8_t *pattern)
+{
+	/* Disable PHY Bypass mode to setup the test pattern */
+	enable_phy_bypass_mode(enc110, false);
+
+	/* Enable debug symbols on the lanes */
+
+	disable_prbs_symbols(enc110, true);
+
+	/* Enable PHY bypass mode to enable the test pattern */
+	/* TODO is it really needed ? */
+
+	enable_phy_bypass_mode(enc110, true);
+
+	/* Program 80 bit custom pattern */
+	{
+		uint16_t pattern_symbols[8];
+
+		pattern_symbols[0] =
+			((pattern[1] & 0x03) << 8) | pattern[0];
+		pattern_symbols[1] =
+			((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f);
+		pattern_symbols[2] =
+			((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f);
+		pattern_symbols[3] =
+			(pattern[4] << 2) | ((pattern[3] >> 6) & 0x03);
+		pattern_symbols[4] =
+			((pattern[6] & 0x03) << 8) | pattern[5];
+		pattern_symbols[5] =
+			((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f);
+		pattern_symbols[6] =
+			((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f);
+		pattern_symbols[7] =
+			(pattern[9] << 2) | ((pattern[8] >> 6) & 0x03);
+
+		program_pattern_symbols(enc110, pattern_symbols);
+	}
+
+	/* Enable phy bypass mode to enable the test pattern */
+
+	enable_phy_bypass_mode(enc110, true);
+}
+
+static void set_dp_phy_pattern_hbr2_compliance(
+	struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	/* previously there is a register DP_HBR2_EYE_PATTERN
+	 * that is enabled to get the pattern.
+	 * But it does not work with the latest spec change,
+	 * so we are programming the following registers manually.
+	 *
+	 * The following settings have been confirmed
+	 * by Nick Chorney and Sandra Liu */
+
+	/* Disable PHY Bypass mode to setup the test pattern */
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* Setup DIG encoder in DP SST mode */
+
+	enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);
+
+	/* program correct panel mode*/
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_INTERNAL_CTRL);
+		uint32_t value = 0x0;
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* no vbid after BS (SR)
+	 * DP_LINK_FRAMING_CNTL changed history Sandra Liu
+	 * 11000260 / 11000104 / 110000FC */
+
+	/* TODO DP_LINK_FRAMING_CNTL should always use hardware default value
+	 * output  except output hbr2_compliance pattern for physical PHY
+	 * measurement. This is not normal usage case. SW should reset this
+	 * register to hardware default value after end use of HBR2 eye
+	 */
+	BREAK_TO_DEBUGGER();
+	/* TODO: do we still need this, find out at compliance test
+	addr = mmDP_LINK_FRAMING_CNTL + fe_addr_offset;
+
+	value = (ctx, addr);
+
+	set_reg_field_value(value, 0xFC,
+			DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL);
+	set_reg_field_value(value, 1,
+			DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE);
+	set_reg_field_value(value, 1,
+			DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE);
+
+	dal_write_reg(ctx, addr, value);
+	 */
+
+	/*TODO add support for this test pattern
+	 * support_dp_hbr2_eye_pattern
+	 */
+
+	/* set link training complete */
+	set_link_training_complete(enc110, true);
+	/* do not enable video stream */
+	addr = LINK_REG(DP_VID_STREAM_CNTL);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, 0, DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* Disable PHY Bypass mode to setup the test pattern */
+
+	enable_phy_bypass_mode(enc110, false);
+}
+
+static void set_dp_phy_pattern_passthrough_mode(
+	struct dce110_link_encoder *enc110,
+	enum dp_panel_mode panel_mode)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+
+	/* program correct panel mode */
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_INTERNAL_CTRL);
+
+		uint32_t value;
+
+		value = dm_read_reg(ctx, addr);
+
+		switch (panel_mode) {
+		case DP_PANEL_MODE_EDP:
+			value = 0x1;
+		break;
+		case DP_PANEL_MODE_SPECIAL:
+			value = 0x11;
+		break;
+		default:
+			value = 0x0;
+			break;
+		}
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* set link training complete */
+
+	set_link_training_complete(enc110, true);
+
+	/* Disable PHY Bypass mode to setup the test pattern */
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* Disable PRBS mode,
+	 * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */
+
+	disable_prbs_mode(enc110);
+}
+
+/* return value is bit-vector */
+static uint8_t get_frontend_source(
+	enum engine_id engine)
+{
+	switch (engine) {
+	case ENGINE_ID_DIGA:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGA;
+	case ENGINE_ID_DIGB:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGB;
+	case ENGINE_ID_DIGC:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGC;
+	case ENGINE_ID_DIGD:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGD;
+	case ENGINE_ID_DIGE:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGE;
+	case ENGINE_ID_DIGF:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGF;
+	default:
+		ASSERT_CRITICAL(false);
+		return DCE110_DIG_FE_SOURCE_SELECT_INVALID;
+	}
+}
+
+static void configure_encoder(
+	struct dce110_link_encoder *enc110,
+	const struct link_settings *link_settings)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	/* set number of lanes */
+	addr = LINK_REG(DP_CONFIG);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, link_settings->lane_count - LANE_COUNT_ONE,
+			DP_CONFIG, DP_UDI_LANES);
+	dm_write_reg(ctx, addr, value);
+
+}
+
+static bool is_panel_powered_on(struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t value;
+	bool ret;
+
+	value = dm_read_reg(ctx,
+			BL_REG(LVTMA_PWRSEQ_STATE));
+
+	ret = get_reg_field_value(value,
+			LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R);
+
+	return ret == 1;
+}
+
+/*
+ * @brief
+ * eDP only.
+ */
+static void link_encoder_edp_wait_for_hpd_ready(
+	struct dce110_link_encoder *enc110,
+	bool power_up)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	struct adapter_service *as = enc110->base.adapter_service;
+	struct graphics_object_id connector = enc110->base.connector;
+	struct irq *hpd;
+	bool edp_hpd_high = false;
+	uint32_t time_elapsed = 0;
+	uint32_t timeout = power_up ?
+		PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
+
+	if (dal_graphics_object_id_get_connector_id(connector) !=
+		CONNECTOR_ID_EDP) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if (!power_up && dal_adapter_service_is_feature_supported(
+		FEATURE_NO_HPD_LOW_POLLING_VCC_OFF))
+		/* from KV, we will not HPD low after turning off VCC -
+		 * instead, we will check the SW timer in power_up(). */
+		return;
+
+	/* when we power on/off the eDP panel,
+	 * we need to wait until SENSE bit is high/low */
+
+	/* obtain HPD */
+
+	hpd = dal_adapter_service_obtain_hpd_irq(as, connector);
+
+	if (!hpd) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	dal_irq_open(hpd);
+
+	/* wait until timeout or panel detected */
+
+	do {
+		uint32_t detected = 0;
+
+		dal_irq_get_value(hpd, &detected);
+
+		if (!(detected ^ power_up)) {
+			edp_hpd_high = true;
+			break;
+		}
+
+		dm_sleep_in_milliseconds(ctx, HPD_CHECK_INTERVAL);
+
+		time_elapsed += HPD_CHECK_INTERVAL;
+	} while (time_elapsed < timeout);
+
+	dal_irq_close(hpd);
+
+	dal_adapter_service_release_irq(as, hpd);
+
+	if (false == edp_hpd_high) {
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: wait timed out!\n", __func__);
+	}
+}
+
+/*
+ * @brief
+ * eDP only. Control the power of the eDP panel.
+ */
+void dce110_link_encoder_edp_power_control(
+	struct link_encoder *enc,
+	bool power_up)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result bp_result;
+
+	if (dal_graphics_object_id_get_connector_id(enc110->base.connector) !=
+		CONNECTOR_ID_EDP) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if ((power_up && !is_panel_powered_on(enc110)) ||
+		(!power_up && is_panel_powered_on(enc110))) {
+
+		/* Send VBIOS command to prompt eDP panel power */
+
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: Panel Power action: %s\n",
+				__func__, (power_up ? "On":"Off"));
+
+		cntl.action = power_up ?
+			TRANSMITTER_CONTROL_POWER_ON :
+			TRANSMITTER_CONTROL_POWER_OFF;
+		cntl.transmitter = enc110->base.transmitter;
+		cntl.connector_obj_id = enc110->base.connector;
+		cntl.coherent = false;
+		cntl.lanes_number = LANE_COUNT_FOUR;
+		cntl.hpd_sel = enc110->base.hpd_source;
+
+		bp_result = link_transmitter_control(enc110, &cntl);
+
+		if (BP_RESULT_OK != bp_result) {
+
+			dal_logger_write(ctx->logger,
+					LOG_MAJOR_ERROR,
+					LOG_MINOR_HW_TRACE_RESUME_S3,
+					"%s: Panel Power bp_result: %d\n",
+					__func__, bp_result);
+		}
+	} else {
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: Skipping Panel Power action: %s\n",
+				__func__, (power_up ? "On":"Off"));
+	}
+
+	link_encoder_edp_wait_for_hpd_ready(enc110, true);
+}
+
+static void aux_initialize(
+	struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	enum hpd_source_id hpd_source = enc110->base.hpd_source;
+	uint32_t addr = AUX_REG(AUX_CONTROL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL);
+	set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN);
+	dm_write_reg(ctx, addr, value);
+
+	addr = AUX_REG(AUX_DPHY_RX_CONTROL0);
+	value = dm_read_reg(ctx, addr);
+
+	/* 1/4 window (the maximum allowed) */
+	set_reg_field_value(value, 1,
+			AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW);
+	dm_write_reg(ctx, addr, value);
+
+}
+
+/*todo: cloned in stream enc, fix*/
+static bool is_panel_backlight_on(struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t value;
+
+	value = dm_read_reg(ctx, BL_REG(LVTMA_PWRSEQ_CNTL));
+
+	return get_reg_field_value(value, LVTMA_PWRSEQ_CNTL, LVTMA_BLON);
+}
+
+/*todo: cloned in stream enc, fix*/
+/*
+ * @brief
+ * eDP only. Control the backlight of the eDP panel
+ */
+void dce110_link_encoder_edp_backlight_control(
+	struct link_encoder *enc,
+	bool enable)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+
+	if (dal_graphics_object_id_get_connector_id(enc110->base.connector)
+		!= CONNECTOR_ID_EDP) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if (enable && is_panel_backlight_on(enc110)) {
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: panel already powered up. Do nothing.\n",
+				__func__);
+		return;
+	}
+
+	if (!enable && !is_panel_powered_on(enc110)) {
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: panel already powered down. Do nothing.\n",
+				__func__);
+		return;
+	}
+
+	/* Send VBIOS command to control eDP panel backlight */
+
+	dal_logger_write(ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_RESUME_S3,
+			"%s: backlight action: %s\n",
+			__func__, (enable ? "On":"Off"));
+
+	cntl.action = enable ?
+		TRANSMITTER_CONTROL_BACKLIGHT_ON :
+		TRANSMITTER_CONTROL_BACKLIGHT_OFF;
+	/*cntl.engine_id = ctx->engine;*/
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.connector_obj_id = enc110->base.connector;
+	/*todo: unhardcode*/
+	cntl.lanes_number = LANE_COUNT_FOUR;
+	cntl.hpd_sel = enc110->base.hpd_source;
+
+	/* For eDP, the following delays might need to be considered
+	 * after link training completed:
+	 * idle period - min. accounts for required BS-Idle pattern,
+	 * max. allows for source frame synchronization);
+	 * 50 msec max. delay from valid video data from source
+	 * to video on dislpay or backlight enable.
+	 *
+	 * Disable the delay for now.
+	 * Enable it in the future if necessary.
+	 */
+	/* dc_service_sleep_in_milliseconds(50); */
+	link_transmitter_control(enc110, &cntl);
+}
+
+static bool is_dig_enabled(const struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t value;
+
+	value = dm_read_reg(ctx, LINK_REG(DIG_BE_EN_CNTL));
+
+	return get_reg_field_value(value, DIG_BE_EN_CNTL, DIG_ENABLE);
+}
+
+static void link_encoder_disable(struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	/* reset training pattern */
+	addr = LINK_REG(DP_DPHY_TRAINING_PATTERN_SEL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 0,
+			DP_DPHY_TRAINING_PATTERN_SEL,
+			DPHY_TRAINING_PATTERN_SEL);
+	dm_write_reg(ctx, addr, value);
+
+	/* reset training complete */
+	addr = LINK_REG(DP_LINK_CNTL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 0, DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE);
+	dm_write_reg(ctx, addr, value);
+
+	/* reset panel mode */
+	addr = LINK_REG(DP_DPHY_INTERNAL_CTRL);
+	value = 0;
+	dm_write_reg(ctx, addr, value);
+}
+
+static void hpd_initialize(
+	struct dce110_link_encoder *enc110)
+{
+	/* Associate HPD with DIG_BE */
+	struct dc_context *ctx = enc110->base.ctx;
+	enum hpd_source_id hpd_source = enc110->base.hpd_source;
+	const uint32_t addr = LINK_REG(DIG_BE_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, hpd_source, DIG_BE_CNTL, DIG_HPD_SELECT);
+	dm_write_reg(ctx, addr, value);
+}
+
+static bool validate_dvi_output(
+	const struct dce110_link_encoder *enc110,
+	enum signal_type connector_signal,
+	enum signal_type signal,
+	const struct dc_crtc_timing *crtc_timing)
+{
+	uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK;
+
+	if (enc110->base.features.max_pixel_clock < TMDS_MAX_PIXEL_CLOCK)
+		max_pixel_clock = enc110->base.features.max_pixel_clock;
+
+	if (signal == SIGNAL_TYPE_DVI_DUAL_LINK)
+		max_pixel_clock <<= 1;
+
+	/* This handles the case of HDMI downgrade to DVI we don't want to
+	 * we don't want to cap the pixel clock if the DDI is not DVI.
+	 */
+	if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK &&
+			connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
+		max_pixel_clock = enc110->base.features.max_pixel_clock;
+
+	/* DVI only support RGB pixel encoding */
+	if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB)
+		return false;
+
+	if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
+		return false;
+
+	if (crtc_timing->pix_clk_khz > max_pixel_clock)
+		return false;
+
+	/* DVI supports 6/8bpp single-link and 10/16bpp dual-link */
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_666:
+	case COLOR_DEPTH_888:
+	break;
+	case COLOR_DEPTH_101010:
+	case COLOR_DEPTH_161616:
+		if (signal != SIGNAL_TYPE_DVI_DUAL_LINK)
+			return false;
+	break;
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+static bool validate_hdmi_output(
+	const struct dce110_link_encoder *enc110,
+	const struct dc_crtc_timing *crtc_timing,
+	uint32_t max_tmds_clk_from_edid_in_mhz,
+	enum dc_color_depth max_hdmi_deep_color,
+	uint32_t max_hdmi_pixel_clock)
+{
+	enum dc_color_depth max_deep_color = max_hdmi_deep_color;
+	/* expressed in KHz */
+	uint32_t pixel_clock = 0;
+
+	/*TODO: unhardcode*/
+	max_tmds_clk_from_edid_in_mhz = 0;
+	max_hdmi_deep_color = COLOR_DEPTH_121212;
+	max_hdmi_pixel_clock = 600000;
+
+	if (max_deep_color > enc110->base.features.max_deep_color)
+		max_deep_color = enc110->base.features.max_deep_color;
+
+	if (max_deep_color < crtc_timing->display_color_depth)
+		return false;
+
+	if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
+		return false;
+
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_666:
+		pixel_clock = (crtc_timing->pix_clk_khz * 3) >> 2;
+	break;
+	case COLOR_DEPTH_888:
+		pixel_clock = crtc_timing->pix_clk_khz;
+	break;
+	case COLOR_DEPTH_101010:
+		pixel_clock = (crtc_timing->pix_clk_khz * 10) >> 3;
+	break;
+	case COLOR_DEPTH_121212:
+		pixel_clock = (crtc_timing->pix_clk_khz * 3) >> 1;
+	break;
+	case COLOR_DEPTH_161616:
+		pixel_clock = crtc_timing->pix_clk_khz << 1;
+	break;
+	default:
+	break;
+	}
+
+	if (max_tmds_clk_from_edid_in_mhz > 0)
+		if (pixel_clock > max_tmds_clk_from_edid_in_mhz * 1000)
+			return false;
+
+	if ((pixel_clock == 0) ||
+		(pixel_clock > max_hdmi_pixel_clock) ||
+		(pixel_clock > enc110->base.features.max_pixel_clock))
+		return false;
+
+	/*
+	 * Restriction: allow non-CE mode (IT mode) to support RGB only.
+	 * When it is IT mode, the format mode will be 0,
+	 * but currently the code is broken,
+	 * VIDEO FORMAT is always 0 in validatepathMode().
+	 * Due to overscan change - need fix there and test the impact - to do.
+	 */
+	if (crtc_timing->timing_standard != TIMING_STANDARD_CEA861 &&
+		crtc_timing->timing_standard != TIMING_STANDARD_HDMI)
+		if (crtc_timing->pixel_encoding !=
+			PIXEL_ENCODING_RGB)
+			return false;
+
+	/* DCE11 HW does not support 420 */
+	if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
+		return false;
+
+	return true;
+}
+
+static bool validate_rgb_output(
+	const struct dce110_link_encoder *enc110,
+	const struct dc_crtc_timing *crtc_timing)
+{
+	if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock)
+		return false;
+
+	if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB)
+		return false;
+
+	return true;
+}
+
+static bool validate_dp_output(
+	const struct dce110_link_encoder *enc110,
+	const struct dc_crtc_timing *crtc_timing)
+{
+	if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock)
+		return false;
+
+	/* default RGB only */
+	if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
+		return true;
+
+	if (enc110->base.features.flags.bits.IS_YCBCR_CAPABLE)
+		return true;
+
+	/* for DCE 8.x or later DP Y-only feature,
+	 * we need ASIC cap + FeatureSupportDPYonly, not support 666 */
+	if (crtc_timing->flags.Y_ONLY &&
+		enc110->base.features.flags.bits.IS_YCBCR_CAPABLE &&
+		crtc_timing->display_color_depth != COLOR_DEPTH_666)
+		return true;
+
+	return false;
+}
+
+static bool validate_wireless_output(
+	const struct dce110_link_encoder *enc110,
+	const struct dc_crtc_timing *crtc_timing)
+{
+	if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock)
+		return false;
+
+	/* Wireless only supports YCbCr444 */
+	if (crtc_timing->pixel_encoding ==
+			PIXEL_ENCODING_YCBCR444)
+		return true;
+
+	return false;
+}
+
+bool dce110_link_encoder_construct(
+	struct dce110_link_encoder *enc110,
+	const struct encoder_init_data *init_data,
+	const struct dce110_link_enc_registers *link_regs,
+	const struct dce110_link_enc_aux_registers *aux_regs,
+	const struct dce110_link_enc_bl_registers *bl_regs)
+{
+	struct graphics_object_encoder_cap_info enc_cap_info = {0};
+
+	enc110->base.funcs = &dce110_lnk_enc_funcs;
+	enc110->base.ctx = init_data->ctx;
+	enc110->base.id = init_data->encoder;
+
+	enc110->base.hpd_source = init_data->hpd_source;
+	enc110->base.connector = init_data->connector;
+	enc110->base.input_signals = SIGNAL_TYPE_ALL;
+
+	enc110->base.adapter_service = init_data->adapter_service;
+
+	enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
+
+	enc110->base.features.flags.raw = 0;
+
+	enc110->base.transmitter = init_data->transmitter;
+
+	enc110->base.features.flags.bits.IS_AUDIO_CAPABLE = true;
+
+	enc110->base.features.max_pixel_clock =
+		DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ;
+
+	/* set the flag to indicate whether driver poll the I2C data pin
+	 * while doing the DP sink detect
+	 */
+
+	if (dal_adapter_service_is_feature_supported(
+		FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
+		enc110->base.features.flags.bits.
+			DP_SINK_DETECT_POLL_DATA_PIN = true;
+
+	enc110->base.output_signals =
+		SIGNAL_TYPE_DVI_SINGLE_LINK |
+		SIGNAL_TYPE_DVI_DUAL_LINK |
+		SIGNAL_TYPE_LVDS |
+		SIGNAL_TYPE_DISPLAY_PORT |
+		SIGNAL_TYPE_DISPLAY_PORT_MST |
+		SIGNAL_TYPE_EDP |
+		SIGNAL_TYPE_HDMI_TYPE_A;
+
+	/* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.
+	 * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.
+	 * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer
+	 * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.
+	 * Prefer DIG assignment is decided by board design.
+	 * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design
+	 * and VBIOS will filter out 7 UNIPHY for DCE 8.0.
+	 * By this, adding DIGG should not hurt DCE 8.0.
+	 * This will let DCE 8.1 share DCE 8.0 as much as possible
+	 */
+
+	enc110->link_regs = link_regs;
+	enc110->aux_regs = aux_regs;
+	enc110->bl_regs = bl_regs;
+
+	switch (enc110->base.transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+		enc110->base.preferred_engine = ENGINE_ID_DIGA;
+	break;
+	case TRANSMITTER_UNIPHY_B:
+		enc110->base.preferred_engine = ENGINE_ID_DIGB;
+	break;
+	case TRANSMITTER_UNIPHY_C:
+		enc110->base.preferred_engine = ENGINE_ID_DIGC;
+	break;
+	case TRANSMITTER_UNIPHY_D:
+		enc110->base.preferred_engine = ENGINE_ID_DIGD;
+	break;
+	case TRANSMITTER_UNIPHY_E:
+		enc110->base.preferred_engine = ENGINE_ID_DIGE;
+	break;
+	case TRANSMITTER_UNIPHY_F:
+		enc110->base.preferred_engine = ENGINE_ID_DIGF;
+	break;
+	default:
+		ASSERT_CRITICAL(false);
+		enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
+	}
+
+	dal_logger_write(init_data->ctx->logger,
+			LOG_MAJOR_I2C_AUX,
+			LOG_MINOR_I2C_AUX_CFG,
+			"Using channel: %s [%d]\n",
+			DECODE_CHANNEL_ID(init_data->channel),
+			init_data->channel);
+
+	/* Override features with DCE-specific values */
+	if (dal_adapter_service_get_encoder_cap_info(
+			enc110->base.adapter_service,
+			enc110->base.id, &enc_cap_info))
+		enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
+				enc_cap_info.dp_hbr2_cap;
+
+	/* test pattern 3 support */
+	enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true;
+	enc110->base.features.max_deep_color = COLOR_DEPTH_121212;
+
+	enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE =
+		dal_adapter_service_is_feature_supported(
+			FEATURE_SUPPORT_DP_Y_ONLY);
+
+	enc110->base.features.flags.bits.IS_YCBCR_CAPABLE =
+		dal_adapter_service_is_feature_supported(
+			FEATURE_SUPPORT_DP_YUV);
+	return true;
+}
+
+bool dce110_link_encoder_validate_output_with_stream(
+	struct link_encoder *enc,
+	struct core_stream *stream)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	bool is_valid;
+
+	switch (stream->signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		is_valid = validate_dvi_output(
+			enc110,
+			stream->sink->link->public.connector_signal,
+			stream->signal,
+			&stream->public.timing);
+	break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		is_valid = validate_hdmi_output(
+				enc110,
+				&stream->public.timing,
+				stream->max_tmds_clk_from_edid_in_mhz,
+				stream->max_hdmi_deep_color,
+				stream->max_hdmi_pixel_clock);
+	break;
+	case SIGNAL_TYPE_RGB:
+		is_valid = validate_rgb_output(
+			enc110, &stream->public.timing);
+	break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		is_valid = validate_dp_output(
+			enc110, &stream->public.timing);
+	break;
+	case SIGNAL_TYPE_WIRELESS:
+		is_valid = validate_wireless_output(
+			enc110, &stream->public.timing);
+	break;
+	default:
+		is_valid = true;
+	break;
+	}
+
+	return is_valid;
+}
+
+void dce110_link_encoder_hw_init(
+	struct link_encoder *enc)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	cntl.action = TRANSMITTER_CONTROL_INIT;
+	cntl.engine_id = ENGINE_ID_UNKNOWN;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.connector_obj_id = enc110->base.connector;
+	cntl.lanes_number = LANE_COUNT_FOUR;
+	cntl.coherent = false;
+	cntl.hpd_sel = enc110->base.hpd_source;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if (enc110->base.connector.id == CONNECTOR_ID_LVDS) {
+		cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS;
+
+		result = link_transmitter_control(enc110, &cntl);
+
+		ASSERT(result == BP_RESULT_OK);
+
+	} else if (enc110->base.connector.id == CONNECTOR_ID_EDP) {
+		enc->funcs->power_control(&enc110->base, true);
+	}
+	aux_initialize(enc110);
+
+	/* reinitialize HPD.
+	 * hpd_initialize() will pass DIG_FE id to HW context.
+	 * All other routine within HW context will use fe_engine_offset
+	 * as DIG_FE id even caller pass DIG_FE id.
+	 * So this routine must be called first. */
+	hpd_initialize(enc110);
+}
+
+void dce110_link_encoder_setup(
+	struct link_encoder *enc,
+	enum signal_type signal)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	const uint32_t addr = LINK_REG(DIG_BE_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	switch (signal) {
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+		/* DP SST */
+		set_reg_field_value(value, 0, DIG_BE_CNTL, DIG_MODE);
+		break;
+	case SIGNAL_TYPE_LVDS:
+		/* LVDS */
+		set_reg_field_value(value, 1, DIG_BE_CNTL, DIG_MODE);
+		break;
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		/* TMDS-DVI */
+		set_reg_field_value(value, 2, DIG_BE_CNTL, DIG_MODE);
+		break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		/* TMDS-HDMI */
+		set_reg_field_value(value, 3, DIG_BE_CNTL, DIG_MODE);
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		/* DP MST */
+		set_reg_field_value(value, 5, DIG_BE_CNTL, DIG_MODE);
+		break;
+	default:
+		ASSERT_CRITICAL(false);
+		/* invalid mode ! */
+		break;
+	}
+
+	dm_write_reg(ctx, addr, value);
+}
+
+/* TODO: still need depth or just pass in adjusted pixel clock? */
+void dce110_link_encoder_enable_tmds_output(
+	struct link_encoder *enc,
+	enum clock_source_id clock_source,
+	enum dc_color_depth color_depth,
+	bool hdmi,
+	bool dual_link,
+	uint32_t pixel_clock)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	/* Enable the PHY */
+
+	cntl.action = TRANSMITTER_CONTROL_ENABLE;
+	cntl.engine_id = ENGINE_ID_UNKNOWN;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.pll_id = clock_source;
+	if (hdmi) {
+		cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+		cntl.lanes_number = 4;
+	} else if (dual_link) {
+		cntl.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+		cntl.lanes_number = 8;
+	} else {
+		cntl.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		cntl.lanes_number = 4;
+	}
+	cntl.hpd_sel = enc110->base.hpd_source;
+
+	cntl.pixel_clock = pixel_clock;
+	cntl.color_depth = color_depth;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+	}
+}
+
+/* enables DP PHY output */
+void dce110_link_encoder_enable_dp_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	/* Enable the PHY */
+
+	/* number_of_lanes is used for pixel clock adjust,
+	 * but it's not passed to asic_control.
+	 * We need to set number of lanes manually.
+	 */
+	configure_encoder(enc110, link_settings);
+
+	cntl.action = TRANSMITTER_CONTROL_ENABLE;
+	cntl.engine_id = enc->preferred_engine;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.pll_id = clock_source;
+	cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;
+	cntl.lanes_number = link_settings->lane_count;
+	cntl.hpd_sel = enc110->base.hpd_source;
+	cntl.pixel_clock = link_settings->link_rate
+						* LINK_RATE_REF_FREQ_IN_KHZ;
+	/* TODO: check if undefined works */
+	cntl.color_depth = COLOR_DEPTH_UNDEFINED;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+	}
+}
+
+/* enables DP PHY output in MST mode */
+void dce110_link_encoder_enable_dp_mst_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	/* Enable the PHY */
+
+	/* number_of_lanes is used for pixel clock adjust,
+	 * but it's not passed to asic_control.
+	 * We need to set number of lanes manually.
+	 */
+	configure_encoder(enc110, link_settings);
+
+	cntl.action = TRANSMITTER_CONTROL_ENABLE;
+	cntl.engine_id = enc->preferred_engine;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.pll_id = clock_source;
+	cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
+	cntl.lanes_number = link_settings->lane_count;
+	cntl.hpd_sel = enc110->base.hpd_source;
+	cntl.pixel_clock = link_settings->link_rate
+						* LINK_RATE_REF_FREQ_IN_KHZ;
+	/* TODO: check if undefined works */
+	cntl.color_depth = COLOR_DEPTH_UNDEFINED;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+	}
+}
+/*
+ * @brief
+ * Disable transmitter and its encoder
+ */
+void dce110_link_encoder_disable_output(
+	struct link_encoder *enc,
+	enum signal_type signal)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	if (!is_dig_enabled(enc110) &&
+		dal_adapter_service_should_optimize(
+			enc110->base.adapter_service,
+			OF_SKIP_POWER_DOWN_INACTIVE_ENCODER)) {
+		return;
+	}
+	/* Power-down RX and disable GPU PHY should be paired.
+	 * Disabling PHY without powering down RX may cause
+	 * symbol lock loss, on which we will get DP Sink interrupt. */
+
+	/* There is a case for the DP active dongles
+	 * where we want to disable the PHY but keep RX powered,
+	 * for those we need to ignore DP Sink interrupt
+	 * by checking lane count that has been set
+	 * on the last do_enable_output(). */
+
+	/* disable transmitter */
+	cntl.action = TRANSMITTER_CONTROL_DISABLE;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.hpd_sel = enc110->base.hpd_source;
+	cntl.signal = signal;
+	cntl.connector_obj_id = enc110->base.connector;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	/* disable encoder */
+	if (dc_is_dp_signal(signal))
+		link_encoder_disable(enc110);
+
+	if (enc110->base.connector.id == CONNECTOR_ID_EDP) {
+		/* power down eDP panel */
+		/* TODO: Power control cause regression, we should implement
+		 * it properly, for now just comment it.
+		 *
+		 * link_encoder_edp_wait_for_hpd_ready(
+			link_enc,
+			link_enc->connector,
+			false);
+
+		 * link_encoder_edp_power_control(
+				link_enc, false); */
+	}
+}
+
+void dce110_link_encoder_dp_set_lane_settings(
+	struct link_encoder *enc,
+	const struct link_training_settings *link_settings)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	union dpcd_training_lane_set training_lane_set = { { 0 } };
+	int32_t lane = 0;
+	struct bp_transmitter_control cntl = { 0 };
+
+	if (!link_settings) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.connector_obj_id = enc110->base.connector;
+	cntl.lanes_number = link_settings->link_settings.lane_count;
+	cntl.hpd_sel = enc110->base.hpd_source;
+	cntl.pixel_clock = link_settings->link_settings.link_rate *
+						LINK_RATE_REF_FREQ_IN_KHZ;
+
+	for (lane = 0; lane < link_settings->link_settings.lane_count; ++lane) {
+		/* translate lane settings */
+
+		training_lane_set.bits.VOLTAGE_SWING_SET =
+			link_settings->lane_settings[lane].VOLTAGE_SWING;
+		training_lane_set.bits.PRE_EMPHASIS_SET =
+			link_settings->lane_settings[lane].PRE_EMPHASIS;
+
+		/* post cursor 2 setting only applies to HBR2 link rate */
+		if (link_settings->link_settings.link_rate == LINK_RATE_HIGH2) {
+			/* this is passed to VBIOS
+			 * to program post cursor 2 level */
+
+			training_lane_set.bits.POST_CURSOR2_SET =
+				link_settings->lane_settings[lane].POST_CURSOR2;
+		}
+
+		cntl.lane_select = lane;
+		cntl.lane_settings = training_lane_set.raw;
+
+		/* call VBIOS table to set voltage swing and pre-emphasis */
+		link_transmitter_control(enc110, &cntl);
+	}
+}
+
+/* set DP PHY test and training patterns */
+void dce110_link_encoder_dp_set_phy_pattern(
+	struct link_encoder *enc,
+	const struct encoder_set_dp_phy_pattern_param *param)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+
+	switch (param->dp_phy_pattern) {
+	case DP_TEST_PATTERN_TRAINING_PATTERN1:
+		set_dp_phy_pattern_training_pattern(enc110, 0);
+		break;
+	case DP_TEST_PATTERN_TRAINING_PATTERN2:
+		set_dp_phy_pattern_training_pattern(enc110, 1);
+		break;
+	case DP_TEST_PATTERN_TRAINING_PATTERN3:
+		set_dp_phy_pattern_training_pattern(enc110, 2);
+		break;
+	case DP_TEST_PATTERN_D102:
+		set_dp_phy_pattern_d102(enc110);
+		break;
+	case DP_TEST_PATTERN_SYMBOL_ERROR:
+		set_dp_phy_pattern_symbol_error(enc110);
+		break;
+	case DP_TEST_PATTERN_PRBS7:
+		set_dp_phy_pattern_prbs7(enc110);
+		break;
+	case DP_TEST_PATTERN_80BIT_CUSTOM:
+		set_dp_phy_pattern_80bit_custom(
+			enc110, param->custom_pattern);
+		break;
+	case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE:
+		set_dp_phy_pattern_hbr2_compliance(enc110);
+		break;
+	case DP_TEST_PATTERN_VIDEO_MODE: {
+		set_dp_phy_pattern_passthrough_mode(
+			enc110, param->dp_panel_mode);
+		break;
+	}
+
+	default:
+		/* invalid phy pattern */
+		ASSERT_CRITICAL(false);
+		break;
+	}
+}
+
+static void fill_stream_allocation_row_info(
+	const struct link_mst_stream_allocation *stream_allocation,
+	uint32_t *src,
+	uint32_t *slots)
+{
+	const struct stream_encoder *stream_enc = stream_allocation->stream_enc;
+
+	if (stream_enc) {
+		*src = stream_enc->id;
+		*slots = stream_allocation->slot_count;
+	} else {
+		*src = 0;
+		*slots = 0;
+	}
+}
+
+/* programs DP MST VC payload allocation */
+void dce110_link_encoder_update_mst_stream_allocation_table(
+	struct link_encoder *enc,
+	const struct link_mst_stream_allocation_table *table)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t value0 = 0;
+	uint32_t value1 = 0;
+	uint32_t value2 = 0;
+	uint32_t slots = 0;
+	uint32_t src = 0;
+	uint32_t retries = 0;
+
+	/* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/
+
+	/* --- Set MSE Stream Attribute -
+	 * Setup VC Payload Table on Tx Side,
+	 * Issue allocation change trigger
+	 * to commit payload on both tx and rx side */
+
+	/* we should clean-up table each time */
+	value0 = dm_read_reg(ctx, LINK_REG(DP_MSE_SAT0));
+	value1 = dm_read_reg(ctx, LINK_REG(DP_MSE_SAT1));
+
+	if (table->stream_count >= 1) {
+		fill_stream_allocation_row_info(
+			&table->stream_allocations[0],
+			&src,
+			&slots);
+	} else {
+		src = 0;
+		slots = 0;
+	}
+
+	set_reg_field_value(
+		value0,
+		src,
+		DP_MSE_SAT0,
+		DP_MSE_SAT_SRC0);
+
+	set_reg_field_value(
+		value0,
+		slots,
+		DP_MSE_SAT0,
+		DP_MSE_SAT_SLOT_COUNT0);
+
+	if (table->stream_count >= 2) {
+		fill_stream_allocation_row_info(
+			&table->stream_allocations[1],
+			&src,
+			&slots);
+	} else {
+		src = 0;
+		slots = 0;
+	}
+
+	set_reg_field_value(
+		value0,
+		src,
+		DP_MSE_SAT0,
+		DP_MSE_SAT_SRC1);
+
+	set_reg_field_value(
+		value0,
+		slots,
+		DP_MSE_SAT0,
+		DP_MSE_SAT_SLOT_COUNT1);
+
+	if (table->stream_count >= 3) {
+		fill_stream_allocation_row_info(
+			&table->stream_allocations[2],
+			&src,
+			&slots);
+	} else {
+		src = 0;
+		slots = 0;
+	}
+
+	set_reg_field_value(
+		value1,
+		src,
+		DP_MSE_SAT1,
+		DP_MSE_SAT_SRC2);
+
+	set_reg_field_value(
+		value1,
+		slots,
+		DP_MSE_SAT1,
+		DP_MSE_SAT_SLOT_COUNT2);
+
+	/* update ASIC MSE stream allocation table */
+	dm_write_reg(ctx, LINK_REG(DP_MSE_SAT0), value0);
+	dm_write_reg(ctx, LINK_REG(DP_MSE_SAT1), value1);
+
+	/* --- wait for transaction finish */
+
+	/* send allocation change trigger (ACT) ?
+	 * this step first sends the ACT,
+	 * then double buffers the SAT into the hardware
+	 * making the new allocation active on the DP MST mode link */
+
+	value0 = dm_read_reg(ctx, LINK_REG(DP_MSE_SAT_UPDATE));
+
+	/* DP_MSE_SAT_UPDATE:
+	 * 0 - No Action
+	 * 1 - Update SAT with trigger
+	 * 2 - Update SAT without trigger */
+
+	set_reg_field_value(
+		value0,
+		1,
+		DP_MSE_SAT_UPDATE,
+		DP_MSE_SAT_UPDATE);
+
+	dm_write_reg(ctx, LINK_REG(DP_MSE_SAT_UPDATE), value0);
+
+	/* wait for update to complete
+	 * (i.e. DP_MSE_SAT_UPDATE field is reset to 0)
+	 * then wait for the transmission
+	 * of at least 16 MTP headers on immediate local link.
+	 * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0
+	 * a value of 1 indicates that DP MST mode
+	 * is in the 16 MTP keepout region after a VC has been added.
+	 * MST stream bandwidth (VC rate) can be configured
+	 * after this bit is cleared */
+
+	do {
+		dm_delay_in_microseconds(ctx, 10);
+
+		value0 = dm_read_reg(ctx,
+				LINK_REG(DP_MSE_SAT_UPDATE));
+
+		value1 = get_reg_field_value(
+				value0,
+				DP_MSE_SAT_UPDATE,
+				DP_MSE_SAT_UPDATE);
+		value2 = get_reg_field_value(
+				value0,
+				DP_MSE_SAT_UPDATE,
+				DP_MSE_16_MTP_KEEPOUT);
+
+		/* bit field DP_MSE_SAT_UPDATE is set to 1 already */
+		if (!value1 && !value2)
+			break;
+		++retries;
+	} while (retries < DP_MST_UPDATE_MAX_RETRY);
+}
+
+/* black light programming */
+void dce110_link_encoder_set_lcd_backlight_level(
+	struct link_encoder *enc,
+	uint32_t level)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+
+	const uint32_t backlight_update_pending_max_retry = 1000;
+
+	uint32_t backlight;
+	uint32_t backlight_period;
+	uint32_t backlight_lock;
+
+	uint32_t i;
+	uint32_t backlight_24bit;
+	uint32_t backlight_17bit;
+	uint32_t backlight_16bit;
+	uint32_t masked_pwm_period;
+	uint8_t rounding_bit;
+	uint8_t bit_count;
+	uint64_t active_duty_cycle;
+
+	backlight = dm_read_reg(ctx, BL_REG(BL_PWM_CNTL));
+	backlight_period = dm_read_reg(ctx, BL_REG(BL_PWM_PERIOD_CNTL));
+	backlight_lock = dm_read_reg(ctx, BL_REG(BL_PWM_GRP1_REG_LOCK));
+
+	/*
+	 * 1. Convert 8-bit value to 17 bit U1.16 format
+	 * (1 integer, 16 fractional bits)
+	 */
+
+	/* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value,
+	 * effectively multiplying value by 256/255
+	 * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF
+	 */
+	backlight_24bit = level * 0x10101;
+
+	/* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8
+	 * used for rounding, take most significant bit of fraction for
+	 * rounding, e.g. for 0xEFEFEF, rounding bit is 1
+	 */
+	rounding_bit = (backlight_24bit >> 7) & 1;
+
+	/* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit
+	 * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1
+	 */
+	backlight_17bit = (backlight_24bit >> 8) + rounding_bit;
+
+	/*
+	 * 2. Find  16 bit backlight active duty cycle, where 0 <= backlight
+	 * active duty cycle <= backlight period
+	 */
+
+	/* 2.1 Apply bitmask for backlight period value based on value of BITCNT
+	 */
+	{
+		uint32_t pwm_period_bitcnt = get_reg_field_value(
+			backlight_period,
+			BL_PWM_PERIOD_CNTL,
+			BL_PWM_PERIOD_BITCNT);
+		if (pwm_period_bitcnt == 0)
+			bit_count = 16;
+		else
+			bit_count = pwm_period_bitcnt;
+	}
+
+	/* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */
+	masked_pwm_period =
+	get_reg_field_value(
+		backlight_period,
+		BL_PWM_PERIOD_CNTL,
+		BL_PWM_PERIOD) & ((1 << bit_count) - 1);
+
+	/* 2.2 Calculate integer active duty cycle required upper 16 bits
+	 * contain integer component, lower 16 bits contain fractional component
+	 * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24
+	 */
+	active_duty_cycle = backlight_17bit * masked_pwm_period;
+
+	/* 2.3 Calculate 16 bit active duty cycle from integer and fractional
+	 * components shift by bitCount then mask 16 bits and add rounding bit
+	 * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0
+	 */
+	backlight_16bit = active_duty_cycle >> bit_count;
+	backlight_16bit &= 0xFFFF;
+	backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1;
+	set_reg_field_value(
+		backlight,
+		backlight_16bit,
+		BL_PWM_CNTL,
+		BL_ACTIVE_INT_FRAC_CNT);
+
+	/*
+	 * 3. Program register with updated value
+	 */
+
+	/* 3.1 Lock group 2 backlight registers */
+	set_reg_field_value(
+		backlight_lock,
+		1,
+		BL_PWM_GRP1_REG_LOCK,
+		BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN);
+	set_reg_field_value(
+		backlight_lock,
+		1,
+		BL_PWM_GRP1_REG_LOCK,
+		BL_PWM_GRP1_REG_LOCK);
+	dm_write_reg(ctx, BL_REG(BL_PWM_GRP1_REG_LOCK), backlight_lock);
+
+	/* 3.2 Write new active duty cycle */
+	dm_write_reg(ctx, BL_REG(BL_PWM_CNTL), backlight);
+
+	/* 3.3 Unlock group 2 backlight registers */
+	set_reg_field_value(
+		backlight_lock,
+		0,
+		BL_PWM_GRP1_REG_LOCK,
+		BL_PWM_GRP1_REG_LOCK);
+	dm_write_reg(ctx, BL_REG(BL_PWM_GRP1_REG_LOCK), backlight_lock);
+
+	/* 5.4.4 Wait for pending bit to be cleared */
+	for (i = 0; i < backlight_update_pending_max_retry; ++i) {
+		backlight_lock = dm_read_reg(ctx, BL_REG(BL_PWM_GRP1_REG_LOCK));
+		if (!get_reg_field_value(
+			backlight_lock,
+			BL_PWM_GRP1_REG_LOCK,
+			BL_PWM_GRP1_REG_UPDATE_PENDING))
+			break;
+
+		dm_delay_in_microseconds(ctx, 10);
+	}
+}
+
+void dce110_link_encoder_connect_dig_be_to_fe(
+	struct link_encoder *enc,
+	enum engine_id engine,
+	bool connect)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+	uint32_t field;
+
+	if (engine != ENGINE_ID_UNKNOWN) {
+		addr = LINK_REG(DIG_BE_CNTL);
+		value = dm_read_reg(ctx, addr);
+
+		field = get_reg_field_value(
+				value,
+				DIG_BE_CNTL,
+				DIG_FE_SOURCE_SELECT);
+
+		if (connect)
+			field |= get_frontend_source(engine);
+		else
+			field &= ~get_frontend_source(engine);
+
+		set_reg_field_value(
+			value,
+			field,
+			DIG_BE_CNTL,
+			DIG_FE_SOURCE_SELECT);
+		dm_write_reg(ctx, addr, value);
+	}
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
new file mode 100644
index 000000000000..46e297137b19
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_LINK_ENCODER__DCE110_H__
+#define __DC_LINK_ENCODER__DCE110_H__
+
+#include "inc/link_encoder.h"
+
+#define TO_DCE110_LINK_ENC(link_encoder)\
+	container_of(link_encoder, struct dce110_link_encoder, base)
+
+struct dce110_link_enc_bl_registers {
+	uint32_t BL_PWM_CNTL;
+	uint32_t BL_PWM_GRP1_REG_LOCK;
+	uint32_t BL_PWM_PERIOD_CNTL;
+	uint32_t LVTMA_PWRSEQ_CNTL;
+	uint32_t LVTMA_PWRSEQ_STATE;
+};
+
+struct dce110_link_enc_aux_registers {
+	uint32_t AUX_CONTROL;
+	uint32_t AUX_DPHY_RX_CONTROL0;
+};
+
+struct dce110_link_enc_registers {
+	uint32_t DIG_BE_CNTL;
+	uint32_t DIG_BE_EN_CNTL;
+	uint32_t DP_CONFIG;
+	uint32_t DP_DPHY_CNTL;
+	uint32_t DP_DPHY_INTERNAL_CTRL;
+	uint32_t DP_DPHY_PRBS_CNTL;
+	uint32_t DP_DPHY_SYM0;
+	uint32_t DP_DPHY_SYM1;
+	uint32_t DP_DPHY_SYM2;
+	uint32_t DP_DPHY_TRAINING_PATTERN_SEL;
+	uint32_t DP_LINK_CNTL;
+	uint32_t DP_LINK_FRAMING_CNTL;
+	uint32_t DP_MSE_SAT0;
+	uint32_t DP_MSE_SAT1;
+	uint32_t DP_MSE_SAT2;
+	uint32_t DP_MSE_SAT_UPDATE;
+	uint32_t DP_SEC_CNTL;
+	uint32_t DP_VID_STREAM_CNTL;
+};
+
+struct dce110_link_encoder {
+	struct link_encoder base;
+	const struct dce110_link_enc_registers *link_regs;
+	const struct dce110_link_enc_aux_registers *aux_regs;
+	const struct dce110_link_enc_bl_registers *bl_regs;
+};
+
+bool dce110_link_encoder_construct(
+	struct dce110_link_encoder *enc110,
+	const struct encoder_init_data *init_data,
+	const struct dce110_link_enc_registers *link_regs,
+	const struct dce110_link_enc_aux_registers *aux_regs,
+	const struct dce110_link_enc_bl_registers *bl_regs);
+
+bool dce110_link_encoder_validate_output_with_stream(
+	struct link_encoder *enc,
+	struct core_stream *stream);
+
+/****************** HW programming ************************/
+
+/* initialize HW */  /* why do we initialze aux in here? */
+void dce110_link_encoder_hw_init(struct link_encoder *enc);
+
+/* program DIG_MODE in DIG_BE */
+/* TODO can this be combined with enable_output? */
+void dce110_link_encoder_setup(
+	struct link_encoder *enc,
+	enum signal_type signal);
+
+/* enables TMDS PHY output */
+/* TODO: still need depth or just pass in adjusted pixel clock? */
+void dce110_link_encoder_enable_tmds_output(
+	struct link_encoder *enc,
+	enum clock_source_id clock_source,
+	enum dc_color_depth color_depth,
+	bool hdmi,
+	bool dual_link,
+	uint32_t pixel_clock);
+
+/* enables DP PHY output */
+void dce110_link_encoder_enable_dp_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source);
+
+/* enables DP PHY output in MST mode */
+void dce110_link_encoder_enable_dp_mst_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source);
+
+/* disable PHY output */
+void dce110_link_encoder_disable_output(
+	struct link_encoder *link_enc,
+	enum signal_type signal);
+
+/* set DP lane settings */
+void dce110_link_encoder_dp_set_lane_settings(
+	struct link_encoder *enc,
+	const struct link_training_settings *link_settings);
+
+void dce110_link_encoder_dp_set_phy_pattern(
+	struct link_encoder *enc,
+	const struct encoder_set_dp_phy_pattern_param *param);
+
+/* programs DP MST VC payload allocation */
+void dce110_link_encoder_update_mst_stream_allocation_table(
+	struct link_encoder *enc,
+	const struct link_mst_stream_allocation_table *table);
+
+void dce110_link_encoder_set_lcd_backlight_level(
+	struct link_encoder *enc,
+	uint32_t level);
+
+void dce110_link_encoder_edp_backlight_control(
+	struct link_encoder *enc,
+	bool enable);
+
+void dce110_link_encoder_edp_power_control(
+	struct link_encoder *enc,
+	bool power_up);
+
+void dce110_link_encoder_connect_dig_be_to_fe(
+	struct link_encoder *enc,
+	enum engine_id engine,
+	bool connect);
+
+
+#endif /* __DC_LINK_ENCODER__DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
new file mode 100644
index 000000000000..210730972c08
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
@@ -0,0 +1,1123 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dc_bios_types.h"
+#include "dce110_stream_encoder.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dce/dce_11_0_enum.h"
+
+#define LINK_REG(reg)\
+	(enc110->regs->reg)
+
+#define VBI_LINE_0 0
+#define DP_BLANK_MAX_RETRY 20
+#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000
+
+#ifndef HDMI_CONTROL__HDMI_DATA_SCRAMBLE_EN_MASK
+	#define HDMI_CONTROL__HDMI_DATA_SCRAMBLE_EN_MASK 0x2
+	#define HDMI_CONTROL__HDMI_DATA_SCRAMBLE_EN__SHIFT 0x1
+#endif
+
+enum {
+	DP_MST_UPDATE_MAX_RETRY = 50
+};
+
+static struct stream_encoder_funcs dce110_str_enc_funcs = {
+	.dp_set_stream_attribute =
+		dce110_stream_encoder_dp_set_stream_attribute,
+	.hdmi_set_stream_attribute =
+		dce110_stream_encoder_hdmi_set_stream_attribute,
+	.dvi_set_stream_attribute =
+		dce110_stream_encoder_dvi_set_stream_attribute,
+	.set_mst_bandwidth =
+		dce110_stream_encoder_set_mst_bandwidth,
+	.update_hdmi_info_packets =
+		dce110_stream_encoder_update_hdmi_info_packets,
+	.stop_hdmi_info_packets =
+		dce110_stream_encoder_stop_hdmi_info_packets,
+	.update_dp_info_packets =
+		dce110_stream_encoder_update_dp_info_packets,
+	.stop_dp_info_packets =
+		dce110_stream_encoder_stop_dp_info_packets,
+	.dp_blank =
+		dce110_stream_encoder_dp_blank,
+	.dp_unblank =
+		dce110_stream_encoder_dp_unblank,
+};
+
+static void dce110_update_generic_info_packet(
+	struct dce110_stream_encoder *enc110,
+	uint32_t packet_index,
+	const struct encoder_info_packet *info_packet)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t regval;
+	/* choose which generic packet to use */
+	{
+		addr = LINK_REG(AFMT_VBI_PACKET_CONTROL);
+
+		regval = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			regval,
+			packet_index,
+			AFMT_VBI_PACKET_CONTROL,
+			AFMT_GENERIC_INDEX);
+
+		dm_write_reg(ctx, addr, regval);
+	}
+
+	/* write generic packet header
+	 * (4th byte is for GENERIC0 only) */
+	{
+		addr = LINK_REG(AFMT_GENERIC_HDR);
+
+		regval = 0;
+
+		set_reg_field_value(
+			regval,
+			info_packet->hb0,
+			AFMT_GENERIC_HDR,
+			AFMT_GENERIC_HB0);
+
+		set_reg_field_value(
+			regval,
+			info_packet->hb1,
+			AFMT_GENERIC_HDR,
+			AFMT_GENERIC_HB1);
+
+		set_reg_field_value(
+			regval,
+			info_packet->hb2,
+			AFMT_GENERIC_HDR,
+			AFMT_GENERIC_HB2);
+
+		set_reg_field_value(
+			regval,
+			info_packet->hb3,
+			AFMT_GENERIC_HDR,
+			AFMT_GENERIC_HB3);
+
+		dm_write_reg(ctx, addr, regval);
+	}
+
+	/* write generic packet contents
+	 * (we never use last 4 bytes)
+	 * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers */
+	{
+		const uint32_t *content =
+			(const uint32_t *) &info_packet->sb[0];
+
+		uint32_t counter = 0;
+
+		addr = LINK_REG(AFMT_GENERIC_0);
+
+		do {
+			dm_write_reg(ctx, addr++, *content++);
+
+			++counter;
+		} while (counter < 7);
+	}
+
+	addr = LINK_REG(AFMT_GENERIC_7);
+
+	dm_write_reg(
+		ctx,
+		addr,
+		0);
+
+	/* force double-buffered packet update */
+	{
+		addr = LINK_REG(AFMT_VBI_PACKET_CONTROL);
+
+		regval = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			regval,
+			(packet_index == 0),
+			AFMT_VBI_PACKET_CONTROL,
+			AFMT_GENERIC0_UPDATE);
+
+		set_reg_field_value(
+			regval,
+			(packet_index == 2),
+			AFMT_VBI_PACKET_CONTROL,
+			AFMT_GENERIC2_UPDATE);
+
+		dm_write_reg(ctx, addr, regval);
+	}
+}
+
+static void dce110_update_hdmi_info_packet(
+	struct dce110_stream_encoder *enc110,
+	uint32_t packet_index,
+	const struct encoder_info_packet *info_packet)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t cont, send, line;
+	uint32_t addr;
+	uint32_t regval;
+
+	if (info_packet->valid) {
+		dce110_update_generic_info_packet(
+			enc110,
+			packet_index,
+			info_packet);
+
+		/* enable transmission of packet(s) -
+		 * packet transmission begins on the next frame */
+		cont = 1;
+		/* send packet(s) every frame */
+		send = 1;
+		/* select line number to send packets on */
+		line = 2;
+	} else {
+		cont = 0;
+		send = 0;
+		line = 0;
+	}
+
+	/* choose which generic packet control to use */
+
+	switch (packet_index) {
+	case 0:
+	case 1:
+		addr = LINK_REG(HDMI_GENERIC_PACKET_CONTROL0);
+		break;
+	case 2:
+	case 3:
+		addr = LINK_REG(HDMI_GENERIC_PACKET_CONTROL1);
+		break;
+	default:
+		/* invalid HW packet index */
+		dal_logger_write(
+			ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"Invalid HW packet index: %s()\n",
+			__func__);
+		return;
+	}
+
+	regval = dm_read_reg(ctx, addr);
+
+	switch (packet_index) {
+	case 0:
+	case 2:
+		set_reg_field_value(
+			regval,
+			cont,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC0_CONT);
+		set_reg_field_value(
+			regval,
+			send,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC0_SEND);
+		set_reg_field_value(
+			regval,
+			line,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC0_LINE);
+		break;
+	case 1:
+	case 3:
+		set_reg_field_value(
+			regval,
+			cont,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC1_CONT);
+		set_reg_field_value(
+			regval,
+			send,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC1_SEND);
+		set_reg_field_value(
+			regval,
+			line,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC1_LINE);
+		break;
+	default:
+		/* invalid HW packet index */
+		dal_logger_write(
+			ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"Invalid HW packet index: %s()\n",
+			__func__);
+		return;
+	}
+
+	dm_write_reg(ctx, addr, regval);
+}
+
+bool dce110_stream_encoder_construct(
+	struct dce110_stream_encoder *enc110,
+	struct dc_context *ctx,
+	struct dc_bios *bp,
+	enum engine_id eng_id,
+	const struct dce110_stream_enc_registers *regs)
+{
+	if (!enc110)
+		return false;
+	if (!bp)
+		return false;
+
+	enc110->base.funcs = &dce110_str_enc_funcs;
+	enc110->base.ctx = ctx;
+	enc110->base.id = eng_id;
+	enc110->base.bp = bp;
+	enc110->regs = regs;
+
+	return true;
+}
+
+/* setup stream encoder in dp mode */
+void dce110_stream_encoder_dp_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	const uint32_t addr = LINK_REG(DP_PIXEL_FORMAT);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	/* set pixel encoding */
+	switch (crtc_timing->pixel_encoding) {
+	case PIXEL_ENCODING_YCBCR422:
+		set_reg_field_value(
+			value,
+			DP_PIXEL_ENCODING_YCBCR422,
+			DP_PIXEL_FORMAT,
+			DP_PIXEL_ENCODING);
+		break;
+	case PIXEL_ENCODING_YCBCR444:
+		set_reg_field_value(
+			value,
+			DP_PIXEL_ENCODING_YCBCR444,
+			DP_PIXEL_FORMAT,
+			DP_PIXEL_ENCODING);
+
+		if (crtc_timing->flags.Y_ONLY)
+			if (crtc_timing->display_color_depth != COLOR_DEPTH_666)
+				/* HW testing only, no use case yet.
+				 * Color depth of Y-only could be
+				 * 8, 10, 12, 16 bits */
+				set_reg_field_value(
+					value,
+					DP_PIXEL_ENCODING_Y_ONLY,
+					DP_PIXEL_FORMAT,
+					DP_PIXEL_ENCODING);
+		/* Note: DP_MSA_MISC1 bit 7 is the indicator
+		 * of Y-only mode.
+		 * This bit is set in HW if register
+		 * DP_PIXEL_ENCODING is programmed to 0x4 */
+		break;
+	default:
+		set_reg_field_value(
+			value,
+			DP_PIXEL_ENCODING_RGB444,
+			DP_PIXEL_FORMAT,
+			DP_PIXEL_ENCODING);
+		break;
+	}
+
+	/* set color depth */
+
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_888:
+		set_reg_field_value(
+			value,
+			DP_COMPONENT_DEPTH_8BPC,
+			DP_PIXEL_FORMAT,
+			DP_COMPONENT_DEPTH);
+		break;
+	case COLOR_DEPTH_101010:
+		set_reg_field_value(
+			value,
+			DP_COMPONENT_DEPTH_10BPC,
+			DP_PIXEL_FORMAT,
+			DP_COMPONENT_DEPTH);
+		break;
+	case COLOR_DEPTH_121212:
+		set_reg_field_value(
+			value,
+			DP_COMPONENT_DEPTH_12BPC,
+			DP_PIXEL_FORMAT,
+			DP_COMPONENT_DEPTH);
+		break;
+	default:
+		set_reg_field_value(
+			value,
+			DP_COMPONENT_DEPTH_6BPC,
+			DP_PIXEL_FORMAT,
+			DP_COMPONENT_DEPTH);
+		break;
+	}
+
+	/* set dynamic range and YCbCr range */
+	set_reg_field_value(value, 0, DP_PIXEL_FORMAT, DP_DYN_RANGE);
+	set_reg_field_value(value, 0, DP_PIXEL_FORMAT, DP_YCBCR_RANGE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+/* setup stream encoder in hdmi mode */
+void dce110_stream_encoder_hdmi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool enable_audio)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t output_pixel_clock = crtc_timing->pix_clk_khz;
+	uint32_t value;
+	uint32_t addr;
+	struct bp_encoder_control cntl = {0};
+
+	cntl.action = ENCODER_CONTROL_SETUP;
+	cntl.engine_id = enc110->base.id;
+	cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+	cntl.enable_dp_audio = enable_audio;
+	cntl.pixel_clock = crtc_timing->pix_clk_khz;
+	cntl.lanes_number = LANE_COUNT_FOUR;
+	cntl.color_depth = crtc_timing->display_color_depth;
+
+	if (enc110->base.bp->funcs->encoder_control(
+			enc110->base.bp, &cntl) != BP_RESULT_OK)
+		return;
+
+	addr = LINK_REG(DIG_FE_CNTL);
+	value = dm_read_reg(ctx, addr);
+
+	switch (crtc_timing->pixel_encoding) {
+	case PIXEL_ENCODING_YCBCR422:
+		set_reg_field_value(value, 1, DIG_FE_CNTL, TMDS_PIXEL_ENCODING);
+		break;
+	default:
+		set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_PIXEL_ENCODING);
+		break;
+	}
+	set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_COLOR_FORMAT);
+	dm_write_reg(ctx, addr, value);
+
+	/* setup HDMI engine */
+	addr = LINK_REG(HDMI_CONTROL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 1, HDMI_CONTROL, HDMI_PACKET_GEN_VERSION);
+	set_reg_field_value(value, 1, HDMI_CONTROL, HDMI_KEEPOUT_MODE);
+	set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE);
+	set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN);
+	set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE);
+
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_888:
+		set_reg_field_value(
+			value,
+			0,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_DEPTH);
+		break;
+	case COLOR_DEPTH_101010:
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_DEPTH);
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_ENABLE);
+		output_pixel_clock = (crtc_timing->pix_clk_khz * 30) / 24;
+		break;
+	case COLOR_DEPTH_121212:
+		set_reg_field_value(
+			value,
+			2,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_DEPTH);
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_ENABLE);
+		output_pixel_clock = (crtc_timing->pix_clk_khz * 36) / 24;
+		break;
+	case COLOR_DEPTH_161616:
+		set_reg_field_value(
+			value,
+			3,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_DEPTH);
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_ENABLE);
+		output_pixel_clock = (crtc_timing->pix_clk_khz * 48) / 24;
+		break;
+	default:
+		break;
+	}
+
+	if (output_pixel_clock >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) {
+		/* enable HDMI data scrambler */
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DATA_SCRAMBLE_EN);
+
+		/* HDMI_CLOCK_CHANNEL_RATE_MORE_340M
+		 * Clock channel frequency is 1/4 of character rate.*/
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_CLOCK_CHANNEL_RATE);
+	} else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) {
+
+		/* TODO: New feature for DCE11, still need to implement */
+
+		/* enable HDMI data scrambler */
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DATA_SCRAMBLE_EN);
+
+		/* HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE
+		 * Clock channel frequency is the same
+		 * as character rate */
+		set_reg_field_value(
+			value,
+			0,
+			HDMI_CONTROL,
+			HDMI_CLOCK_CHANNEL_RATE);
+	}
+
+	dm_write_reg(ctx, addr, value);
+
+	addr = LINK_REG(HDMI_VBI_PACKET_CONTROL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT);
+	set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND);
+	set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* following belongs to audio */
+	addr = LINK_REG(HDMI_INFOFRAME_CONTROL0);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		HDMI_INFOFRAME_CONTROL0,
+		HDMI_AUDIO_INFO_SEND);
+	dm_write_reg(ctx, addr, value);
+
+	addr = LINK_REG(AFMT_INFOFRAME_CONTROL0);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		AFMT_INFOFRAME_CONTROL0,
+		AFMT_AUDIO_INFO_UPDATE);
+	dm_write_reg(ctx, addr, value);
+
+	addr = LINK_REG(HDMI_INFOFRAME_CONTROL1);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		VBI_LINE_0 + 2,
+		HDMI_INFOFRAME_CONTROL1,
+		HDMI_AUDIO_INFO_LINE);
+	dm_write_reg(ctx, addr, value);
+
+	addr = LINK_REG(HDMI_GC);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 0, HDMI_GC, HDMI_GC_AVMUTE);
+	dm_write_reg(ctx, addr, value);
+}
+
+/* setup stream encoder in dvi mode */
+void dce110_stream_encoder_dvi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool is_dual_link)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DIG_FE_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+	struct bp_encoder_control cntl = {0};
+
+	cntl.action = ENCODER_CONTROL_SETUP;
+	cntl.engine_id = enc110->base.id;
+	cntl.signal = is_dual_link ?
+		SIGNAL_TYPE_DVI_DUAL_LINK :
+		SIGNAL_TYPE_DVI_SINGLE_LINK;
+	cntl.enable_dp_audio = false;
+	cntl.pixel_clock = crtc_timing->pix_clk_khz;
+	cntl.lanes_number = (is_dual_link) ?
+				LANE_COUNT_EIGHT : LANE_COUNT_FOUR;
+	cntl.color_depth = crtc_timing->display_color_depth;
+
+	if (enc110->base.bp->funcs->encoder_control(
+			enc110->base.bp, &cntl) != BP_RESULT_OK)
+		return;
+
+	switch (crtc_timing->pixel_encoding) {
+	case PIXEL_ENCODING_YCBCR422:
+		set_reg_field_value(value, 1, DIG_FE_CNTL, TMDS_PIXEL_ENCODING);
+		break;
+	default:
+		set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_PIXEL_ENCODING);
+		break;
+	}
+
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_101010:
+		if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
+			set_reg_field_value(
+				value,
+				2,
+				DIG_FE_CNTL,
+				TMDS_COLOR_FORMAT);
+		else
+			set_reg_field_value(
+				value,
+				0,
+				DIG_FE_CNTL,
+				TMDS_COLOR_FORMAT);
+		break;
+	default:
+		set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_COLOR_FORMAT);
+		break;
+	}
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_stream_encoder_set_mst_bandwidth(
+	struct stream_encoder *enc,
+	struct fixed31_32 avg_time_slots_per_mtp)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t field;
+	uint32_t value;
+	uint32_t retries = 0;
+	uint32_t x = dal_fixed31_32_floor(
+		avg_time_slots_per_mtp);
+	uint32_t y = dal_fixed31_32_ceil(
+		dal_fixed31_32_shl(
+			dal_fixed31_32_sub_int(
+				avg_time_slots_per_mtp,
+				x),
+			26));
+
+	{
+		addr = LINK_REG(DP_MSE_RATE_CNTL);
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			x,
+			DP_MSE_RATE_CNTL,
+			DP_MSE_RATE_X);
+
+		set_reg_field_value(
+			value,
+			y,
+			DP_MSE_RATE_CNTL,
+			DP_MSE_RATE_Y);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* wait for update to be completed on the link */
+	/* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */
+	/* is reset to 0 (not pending) */
+	{
+		addr = LINK_REG(DP_MSE_RATE_UPDATE);
+
+		do {
+			value = dm_read_reg(ctx, addr);
+
+			field = get_reg_field_value(
+					value,
+					DP_MSE_RATE_UPDATE,
+					DP_MSE_RATE_UPDATE_PENDING);
+
+			if (!(field &
+			DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING_MASK))
+				break;
+
+			dm_delay_in_microseconds(ctx, 10);
+
+			++retries;
+		} while (retries < DP_MST_UPDATE_MAX_RETRY);
+	}
+}
+
+void dce110_stream_encoder_update_hdmi_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t regval;
+	uint32_t addr;
+	uint32_t control0val;
+	uint32_t control1val;
+
+	if (info_frame->avi.valid) {
+		const uint32_t *content =
+			(const uint32_t *) &info_frame->avi.sb[0];
+
+		addr = LINK_REG(AFMT_AVI_INFO0);
+		regval = content[0];
+		dm_write_reg(
+			ctx,
+			addr,
+			regval);
+		regval = content[1];
+
+		addr = LINK_REG(AFMT_AVI_INFO1);
+		dm_write_reg(
+			ctx,
+			addr,
+			regval);
+		regval = content[2];
+
+		addr = LINK_REG(AFMT_AVI_INFO2);
+		dm_write_reg(
+			ctx,
+			addr,
+			regval);
+		regval = content[3];
+
+		/* move version to AVI_INFO3 */
+		addr = LINK_REG(AFMT_AVI_INFO3);
+		set_reg_field_value(
+			regval,
+			info_frame->avi.hb1,
+			AFMT_AVI_INFO3,
+			AFMT_AVI_INFO_VERSION);
+
+		dm_write_reg(
+			ctx,
+			addr,
+			regval);
+
+		addr = LINK_REG(HDMI_INFOFRAME_CONTROL0);
+
+		control0val = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			control0val,
+			1,
+			HDMI_INFOFRAME_CONTROL0,
+			HDMI_AVI_INFO_SEND);
+
+		set_reg_field_value(
+			control0val,
+			1,
+			HDMI_INFOFRAME_CONTROL0,
+			HDMI_AVI_INFO_CONT);
+
+		dm_write_reg(ctx, addr, control0val);
+
+		addr = LINK_REG(HDMI_INFOFRAME_CONTROL1);
+
+		control1val = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			control1val,
+			VBI_LINE_0 + 2,
+			HDMI_INFOFRAME_CONTROL1,
+			HDMI_AVI_INFO_LINE);
+
+		dm_write_reg(ctx, addr, control1val);
+	} else {
+		addr = LINK_REG(HDMI_INFOFRAME_CONTROL0);
+
+		regval = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			regval,
+			0,
+			HDMI_INFOFRAME_CONTROL0,
+			HDMI_AVI_INFO_SEND);
+
+		set_reg_field_value(
+			regval,
+			0,
+			HDMI_INFOFRAME_CONTROL0,
+			HDMI_AVI_INFO_CONT);
+
+		dm_write_reg(ctx, addr, regval);
+	}
+
+	dce110_update_hdmi_info_packet(enc110, 0, &info_frame->vendor);
+	dce110_update_hdmi_info_packet(enc110, 1, &info_frame->gamut);
+	dce110_update_hdmi_info_packet(enc110, 2, &info_frame->spd);
+}
+
+void dce110_stream_encoder_stop_hdmi_info_packets(
+	struct stream_encoder *enc)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* stop generic packets 0 & 1 on HDMI */
+	addr = LINK_REG(HDMI_GENERIC_PACKET_CONTROL0);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC1_CONT);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC1_LINE);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC1_SEND);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC0_CONT);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC0_LINE);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC0_SEND);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* stop generic packets 2 & 3 on HDMI */
+	addr = LINK_REG(HDMI_GENERIC_PACKET_CONTROL1);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC2_CONT);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC2_LINE);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC2_SEND);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC3_CONT);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC3_LINE);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC3_SEND);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* stop AVI packet on HDMI */
+	addr = LINK_REG(HDMI_INFOFRAME_CONTROL0);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_INFOFRAME_CONTROL0,
+		HDMI_AVI_INFO_SEND);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_INFOFRAME_CONTROL0,
+		HDMI_AVI_INFO_CONT);
+
+	dm_write_reg(ctx, addr, value);
+}
+void dce110_stream_encoder_update_dp_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DP_SEC_CNTL);
+	uint32_t value;
+
+	if (info_frame->vsc.valid)
+		dce110_update_generic_info_packet(
+			enc110,
+			0,
+			&info_frame->vsc);
+
+	/* enable/disable transmission of packet(s).
+	*  If enabled, packet transmission begins on the next frame
+	*/
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		info_frame->vsc.valid,
+		DP_SEC_CNTL,
+		DP_SEC_GSP0_ENABLE);
+	/* This bit is the master enable bit.
+	* When enabling secondary stream engine,
+	* this master bit must also be set.
+	* This register shared with audio info frame.
+	* Therefore we need to enable master bit
+	* if at least on of the fields is not 0
+	*/
+	if (value)
+		set_reg_field_value(
+			value,
+			1,
+			DP_SEC_CNTL,
+			DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_stream_encoder_stop_dp_info_packets(
+	struct stream_encoder *enc)
+{
+	/* stop generic packets on DP */
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DP_SEC_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP0_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP1_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP2_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP3_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_AVI_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_MPG_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_STREAM_ENABLE);
+
+	/* this register shared with audio info frame.
+	 * therefore we need to keep master enabled
+	 * if at least one of the fields is not 0 */
+
+	if (value)
+		set_reg_field_value(
+			value,
+			1,
+			DP_SEC_CNTL,
+			DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_stream_encoder_dp_blank(
+	struct stream_encoder *enc)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DP_VID_STREAM_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+	uint32_t retries = 0;
+	uint32_t max_retries = DP_BLANK_MAX_RETRY * 10;
+
+	/* Note: For CZ, we are changing driver default to disable
+	 * stream deferred to next VBLANK. If results are positive, we
+	 * will make the same change to all DCE versions. There are a
+	 * handful of panels that cannot handle disable stream at
+	 * HBLANK and will result in a white line flash across the
+	 * screen on stream disable. */
+
+	/* Specify the video stream disable point
+	 * (2 = start of the next vertical blank) */
+	set_reg_field_value(
+		value,
+		2,
+		DP_VID_STREAM_CNTL,
+		DP_VID_STREAM_DIS_DEFER);
+	/* Larger delay to wait until VBLANK - use max retry of
+	* 10us*3000=30ms. This covers 16.6ms of typical 60 Hz mode +
+	* a little more because we may not trust delay accuracy.
+	*/
+	max_retries = DP_BLANK_MAX_RETRY * 150;
+
+	/* disable DP stream */
+	set_reg_field_value(value, 0, DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE);
+	dm_write_reg(ctx, addr, value);
+
+	/* the encoder stops sending the video stream
+	* at the start of the vertical blanking.
+	* Poll for DP_VID_STREAM_STATUS == 0
+	*/
+
+	do {
+		value = dm_read_reg(ctx, addr);
+
+		if (!get_reg_field_value(
+			value,
+			DP_VID_STREAM_CNTL,
+			DP_VID_STREAM_STATUS))
+			break;
+
+		dm_delay_in_microseconds(ctx, 10);
+
+		++retries;
+	} while (retries < max_retries);
+
+	ASSERT(retries <= max_retries);
+
+	/* Tell the DP encoder to ignore timing from CRTC, must be done after
+	* the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is
+	* complete, stream status will be stuck in video stream enabled state,
+	* i.e. DP_VID_STREAM_STATUS stuck at 1.
+	*/
+	addr = LINK_REG(DP_STEER_FIFO);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, true, DP_STEER_FIFO, DP_STEER_FIFO_RESET);
+	dm_write_reg(ctx, addr, value);
+}
+
+/* output video stream to link encoder */
+void dce110_stream_encoder_dp_unblank(
+	struct stream_encoder *enc,
+	const struct encoder_unblank_param *param)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
+		uint32_t n_vid = 0x8000;
+		uint32_t m_vid;
+
+		/* M / N = Fstream / Flink
+		* m_vid / n_vid = pixel rate / link rate
+		*/
+
+		uint64_t m_vid_l = n_vid;
+
+		m_vid_l *= param->crtc_timing.pixel_clock;
+		m_vid_l = div_u64(m_vid_l,
+			param->link_settings.link_rate
+				* LINK_RATE_REF_FREQ_IN_KHZ);
+
+		m_vid = (uint32_t) m_vid_l;
+
+		/* enable auto measurement */
+		addr = LINK_REG(DP_VID_TIMING);
+		value = dm_read_reg(ctx, addr);
+		set_reg_field_value(value, 0, DP_VID_TIMING, DP_VID_M_N_GEN_EN);
+		dm_write_reg(ctx, addr, value);
+
+		/* auto measurement need 1 full 0x8000 symbol cycle to kick in,
+		* therefore program initial value for Mvid and Nvid
+		*/
+		addr = LINK_REG(DP_VID_N);
+		value = dm_read_reg(ctx, addr);
+		set_reg_field_value(value, n_vid, DP_VID_N, DP_VID_N);
+		dm_write_reg(ctx, addr, value);
+
+		addr = LINK_REG(DP_VID_M);
+		value = dm_read_reg(ctx, addr);
+		set_reg_field_value(value, m_vid, DP_VID_M, DP_VID_M);
+		dm_write_reg(ctx, addr, value);
+
+		addr = LINK_REG(DP_VID_TIMING);
+		value = dm_read_reg(ctx, addr);
+		set_reg_field_value(value, 1, DP_VID_TIMING, DP_VID_M_N_GEN_EN);
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* set DIG_START to 0x1 to resync FIFO */
+	addr = LINK_REG(DIG_FE_CNTL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 1, DIG_FE_CNTL, DIG_START);
+	dm_write_reg(ctx, addr, value);
+
+	/* switch DP encoder to CRTC data */
+	addr = LINK_REG(DP_STEER_FIFO);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 0, DP_STEER_FIFO, DP_STEER_FIFO_RESET);
+	dm_write_reg(ctx, addr, value);
+
+	/* wait 100us for DIG/DP logic to prime
+	* (i.e. a few video lines)
+	*/
+	dm_delay_in_microseconds(ctx, 100);
+
+	/* the hardware would start sending video at the start of the next DP
+	* frame (i.e. rising edge of the vblank).
+	* NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this
+	* register has no effect on enable transition! HW always guarantees
+	* VID_STREAM enable at start of next frame, and this is not
+	* programmable
+	*/
+	addr = LINK_REG(DP_VID_STREAM_CNTL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		true,
+		DP_VID_STREAM_CNTL,
+		DP_VID_STREAM_ENABLE);
+	dm_write_reg(ctx, addr, value);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h
new file mode 100644
index 000000000000..5753a1b7614e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_STREAM_ENCODER_DCE110_H__
+#define __DC_STREAM_ENCODER_DCE110_H__
+
+#include "inc/stream_encoder.h"
+
+#define DCE110STRENC_FROM_STRENC(stream_encoder)\
+	container_of(stream_encoder, struct dce110_stream_encoder, base)
+
+struct dce110_stream_enc_registers {
+	uint32_t AFMT_AVI_INFO0;
+	uint32_t AFMT_AVI_INFO1;
+	uint32_t AFMT_AVI_INFO2;
+	uint32_t AFMT_AVI_INFO3;
+	uint32_t AFMT_GENERIC_0;
+	uint32_t AFMT_GENERIC_7;
+	uint32_t AFMT_GENERIC_HDR;
+	uint32_t AFMT_INFOFRAME_CONTROL0;
+	uint32_t AFMT_VBI_PACKET_CONTROL;
+	uint32_t DIG_FE_CNTL;
+	uint32_t DP_MSE_RATE_CNTL;
+	uint32_t DP_MSE_RATE_UPDATE;
+	uint32_t DP_PIXEL_FORMAT;
+	uint32_t DP_SEC_CNTL;
+	uint32_t DP_STEER_FIFO;
+	uint32_t DP_VID_M;
+	uint32_t DP_VID_N;
+	uint32_t DP_VID_STREAM_CNTL;
+	uint32_t DP_VID_TIMING;
+	uint32_t HDMI_CONTROL;
+	uint32_t HDMI_GC;
+	uint32_t HDMI_GENERIC_PACKET_CONTROL0;
+	uint32_t HDMI_GENERIC_PACKET_CONTROL1;
+	uint32_t HDMI_INFOFRAME_CONTROL0;
+	uint32_t HDMI_INFOFRAME_CONTROL1;
+	uint32_t HDMI_VBI_PACKET_CONTROL;
+	uint32_t TMDS_CNTL;
+};
+
+struct dce110_stream_encoder {
+	struct stream_encoder base;
+	const struct dce110_stream_enc_registers *regs;
+};
+
+bool dce110_stream_encoder_construct(
+	struct dce110_stream_encoder *enc110,
+	struct dc_context *ctx,
+	struct dc_bios *bp,
+	enum engine_id eng_id,
+	const struct dce110_stream_enc_registers *regs);
+
+/***** HW programming ***********/
+/* setup stream encoder in dp mode */
+void dce110_stream_encoder_dp_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing);
+
+/* setup stream encoder in hdmi mode */
+void dce110_stream_encoder_hdmi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool enable_audio);
+
+/* setup stream encoder in dvi mode */
+void dce110_stream_encoder_dvi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool is_dual_link);
+
+/* set throttling for DP MST */
+void dce110_stream_encoder_set_mst_bandwidth(
+	struct stream_encoder *enc,
+	struct fixed31_32 avg_time_slots_per_mtp);
+
+void dce110_stream_encoder_update_hdmi_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame);
+
+void dce110_stream_encoder_stop_hdmi_info_packets(
+	struct stream_encoder *enc);
+
+void dce110_stream_encoder_update_dp_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame);
+
+void dce110_stream_encoder_stop_dp_info_packets(
+	struct stream_encoder *enc);
+
+/* output blank/idle stream to link encoder */
+void dce110_stream_encoder_dp_blank(
+	struct stream_encoder *enc);
+
+/* output video stream to link encoder */
+void dce110_stream_encoder_dp_unblank(
+	struct stream_encoder *enc,
+	const struct encoder_unblank_param *param);
+
+#endif /* __DC_STREAM_ENCODER_DCE110_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 14/29] drm/amd/dal: Add clock source HW programming
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (12 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 13/29] drm/amd/dal: Add encoder HW programming Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 15/29] drm/amd/dal: Add timing generator " Harry Wentland
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Adds pixel clock programming and functionality to
power down clock sources.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../drm/amd/dal/dc/dce110/dce110_clock_source.c    | 1162 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_clock_source.h    |   64 ++
 2 files changed, 1226 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
new file mode 100644
index 000000000000..e1bac1f77b79
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
@@ -0,0 +1,1162 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dc_types.h"
+#include "core_types.h"
+
+#include "include/grph_object_id.h"
+#include "include/logger_interface.h"
+
+#include "dce110_clock_source.h"
+
+#define FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM 6
+#define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1
+#define MAX_PLL_CALC_ERROR 0xFFFFFFFF
+
+static const struct spread_spectrum_data *get_ss_data_entry(
+		struct dce110_clk_src *clk_src,
+		enum signal_type signal,
+		uint32_t pix_clk_khz)
+{
+
+	uint32_t entrys_num;
+	uint32_t i;
+	struct spread_spectrum_data *ss_parm = NULL;
+	struct spread_spectrum_data *ret = NULL;
+
+	switch (signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		ss_parm = clk_src->dvi_ss_params;
+		entrys_num = clk_src->dvi_ss_params_cnt;
+		break;
+
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		ss_parm = clk_src->hdmi_ss_params;
+		entrys_num = clk_src->hdmi_ss_params_cnt;
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		ss_parm = clk_src->dp_ss_params;
+		entrys_num = clk_src->dp_ss_params_cnt;
+		break;
+
+	default:
+		ss_parm = NULL;
+		entrys_num = 0;
+		break;
+	}
+
+	if (ss_parm == NULL)
+		return ret;
+
+	for (i = 0; i < entrys_num; ++i, ++ss_parm) {
+		if (ss_parm->freq_range_khz >= pix_clk_khz) {
+			ret = ss_parm;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+* Function: calculate_fb_and_fractional_fb_divider
+*
+* * DESCRIPTION: Calculates feedback and fractional feedback dividers values
+*
+*PARAMETERS:
+* targetPixelClock             Desired frequency in 10 KHz
+* ref_divider                  Reference divider (already known)
+* postDivider                  Post Divider (already known)
+* feedback_divider_param       Pointer where to store
+*					calculated feedback divider value
+* fract_feedback_divider_param Pointer where to store
+*					calculated fract feedback divider value
+*
+*RETURNS:
+* It fills the locations pointed by feedback_divider_param
+*					and fract_feedback_divider_param
+* It returns	- true if feedback divider not 0
+*		- false should never happen)
+*/
+static bool calculate_fb_and_fractional_fb_divider(
+		struct calc_pll_clock_source *calc_pll_cs,
+		uint32_t target_pix_clk_khz,
+		uint32_t ref_divider,
+		uint32_t post_divider,
+		uint32_t *feedback_divider_param,
+		uint32_t *fract_feedback_divider_param)
+{
+	uint64_t feedback_divider;
+
+	feedback_divider =
+		(uint64_t)(target_pix_clk_khz * ref_divider * post_divider);
+	feedback_divider *= 10;
+	/* additional factor, since we divide by 10 afterwards */
+	feedback_divider *= (uint64_t)(calc_pll_cs->fract_fb_divider_factor);
+	feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz);
+
+/*Round to the number of precision
+ * The following code replace the old code (ullfeedbackDivider + 5)/10
+ * for example if the difference between the number
+ * of fractional feedback decimal point and the fractional FB Divider precision
+ * is 2 then the equation becomes (ullfeedbackDivider + 5*100) / (10*100))*/
+
+	feedback_divider += (uint64_t)
+			(5 * calc_pll_cs->fract_fb_divider_precision_factor);
+	feedback_divider =
+		div_u64(feedback_divider,
+			calc_pll_cs->fract_fb_divider_precision_factor * 10);
+	feedback_divider *= (uint64_t)
+			(calc_pll_cs->fract_fb_divider_precision_factor);
+
+	*feedback_divider_param =
+		div_u64_rem(
+			feedback_divider,
+			calc_pll_cs->fract_fb_divider_factor,
+			fract_feedback_divider_param);
+
+	if (*feedback_divider_param != 0)
+		return true;
+	return false;
+}
+
+/**
+*calc_fb_divider_checking_tolerance
+*
+*DESCRIPTION: Calculates Feedback and Fractional Feedback divider values
+*		for passed Reference and Post divider, checking for tolerance.
+*PARAMETERS:
+* pll_settings		Pointer to structure
+* ref_divider		Reference divider (already known)
+* postDivider		Post Divider (already known)
+* tolerance		Tolerance for Calculated Pixel Clock to be within
+*
+*RETURNS:
+* It fills the PLLSettings structure with PLL Dividers values
+* if calculated values are within required tolerance
+* It returns	- true if eror is within tolerance
+*		- false if eror is not within tolerance
+*/
+static bool calc_fb_divider_checking_tolerance(
+		struct calc_pll_clock_source *calc_pll_cs,
+		struct pll_settings *pll_settings,
+		uint32_t ref_divider,
+		uint32_t post_divider,
+		uint32_t tolerance)
+{
+	uint32_t feedback_divider;
+	uint32_t fract_feedback_divider;
+	uint32_t actual_calculated_clock_khz;
+	uint32_t abs_err;
+	uint64_t actual_calc_clk_khz;
+
+	calculate_fb_and_fractional_fb_divider(
+			calc_pll_cs,
+			pll_settings->adjusted_pix_clk,
+			ref_divider,
+			post_divider,
+			&feedback_divider,
+			&fract_feedback_divider);
+
+	/*Actual calculated value*/
+	actual_calc_clk_khz = (uint64_t)(feedback_divider *
+					calc_pll_cs->fract_fb_divider_factor) +
+							fract_feedback_divider;
+	actual_calc_clk_khz *= calc_pll_cs->ref_freq_khz;
+	actual_calc_clk_khz =
+		div_u64(actual_calc_clk_khz,
+			ref_divider * post_divider *
+				calc_pll_cs->fract_fb_divider_factor);
+
+	actual_calculated_clock_khz = (uint32_t)(actual_calc_clk_khz);
+
+	abs_err = (actual_calculated_clock_khz >
+					pll_settings->adjusted_pix_clk)
+			? actual_calculated_clock_khz -
+					pll_settings->adjusted_pix_clk
+			: pll_settings->adjusted_pix_clk -
+						actual_calculated_clock_khz;
+
+	if (abs_err <= tolerance) {
+		/*found good values*/
+		pll_settings->reference_freq = calc_pll_cs->ref_freq_khz;
+		pll_settings->reference_divider = ref_divider;
+		pll_settings->feedback_divider = feedback_divider;
+		pll_settings->fract_feedback_divider = fract_feedback_divider;
+		pll_settings->pix_clk_post_divider = post_divider;
+		pll_settings->calculated_pix_clk =
+			actual_calculated_clock_khz;
+		pll_settings->vco_freq =
+			actual_calculated_clock_khz * post_divider;
+		return true;
+	}
+	return false;
+}
+
+
+static bool calc_pll_dividers_in_range(
+		struct calc_pll_clock_source *calc_pll_cs,
+		struct pll_settings *pll_settings,
+		uint32_t min_ref_divider,
+		uint32_t max_ref_divider,
+		uint32_t min_post_divider,
+		uint32_t max_post_divider,
+		uint32_t err_tolerance)
+{
+	uint32_t ref_divider;
+	uint32_t post_divider;
+	uint32_t tolerance;
+
+/* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25%
+ * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/
+	tolerance = (pll_settings->adjusted_pix_clk * err_tolerance) /
+									10000;
+	if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE)
+		tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE;
+
+	for (
+			post_divider = max_post_divider;
+			post_divider >= min_post_divider;
+			--post_divider) {
+		for (
+				ref_divider = min_ref_divider;
+				ref_divider <= max_ref_divider;
+				++ref_divider) {
+			if (calc_fb_divider_checking_tolerance(
+					calc_pll_cs,
+					pll_settings,
+					ref_divider,
+					post_divider,
+					tolerance)) {
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+static uint32_t calculate_pixel_clock_pll_dividers(
+		struct calc_pll_clock_source *calc_pll_cs,
+		struct pll_settings *pll_settings)
+{
+	uint32_t err_tolerance;
+	uint32_t min_post_divider;
+	uint32_t max_post_divider;
+	uint32_t min_ref_divider;
+	uint32_t max_ref_divider;
+
+	if (pll_settings->adjusted_pix_clk == 0) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s Bad requested pixel clock", __func__);
+		return MAX_PLL_CALC_ERROR;
+	}
+
+/* 1) Find Post divider ranges */
+	if (pll_settings->pix_clk_post_divider) {
+		min_post_divider = pll_settings->pix_clk_post_divider;
+		max_post_divider = pll_settings->pix_clk_post_divider;
+	} else {
+		min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider;
+		if (min_post_divider * pll_settings->adjusted_pix_clk <
+						calc_pll_cs->min_vco_khz) {
+			min_post_divider = calc_pll_cs->min_vco_khz /
+					pll_settings->adjusted_pix_clk;
+			if ((min_post_divider *
+					pll_settings->adjusted_pix_clk) <
+						calc_pll_cs->min_vco_khz)
+				min_post_divider++;
+		}
+
+		max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider;
+		if (max_post_divider * pll_settings->adjusted_pix_clk
+				> calc_pll_cs->max_vco_khz)
+			max_post_divider = calc_pll_cs->max_vco_khz /
+					pll_settings->adjusted_pix_clk;
+	}
+
+/* 2) Find Reference divider ranges
+ * When SS is enabled, or for Display Port even without SS,
+ * pll_settings->referenceDivider is not zero.
+ * So calculate PPLL FB and fractional FB divider
+ * using the passed reference divider*/
+
+	if (pll_settings->reference_divider) {
+		min_ref_divider = pll_settings->reference_divider;
+		max_ref_divider = pll_settings->reference_divider;
+	} else {
+		min_ref_divider = ((calc_pll_cs->ref_freq_khz
+				/ calc_pll_cs->max_pll_input_freq_khz)
+				> calc_pll_cs->min_pll_ref_divider)
+			? calc_pll_cs->ref_freq_khz
+					/ calc_pll_cs->max_pll_input_freq_khz
+			: calc_pll_cs->min_pll_ref_divider;
+
+		max_ref_divider = ((calc_pll_cs->ref_freq_khz
+				/ calc_pll_cs->min_pll_input_freq_khz)
+				< calc_pll_cs->max_pll_ref_divider)
+			? calc_pll_cs->ref_freq_khz /
+					calc_pll_cs->min_pll_input_freq_khz
+			: calc_pll_cs->max_pll_ref_divider;
+	}
+
+/* If some parameters are invalid we could have scenario when  "min">"max"
+ * which produced endless loop later.
+ * We should investigate why we get the wrong parameters.
+ * But to follow the similar logic when "adjustedPixelClock" is set to be 0
+ * it is better to return here than cause system hang/watchdog timeout later.
+ *  ## SVS Wed 15 Jul 2009 */
+
+	if (min_post_divider > max_post_divider) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s Post divider range is invalid", __func__);
+		return MAX_PLL_CALC_ERROR;
+	}
+
+	if (min_ref_divider > max_ref_divider) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s Reference divider range is invalid", __func__);
+		return MAX_PLL_CALC_ERROR;
+	}
+
+/* 3) Try to find PLL dividers given ranges
+ * starting with minimal error tolerance.
+ * Increase error tolerance until PLL dividers found*/
+	err_tolerance = MAX_PLL_CALC_ERROR;
+
+	while (!calc_pll_dividers_in_range(
+			calc_pll_cs,
+			pll_settings,
+			min_ref_divider,
+			max_ref_divider,
+			min_post_divider,
+			max_post_divider,
+			err_tolerance))
+		err_tolerance += (err_tolerance > 10)
+				? (err_tolerance / 10)
+				: 1;
+
+	return err_tolerance;
+}
+
+static bool pll_adjust_pix_clk(
+		struct dce110_clk_src *clk_src,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	uint32_t actual_pix_clk_khz = 0;
+	uint32_t requested_clk_khz = 0;
+	struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = {
+							0 };
+	enum bp_result bp_result;
+
+	switch (pix_clk_params->signal_type) {
+	case SIGNAL_TYPE_HDMI_TYPE_A: {
+		requested_clk_khz = pix_clk_params->requested_pix_clk;
+
+		switch (pix_clk_params->color_depth) {
+		case COLOR_DEPTH_101010:
+			requested_clk_khz = (requested_clk_khz * 5) >> 2;
+			break; /* x1.25*/
+		case COLOR_DEPTH_121212:
+			requested_clk_khz = (requested_clk_khz * 6) >> 2;
+			break; /* x1.5*/
+		case COLOR_DEPTH_161616:
+			requested_clk_khz = requested_clk_khz * 2;
+			break; /* x2.0*/
+		default:
+			break;
+		}
+
+		actual_pix_clk_khz = requested_clk_khz;
+	}
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		requested_clk_khz = pix_clk_params->requested_sym_clk;
+		actual_pix_clk_khz = pix_clk_params->requested_pix_clk;
+		break;
+
+	default:
+		requested_clk_khz = pix_clk_params->requested_pix_clk;
+		actual_pix_clk_khz = pix_clk_params->requested_pix_clk;
+		break;
+	}
+
+	bp_adjust_pixel_clock_params.pixel_clock = requested_clk_khz;
+	bp_adjust_pixel_clock_params.
+		encoder_object_id = pix_clk_params->encoder_object_id;
+	bp_adjust_pixel_clock_params.signal_type = pix_clk_params->signal_type;
+	bp_adjust_pixel_clock_params.
+		ss_enable = pix_clk_params->flags.ENABLE_SS;
+	bp_result = clk_src->bios->funcs->adjust_pixel_clock(
+			clk_src->bios, &bp_adjust_pixel_clock_params);
+	if (bp_result == BP_RESULT_OK) {
+		pll_settings->actual_pix_clk = actual_pix_clk_khz;
+		pll_settings->adjusted_pix_clk =
+			bp_adjust_pixel_clock_params.adjusted_pixel_clock;
+		pll_settings->reference_divider =
+			bp_adjust_pixel_clock_params.reference_divider;
+		pll_settings->pix_clk_post_divider =
+			bp_adjust_pixel_clock_params.pixel_clock_post_divider;
+
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * Calculate PLL Dividers for given Clock Value.
+ * First will call VBIOS Adjust Exec table to check if requested Pixel clock
+ * will be Adjusted based on usage.
+ * Then it will calculate PLL Dividers for this Adjusted clock using preferred
+ * method (Maximum VCO frequency).
+ *
+ * \return
+ *     Calculation error in units of 0.01%
+ */
+static uint32_t dce110_get_pix_clk_dividers(
+		struct clock_source *cs,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs);
+	uint32_t pll_calc_error = MAX_PLL_CALC_ERROR;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	uint32_t field = 0;
+
+	if (pix_clk_params == NULL || pll_settings == NULL
+			|| pix_clk_params->requested_pix_clk == 0) {
+		dal_logger_write(clk_src->base.ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Invalid parameters!!\n", __func__);
+		return pll_calc_error;
+	}
+
+	dm_memset(pll_settings, 0, sizeof(*pll_settings));
+
+	if (cs->id == CLOCK_SOURCE_ID_EXTERNAL) {
+		pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz;
+		pll_settings->calculated_pix_clk = clk_src->ext_clk_khz;
+		pll_settings->actual_pix_clk =
+					pix_clk_params->requested_pix_clk;
+		return 0;
+	}
+	/* PLL only after this point */
+
+	/* Check if reference clock is external (not pcie/xtalin)
+	* HW Dce80 spec:
+	* 00 - PCIE_REFCLK, 01 - XTALIN,    02 - GENERICA,    03 - GENERICB
+	* 04 - HSYNCA,      05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */
+	addr = clk_src->offsets.pll_cntl;
+	value = dm_read_reg(clk_src->base.ctx, addr);
+	field = get_reg_field_value(value, PLL_CNTL, PLL_REF_DIV_SRC);
+	pll_settings->use_external_clk = (field > 1);
+
+	/* VBIOS by default enables DP SS (spread on IDCLK) for DCE 8.0 always
+	 * (we do not care any more from SI for some older DP Sink which
+	 * does not report SS support, no known issues) */
+	if ((pix_clk_params->flags.ENABLE_SS) ||
+			(dc_is_dp_signal(pix_clk_params->signal_type))) {
+
+		const struct spread_spectrum_data *ss_data = get_ss_data_entry(
+					clk_src,
+					pix_clk_params->signal_type,
+					pll_settings->adjusted_pix_clk);
+
+		if (NULL != ss_data)
+			pll_settings->ss_percentage = ss_data->percentage;
+	}
+
+	/* Check VBIOS AdjustPixelClock Exec table */
+	if (!pll_adjust_pix_clk(clk_src, pix_clk_params, pll_settings)) {
+		/* Should never happen, ASSERT and fill up values to be able
+		 * to continue. */
+		dal_logger_write(clk_src->base.ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Failed to adjust pixel clock!!", __func__);
+		pll_settings->actual_pix_clk =
+				pix_clk_params->requested_pix_clk;
+		pll_settings->adjusted_pix_clk =
+				pix_clk_params->requested_pix_clk;
+
+		if (dc_is_dp_signal(pix_clk_params->signal_type))
+			pll_settings->adjusted_pix_clk = 100000;
+	}
+
+	/* Calculate Dividers */
+	if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
+		/*Calculate Dividers by HDMI object, no SS case or SS case */
+		pll_calc_error =
+			calculate_pixel_clock_pll_dividers(
+					&clk_src->calc_pll_hdmi,
+					pll_settings);
+	else
+		/*Calculate Dividers by default object, no SS case or SS case */
+		pll_calc_error =
+			calculate_pixel_clock_pll_dividers(
+					&clk_src->calc_pll,
+					pll_settings);
+
+	return pll_calc_error;
+}
+
+static bool disable_spread_spectrum(struct dce110_clk_src *clk_src)
+{
+	enum bp_result result;
+	struct bp_spread_spectrum_parameters bp_ss_params = {0};
+
+	bp_ss_params.pll_id = clk_src->base.id;
+
+	/*Call ASICControl to process ATOMBIOS Exec table*/
+	result = clk_src->bios->funcs->enable_spread_spectrum_on_ppll(
+			clk_src->bios,
+			&bp_ss_params,
+			false);
+
+	return result == BP_RESULT_OK;
+}
+
+static bool calculate_ss(
+		const struct pll_settings *pll_settings,
+		const struct spread_spectrum_data *ss_data,
+		struct delta_sigma_data *ds_data)
+{
+	struct fixed32_32 fb_div;
+	struct fixed32_32 ss_amount;
+	struct fixed32_32 ss_nslip_amount;
+	struct fixed32_32 ss_ds_frac_amount;
+	struct fixed32_32 ss_step_size;
+	struct fixed32_32 modulation_time;
+
+	if (ds_data == NULL)
+		return false;
+	if (ss_data == NULL)
+		return false;
+	if (ss_data->percentage == 0)
+		return false;
+	if (pll_settings == NULL)
+		return false;
+
+
+	dm_memset(ds_data, 0, sizeof(struct delta_sigma_data));
+
+
+
+	/* compute SS_AMOUNT_FBDIV & SS_AMOUNT_NFRAC_SLIP & SS_AMOUNT_DSFRAC*/
+	/* 6 decimal point support in fractional feedback divider */
+	fb_div  = dal_fixed32_32_from_fraction(
+		pll_settings->fract_feedback_divider, 1000000);
+	fb_div = dal_fixed32_32_add_int(fb_div, pll_settings->feedback_divider);
+
+	ds_data->ds_frac_amount = 0;
+	/*spreadSpectrumPercentage is in the unit of .01%,
+	 * so have to divided by 100 * 100*/
+	ss_amount = dal_fixed32_32_mul(
+		fb_div, dal_fixed32_32_from_fraction(ss_data->percentage,
+					100 * ss_data->percentage_divider));
+	ds_data->feedback_amount = dal_fixed32_32_floor(ss_amount);
+
+	ss_nslip_amount = dal_fixed32_32_sub(ss_amount,
+		dal_fixed32_32_from_int(ds_data->feedback_amount));
+	ss_nslip_amount = dal_fixed32_32_mul_int(ss_nslip_amount, 10);
+	ds_data->nfrac_amount = dal_fixed32_32_floor(ss_nslip_amount);
+
+	ss_ds_frac_amount = dal_fixed32_32_sub(ss_nslip_amount,
+		dal_fixed32_32_from_int(ds_data->nfrac_amount));
+	ss_ds_frac_amount = dal_fixed32_32_mul_int(ss_ds_frac_amount, 65536);
+	ds_data->ds_frac_amount = dal_fixed32_32_floor(ss_ds_frac_amount);
+
+	/* compute SS_STEP_SIZE_DSFRAC */
+	modulation_time = dal_fixed32_32_from_fraction(
+		pll_settings->reference_freq * 1000,
+		pll_settings->reference_divider * ss_data->modulation_freq_hz);
+
+
+	if (ss_data->flags.CENTER_SPREAD)
+		modulation_time = dal_fixed32_32_div_int(modulation_time, 4);
+	else
+		modulation_time = dal_fixed32_32_div_int(modulation_time, 2);
+
+	ss_step_size = dal_fixed32_32_div(ss_amount, modulation_time);
+	/* SS_STEP_SIZE_DSFRAC_DEC = Int(SS_STEP_SIZE * 2 ^ 16 * 10)*/
+	ss_step_size = dal_fixed32_32_mul_int(ss_step_size, 65536 * 10);
+	ds_data->ds_frac_size =  dal_fixed32_32_floor(ss_step_size);
+
+	return true;
+}
+
+static bool enable_spread_spectrum(
+		struct dce110_clk_src *clk_src,
+		enum signal_type signal, struct pll_settings *pll_settings)
+{
+	struct bp_spread_spectrum_parameters bp_params = {0};
+	struct delta_sigma_data d_s_data;
+	const struct spread_spectrum_data *ss_data = NULL;
+
+	ss_data = get_ss_data_entry(
+			clk_src,
+			signal,
+			pll_settings->calculated_pix_clk);
+
+/* Pixel clock PLL has been programmed to generate desired pixel clock,
+ * now enable SS on pixel clock */
+/* TODO is it OK to return true not doing anything ??*/
+	if (ss_data != NULL && pll_settings->ss_percentage != 0) {
+		if (calculate_ss(pll_settings, ss_data, &d_s_data)) {
+			bp_params.ds.feedback_amount =
+					d_s_data.feedback_amount;
+			bp_params.ds.nfrac_amount =
+					d_s_data.nfrac_amount;
+			bp_params.ds.ds_frac_size = d_s_data.ds_frac_size;
+			bp_params.ds_frac_amount =
+					d_s_data.ds_frac_amount;
+			bp_params.flags.DS_TYPE = 1;
+			bp_params.pll_id = clk_src->base.id;
+			bp_params.percentage = ss_data->percentage;
+			if (ss_data->flags.CENTER_SPREAD)
+				bp_params.flags.CENTER_SPREAD = 1;
+			if (ss_data->flags.EXTERNAL_SS)
+				bp_params.flags.EXTERNAL_SS = 1;
+
+			if (BP_RESULT_OK !=
+				clk_src->bios->funcs->
+					enable_spread_spectrum_on_ppll(
+							clk_src->bios,
+							&bp_params,
+							true))
+				return false;
+		} else
+			return false;
+	}
+	return true;
+}
+
+static void program_pixel_clk_resync(
+		struct dce110_clk_src *clk_src,
+		enum signal_type signal_type,
+		enum dc_color_depth colordepth)
+{
+	uint32_t value = 0;
+
+	value = dm_read_reg(clk_src->base.ctx, clk_src->offsets.pixclk_resync_cntl);
+
+	set_reg_field_value(
+		value,
+		0,
+		PIXCLK1_RESYNC_CNTL,
+		DCCG_DEEP_COLOR_CNTL1);
+
+	/*
+	 24 bit mode: TMDS clock = 1.0 x pixel clock  (1:1)
+	 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4)
+	 36 bit mode: TMDS clock = 1.5 x pixel clock  (3:2)
+	 48 bit mode: TMDS clock = 2 x pixel clock    (2:1)
+	 */
+	if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A)
+		return;
+
+	switch (colordepth) {
+	case COLOR_DEPTH_888:
+		set_reg_field_value(
+			value,
+			0,
+			PIXCLK1_RESYNC_CNTL,
+			DCCG_DEEP_COLOR_CNTL1);
+		break;
+	case COLOR_DEPTH_101010:
+		set_reg_field_value(
+			value,
+			1,
+			PIXCLK1_RESYNC_CNTL,
+			DCCG_DEEP_COLOR_CNTL1);
+		break;
+	case COLOR_DEPTH_121212:
+		set_reg_field_value(
+			value,
+			2,
+			PIXCLK1_RESYNC_CNTL,
+			DCCG_DEEP_COLOR_CNTL1);
+		break;
+	case COLOR_DEPTH_161616:
+		set_reg_field_value(
+			value,
+			3,
+			PIXCLK1_RESYNC_CNTL,
+			DCCG_DEEP_COLOR_CNTL1);
+		break;
+	default:
+		break;
+	}
+
+	dm_write_reg(
+		clk_src->base.ctx,
+		clk_src->offsets.pixclk_resync_cntl,
+		value);
+}
+
+static bool dce110_program_pix_clk(
+		struct clock_source *clk_src,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src);
+	struct bp_pixel_clock_parameters bp_pc_params = {0};
+
+	/* First disable SS
+	 * ATOMBIOS will enable by default SS on PLL for DP,
+	 * do not disable it here
+	 */
+	if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL &&
+			!dc_is_dp_signal(pix_clk_params->signal_type))
+		disable_spread_spectrum(dce110_clk_src);
+
+	/*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/
+	bp_pc_params.controller_id = pix_clk_params->controller_id;
+	bp_pc_params.pll_id = clk_src->id;
+	bp_pc_params.target_pixel_clock =
+			pll_settings->actual_pix_clk;
+	bp_pc_params.reference_divider = pll_settings->reference_divider;
+	bp_pc_params.feedback_divider = pll_settings->feedback_divider;
+	bp_pc_params.fractional_feedback_divider =
+			pll_settings->fract_feedback_divider;
+	bp_pc_params.pixel_clock_post_divider =
+			pll_settings->pix_clk_post_divider;
+	bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id;
+	bp_pc_params.signal_type = pix_clk_params->signal_type;
+	bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC =
+					pll_settings->use_external_clk;
+
+	if (dce110_clk_src->bios->funcs->set_pixel_clock(
+			dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK)
+		return false;
+
+/* Enable SS
+ * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock),
+ * based on HW display PLL team, SS control settings should be programmed
+ * during PLL Reset, but they do not have effect
+ * until SS_EN is asserted.*/
+	if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL
+		&& pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal(
+						pix_clk_params->signal_type))
+		if (!enable_spread_spectrum(dce110_clk_src,
+						pix_clk_params->signal_type,
+						pll_settings))
+			return false;
+
+/* Resync deep color DTO */
+	if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL)
+		program_pixel_clk_resync(dce110_clk_src,
+					pix_clk_params->signal_type,
+					pix_clk_params->color_depth);
+
+	return true;
+}
+
+static bool dce110_clock_source_power_down(
+		struct clock_source *clk_src)
+{
+	struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src);
+	enum bp_result bp_result;
+	struct bp_pixel_clock_parameters bp_pixel_clock_params = {0};
+
+	if (clk_src->id == CLOCK_SOURCE_ID_EXTERNAL)
+		return true;
+
+	/* If Pixel Clock is 0 it means Power Down Pll*/
+	bp_pixel_clock_params.controller_id = CONTROLLER_ID_UNDEFINED;
+	bp_pixel_clock_params.pll_id = clk_src->id;
+	bp_pixel_clock_params.flags.FORCE_PROGRAMMING_OF_PLL = 1;
+
+	/*Call ASICControl to process ATOMBIOS Exec table*/
+	bp_result = dce110_clk_src->bios->funcs->set_pixel_clock(
+			dce110_clk_src->bios,
+			&bp_pixel_clock_params);
+
+	return bp_result == BP_RESULT_OK;
+}
+
+/*****************************************/
+/* Constructor                           */
+/*****************************************/
+static struct clock_source_funcs dce110_clk_src_funcs = {
+	.cs_power_down = dce110_clock_source_power_down,
+	.program_pix_clk = dce110_program_pix_clk,
+	.get_pix_clk_dividers = dce110_get_pix_clk_dividers
+};
+
+
+static void get_ss_info_from_atombios(
+		struct dce110_clk_src *clk_src,
+		enum as_signal_type as_signal,
+		struct spread_spectrum_data *spread_spectrum_data[],
+		uint32_t *ss_entries_num)
+{
+	enum bp_result bp_result = BP_RESULT_FAILURE;
+	struct spread_spectrum_info *ss_info;
+	struct spread_spectrum_data *ss_data;
+	struct spread_spectrum_info *ss_info_cur;
+	struct spread_spectrum_data *ss_data_cur;
+	uint32_t i;
+
+	if (ss_entries_num == NULL) {
+		dal_logger_write(clk_src->base.ctx->logger,
+			LOG_MAJOR_SYNC,
+			LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+			"Invalid entry !!!\n");
+		return;
+	}
+	if (spread_spectrum_data == NULL) {
+		dal_logger_write(clk_src->base.ctx->logger,
+			LOG_MAJOR_SYNC,
+			LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+			"Invalid array pointer!!!\n");
+		return;
+	}
+
+	spread_spectrum_data[0] = NULL;
+	*ss_entries_num = 0;
+
+	*ss_entries_num = clk_src->bios->funcs->get_ss_entry_number(
+			clk_src->bios,
+			as_signal);
+
+	if (*ss_entries_num == 0)
+		return;
+
+	ss_info = dm_alloc(clk_src->base.ctx, sizeof(struct spread_spectrum_info)
+				* (*ss_entries_num));
+	ss_info_cur = ss_info;
+	if (ss_info == NULL)
+		return;
+
+	ss_data = dm_alloc(clk_src->base.ctx, sizeof(struct spread_spectrum_data) *
+							(*ss_entries_num));
+	if (ss_data == NULL)
+		goto out_free_info;
+
+	for (i = 0, ss_info_cur = ss_info;
+		i < (*ss_entries_num);
+		++i, ++ss_info_cur) {
+
+		bp_result = clk_src->bios->funcs->get_spread_spectrum_info(
+				clk_src->bios,
+				as_signal,
+				i,
+				ss_info_cur);
+
+		if (bp_result != BP_RESULT_OK)
+			goto out_free_data;
+	}
+
+	for (i = 0, ss_info_cur = ss_info, ss_data_cur = ss_data;
+		i < (*ss_entries_num);
+		++i, ++ss_info_cur, ++ss_data_cur) {
+
+		if (ss_info_cur->type.STEP_AND_DELAY_INFO != false) {
+			dal_logger_write(clk_src->base.ctx->logger,
+				LOG_MAJOR_SYNC,
+				LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+				"Invalid ATOMBIOS SS Table!!!\n");
+			goto out_free_data;
+		}
+
+		/* for HDMI check SS percentage,
+		 * if it is > 6 (0.06%), the ATOMBIOS table info is invalid*/
+		if (as_signal == AS_SIGNAL_TYPE_HDMI
+				&& ss_info_cur->spread_spectrum_percentage > 6){
+			/* invalid input, do nothing */
+			dal_logger_write(clk_src->base.ctx->logger,
+				LOG_MAJOR_SYNC,
+				LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+				"Invalid SS percentage ");
+			dal_logger_write(clk_src->base.ctx->logger,
+				LOG_MAJOR_SYNC,
+				LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+				"for HDMI in ATOMBIOS info Table!!!\n");
+			continue;
+		}
+		if (ss_info_cur->spread_percentage_divider == 1000) {
+			/* Keep previous precision from ATOMBIOS for these
+			* in case new precision set by ATOMBIOS for these
+			* (otherwise all code in DCE specific classes
+			* for all previous ASICs would need
+			* to be updated for SS calculations,
+			* Audio SS compensation and DP DTO SS compensation
+			* which assumes fixed SS percentage Divider = 100)*/
+			ss_info_cur->spread_spectrum_percentage /= 10;
+			ss_info_cur->spread_percentage_divider = 100;
+		}
+
+		ss_data_cur->freq_range_khz = ss_info_cur->target_clock_range;
+		ss_data_cur->percentage =
+				ss_info_cur->spread_spectrum_percentage;
+		ss_data_cur->percentage_divider =
+				ss_info_cur->spread_percentage_divider;
+		ss_data_cur->modulation_freq_hz =
+				ss_info_cur->spread_spectrum_range;
+
+		if (ss_info_cur->type.CENTER_MODE)
+			ss_data_cur->flags.CENTER_SPREAD = 1;
+
+		if (ss_info_cur->type.EXTERNAL)
+			ss_data_cur->flags.EXTERNAL_SS = 1;
+
+	}
+
+	*spread_spectrum_data = ss_data;
+	dm_free(clk_src->base.ctx, ss_info);
+	return;
+
+out_free_data:
+	dm_free(clk_src->base.ctx, ss_data);
+	*ss_entries_num = 0;
+out_free_info:
+	dm_free(clk_src->base.ctx, ss_info);
+}
+
+static void ss_info_from_atombios_create(
+	struct dce110_clk_src *clk_src)
+{
+	get_ss_info_from_atombios(
+		clk_src,
+		AS_SIGNAL_TYPE_DISPLAY_PORT,
+		&clk_src->dp_ss_params,
+		&clk_src->dp_ss_params_cnt);
+	get_ss_info_from_atombios(
+		clk_src,
+		AS_SIGNAL_TYPE_HDMI,
+		&clk_src->hdmi_ss_params,
+		&clk_src->hdmi_ss_params_cnt);
+	get_ss_info_from_atombios(
+		clk_src,
+		AS_SIGNAL_TYPE_DVI,
+		&clk_src->dvi_ss_params,
+		&clk_src->dvi_ss_params_cnt);
+}
+
+static bool calc_pll_max_vco_construct(
+			struct calc_pll_clock_source *calc_pll_cs,
+			struct calc_pll_clock_source_init_data *init_data)
+{
+	uint32_t i;
+	struct firmware_info fw_info = { { 0 } };
+	if (calc_pll_cs == NULL ||
+			init_data == NULL ||
+			init_data->bp == NULL)
+		return false;
+
+	if (init_data->bp->funcs->get_firmware_info(
+				init_data->bp,
+				&fw_info) != BP_RESULT_OK)
+		return false;
+
+	calc_pll_cs->ctx = init_data->ctx;
+	calc_pll_cs->ref_freq_khz = fw_info.pll_info.crystal_frequency;
+	calc_pll_cs->min_vco_khz =
+			fw_info.pll_info.min_output_pxl_clk_pll_frequency;
+	calc_pll_cs->max_vco_khz =
+			fw_info.pll_info.max_output_pxl_clk_pll_frequency;
+
+	if (init_data->max_override_input_pxl_clk_pll_freq_khz != 0)
+		calc_pll_cs->max_pll_input_freq_khz =
+			init_data->max_override_input_pxl_clk_pll_freq_khz;
+	else
+		calc_pll_cs->max_pll_input_freq_khz =
+			fw_info.pll_info.max_input_pxl_clk_pll_frequency;
+
+	if (init_data->min_override_input_pxl_clk_pll_freq_khz != 0)
+		calc_pll_cs->min_pll_input_freq_khz =
+			init_data->min_override_input_pxl_clk_pll_freq_khz;
+	else
+		calc_pll_cs->min_pll_input_freq_khz =
+			fw_info.pll_info.min_input_pxl_clk_pll_frequency;
+
+	calc_pll_cs->min_pix_clock_pll_post_divider =
+			init_data->min_pix_clk_pll_post_divider;
+	calc_pll_cs->max_pix_clock_pll_post_divider =
+			init_data->max_pix_clk_pll_post_divider;
+	calc_pll_cs->min_pll_ref_divider =
+			init_data->min_pll_ref_divider;
+	calc_pll_cs->max_pll_ref_divider =
+			init_data->max_pll_ref_divider;
+
+	if (init_data->num_fract_fb_divider_decimal_point == 0 ||
+		init_data->num_fract_fb_divider_decimal_point_precision >
+				init_data->num_fract_fb_divider_decimal_point) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"The dec point num or precision is incorrect!");
+		return false;
+	}
+	if (init_data->num_fract_fb_divider_decimal_point_precision == 0) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"Incorrect fract feedback divider precision num!");
+		return false;
+	}
+
+	calc_pll_cs->fract_fb_divider_decimal_points_num =
+				init_data->num_fract_fb_divider_decimal_point;
+	calc_pll_cs->fract_fb_divider_precision =
+			init_data->num_fract_fb_divider_decimal_point_precision;
+	calc_pll_cs->fract_fb_divider_factor = 1;
+	for (i = 0; i < calc_pll_cs->fract_fb_divider_decimal_points_num; ++i)
+		calc_pll_cs->fract_fb_divider_factor *= 10;
+
+	calc_pll_cs->fract_fb_divider_precision_factor = 1;
+	for (
+		i = 0;
+		i < (calc_pll_cs->fract_fb_divider_decimal_points_num -
+				calc_pll_cs->fract_fb_divider_precision);
+		++i)
+		calc_pll_cs->fract_fb_divider_precision_factor *= 10;
+
+	return true;
+}
+
+bool dce110_clk_src_construct(
+	struct dce110_clk_src *clk_src,
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_reg_offsets *reg_offsets)
+{
+	struct firmware_info fw_info = { { 0 } };
+/* structure normally used with PLL ranges from ATOMBIOS; DS on by default */
+	struct calc_pll_clock_source_init_data calc_pll_cs_init_data = {
+		bios,
+		1, /* minPixelClockPLLPostDivider */
+		PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK,
+		/* maxPixelClockPLLPostDivider*/
+		1,/* minPLLRefDivider*/
+		PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/
+		0,
+/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+		0,
+/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+		FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM,
+/*numberOfFractFBDividerDecimalPoints*/
+		FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM,
+/*number of decimal point to round off for fractional feedback divider value*/
+		ctx
+	};
+/*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */
+	struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi = {
+		bios,
+		1, /* minPixelClockPLLPostDivider */
+		PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK,
+		/* maxPixelClockPLLPostDivider*/
+		1,/* minPLLRefDivider*/
+		PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/
+		13500,
+	/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+		27000,
+	/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+		FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM,
+		/*numberOfFractFBDividerDecimalPoints*/
+		FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM,
+/*number of decimal point to round off for fractional feedback divider value*/
+		ctx
+	};
+
+	clk_src->base.ctx = ctx;
+	clk_src->bios = bios;
+	clk_src->base.id = id;
+	clk_src->base.funcs = &dce110_clk_src_funcs;
+	clk_src->offsets = *reg_offsets;
+
+	if (clk_src->bios->funcs->get_firmware_info(
+			clk_src->bios, &fw_info) != BP_RESULT_OK) {
+		ASSERT_CRITICAL(false);
+		goto unexpected_failure;
+	}
+
+	clk_src->ext_clk_khz =
+			fw_info.external_clock_source_frequency_for_dp;
+	clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency;
+
+	if (clk_src->base.id == CLOCK_SOURCE_ID_EXTERNAL)
+		return true;
+
+	/* PLL only from here on */
+	ss_info_from_atombios_create(clk_src);
+
+	if (!calc_pll_max_vco_construct(
+			&clk_src->calc_pll,
+			&calc_pll_cs_init_data)) {
+		ASSERT_CRITICAL(false);
+		goto unexpected_failure;
+	}
+
+	if (clk_src->ref_freq_khz == 48000) {
+		calc_pll_cs_init_data_hdmi.
+			min_override_input_pxl_clk_pll_freq_khz = 24000;
+		calc_pll_cs_init_data_hdmi.
+			max_override_input_pxl_clk_pll_freq_khz = 48000;
+	} else if (clk_src->ref_freq_khz == 100000) {
+		calc_pll_cs_init_data_hdmi.
+			min_override_input_pxl_clk_pll_freq_khz = 25000;
+		calc_pll_cs_init_data_hdmi.
+			max_override_input_pxl_clk_pll_freq_khz = 50000;
+	}
+
+	if (!calc_pll_max_vco_construct(
+			&clk_src->calc_pll_hdmi, &calc_pll_cs_init_data_hdmi)) {
+		ASSERT_CRITICAL(false);
+		goto unexpected_failure;
+	}
+
+	return true;
+
+unexpected_failure:
+	return false;
+}
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h
new file mode 100644
index 000000000000..4fa82dad271f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h
@@ -0,0 +1,64 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_CLOCK_SOURCE_DCE110_H__
+#define __DC_CLOCK_SOURCE_DCE110_H__
+
+#include "../inc/clock_source.h"
+
+#define TO_DCE110_CLK_SRC(clk_src)\
+	container_of(clk_src, struct dce110_clk_src, base)
+
+struct dce110_clk_src_reg_offsets {
+	uint32_t pll_cntl;
+	uint32_t pixclk_resync_cntl;
+};
+
+struct dce110_clk_src {
+	struct clock_source base;
+	struct dce110_clk_src_reg_offsets offsets;
+	struct dc_bios *bios;
+
+	struct spread_spectrum_data *dp_ss_params;
+	uint32_t dp_ss_params_cnt;
+	struct spread_spectrum_data *hdmi_ss_params;
+	uint32_t hdmi_ss_params_cnt;
+	struct spread_spectrum_data *dvi_ss_params;
+	uint32_t dvi_ss_params_cnt;
+
+	uint32_t ext_clk_khz;
+	uint32_t ref_freq_khz;
+
+	struct calc_pll_clock_source calc_pll;
+	struct calc_pll_clock_source calc_pll_hdmi;
+};
+
+bool dce110_clk_src_construct(
+	struct dce110_clk_src *clk_src,
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id,
+	const struct dce110_clk_src_reg_offsets *reg_offsets);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 15/29] drm/amd/dal: Add timing generator HW programming
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (13 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 14/29] drm/amd/dal: Add clock source " Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 16/29] drm/amd/dal: Add surface " Harry Wentland
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Adds ability to validate and program timings, enable, disable, and blank
CRTCs, and get CRTC status information.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../amd/dal/dc/dce110/dce110_timing_generator.c    | 1864 ++++++++++++++++++++
 .../amd/dal/dc/dce110/dce110_timing_generator.h    |  234 +++
 2 files changed, 2098 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
new file mode 100644
index 000000000000..6e6a7a5cac6a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
@@ -0,0 +1,1864 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dc_types.h"
+#include "dc_bios_types.h"
+
+#include "include/grph_object_id.h"
+#include "include/adapter_service_interface.h"
+#include "include/logger_interface.h"
+#include "dce110_timing_generator.h"
+
+#include "../inc/timing_generator.h"
+
+enum black_color_format {
+	BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0,	/* used as index in array */
+	BLACK_COLOR_FORMAT_RGB_LIMITED,
+	BLACK_COLOR_FORMAT_YUV_TV,
+	BLACK_COLOR_FORMAT_YUV_CV,
+	BLACK_COLOR_FORMAT_YUV_SUPER_AA,
+
+	BLACK_COLOR_FORMAT_COUNT
+};
+
+#define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10
+
+#define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1)
+#define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1)
+
+#define CRTC_REG(reg) (reg + tg110->offsets.crtc)
+#define DCP_REG(reg) (reg + tg110->offsets.dcp)
+
+
+/*******************************************************************************
+ * GSL Sync related values */
+
+/* In VSync mode, after 4 units of time, master pipe will generate
+ * flip_ready signal */
+#define VFLIP_READY_DELAY 4
+/* In HSync mode, after 2 units of time, master pipe will generate
+ * flip_ready signal */
+#define HFLIP_READY_DELAY 2
+/* 6 lines delay between forcing flip and checking all pipes ready */
+#define HFLIP_CHECK_DELAY 6
+/* 3 lines before end of frame */
+#define FLIP_READY_BACK_LOOKUP 3
+
+/* Trigger Source Select - ASIC-dependant, actual values for the
+ * register programming */
+enum trigger_source_select {
+	TRIGGER_SOURCE_SELECT_LOGIC_ZERO = 0,
+	TRIGGER_SOURCE_SELECT_CRTC_VSYNCA = 1,
+	TRIGGER_SOURCE_SELECT_CRTC_HSYNCA = 2,
+	TRIGGER_SOURCE_SELECT_CRTC_VSYNCB = 3,
+	TRIGGER_SOURCE_SELECT_CRTC_HSYNCB = 4,
+	TRIGGER_SOURCE_SELECT_GENERICF = 5,
+	TRIGGER_SOURCE_SELECT_GENERICE = 6,
+	TRIGGER_SOURCE_SELECT_VSYNCA = 7,
+	TRIGGER_SOURCE_SELECT_HSYNCA = 8,
+	TRIGGER_SOURCE_SELECT_VSYNCB = 9,
+	TRIGGER_SOURCE_SELECT_HSYNCB = 10,
+	TRIGGER_SOURCE_SELECT_HPD1 = 11,
+	TRIGGER_SOURCE_SELECT_HPD2 = 12,
+	TRIGGER_SOURCE_SELECT_GENERICD = 13,
+	TRIGGER_SOURCE_SELECT_GENERICC = 14,
+	TRIGGER_SOURCE_SELECT_VIDEO_CAPTURE = 15,
+	TRIGGER_SOURCE_SELECT_GSL_GROUP0 = 16,
+	TRIGGER_SOURCE_SELECT_GSL_GROUP1 = 17,
+	TRIGGER_SOURCE_SELECT_GSL_GROUP2 = 18,
+	TRIGGER_SOURCE_SELECT_BLONY = 19,
+	TRIGGER_SOURCE_SELECT_GENERICA = 20,
+	TRIGGER_SOURCE_SELECT_GENERICB = 21,
+	TRIGGER_SOURCE_SELECT_GSL_ALLOW_FLIP = 22,
+	TRIGGER_SOURCE_SELECT_MANUAL_TRIGGER = 23
+};
+
+/* Trigger Source Select - ASIC-dependant, actual values for the
+ * register programming */
+enum trigger_polarity_select {
+	TRIGGER_POLARITY_SELECT_LOGIC_ZERO = 0,
+	TRIGGER_POLARITY_SELECT_CRTC = 1,
+	TRIGGER_POLARITY_SELECT_GENERICA = 2,
+	TRIGGER_POLARITY_SELECT_GENERICB = 3,
+	TRIGGER_POLARITY_SELECT_HSYNCA = 4,
+	TRIGGER_POLARITY_SELECT_HSYNCB = 5,
+	TRIGGER_POLARITY_SELECT_VIDEO_CAPTURE = 6,
+	TRIGGER_POLARITY_SELECT_GENERICC = 7
+};
+
+/******************************************************************************/
+
+static struct timing_generator_funcs dce110_tg_funcs = {
+		.validate_timing = dce110_tg_validate_timing,
+		.program_timing = dce110_tg_program_timing,
+		.enable_crtc = dce110_timing_generator_enable_crtc,
+		.disable_crtc = dce110_timing_generator_disable_crtc,
+		.is_counter_moving = dce110_timing_generator_is_counter_moving,
+		.get_position = dce110_timing_generator_get_crtc_positions,
+		.get_frame_count = dce110_timing_generator_get_vblank_counter,
+		.set_early_control = dce110_timing_generator_set_early_control,
+		.wait_for_state = dce110_tg_wait_for_state,
+		.set_blank = dce110_tg_set_blank,
+		.set_colors = dce110_tg_set_colors,
+		.set_overscan_blank_color =
+				dce110_timing_generator_set_overscan_color_black,
+		.set_blank_color = dce110_timing_generator_program_blank_color,
+		.disable_vga = dce110_timing_generator_disable_vga,
+		.did_triggered_reset_occur =
+				dce110_timing_generator_did_triggered_reset_occur,
+		.setup_global_swap_lock =
+				dce110_timing_generator_setup_global_swap_lock,
+		.enable_reset_trigger = dce110_timing_generator_enable_reset_trigger,
+		.disable_reset_trigger = dce110_timing_generator_disable_reset_trigger,
+		.tear_down_global_swap_lock =
+				dce110_timing_generator_tear_down_global_swap_lock,
+		.enable_advanced_request =
+				dce110_timing_generator_enable_advanced_request
+};
+
+static const struct crtc_black_color black_color_format[] = {
+	/* BlackColorFormat_RGB_FullRange */
+	{0, 0, 0},
+	/* BlackColorFormat_RGB_Limited */
+	{CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE},
+	/* BlackColorFormat_YUV_TV */
+	{CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV},
+	/* BlackColorFormat_YUV_CV */
+	{CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4CV,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV},
+	/* BlackColorFormat_YUV_SuperAA */
+	{CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA}
+};
+
+/**
+* apply_front_porch_workaround
+*
+* This is a workaround for a bug that has existed since R5xx and has not been
+* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
+*/
+static void dce110_timing_generator_apply_front_porch_workaround(
+	struct timing_generator *tg,
+	struct dc_crtc_timing *timing)
+{
+	if (timing->flags.INTERLACE == 1) {
+		if (timing->v_front_porch < 2)
+			timing->v_front_porch = 2;
+	} else {
+		if (timing->v_front_porch < 1)
+			timing->v_front_porch = 1;
+	}
+}
+
+static void dce110_timing_generator_color_space_to_black_color(
+		enum color_space colorspace,
+	struct crtc_black_color *black_color)
+{
+	switch (colorspace) {
+	case COLOR_SPACE_YPBPR601:
+		*black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_TV];
+		break;
+
+	case COLOR_SPACE_YPBPR709:
+	case COLOR_SPACE_YCBCR601:
+	case COLOR_SPACE_YCBCR709:
+		*black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV];
+		break;
+
+	case COLOR_SPACE_N_MVPU_SUPER_AA:
+		/* In crossfire SuperAA mode, the slave overscan data is forced
+		 * to 0 in the pixel mixer on the master.  As a result, we need
+		 * to adjust the blank color so that after blending the
+		 * master+slave, it will appear black
+		 */
+		*black_color =
+			black_color_format[BLACK_COLOR_FORMAT_YUV_SUPER_AA];
+		break;
+
+	case COLOR_SPACE_SRGB_LIMITED_RANGE:
+		*black_color =
+			black_color_format[BLACK_COLOR_FORMAT_RGB_LIMITED];
+		break;
+
+	default:
+		/* fefault is sRGB black (full range). */
+		*black_color =
+			black_color_format[BLACK_COLOR_FORMAT_RGB_FULLRANGE];
+		/* default is sRGB black 0. */
+		break;
+	}
+}
+
+/**
+ *****************************************************************************
+ *  Function: is_in_vertical_blank
+ *
+ *  @brief
+ *     check the current status of CRTC to check if we are in Vertical Blank
+ *     regioneased" state
+ *
+ *  @return
+ *     true if currently in blank region, false otherwise
+ *
+ *****************************************************************************
+ */
+static bool dce110_timing_generator_is_in_vertical_blank(
+		struct timing_generator *tg)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	uint32_t field = 0;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	addr = CRTC_REG(mmCRTC_STATUS);
+	value = dm_read_reg(tg->ctx, addr);
+	field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK);
+	return field == 1;
+}
+
+void dce110_timing_generator_set_early_control(
+		struct timing_generator *tg,
+		uint32_t early_cntl)
+{
+	uint32_t regval;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t address = CRTC_REG(mmCRTC_CONTROL);
+
+	regval = dm_read_reg(tg->ctx, address);
+	set_reg_field_value(regval, early_cntl,
+			CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
+	dm_write_reg(tg->ctx, address, regval);
+}
+
+/**
+ * Enable CRTC
+ * Enable CRTC - call ASIC Control Object to enable Timing generator.
+ */
+bool dce110_timing_generator_enable_crtc(struct timing_generator *tg)
+{
+	enum bp_result result;
+
+	/* 0 value is needed by DRR and is also suggested default value for CZ
+	 */
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	value = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_MASTER_UPDATE_MODE));
+	set_reg_field_value(value, 3,
+			CRTC_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE);
+	dm_write_reg(tg->ctx,
+			CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
+
+	result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
+
+	return result == BP_RESULT_OK;
+}
+
+void dce110_timing_generator_program_blank_color(
+		struct timing_generator *tg,
+		enum color_space color_space)
+{
+	struct crtc_black_color black_color;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+
+	dce110_timing_generator_color_space_to_black_color(
+		color_space,
+		&black_color);
+
+	set_reg_field_value(
+		value,
+		black_color.black_color_b_cb,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_B_CB);
+	set_reg_field_value(
+		value,
+		black_color.black_color_g_y,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_G_Y);
+	set_reg_field_value(
+		value,
+		black_color.black_color_r_cr,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_R_CR);
+
+	dm_write_reg(tg->ctx, addr, value);
+}
+
+/**
+ * blank_crtc
+ * Call ASIC Control Object to Blank CRTC.
+ */
+
+bool dce110_timing_generator_blank_crtc(struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_BLANK_CONTROL);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+	uint8_t counter = 100;
+
+	set_reg_field_value(
+		value,
+		1,
+		CRTC_BLANK_CONTROL,
+		CRTC_BLANK_DATA_EN);
+
+	set_reg_field_value(
+		value,
+		1,
+		CRTC_BLANK_CONTROL,
+		CRTC_BLANK_DE_MODE);
+
+	dm_write_reg(tg->ctx, addr, value);
+
+	while (counter > 0) {
+		value = dm_read_reg(tg->ctx, addr);
+
+		if (get_reg_field_value(
+			value,
+			CRTC_BLANK_CONTROL,
+			CRTC_BLANK_DATA_EN) == 1 &&
+			get_reg_field_value(
+			value,
+			CRTC_BLANK_CONTROL,
+			CRTC_CURRENT_BLANK_STATE) == 1)
+			break;
+
+		dm_sleep_in_milliseconds(tg->ctx, 1);
+		counter--;
+	}
+
+	if (!counter) {
+		dal_logger_write(tg->ctx->logger, LOG_MAJOR_ERROR,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"timing generator %d blank timing out.\n",
+				tg110->controller_id);
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * unblank_crtc
+ * Call ASIC Control Object to UnBlank CRTC.
+ */
+bool dce110_timing_generator_unblank_crtc(struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_BLANK_CONTROL);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		CRTC_BLANK_CONTROL,
+		CRTC_BLANK_DATA_EN);
+
+	set_reg_field_value(
+		value,
+		0,
+		CRTC_BLANK_CONTROL,
+		CRTC_BLANK_DE_MODE);
+
+	dm_write_reg(tg->ctx, addr, value);
+
+	return true;
+}
+
+/**
+ *****************************************************************************
+ *  Function: disable_stereo
+ *
+ *  @brief
+ *     Disables active stereo on controller
+ *     Frame Packing need to be disabled in vBlank or when CRTC not running
+ *****************************************************************************
+ */
+#if 0
+@TODOSTEREO
+static void disable_stereo(struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL);
+	uint32_t value = 0;
+	uint32_t test = 0;
+	uint32_t field = 0;
+	uint32_t struc_en = 0;
+	uint32_t struc_stereo_sel_ovr = 0;
+
+	value = dm_read_reg(tg->ctx, addr);
+	struc_en = get_reg_field_value(
+			value,
+			CRTC_3D_STRUCTURE_CONTROL,
+			CRTC_3D_STRUCTURE_EN);
+
+	struc_stereo_sel_ovr = get_reg_field_value(
+			value,
+			CRTC_3D_STRUCTURE_CONTROL,
+			CRTC_3D_STRUCTURE_STEREO_SEL_OVR);
+
+	/*
+	 * When disabling Frame Packing in 2 step mode, we need to program both
+	 * registers at the same frame
+	 * Programming it in the beginning of VActive makes sure we are ok
+	 */
+
+	if (struc_en != 0 && struc_stereo_sel_ovr == 0) {
+		tg->funcs->wait_for_vblank(tg);
+		tg->funcs->wait_for_vactive(tg);
+	}
+
+	value = 0;
+	dm_write_reg(tg->ctx, addr, value);
+
+
+	addr = tg->regs[IDX_CRTC_STEREO_CONTROL];
+	dm_write_reg(tg->ctx, addr, value);
+}
+#endif
+
+/**
+ * disable_crtc - call ASIC Control Object to disable Timing generator.
+ */
+bool dce110_timing_generator_disable_crtc(struct timing_generator *tg)
+{
+	enum bp_result result;
+
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, false);
+
+	/* Need to make sure stereo is disabled according to the DCE5.0 spec */
+
+	/*
+	 * @TODOSTEREO call this when adding stereo support
+	 * tg->funcs->disable_stereo(tg);
+	 */
+
+	return result == BP_RESULT_OK;
+}
+
+/**
+* program_horz_count_by_2
+* Programs DxCRTC_HORZ_COUNT_BY2_EN - 1 for DVI 30bpp mode, 0 otherwise
+*
+*/
+static void program_horz_count_by_2(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t regval;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	regval = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_COUNT_CONTROL));
+
+	set_reg_field_value(regval, 0, CRTC_COUNT_CONTROL,
+			CRTC_HORZ_COUNT_BY2_EN);
+
+	if (timing->flags.HORZ_COUNT_BY_TWO)
+		set_reg_field_value(regval, 1, CRTC_COUNT_CONTROL,
+					CRTC_HORZ_COUNT_BY2_EN);
+
+	dm_write_reg(tg->ctx,
+			CRTC_REG(mmCRTC_COUNT_CONTROL), regval);
+}
+
+/**
+ * program_timing_generator
+ * Program CRTC Timing Registers - DxCRTC_H_*, DxCRTC_V_*, Pixel repetition.
+ * Call ASIC Control Object to program Timings.
+ */
+bool dce110_timing_generator_program_timing_generator(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *dc_crtc_timing)
+{
+	enum bp_result result;
+	struct bp_hw_crtc_timing_parameters bp_params;
+	struct dc_crtc_timing patched_crtc_timing;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	uint32_t vsync_offset = dc_crtc_timing->v_border_bottom +
+			dc_crtc_timing->v_front_porch;
+	uint32_t v_sync_start =dc_crtc_timing->v_addressable + vsync_offset;
+
+	uint32_t hsync_offset = dc_crtc_timing->h_border_right +
+			dc_crtc_timing->h_front_porch;
+	uint32_t h_sync_start = dc_crtc_timing->h_addressable + hsync_offset;
+
+	dm_memset(&bp_params, 0, sizeof(struct bp_hw_crtc_timing_parameters));
+
+	/* Due to an asic bug we need to apply the Front Porch workaround prior
+	 * to programming the timing.
+	 */
+
+	patched_crtc_timing = *dc_crtc_timing;
+
+	dce110_timing_generator_apply_front_porch_workaround(tg, &patched_crtc_timing);
+
+	bp_params.controller_id = tg110->controller_id;
+
+	bp_params.h_total = patched_crtc_timing.h_total;
+	bp_params.h_addressable =
+		patched_crtc_timing.h_addressable;
+	bp_params.v_total = patched_crtc_timing.v_total;
+	bp_params.v_addressable = patched_crtc_timing.v_addressable;
+
+	bp_params.h_sync_start = h_sync_start;
+	bp_params.h_sync_width = patched_crtc_timing.h_sync_width;
+	bp_params.v_sync_start = v_sync_start;
+	bp_params.v_sync_width = patched_crtc_timing.v_sync_width;
+
+	/* Set overscan */
+	bp_params.h_overscan_left =
+		patched_crtc_timing.h_border_left;
+	bp_params.h_overscan_right =
+		patched_crtc_timing.h_border_right;
+	bp_params.v_overscan_top = patched_crtc_timing.v_border_top;
+	bp_params.v_overscan_bottom =
+		patched_crtc_timing.v_border_bottom;
+
+	/* Set flags */
+	if (patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY == 1)
+		bp_params.flags.HSYNC_POSITIVE_POLARITY = 1;
+
+	if (patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY == 1)
+		bp_params.flags.VSYNC_POSITIVE_POLARITY = 1;
+
+	if (patched_crtc_timing.flags.INTERLACE == 1)
+		bp_params.flags.INTERLACE = 1;
+
+	if (patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1)
+		bp_params.flags.HORZ_COUNT_BY_TWO = 1;
+
+	result = tg->bp->funcs->program_crtc_timing(tg->bp, &bp_params);
+
+	program_horz_count_by_2(tg, &patched_crtc_timing);
+
+	tg110->base.funcs->enable_advanced_request(tg, true, &patched_crtc_timing);
+
+	/* Enable stereo - only when we need to pack 3D frame. Other types
+	 * of stereo handled in explicit call */
+
+	return result == BP_RESULT_OK;
+}
+
+/**
+ *****************************************************************************
+ *  Function: program_drr
+ *
+ *  @brief
+ *     Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*.
+ *
+ *  @param [in] pHwCrtcTiming: point to H
+ *  wCrtcTiming struct
+ *****************************************************************************
+ */
+void dce110_timing_generator_program_drr(
+	struct timing_generator *tg,
+	const struct hw_ranged_timing *timing)
+{
+	/* register values */
+	uint32_t v_total_min = 0;
+	uint32_t v_total_max = 0;
+	uint32_t v_total_cntl = 0;
+	uint32_t static_screen_cntl = 0;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	uint32_t addr = 0;
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
+	v_total_min = dm_read_reg(tg->ctx, addr);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
+	v_total_max = dm_read_reg(tg->ctx, addr);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
+	v_total_cntl = dm_read_reg(tg->ctx, addr);
+
+	addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
+	static_screen_cntl = dm_read_reg(tg->ctx, addr);
+
+	if (timing != NULL) {
+		/* Set Static Screen trigger events
+		 * If CRTC_SET_V_TOTAL_MIN_MASK_EN is set, use legacy event mask
+		 * register
+		 */
+		if (get_reg_field_value(
+			v_total_cntl,
+			CRTC_V_TOTAL_CONTROL,
+			CRTC_SET_V_TOTAL_MIN_MASK_EN)) {
+			set_reg_field_value(v_total_cntl,
+				/* TODO: add implementation
+				translate_to_dce_static_screen_events(
+					timing->control.event_mask.u_all),
+					*/ 0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_SET_V_TOTAL_MIN_MASK);
+		} else {
+			set_reg_field_value(static_screen_cntl,
+				/* TODO: add implementation
+				translate_to_dce_static_screen_events(
+					timing->control.event_mask.u_all),
+					*/ 0,
+				CRTC_STATIC_SCREEN_CONTROL,
+				CRTC_STATIC_SCREEN_EVENT_MASK);
+		}
+
+		/* Number of consecutive static screen frames before interrupt
+		 * is triggered. 0 is an invalid setting, which means we should
+		 * leaving HW setting unchanged. */
+		if (timing->control.static_frame_count != 0) {
+			set_reg_field_value(
+				static_screen_cntl,
+				timing->control.static_frame_count,
+				CRTC_STATIC_SCREEN_CONTROL,
+				CRTC_STATIC_SCREEN_FRAME_COUNT);
+		}
+
+		/* This value is reduced by 1 based on the register definition
+		 * of the VTOTAL value:
+		 * CRTC_V_TOTAL should be set to Vertical total minus one. (E.g.
+		 * for 525 lines, set to 524 = 0x20C)
+		 */
+		set_reg_field_value(v_total_min,
+				timing->vertical_total_min,
+				CRTC_V_TOTAL_MIN,
+				CRTC_V_TOTAL_MIN);
+		set_reg_field_value(v_total_max,
+				timing->vertical_total_max,
+				CRTC_V_TOTAL_MAX,
+				CRTC_V_TOTAL_MAX);
+
+		/* set VTotalControl value according to ranged timing control.
+		 */
+
+		if (timing->vertical_total_min != 0) {
+			set_reg_field_value(v_total_cntl,
+					1,
+					CRTC_V_TOTAL_CONTROL,
+					CRTC_V_TOTAL_MIN_SEL);
+		} else {
+			set_reg_field_value(v_total_cntl,
+					0,
+					CRTC_V_TOTAL_CONTROL,
+					CRTC_V_TOTAL_MIN_SEL);
+		}
+		if (timing->vertical_total_max != 0) {
+			set_reg_field_value(v_total_cntl,
+					1,
+					CRTC_V_TOTAL_CONTROL,
+					CRTC_V_TOTAL_MAX_SEL);
+		} else {
+			set_reg_field_value(v_total_cntl,
+					0,
+					CRTC_V_TOTAL_CONTROL,
+					CRTC_V_TOTAL_MAX_SEL);
+		}
+		set_reg_field_value(v_total_cntl,
+				timing->control.force_lock_on_event,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_FORCE_LOCK_ON_EVENT);
+		set_reg_field_value(v_total_cntl,
+				timing->control.lock_to_master_vsync,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
+	} else {
+		set_reg_field_value(v_total_cntl,
+			0,
+			CRTC_V_TOTAL_CONTROL,
+			CRTC_SET_V_TOTAL_MIN_MASK);
+		set_reg_field_value(static_screen_cntl,
+			0,
+			CRTC_STATIC_SCREEN_CONTROL,
+			CRTC_STATIC_SCREEN_EVENT_MASK);
+		set_reg_field_value(v_total_min,
+				0,
+				CRTC_V_TOTAL_MIN,
+				CRTC_V_TOTAL_MIN);
+		set_reg_field_value(v_total_max,
+				0,
+				CRTC_V_TOTAL_MAX,
+				CRTC_V_TOTAL_MAX);
+		set_reg_field_value(v_total_cntl,
+				0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_V_TOTAL_MIN_SEL);
+		set_reg_field_value(v_total_cntl,
+				0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_V_TOTAL_MAX_SEL);
+		set_reg_field_value(v_total_cntl,
+				0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_FORCE_LOCK_ON_EVENT);
+		set_reg_field_value(v_total_cntl,
+				0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
+	}
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
+	dm_write_reg(tg->ctx, addr, v_total_min);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
+	dm_write_reg(tg->ctx, addr, v_total_max);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
+	dm_write_reg(tg->ctx, addr, v_total_cntl);
+
+	addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
+	dm_write_reg(tg->ctx, addr, static_screen_cntl);
+}
+
+/*
+ * get_vblank_counter
+ *
+ * @brief
+ * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
+ * holds the counter of frames.
+ *
+ * @param
+ * struct timing_generator *tg - [in] timing generator which controls the
+ * desired CRTC
+ *
+ * @return
+ * Counter of frames, which should equal to number of vblanks.
+ */
+uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_STATUS_FRAME_COUNT);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+	uint32_t field = get_reg_field_value(
+			value, CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
+
+	return field;
+}
+
+/**
+ *****************************************************************************
+ *  Function: dce110_get_crtc_positions
+ *
+ *  @brief
+ *     Returns CRTC vertical/horizontal counters
+ *
+ *  @param [out] v_position, h_position
+ *****************************************************************************
+ */
+
+void dce110_timing_generator_get_crtc_positions(
+	struct timing_generator *tg,
+	int32_t *h_position,
+	int32_t *v_position)
+{
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION));
+
+	*h_position = get_reg_field_value(
+			value,
+			CRTC_STATUS_POSITION,
+			CRTC_HORZ_COUNT);
+
+	*v_position = get_reg_field_value(
+			value,
+			CRTC_STATUS_POSITION,
+			CRTC_VERT_COUNT);
+}
+
+/**
+ *****************************************************************************
+ *  Function: get_crtc_scanoutpos
+ *
+ *  @brief
+ *     Returns CRTC vertical/horizontal counters
+ *
+ *  @param [out] vpos, hpos
+ *****************************************************************************
+ */
+uint32_t dce110_timing_generator_get_crtc_scanoutpos(
+	struct timing_generator *tg,
+	int32_t *vbl,
+	int32_t *position)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	/* TODO 1: Update the implementation once caller is updated
+	 * WARNING!! This function is returning the whole register value
+	 * because the caller is expecting it instead of proper vertical and
+	 * horizontal position. This should be a temporary implementation
+	 * until the caller is updated. */
+
+	/* TODO 2: re-use dce110_timing_generator_get_crtc_positions() */
+
+	*vbl = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_V_BLANK_START_END));
+
+	*position = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_STATUS_POSITION));
+
+	/* @TODO: return value should indicate if current
+	 * crtc is inside vblank*/
+	return 0;
+}
+
+/* TODO: is it safe to assume that mask/shift of Primary and Underlay
+ * are the same?
+ * For example: today CRTC_H_TOTAL == CRTCV_H_TOTAL but is it always
+ * guaranteed? */
+void dce110_timing_generator_program_blanking(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t vsync_offset = timing->v_border_bottom +
+			timing->v_front_porch;
+	uint32_t v_sync_start =timing->v_addressable + vsync_offset;
+
+	uint32_t hsync_offset = timing->h_border_right +
+			timing->h_front_porch;
+	uint32_t h_sync_start = timing->h_addressable + hsync_offset;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	struct dc_context *ctx = tg->ctx;
+	uint32_t value = 0;
+	uint32_t addr = 0;
+	uint32_t tmp = 0;
+
+	addr = CRTC_REG(mmCRTC_H_TOTAL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		timing->h_total - 1,
+		CRTC_H_TOTAL,
+		CRTC_H_TOTAL);
+	dm_write_reg(ctx, addr, value);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		timing->v_total - 1,
+		CRTC_V_TOTAL,
+		CRTC_V_TOTAL);
+	dm_write_reg(ctx, addr, value);
+
+	addr = CRTC_REG(mmCRTC_H_BLANK_START_END);
+	value = dm_read_reg(ctx, addr);
+
+	tmp = timing->h_total -
+		(h_sync_start + timing->h_border_left);
+
+	set_reg_field_value(
+		value,
+		tmp,
+		CRTC_H_BLANK_START_END,
+		CRTC_H_BLANK_END);
+
+	tmp = tmp + timing->h_addressable +
+		timing->h_border_left + timing->h_border_right;
+
+	set_reg_field_value(
+		value,
+		tmp,
+		CRTC_H_BLANK_START_END,
+		CRTC_H_BLANK_START);
+
+	dm_write_reg(ctx, addr, value);
+
+	addr = CRTC_REG(mmCRTC_V_BLANK_START_END);
+	value = dm_read_reg(ctx, addr);
+
+	tmp = timing->v_total - (v_sync_start + timing->v_border_top);
+
+	set_reg_field_value(
+		value,
+		tmp,
+		CRTC_V_BLANK_START_END,
+		CRTC_V_BLANK_END);
+
+	tmp = tmp + timing->v_addressable + timing->v_border_top +
+		timing->v_border_bottom;
+
+	set_reg_field_value(
+		value,
+		tmp,
+		CRTC_V_BLANK_START_END,
+		CRTC_V_BLANK_START);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_timing_generator_set_test_pattern(
+	struct timing_generator *tg,
+	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
+	 * because this is not DP-specific (which is probably somewhere in DP
+	 * encoder) */
+	enum controller_dp_test_pattern test_pattern,
+	enum dc_color_depth color_depth)
+{
+	struct dc_context *ctx = tg->ctx;
+	uint32_t value;
+	uint32_t addr;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	/* TODO: add support for other test patterns */
+	switch (test_pattern) {
+	default:
+		value = 0;
+		addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
+
+		set_reg_field_value(
+			value,
+			6,
+			CRTC_TEST_PATTERN_PARAMETERS,
+			CRTC_TEST_PATTERN_VRES);
+		set_reg_field_value(
+			value,
+			6,
+			CRTC_TEST_PATTERN_PARAMETERS,
+			CRTC_TEST_PATTERN_HRES);
+
+		dm_write_reg(ctx, addr, value);
+
+		addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
+		value = 0;
+
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_TEST_PATTERN_CONTROL,
+			CRTC_TEST_PATTERN_EN);
+
+		set_reg_field_value(
+			value,
+			0,
+			CRTC_TEST_PATTERN_CONTROL,
+			CRTC_TEST_PATTERN_MODE);
+
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_TEST_PATTERN_CONTROL,
+			CRTC_TEST_PATTERN_DYNAMIC_RANGE);
+		/* add color depth translation here */
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_TEST_PATTERN_CONTROL,
+			CRTC_TEST_PATTERN_COLOR_FORMAT);
+		dm_write_reg(ctx, addr, value);
+		break;
+	} /* switch() */
+}
+
+/**
+* dce110_timing_generator_validate_timing
+* The timing generators support a maximum display size of is 8192 x 8192 pixels,
+* including both active display and blanking periods. Check H Total and V Total.
+*/
+bool dce110_timing_generator_validate_timing(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing,
+	enum signal_type signal)
+{
+	uint32_t h_blank;
+	uint32_t h_back_porch;
+	uint32_t hsync_offset = timing->h_border_right +
+			timing->h_front_porch;
+	uint32_t h_sync_start = timing->h_addressable + hsync_offset;
+
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	ASSERT(timing != NULL);
+
+	if (!timing)
+		return false;
+
+	/* Check maximum number of pixels supported by Timing Generator
+	 * (Currently will never fail, in order to fail needs display which
+	 * needs more than 8192 horizontal and
+	 * more than 8192 vertical total pixels)
+	 */
+	if (timing->h_total > tg110->max_h_total ||
+		timing->v_total > tg110->max_v_total)
+		return false;
+
+	h_blank = (timing->h_total - timing->h_addressable -
+		timing->h_border_right -
+		timing->h_border_left);
+
+	if (h_blank < tg110->min_h_blank)
+		return false;
+
+	if (timing->h_front_porch < tg110->min_h_front_porch)
+		return false;
+
+	h_back_porch = h_blank - (h_sync_start -
+		timing->h_addressable -
+		timing->h_border_right -
+		timing->h_sync_width);
+
+	if (h_back_porch < tg110->min_h_back_porch)
+		return false;
+
+	return true;
+}
+
+/**
+* Wait till we are at the beginning of VBlank.
+*/
+void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg)
+{
+	/* We want to catch beginning of VBlank here, so if the first try are
+	 * in VBlank, we might be very close to Active, in this case wait for
+	 * another frame
+	 */
+	while (dce110_timing_generator_is_in_vertical_blank(tg)) {
+		if (!dce110_timing_generator_is_counter_moving(tg)) {
+			/* error - no point to wait if counter is not moving */
+			break;
+		}
+	}
+
+	while (!dce110_timing_generator_is_in_vertical_blank(tg)) {
+		if (!dce110_timing_generator_is_counter_moving(tg)) {
+			/* error - no point to wait if counter is not moving */
+			break;
+		}
+	}
+}
+
+/**
+* Wait till we are in VActive (anywhere in VActive)
+*/
+void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg)
+{
+	while (dce110_timing_generator_is_in_vertical_blank(tg)) {
+		if (!dce110_timing_generator_is_counter_moving(tg)) {
+			/* error - no point to wait if counter is not moving */
+			break;
+		}
+	}
+}
+
+bool dce110_timing_generator_construct(
+	struct dce110_timing_generator *tg110,
+	struct adapter_service *as,
+	struct dc_context *ctx,
+	uint32_t instance,
+	const struct dce110_timing_generator_offsets *offsets)
+{
+	if (!tg110)
+		return false;
+
+	if (!as)
+		return false;
+
+	tg110->controller_id = CONTROLLER_ID_D0 + instance;
+	tg110->offsets = *offsets;
+
+	tg110->base.funcs = &dce110_tg_funcs;
+
+	tg110->base.ctx = ctx;
+	tg110->base.bp = dal_adapter_service_get_bios_parser(as);
+
+	tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
+	tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
+
+	tg110->min_h_blank = 56;
+	tg110->min_h_front_porch = 4;
+	tg110->min_h_back_porch = 4;
+
+	return true;
+}
+
+/**
+ *****************************************************************************
+ *  Function: dce110_timing_generator_setup_global_swap_lock
+ *
+ *  @brief
+ *     Setups Global Swap Lock group for current pipe
+ *     Pipe can join or leave GSL group, become a TimingServer or TimingClient
+ *
+ *  @param [in] gsl_params: setup data
+ *****************************************************************************
+ */
+
+void dce110_timing_generator_setup_global_swap_lock(
+	struct timing_generator *tg,
+	const struct dcp_gsl_params *gsl_params)
+{
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
+	uint32_t check_point = FLIP_READY_BACK_LOOKUP;
+
+	value = dm_read_reg(tg->ctx, address);
+
+	/* This pipe will belong to GSL Group zero. */
+	set_reg_field_value(value,
+			1,
+			DCP_GSL_CONTROL,
+			DCP_GSL0_EN);
+
+	set_reg_field_value(value,
+			gsl_params->timing_server,
+			DCP_GSL_CONTROL,
+			DCP_GSL_MASTER_EN);
+
+	set_reg_field_value(value,
+			HFLIP_READY_DELAY,
+			DCP_GSL_CONTROL,
+			DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
+
+        /* Keep signal low (pending high) during 6 lines.
+         * Also defines minimum interval before re-checking signal. */
+	set_reg_field_value(value,
+			HFLIP_CHECK_DELAY,
+			DCP_GSL_CONTROL,
+			DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
+
+	/* DCP_GSL_PURPOSE_SURFACE_FLIP */
+	{
+		uint32_t value_crtc_vtotal;
+
+		value_crtc_vtotal = dm_read_reg(tg->ctx,
+				CRTC_REG(mmCRTC_V_TOTAL));
+
+		set_reg_field_value(value,
+				gsl_params->gsl_purpose,
+				DCP_GSL_CONTROL,
+				DCP_GSL_SYNC_SOURCE);
+
+		/* Checkpoint relative to end of frame */
+		check_point = get_reg_field_value(value_crtc_vtotal,
+				CRTC_V_TOTAL,
+				CRTC_V_TOTAL);
+
+		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0);
+	}
+
+	set_reg_field_value(value,
+			1,
+			DCP_GSL_CONTROL,
+			DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
+
+	dm_write_reg(tg->ctx, address, value);
+
+	/********************************************************************/
+	address = CRTC_REG(mmCRTC_GSL_CONTROL);
+
+	value = 0;
+	set_reg_field_value(value,
+			check_point - FLIP_READY_BACK_LOOKUP,
+			CRTC_GSL_CONTROL,
+			CRTC_GSL_CHECK_LINE_NUM);
+
+	set_reg_field_value(value,
+			VFLIP_READY_DELAY,
+			CRTC_GSL_CONTROL,
+			CRTC_GSL_FORCE_DELAY);
+
+	dm_write_reg(tg->ctx, address, value);
+}
+
+
+void dce110_timing_generator_tear_down_global_swap_lock(
+	struct timing_generator *tg)
+{
+	/* Clear all the register writes done by
+	 * dce110_timing_generator_setup_global_swap_lock
+	 */
+
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
+
+	value = 0;
+
+	/* This pipe will belong to GSL Group zero. */
+	/* Settig HW default values from reg specs */
+	set_reg_field_value(value,
+			0,
+			DCP_GSL_CONTROL,
+			DCP_GSL0_EN);
+
+	set_reg_field_value(value,
+			0,
+			DCP_GSL_CONTROL,
+			DCP_GSL_MASTER_EN);
+
+	set_reg_field_value(value,
+			0x2,
+			DCP_GSL_CONTROL,
+			DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
+
+
+	set_reg_field_value(value,
+			0x6,
+			DCP_GSL_CONTROL,
+			DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
+
+	/* Restore DCP_GSL_PURPOSE_SURFACE_FLIP */
+	{
+		uint32_t value_crtc_vtotal;
+
+		value_crtc_vtotal = dm_read_reg(tg->ctx,
+				CRTC_REG(mmCRTC_V_TOTAL));
+
+		set_reg_field_value(value,
+				0,
+				DCP_GSL_CONTROL,
+				DCP_GSL_SYNC_SOURCE);
+	}
+
+	set_reg_field_value(value,
+			0,
+			DCP_GSL_CONTROL,
+			DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
+
+	dm_write_reg(tg->ctx, address, value);
+
+	/********************************************************************/
+	address = CRTC_REG(mmCRTC_GSL_CONTROL);
+
+	value = 0;
+	set_reg_field_value(value,
+			0,
+			CRTC_GSL_CONTROL,
+			CRTC_GSL_CHECK_LINE_NUM);
+
+	set_reg_field_value(value,
+			0x2,
+			CRTC_GSL_CONTROL,
+			CRTC_GSL_FORCE_DELAY);
+
+	dm_write_reg(tg->ctx, address, value);
+}
+/**
+ *****************************************************************************
+ *  Function: is_counter_moving
+ *
+ *  @brief
+ *     check if the timing generator is currently going
+ *
+ *  @return
+ *     true if currently going, false if currently paused or stopped.
+ *
+ *****************************************************************************
+ */
+bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg)
+{
+	uint32_t h1 = 0;
+	uint32_t h2 = 0;
+	uint32_t v1 = 0;
+	uint32_t v2 = 0;
+
+	dce110_timing_generator_get_crtc_positions(tg, &h1, &v1);
+	dce110_timing_generator_get_crtc_positions(tg, &h2, &v2);
+
+	if (h1 == h2 && v1 == v2)
+		return false;
+	else
+		return true;
+}
+
+void dce110_timing_generator_enable_advanced_request(
+	struct timing_generator *tg,
+	bool enable,
+	const struct dc_crtc_timing *timing)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+
+	if (enable && !DCE110TG_FROM_TG(tg)->disable_advanced_request) {
+		set_reg_field_value(
+			value,
+			0,
+			CRTC_START_LINE_CONTROL,
+			CRTC_LEGACY_REQUESTOR_EN);
+	} else {
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_START_LINE_CONTROL,
+			CRTC_LEGACY_REQUESTOR_EN);
+	}
+
+	if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
+		set_reg_field_value(
+			value,
+			3,
+			CRTC_START_LINE_CONTROL,
+			CRTC_ADVANCED_START_LINE_POSITION);
+		set_reg_field_value(
+			value,
+			0,
+			CRTC_START_LINE_CONTROL,
+			CRTC_PREFETCH_EN);
+	} else {
+		set_reg_field_value(
+			value,
+			4,
+			CRTC_START_LINE_CONTROL,
+			CRTC_ADVANCED_START_LINE_POSITION);
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_START_LINE_CONTROL,
+			CRTC_PREFETCH_EN);
+	}
+
+	set_reg_field_value(
+		value,
+		1,
+		CRTC_START_LINE_CONTROL,
+		CRTC_PROGRESSIVE_START_LINE_EARLY);
+
+	set_reg_field_value(
+		value,
+		1,
+		CRTC_START_LINE_CONTROL,
+		CRTC_INTERLACE_START_LINE_EARLY);
+
+	dm_write_reg(tg->ctx, addr, value);
+}
+
+/*TODO: Figure out if we need this function. */
+void dce110_timing_generator_set_lock_master(struct timing_generator *tg,
+		bool lock)
+{
+	struct dc_context *ctx = tg->ctx;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		lock ? 1 : 0,
+		CRTC_MASTER_UPDATE_LOCK,
+		MASTER_UPDATE_LOCK);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_timing_generator_enable_reset_trigger(
+	struct timing_generator *tg,
+	const struct trigger_params *trigger_params)
+{
+	uint32_t value;
+	struct dc_context *dc_ctx = tg->ctx;
+	uint32_t rising_edge = 0;
+	uint32_t falling_edge = 0;
+	enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	/* Setup trigger edge */
+	switch (trigger_params->edge) {
+	/* Default = based on current timing polarity */
+	case TRIGGER_EDGE_DEFAULT:
+		{
+			uint32_t pol_value = dm_read_reg(tg->ctx,
+					CRTC_REG(mmCRTC_V_SYNC_A_CNTL));
+
+			/* Register spec has reversed definition:
+			 *	0 for positive, 1 for negative */
+			if (get_reg_field_value(pol_value,
+					CRTC_V_SYNC_A_CNTL,
+					CRTC_V_SYNC_A_POL) == 0) {
+				rising_edge = 1;
+			} else {
+				falling_edge = 1;
+			}
+		}
+		break;
+	case TRIGGER_EDGE_RISING:
+		rising_edge = 1;
+		break;
+	case TRIGGER_EDGE_FALLING:
+		falling_edge = 1;
+		break;
+	case TRIGGER_EDGE_BOTH:
+		rising_edge = 1;
+		falling_edge = 1;
+		break;
+	default:
+		DC_ERROR("Invalid Trigger Edge!\n");
+		return;
+	}
+
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
+
+	switch(trigger_params->source) {
+	/* Currently supporting only a single group, the group zero. */
+	case SYNC_SOURCE_GSL_GROUP0:
+		trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
+		break;
+	default:
+		DC_ERROR("Unsupported GSL Group!\n");
+		return;
+	}
+
+	set_reg_field_value(value,
+			trig_src_select,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_SOURCE_SELECT);
+
+	set_reg_field_value(value,
+			TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_POLARITY_SELECT);
+
+	set_reg_field_value(value,
+			rising_edge,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
+
+	set_reg_field_value(value,
+			falling_edge,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
+
+	set_reg_field_value(value,
+			0, /* send every signal */
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_FREQUENCY_SELECT);
+
+	set_reg_field_value(value,
+			0, /* no delay */
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_DELAY);
+
+	set_reg_field_value(value,
+			1, /* clear trigger status */
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_CLEAR);
+
+	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
+
+	/**************************************************************/
+
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
+
+	set_reg_field_value(value,
+			2, /* force H count to H_TOTAL and V count to V_TOTAL */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_MODE);
+
+	set_reg_field_value(value,
+			1, /* TriggerB - we never use TriggerA */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_TRIG_SEL);
+
+	set_reg_field_value(value,
+			1, /* clear trigger status */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_CLEAR);
+
+	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
+}
+
+void dce110_timing_generator_disable_reset_trigger(
+	struct timing_generator *tg)
+{
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
+
+	set_reg_field_value(value,
+			0, /* force counter now mode is disabled */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_MODE);
+
+	set_reg_field_value(value,
+			1, /* clear trigger status */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_CLEAR);
+
+	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
+
+	/********************************************************************/
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
+
+	set_reg_field_value(value,
+			TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_SOURCE_SELECT);
+
+	set_reg_field_value(value,
+			TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_POLARITY_SELECT);
+
+	set_reg_field_value(value,
+			1, /* clear trigger status */
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_CLEAR);
+
+	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
+}
+
+/**
+ *****************************************************************************
+ *  @brief
+ *     Checks whether CRTC triggered reset occurred
+ *
+ *  @return
+ *     true if triggered reset occurred, false otherwise
+ *****************************************************************************
+ */
+bool dce110_timing_generator_did_triggered_reset_occur(
+	struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t value = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
+
+	return get_reg_field_value(value,
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
+}
+
+/**
+ * dce110_timing_generator_disable_vga
+ * Turn OFF VGA Mode and Timing  - DxVGA_CONTROL
+ * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors;
+ */
+void dce110_timing_generator_disable_vga(
+	struct timing_generator *tg)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	switch (tg110->controller_id) {
+	case CONTROLLER_ID_D0:
+		addr = mmD1VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D1:
+		addr = mmD2VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D2:
+		addr = mmD3VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D3:
+		addr = mmD4VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D4:
+		addr = mmD5VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D5:
+		addr = mmD6VGA_CONTROL;
+		break;
+	default:
+		break;
+	}
+	value = dm_read_reg(tg->ctx, addr);
+
+	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
+	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
+	set_reg_field_value(
+			value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
+	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
+
+	dm_write_reg(tg->ctx, addr, value);
+}
+
+/**
+* set_overscan_color_black
+*
+* @param :black_color is one of the color space
+*    :this routine will set overscan black color according to the color space.
+* @return none
+*/
+
+void dce110_timing_generator_set_overscan_color_black(
+	struct timing_generator *tg,
+	enum color_space black_color)
+{
+	struct dc_context *ctx = tg->ctx;
+	uint32_t value = 0;
+	uint32_t addr;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	/* Overscan Color for YUV display modes:
+	 * to achieve a black color for both the explicit and implicit overscan,
+	 * the overscan color registers should be programmed to: */
+
+	switch (black_color) {
+	case COLOR_SPACE_YPBPR601:
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_BLUE);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_GREEN);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_RED);
+		break;
+
+	case COLOR_SPACE_YPBPR709:
+	case COLOR_SPACE_YCBCR601:
+	case COLOR_SPACE_YCBCR709:
+	case COLOR_SPACE_YCBCR601_YONLY:
+	case COLOR_SPACE_YCBCR709_YONLY:
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_BLUE);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_GREEN);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_RED);
+		break;
+
+	case COLOR_SPACE_N_MVPU_SUPER_AA:
+		/* In crossfire SuperAA mode, the slave overscan data is forced
+		 * to 0 in the pixel mixer on the master.  As a result, we need
+		 * to adjust the blank color so that after blending the
+		 * master+slave, it will appear black */
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_BLUE);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_GREEN);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_RED);
+		break;
+
+	case COLOR_SPACE_SRGB_LIMITED_RANGE:
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_BLUE);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_GREEN);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_RED);
+		break;
+
+	default:
+		/* default is sRGB black 0. */
+		break;
+	}
+	addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
+	dm_write_reg(ctx, addr, value);
+	addr = CRTC_REG(mmCRTC_BLACK_COLOR);
+	dm_write_reg(ctx, addr, value);
+	/* This is desirable to have a constant DAC output voltage during the
+	 * blank time that is higher than the 0 volt reference level that the
+	 * DAC outputs when the NBLANK signal
+	 * is asserted low, such as for output to an analog TV. */
+	addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
+	dm_write_reg(ctx, addr, value);
+
+	/* TO DO we have to program EXT registers and we need to know LB DATA
+	 * format because it is used when more 10 , i.e. 12 bits per color
+	 *
+	 * m_mmDxCRTC_OVERSCAN_COLOR_EXT
+	 * m_mmDxCRTC_BLACK_COLOR_EXT
+	 * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
+	 */
+
+}
+
+void dce110_tg_program_blank_color(struct timing_generator *tg,
+		const struct crtc_black_color *black_color)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+
+	set_reg_field_value(
+		value,
+		black_color->black_color_b_cb,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_B_CB);
+	set_reg_field_value(
+		value,
+		black_color->black_color_g_y,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_G_Y);
+	set_reg_field_value(
+		value,
+		black_color->black_color_r_cr,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_R_CR);
+
+	dm_write_reg(tg->ctx, addr, value);
+
+	addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
+	dm_write_reg(tg->ctx, addr, value);
+}
+
+void dce110_tg_set_overscan_color(struct timing_generator *tg,
+	const struct crtc_black_color *overscan_color)
+{
+	struct dc_context *ctx = tg->ctx;
+	uint32_t value = 0;
+	uint32_t addr;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	set_reg_field_value(
+		value,
+		overscan_color->black_color_b_cb,
+		CRTC_OVERSCAN_COLOR,
+		CRTC_OVERSCAN_COLOR_BLUE);
+
+	set_reg_field_value(
+		value,
+		overscan_color->black_color_g_y,
+		CRTC_OVERSCAN_COLOR,
+		CRTC_OVERSCAN_COLOR_GREEN);
+
+	set_reg_field_value(
+		value,
+		overscan_color->black_color_r_cr,
+		CRTC_OVERSCAN_COLOR,
+		CRTC_OVERSCAN_COLOR_RED);
+
+	addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_tg_get_position(struct timing_generator *tg,
+	struct crtc_position *position)
+{
+	int32_t h_position;
+	int32_t v_position;
+
+	dce110_timing_generator_get_crtc_positions(tg, &h_position, &v_position);
+
+	position->horizontal_count = (uint32_t)h_position;
+	position->vertical_count = (uint32_t)v_position;
+}
+
+void dce110_tg_program_timing(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing,
+	bool use_vbios)
+{
+	if (use_vbios)
+		dce110_timing_generator_program_timing_generator(tg, timing);
+	else
+		dce110_timing_generator_program_blanking(tg, timing);
+}
+
+bool dce110_tg_set_blank(struct timing_generator *tg,
+		bool enable_blanking)
+{
+	if (enable_blanking)
+		return dce110_timing_generator_blank_crtc(tg);
+	else
+		return dce110_timing_generator_unblank_crtc(tg);
+}
+
+bool dce110_tg_validate_timing(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing)
+{
+	return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
+}
+
+
+void dce110_tg_wait_for_state(struct timing_generator *tg,
+	enum crtc_state state)
+{
+	switch (state) {
+	case CRTC_STATE_VBLANK:
+		dce110_timing_generator_wait_for_vblank(tg);
+		break;
+
+	case CRTC_STATE_VACTIVE:
+		dce110_timing_generator_wait_for_vactive(tg);
+		break;
+
+	default:
+		break;
+	}
+}
+
+void dce110_tg_set_colors(struct timing_generator *tg,
+	const struct crtc_black_color *blank_color,
+	const struct crtc_black_color *overscan_color)
+{
+	if (blank_color != NULL)
+		dce110_tg_program_blank_color(tg, blank_color);
+	if (overscan_color != NULL)
+		dce110_tg_set_overscan_color(tg, overscan_color);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
new file mode 100644
index 000000000000..163fadd1feb9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_TIMING_GENERATOR_DCE110_H__
+#define __DC_TIMING_GENERATOR_DCE110_H__
+
+
+#include "../inc/timing_generator.h"
+#include "../include/grph_object_id.h"
+#include "../include/hw_sequencer_types.h"
+
+/* overscan in blank for YUV color space. For RGB, it is zero for black. */
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV 0x1f4
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4CV 0x40
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV 0x1f4
+
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV 0x200
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV 0x40
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV 0x200
+
+/* overscan in blank for YUV color space when in SuperAA crossfire mode */
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA 0x1a2
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA 0x20
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA 0x1a2
+
+/* OVERSCAN COLOR FOR RGB LIMITED RANGE
+ * (16~253) 16*4 (Multiple over 256 code leve) =64 (0x40) */
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE 0x40
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE 0x40
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE 0X40
+
+struct dce110_timing_generator_offsets {
+	int32_t crtc;
+	int32_t dcp;
+
+	/* DCE80 use only */
+	int32_t dmif;
+};
+
+struct dce110_timing_generator {
+	struct timing_generator base;
+	struct dce110_timing_generator_offsets offsets;
+	struct dce110_timing_generator_offsets derived_offsets;
+
+	enum controller_id controller_id;
+
+	uint32_t max_h_total;
+	uint32_t max_v_total;
+
+	uint32_t min_h_blank;
+	uint32_t min_h_front_porch;
+	uint32_t min_h_back_porch;
+
+	enum sync_source cached_gsl_group;
+	bool disable_advanced_request;
+};
+
+#define DCE110TG_FROM_TG(tg)\
+	container_of(tg, struct dce110_timing_generator, base)
+
+bool dce110_timing_generator_construct(
+	struct dce110_timing_generator *tg,
+	struct adapter_service *as,
+	struct dc_context *ctx,
+	uint32_t instance,
+	const struct dce110_timing_generator_offsets *offsets);
+
+/* determine if given timing can be supported by TG */
+bool dce110_timing_generator_validate_timing(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing,
+	enum signal_type signal);
+
+/******** HW programming ************/
+
+/* Program timing generator with given timing */
+bool dce110_timing_generator_program_timing_generator(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *dc_crtc_timing);
+
+/* Disable/Enable Timing Generator */
+bool dce110_timing_generator_enable_crtc(struct timing_generator *tg);
+bool dce110_timing_generator_disable_crtc(struct timing_generator *tg);
+
+void dce110_timing_generator_set_early_control(
+		struct timing_generator *tg,
+		uint32_t early_cntl);
+
+/**************** TG current status ******************/
+
+/* return the current frame counter. Used by Linux kernel DRM */
+uint32_t dce110_timing_generator_get_vblank_counter(
+		struct timing_generator *tg);
+
+/* Get current H and V position */
+void dce110_timing_generator_get_crtc_positions(
+	struct timing_generator *tg,
+	int32_t *h_position,
+	int32_t *v_position);
+
+/* return true if TG counter is moving. false if TG is stopped */
+bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg);
+
+/* wait until TG is in beginning of vertical blank region */
+void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg);
+
+/* wait until TG is in beginning of active region */
+void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg);
+
+
+/*********** Timing Generator Synchronization routines ****/
+
+/* Setups Global Swap Lock group, TimingServer or TimingClient*/
+void dce110_timing_generator_setup_global_swap_lock(
+	struct timing_generator *tg,
+	const struct dcp_gsl_params *gsl_params);
+
+/* Clear all the register writes done by setup_global_swap_lock */
+void dce110_timing_generator_tear_down_global_swap_lock(
+	struct timing_generator *tg);
+
+/* Reset slave controllers on master VSync */
+void dce110_timing_generator_enable_reset_trigger(
+	struct timing_generator *tg,
+	const struct trigger_params *trigger_params);
+
+/* disabling trigger-reset */
+void dce110_timing_generator_disable_reset_trigger(
+	struct timing_generator *tg);
+
+/* Checks whether CRTC triggered reset occurred */
+bool dce110_timing_generator_did_triggered_reset_occur(
+	struct timing_generator *tg);
+
+/******** Stuff to move to other virtual HW objects *****************/
+/* TODO: Should we move it to mem_input interface? */
+bool dce110_timing_generator_blank_crtc(struct timing_generator *tg);
+bool dce110_timing_generator_unblank_crtc(struct timing_generator *tg);
+/* Move to enable accelerated mode */
+void dce110_timing_generator_disable_vga(struct timing_generator *tg);
+/* TODO: Should we move it to transform */
+/* Fully program CRTC timing in timing generator */
+void dce110_timing_generator_program_blanking(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing);
+
+/* TODO: Should we move it to opp? */
+/* Combine with below and move YUV/RGB color conversion to SW layer */
+void dce110_timing_generator_program_blank_color(
+	struct timing_generator *tg,
+	enum color_space color_space);
+/* Combine with above and move YUV/RGB color conversion to SW layer */
+void dce110_timing_generator_set_overscan_color_black(
+	struct timing_generator *tg,
+	enum color_space black_color);
+/*************** End-of-move ********************/
+
+
+/* Not called yet */
+void dce110_timing_generator_set_test_pattern(
+	struct timing_generator *tg,
+	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
+	 * because this is not DP-specific (which is probably somewhere in DP
+	 * encoder) */
+	enum controller_dp_test_pattern test_pattern,
+	enum dc_color_depth color_depth);
+
+void dce110_timing_generator_program_drr(
+	struct timing_generator *tg,
+	const struct hw_ranged_timing *timing);
+
+uint32_t dce110_timing_generator_get_crtc_scanoutpos(
+	struct timing_generator *tg,
+	int32_t *vbl,
+	int32_t *position);
+
+void dce110_timing_generator_enable_advanced_request(
+	struct timing_generator *tg,
+	bool enable,
+	const struct dc_crtc_timing *timing);
+
+void dce110_timing_generator_set_lock_master(struct timing_generator *tg,
+		bool lock);
+
+void dce110_tg_program_blank_color(struct timing_generator *tg,
+	const struct crtc_black_color *black_color);
+
+void dce110_tg_set_overscan_color(struct timing_generator *tg,
+	const struct crtc_black_color *overscan_color);
+
+void dce110_tg_get_position(struct timing_generator *tg,
+	struct crtc_position *position);
+
+void dce110_tg_program_timing(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing,
+	bool use_vbios);
+
+bool dce110_tg_set_blank(struct timing_generator *tg,
+		bool enable_blanking);
+
+bool dce110_tg_validate_timing(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing);
+
+
+void dce110_tg_wait_for_state(struct timing_generator *tg,
+	enum crtc_state state);
+
+void dce110_tg_set_colors(struct timing_generator *tg,
+	const struct crtc_black_color *blank_color,
+	const struct crtc_black_color *overscan_color);
+
+#endif /* __DC_TIMING_GENERATOR_DCE110_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 16/29] drm/amd/dal: Add surface HW programming
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (14 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 15/29] drm/amd/dal: Add timing generator " Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 17/29] drm/amd/dal: Add framebuffer compression " Harry Wentland
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Adds watermark, DMIF, and surface programming.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c   | 965 +++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h   | 117 +++
 2 files changed, 1082 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
new file mode 100644
index 000000000000..3a928e63e647
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
@@ -0,0 +1,965 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+/* TODO: this needs to be looked at, used by Stella's workaround*/
+#include "gmc/gmc_8_2_d.h"
+#include "gmc/gmc_8_2_sh_mask.h"
+
+#include "include/logger_interface.h"
+#include "adapter_service_interface.h"
+#include "inc/bandwidth_calcs.h"
+
+#include "dce110_mem_input.h"
+
+#define MAX_WATERMARK 0xFFFF
+#define SAFE_NBP_MARK 0x7FFF
+
+#define DCP_REG(reg) (reg + mem_input110->offsets.dcp)
+#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif)
+#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe)
+
+static void set_flip_control(
+	struct dce110_mem_input *mem_input110,
+	bool immediate)
+{
+	uint32_t value = 0;
+
+	value = dm_read_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_FLIP_CONTROL));
+	set_reg_field_value(value, 0,
+				GRPH_FLIP_CONTROL,
+				GRPH_SURFACE_UPDATE_IMMEDIATE_EN);
+	set_reg_field_value(value, 0,
+				GRPH_FLIP_CONTROL,
+				GRPH_SURFACE_UPDATE_H_RETRACE_EN);
+	if (immediate == true)
+		set_reg_field_value(value, 1,
+			GRPH_FLIP_CONTROL,
+			GRPH_SURFACE_UPDATE_IMMEDIATE_EN);
+
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_FLIP_CONTROL),
+		value);
+}
+
+static void program_sec_addr(
+	struct dce110_mem_input *mem_input110,
+	PHYSICAL_ADDRESS_LOC address)
+{
+	uint32_t value = 0;
+	uint32_t temp = 0;
+	/*high register MUST be programmed first*/
+	temp = address.high_part &
+GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK;
+
+	set_reg_field_value(value, temp,
+		GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
+		GRPH_SECONDARY_SURFACE_ADDRESS_HIGH);
+
+	dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH),
+			value);
+
+	temp = 0;
+	value = 0;
+	temp = address.low_part >>
+	GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT;
+
+	set_reg_field_value(value, temp,
+		GRPH_SECONDARY_SURFACE_ADDRESS,
+		GRPH_SECONDARY_SURFACE_ADDRESS);
+
+	dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS),
+			value);
+}
+
+static void program_pri_addr(
+	struct dce110_mem_input *mem_input110,
+	PHYSICAL_ADDRESS_LOC address)
+{
+	uint32_t value = 0;
+	uint32_t temp = 0;
+
+	/*high register MUST be programmed first*/
+	temp = address.high_part &
+GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK;
+
+	set_reg_field_value(value, temp,
+		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
+		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH);
+
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH),
+		value);
+
+	temp = 0;
+	value = 0;
+	temp = address.low_part >>
+	GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT;
+
+	set_reg_field_value(value, temp,
+		GRPH_PRIMARY_SURFACE_ADDRESS,
+		GRPH_PRIMARY_SURFACE_ADDRESS);
+
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS),
+		value);
+}
+
+static void program_addr(
+	struct dce110_mem_input *mem_input110,
+	const struct dc_plane_address *addr)
+{
+	switch (addr->type) {
+	case PLN_ADDR_TYPE_GRAPHICS:
+		program_pri_addr(
+			mem_input110,
+			addr->grph.addr);
+		break;
+	case PLN_ADDR_TYPE_GRPH_STEREO:
+		program_pri_addr(
+			mem_input110,
+			addr->grph_stereo.left_addr);
+		program_sec_addr(
+			mem_input110,
+			addr->grph_stereo.right_addr);
+		break;
+	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
+	default:
+		/* not supported */
+		BREAK_TO_DEBUGGER();
+	}
+}
+
+static void enable(struct dce110_mem_input *mem_input110)
+{
+	uint32_t value = 0;
+
+	value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_ENABLE));
+	set_reg_field_value(value, 1, GRPH_ENABLE, GRPH_ENABLE);
+	dm_write_reg(mem_input110->base.ctx,
+		DCP_REG(mmGRPH_ENABLE),
+		value);
+}
+
+static void program_tiling(
+	struct dce110_mem_input *mem_input110,
+	const struct dc_tiling_info *info,
+	const enum surface_pixel_format pixel_format)
+{
+	uint32_t value = 0;
+
+	value = dm_read_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_CONTROL));
+
+	set_reg_field_value(value, info->num_banks,
+		GRPH_CONTROL, GRPH_NUM_BANKS);
+
+	set_reg_field_value(value, info->bank_width,
+		GRPH_CONTROL, GRPH_BANK_WIDTH);
+
+	set_reg_field_value(value, info->bank_height,
+		GRPH_CONTROL, GRPH_BANK_HEIGHT);
+
+	set_reg_field_value(value, info->tile_aspect,
+		GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT);
+
+	set_reg_field_value(value, info->tile_split,
+		GRPH_CONTROL, GRPH_TILE_SPLIT);
+
+	set_reg_field_value(value, info->tile_mode,
+		GRPH_CONTROL, GRPH_MICRO_TILE_MODE);
+
+	set_reg_field_value(value, info->pipe_config,
+		GRPH_CONTROL, GRPH_PIPE_CONFIG);
+
+	set_reg_field_value(value, info->array_mode,
+		GRPH_CONTROL, GRPH_ARRAY_MODE);
+
+	set_reg_field_value(value, 1,
+		GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE);
+
+	set_reg_field_value(value, 0,
+		GRPH_CONTROL, GRPH_Z);
+
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_CONTROL),
+		value);
+}
+
+static void program_size_and_rotation(
+	struct dce110_mem_input *mem_input110,
+	enum dc_rotation_angle rotation,
+	const union plane_size *plane_size)
+{
+	uint32_t value = 0;
+	union plane_size local_size = *plane_size;
+
+	if (rotation == ROTATION_ANGLE_90 ||
+		rotation == ROTATION_ANGLE_270) {
+
+		uint32_t swap;
+
+		swap = local_size.grph.surface_size.x;
+		local_size.grph.surface_size.x =
+			local_size.grph.surface_size.y;
+		local_size.grph.surface_size.y  = swap;
+
+		swap = local_size.grph.surface_size.width;
+		local_size.grph.surface_size.width =
+			local_size.grph.surface_size.height;
+		local_size.grph.surface_size.height = swap;
+	}
+
+	set_reg_field_value(value, local_size.grph.surface_size.x,
+			GRPH_X_START, GRPH_X_START);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_X_START),
+		value);
+
+	value = 0;
+	set_reg_field_value(value, local_size.grph.surface_size.y,
+			GRPH_Y_START, GRPH_Y_START);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_Y_START),
+		value);
+
+	value = 0;
+	set_reg_field_value(value, local_size.grph.surface_size.width,
+			GRPH_X_END, GRPH_X_END);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_X_END),
+		value);
+
+	value = 0;
+	set_reg_field_value(value, local_size.grph.surface_size.height,
+			GRPH_Y_END, GRPH_Y_END);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_Y_END),
+		value);
+
+	value = 0;
+	set_reg_field_value(value, local_size.grph.surface_pitch,
+			GRPH_PITCH, GRPH_PITCH);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_PITCH),
+		value);
+
+
+	value = 0;
+	switch (rotation) {
+	case ROTATION_ANGLE_90:
+		set_reg_field_value(value, 3,
+			HW_ROTATION, GRPH_ROTATION_ANGLE);
+		break;
+	case ROTATION_ANGLE_180:
+		set_reg_field_value(value, 2,
+			HW_ROTATION, GRPH_ROTATION_ANGLE);
+		break;
+	case ROTATION_ANGLE_270:
+		set_reg_field_value(value, 1,
+			HW_ROTATION, GRPH_ROTATION_ANGLE);
+		break;
+	default:
+		set_reg_field_value(value, 0,
+			HW_ROTATION, GRPH_ROTATION_ANGLE);
+		break;
+	}
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmHW_ROTATION),
+		value);
+}
+
+static void program_pixel_format(
+	struct dce110_mem_input *mem_input110,
+	enum surface_pixel_format format)
+{
+	if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
+		format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
+		uint32_t value = 0;
+
+		/* handle colour twizzle formats, swapping R and B */
+		if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 ||
+			format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
+			format ==
+			SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
+			format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
+			set_reg_field_value(
+				value, 2, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR);
+			set_reg_field_value(
+				value, 2, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR);
+		}
+
+		dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_SWAP_CNTL),
+			value);
+
+
+		value =	dm_read_reg(
+				mem_input110->base.ctx,
+				DCP_REG(mmGRPH_CONTROL));
+
+		switch (format) {
+		case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
+			set_reg_field_value(
+				value, 0, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 0, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+			set_reg_field_value(
+				value, 1, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 1, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+		case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
+			set_reg_field_value(
+				value, 2, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 0, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+		case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+		case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+			set_reg_field_value(
+				value, 2, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 1, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+		case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+			set_reg_field_value(
+				value, 3, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 0, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		default:
+			break;
+		}
+		dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_CONTROL),
+			value);
+
+		/*TODO [hwentlan] MOVE THIS TO CONTROLLER GAMMA!!!!!*/
+		value = dm_read_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmPRESCALE_GRPH_CONTROL));
+
+		if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
+			set_reg_field_value(
+				value, 1, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_SELECT);
+			set_reg_field_value(
+				value, 1, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_R_SIGN);
+			set_reg_field_value(
+				value, 1, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_G_SIGN);
+			set_reg_field_value(
+				value, 1, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_B_SIGN);
+		} else {
+			set_reg_field_value(
+				value, 0, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_SELECT);
+			set_reg_field_value(
+				value, 0, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_R_SIGN);
+			set_reg_field_value(
+				value, 0, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_G_SIGN);
+			set_reg_field_value(
+				value, 0, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_B_SIGN);
+		}
+		dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmPRESCALE_GRPH_CONTROL),
+			value);
+	}
+}
+
+static void wait_for_no_surface_update_pending(
+				struct dce110_mem_input *mem_input110)
+{
+	uint32_t value;
+
+	do  {
+		value = dm_read_reg(mem_input110->base.ctx,
+				DCP_REG(mmGRPH_UPDATE));
+
+	} while (get_reg_field_value(value, GRPH_UPDATE,
+			GRPH_SURFACE_UPDATE_PENDING));
+}
+
+bool dce110_mem_input_program_surface_flip_and_addr(
+	struct mem_input *mem_input,
+	const struct dc_plane_address *address,
+	bool flip_immediate)
+{
+	struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input);
+
+	set_flip_control(mem_input110, flip_immediate);
+	program_addr(mem_input110,
+		address);
+
+	if (flip_immediate)
+		wait_for_no_surface_update_pending(mem_input110);
+
+	return true;
+}
+
+bool dce110_mem_input_program_surface_config(
+	struct mem_input *mem_input,
+	enum surface_pixel_format format,
+	struct dc_tiling_info *tiling_info,
+	union plane_size *plane_size,
+	enum dc_rotation_angle rotation)
+{
+	struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input);
+
+	enable(mem_input110);
+	program_tiling(mem_input110, tiling_info, format);
+	program_size_and_rotation(mem_input110, rotation, plane_size);
+	program_pixel_format(mem_input110, format);
+
+	return true;
+}
+
+static void program_urgency_watermark(
+	const struct dc_context *ctx,
+	const uint32_t offset,
+	struct bw_watermarks marks_low,
+	uint32_t total_dest_line_time_ns)
+{
+	/* register value */
+	uint32_t urgency_cntl = 0;
+	uint32_t wm_mask_cntl = 0;
+
+	uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL;
+	uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL;
+
+	/*Write mask to enable reading/writing of watermark set A*/
+	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
+	set_reg_field_value(wm_mask_cntl,
+			1,
+			DPG_WATERMARK_MASK_CONTROL,
+			URGENCY_WATERMARK_MASK);
+	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
+
+	urgency_cntl = dm_read_reg(ctx, urgency_addr);
+
+	set_reg_field_value(
+		urgency_cntl,
+		marks_low.a_mark,
+		DPG_PIPE_URGENCY_CONTROL,
+		URGENCY_LOW_WATERMARK);
+
+	set_reg_field_value(
+		urgency_cntl,
+		total_dest_line_time_ns,
+		DPG_PIPE_URGENCY_CONTROL,
+		URGENCY_HIGH_WATERMARK);
+	dm_write_reg(ctx, urgency_addr, urgency_cntl);
+
+
+	/*Write mask to enable reading/writing of watermark set B*/
+	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
+	set_reg_field_value(wm_mask_cntl,
+			2,
+			DPG_WATERMARK_MASK_CONTROL,
+			URGENCY_WATERMARK_MASK);
+	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
+
+	urgency_cntl = dm_read_reg(ctx, urgency_addr);
+
+	set_reg_field_value(urgency_cntl,
+		marks_low.b_mark,
+		DPG_PIPE_URGENCY_CONTROL,
+		URGENCY_LOW_WATERMARK);
+
+	set_reg_field_value(urgency_cntl,
+		total_dest_line_time_ns,
+		DPG_PIPE_URGENCY_CONTROL,
+		URGENCY_HIGH_WATERMARK);
+	dm_write_reg(ctx, urgency_addr, urgency_cntl);
+}
+
+static void program_stutter_watermark(
+	const struct dc_context *ctx,
+	const uint32_t offset,
+	struct bw_watermarks marks)
+{
+	/* register value */
+	uint32_t stutter_cntl = 0;
+	uint32_t wm_mask_cntl = 0;
+
+	uint32_t stutter_addr = offset + mmDPG_PIPE_STUTTER_CONTROL;
+	uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL;
+
+	/*Write mask to enable reading/writing of watermark set A*/
+
+	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
+	set_reg_field_value(wm_mask_cntl,
+		1,
+		DPG_WATERMARK_MASK_CONTROL,
+		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK);
+	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
+
+	stutter_cntl = dm_read_reg(ctx, stutter_addr);
+
+	set_reg_field_value(stutter_cntl,
+		1,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_ENABLE);
+	set_reg_field_value(stutter_cntl,
+		1,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_IGNORE_FBC);
+
+	/*Write watermark set A*/
+	set_reg_field_value(stutter_cntl,
+		marks.a_mark,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_EXIT_SELF_REFRESH_WATERMARK);
+	dm_write_reg(ctx, stutter_addr, stutter_cntl);
+
+	/*Write mask to enable reading/writing of watermark set B*/
+	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
+	set_reg_field_value(wm_mask_cntl,
+		2,
+		DPG_WATERMARK_MASK_CONTROL,
+		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK);
+	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
+
+	stutter_cntl = dm_read_reg(ctx, stutter_addr);
+	set_reg_field_value(stutter_cntl,
+		1,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_ENABLE);
+	set_reg_field_value(stutter_cntl,
+		1,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_IGNORE_FBC);
+
+	/*Write watermark set B*/
+	set_reg_field_value(stutter_cntl,
+		marks.b_mark,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_EXIT_SELF_REFRESH_WATERMARK);
+	dm_write_reg(ctx, stutter_addr, stutter_cntl);
+}
+
+static void program_nbp_watermark(
+	const struct dc_context *ctx,
+	const uint32_t offset,
+	struct bw_watermarks marks)
+{
+	uint32_t value;
+	uint32_t addr;
+	/* Write mask to enable reading/writing of watermark set A */
+	addr = offset + mmDPG_WATERMARK_MASK_CONTROL;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_WATERMARK_MASK_CONTROL,
+		NB_PSTATE_CHANGE_WATERMARK_MASK);
+	dm_write_reg(ctx, addr, value);
+
+	addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_ENABLE);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_URGENT_DURING_REQUEST);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST);
+	dm_write_reg(ctx, addr, value);
+
+	/* Write watermark set A */
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		marks.a_mark,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_WATERMARK);
+	dm_write_reg(ctx, addr, value);
+
+	/* Write mask to enable reading/writing of watermark set B */
+	addr = offset + mmDPG_WATERMARK_MASK_CONTROL;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		2,
+		DPG_WATERMARK_MASK_CONTROL,
+		NB_PSTATE_CHANGE_WATERMARK_MASK);
+	dm_write_reg(ctx, addr, value);
+
+	addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_ENABLE);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_URGENT_DURING_REQUEST);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST);
+	dm_write_reg(ctx, addr, value);
+
+	/* Write watermark set B */
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		marks.b_mark,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_WATERMARK);
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_mem_input_program_safe_display_marks(struct mem_input *mi)
+{
+	struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi);
+	struct bw_watermarks max_marks = { MAX_WATERMARK, MAX_WATERMARK };
+	struct bw_watermarks nbp_marks = { SAFE_NBP_MARK, SAFE_NBP_MARK };
+
+	program_urgency_watermark(
+		mi->ctx, bm_dce110->offsets.dmif, max_marks, MAX_WATERMARK);
+	program_stutter_watermark(mi->ctx, bm_dce110->offsets.dmif, max_marks);
+	program_nbp_watermark(mi->ctx, bm_dce110->offsets.dmif, nbp_marks);
+}
+
+void dce110_mem_input_program_display_marks(
+	struct mem_input *mem_input,
+	struct bw_watermarks nbp,
+	struct bw_watermarks stutter,
+	struct bw_watermarks urgent,
+	uint32_t h_total,
+	uint32_t pixel_clk_in_khz,
+	uint32_t pstate_blackout_duration_ns)
+{
+	struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input);
+	uint32_t total_dest_line_time_ns = 1000000UL * h_total
+		/ pixel_clk_in_khz + pstate_blackout_duration_ns;
+
+	program_urgency_watermark(
+		mem_input->ctx,
+		bm_dce110->offsets.dmif,
+		urgent,
+		total_dest_line_time_ns);
+	program_nbp_watermark(
+		mem_input->ctx,
+		bm_dce110->offsets.dmif,
+		nbp);
+	program_stutter_watermark(
+		mem_input->ctx,
+		bm_dce110->offsets.dmif,
+		stutter);
+}
+
+static uint32_t get_dmif_switch_time_us(struct dc_crtc_timing *timing)
+{
+	uint32_t frame_time;
+	uint32_t pixels_per_second;
+	uint32_t pixels_per_frame;
+	uint32_t refresh_rate;
+	const uint32_t us_in_sec = 1000000;
+	const uint32_t min_single_frame_time_us = 30000;
+	/*return double of frame time*/
+	const uint32_t single_frame_time_multiplier = 2;
+
+	if (timing == NULL)
+		return single_frame_time_multiplier * min_single_frame_time_us;
+
+	/*TODO: should we use pixel format normalized pixel clock here?*/
+	pixels_per_second = timing->pix_clk_khz * 1000;
+	pixels_per_frame = timing->h_total * timing->v_total;
+
+	if (!pixels_per_second || !pixels_per_frame) {
+		/* avoid division by zero */
+		ASSERT(pixels_per_frame);
+		ASSERT(pixels_per_second);
+		return single_frame_time_multiplier * min_single_frame_time_us;
+	}
+
+	refresh_rate = pixels_per_second / pixels_per_frame;
+
+	if (!refresh_rate) {
+		/* avoid division by zero*/
+		ASSERT(refresh_rate);
+		return single_frame_time_multiplier * min_single_frame_time_us;
+	}
+
+	frame_time = us_in_sec / refresh_rate;
+
+	if (frame_time < min_single_frame_time_us)
+		frame_time = min_single_frame_time_us;
+
+	frame_time *= single_frame_time_multiplier;
+
+	return frame_time;
+}
+
+void dce110_mem_input_allocate_dmif_buffer(
+		struct mem_input *mi,
+		struct dc_crtc_timing *timing,
+		uint32_t paths_num)
+{
+	const uint32_t retry_delay = 10;
+	uint32_t retry_count = get_dmif_switch_time_us(timing) / retry_delay;
+
+	struct dce110_mem_input *bm110 = TO_DCE110_MEM_INPUT(mi);
+	uint32_t addr = bm110->offsets.pipe + mmPIPE0_DMIF_BUFFER_CONTROL;
+	uint32_t value;
+	uint32_t field;
+	uint32_t pix_dur;
+
+	if (bm110->supported_stutter_mode
+			& STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION)
+		goto register_underflow_int;
+
+	/*Allocate DMIF buffer*/
+	value = dm_read_reg(mi->ctx, addr);
+	field = get_reg_field_value(
+		value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED);
+	if (field == 2)
+		goto register_underflow_int;
+
+	set_reg_field_value(
+			value,
+			2,
+			PIPE0_DMIF_BUFFER_CONTROL,
+			DMIF_BUFFERS_ALLOCATED);
+
+	dm_write_reg(mi->ctx, addr, value);
+
+	do {
+		value = dm_read_reg(mi->ctx, addr);
+		field = get_reg_field_value(
+			value,
+			PIPE0_DMIF_BUFFER_CONTROL,
+			DMIF_BUFFERS_ALLOCATION_COMPLETED);
+
+		if (field)
+			break;
+
+		dm_delay_in_microseconds(mi->ctx, retry_delay);
+		retry_count--;
+
+	} while (retry_count > 0);
+
+	if (field == 0)
+		dal_logger_write(mi->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_COMPONENT_GPU,
+				"%s: DMIF allocation failed",
+				__func__);
+
+
+	if (timing->pix_clk_khz != 0) {
+		addr = mmDPG_PIPE_ARBITRATION_CONTROL1 + bm110->offsets.dmif;
+		value = dm_read_reg(mi->ctx, addr);
+		pix_dur = 1000000000ULL / timing->pix_clk_khz;
+
+		set_reg_field_value(
+			value,
+			pix_dur,
+			DPG_PIPE_ARBITRATION_CONTROL1,
+			PIXEL_DURATION);
+
+		dm_write_reg(mi->ctx, addr, value);
+	}
+
+	/*
+	 * Stella Wong proposed the following change
+	 *
+	 * Value of mcHubRdReqDmifLimit.ENABLE:
+	 * 00 - disable DMIF rdreq limit
+	 * 01 - enable DMIF rdreq limit, disabled by DMIF stall = 1 || urg != 0
+	 * 02 - enable DMIF rdreq limit, disable by DMIF stall = 1
+	 * 03 - force enable DMIF rdreq limit, ignore DMIF stall / urgent
+	 */
+	if (!IS_FPGA_MAXIMUS_DC(mi->ctx->dce_environment)) {
+		addr = mmMC_HUB_RDREQ_DMIF_LIMIT;
+		value = dm_read_reg(mi->ctx, addr);
+
+		if (paths_num > 1)
+			set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE);
+		else
+			set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE);
+		dm_write_reg(mi->ctx, addr, value);
+	}
+
+register_underflow_int:
+	/*todo*/;
+	/*register_interrupt(bm110, irq_source, ctrl_id);*/
+}
+
+static void deallocate_dmif_buffer_helper(
+				struct dc_context *ctx, uint32_t offset)
+{
+	uint32_t value;
+	uint32_t count = 0xBB8; /* max retry count */
+
+	value = dm_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset);
+
+	if (!get_reg_field_value(
+		value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED))
+		return;
+
+	set_reg_field_value(
+		value, 0, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED);
+
+	dm_write_reg(
+		ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset, value);
+
+	do {
+		value = dm_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset);
+		dm_delay_in_microseconds(ctx, 10);
+		count--;
+	} while (count > 0 &&
+		!get_reg_field_value(
+			value,
+			PIPE0_DMIF_BUFFER_CONTROL,
+			DMIF_BUFFERS_ALLOCATION_COMPLETED));
+}
+
+void dce110_mem_input_deallocate_dmif_buffer(
+	struct mem_input *mi, uint32_t paths_num)
+{
+	struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi);
+	uint32_t value;
+
+	if (!(bm_dce110->supported_stutter_mode &
+		STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION)) {
+
+		/* De-allocate DMIF buffer first */
+		if (mmPIPE0_DMIF_BUFFER_CONTROL + bm_dce110->offsets.pipe != 0)
+			deallocate_dmif_buffer_helper(
+					mi->ctx, bm_dce110->offsets.pipe);
+	}
+
+	/* TODO: unregister underflow interrupt
+	unregisterInterrupt();
+	*/
+
+	/* Value of mcHubRdReqDmifLimit.ENABLE.
+	 * 00 - disable dmif rdreq limit
+	 * 01 - enable dmif rdreq limit, disable by dmif stall=1||urg!=0
+	 * 02 - enable dmif rdreq limit, disable by dmif stall=1
+	 * 03 - force enable dmif rdreq limit, ignore dmif stall/urgent
+	 * Stella Wong proposed this change. */
+	if (!IS_FPGA_MAXIMUS_DC(mi->ctx->dce_environment)) {
+		value = dm_read_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT);
+		if (paths_num > 1)
+			set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE);
+		else
+			set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE);
+
+		dm_write_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT, value);
+	}
+}
+
+static struct mem_input_funcs dce110_mem_input_funcs = {
+	.mem_input_program_safe_display_marks =
+			dce110_mem_input_program_safe_display_marks,
+	.mem_input_program_display_marks =
+			dce110_mem_input_program_display_marks,
+	.mem_input_allocate_dmif_buffer = dce110_mem_input_allocate_dmif_buffer,
+	.mem_input_deallocate_dmif_buffer =
+			dce110_mem_input_deallocate_dmif_buffer,
+	.mem_input_program_surface_flip_and_addr =
+			dce110_mem_input_program_surface_flip_and_addr,
+	.mem_input_program_surface_config =
+			dce110_mem_input_program_surface_config,
+};
+/*****************************************/
+/* Constructor, Destructor               */
+/*****************************************/
+
+bool dce110_mem_input_construct(
+	struct dce110_mem_input *mem_input110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_mem_input_reg_offsets *offsets)
+{
+	mem_input110->base.funcs = &dce110_mem_input_funcs;
+	mem_input110->base.ctx = ctx;
+
+	mem_input110->base.inst = inst;
+
+	mem_input110->offsets = *offsets;
+
+	mem_input110->supported_stutter_mode = 0;
+	dal_adapter_service_get_feature_value(FEATURE_STUTTER_MODE,
+			&(mem_input110->supported_stutter_mode),
+			sizeof(mem_input110->supported_stutter_mode));
+
+	return true;
+}
+
+void dce110_mem_input_destroy(struct mem_input **mem_input)
+{
+	dm_free((*mem_input)->ctx, TO_DCE110_MEM_INPUT(*mem_input));
+	*mem_input = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h
new file mode 100644
index 000000000000..5a4e5fe33a79
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h
@@ -0,0 +1,117 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_MEM_INPUT_DCE110_H__
+#define __DC_MEM_INPUT_DCE110_H__
+
+#include "inc/mem_input.h"
+
+#define TO_DCE110_MEM_INPUT(mi)\
+	container_of(mi, struct dce110_mem_input, base)
+
+struct dce110_mem_input_reg_offsets {
+	uint32_t dcp;
+	uint32_t dmif;
+	uint32_t pipe;
+};
+
+struct dce110_mem_input {
+	struct mem_input base;
+	struct dce110_mem_input_reg_offsets offsets;
+	uint32_t supported_stutter_mode;
+};
+
+bool dce110_mem_input_construct(
+	struct dce110_mem_input *mem_input110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_mem_input_reg_offsets *offsets);
+
+/*
+ * dce110_mem_input_program_display_marks
+ *
+ * This function will program nbp stutter and urgency watermarks to maximum
+ * safe values
+ */
+void dce110_mem_input_program_safe_display_marks(struct mem_input *mi);
+
+/*
+ * dce110_mem_input_program_display_marks
+ *
+ * This function will program nbp stutter and urgency watermarks to minimum
+ * allowable values
+ */
+void dce110_mem_input_program_display_marks(
+	struct mem_input *mem_input,
+	struct bw_watermarks nbp,
+	struct bw_watermarks stutter,
+	struct bw_watermarks urgent,
+	uint32_t h_total,
+	uint32_t pixel_clk_in_khz,
+	uint32_t pstate_blackout_duration_ns);
+
+/*
+ * dce110_mem_input_allocate_dmif_buffer
+ *
+ * This function will allocate a dmif buffer and program required
+ * pixel duration for pipe
+ */
+void dce110_mem_input_allocate_dmif_buffer(
+		struct mem_input *mem_input,
+		struct dc_crtc_timing *timing,
+		uint32_t paths_num);
+
+/*
+ * dce110_mem_input_deallocate_dmif_buffer
+ *
+ * This function will deallocate a dmif buffer from pipe
+ */
+void dce110_mem_input_deallocate_dmif_buffer(
+	struct mem_input *mem_input, uint32_t paths_num);
+
+/*
+ * dce110_mem_input_program_surface_flip_and_addr
+ *
+ * This function programs hsync/vsync mode and surface address
+ */
+bool dce110_mem_input_program_surface_flip_and_addr(
+	struct mem_input *mem_input,
+	const struct dc_plane_address *address,
+	bool flip_immediate);
+
+/*
+ * dce110_mem_input_program_surface_config
+ *
+ * This function will program surface tiling, size, rotation and pixel format
+ * to corresponding dcp registers.
+ */
+bool  dce110_mem_input_program_surface_config(
+	struct mem_input *mem_input,
+	enum surface_pixel_format format,
+	struct dc_tiling_info *tiling_info,
+	union plane_size *plane_size,
+	enum dc_rotation_angle rotation);
+
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 17/29] drm/amd/dal: Add framebuffer compression HW programming
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (15 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 16/29] drm/amd/dal: Add surface " Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 18/29] drm/amd/dal: Add input pixel processing " Harry Wentland
                   ` (15 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Adds framebuffer compression programming. Currently unused.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.c  | 886 +++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.h  |  84 ++
 2 files changed, 970 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
new file mode 100644
index 000000000000..285d54439f4c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
@@ -0,0 +1,886 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "gmc/gmc_8_2_sh_mask.h"
+#include "gmc/gmc_8_2_d.h"
+
+#include "include/logger_interface.h"
+#include "include/adapter_service_interface.h"
+
+#include "dce110_compressor.h"
+
+#define DCP_REG(reg)\
+	(reg + cp110->offsets.dcp_offset)
+#define DMIF_REG(reg)\
+	(reg + cp110->offsets.dmif_offset)
+
+static const struct dce110_compressor_reg_offsets reg_offsets[] = {
+{
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+	.dmif_offset =
+		(mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
+			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+	.dmif_offset =
+		(mmDMIF_PG1_DPG_PIPE_DPM_CONTROL
+			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+	.dmif_offset =
+		(mmDMIF_PG2_DPG_PIPE_DPM_CONTROL
+			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
+}
+};
+
+static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600;
+
+enum fbc_idle_force {
+	/* Bit 0 - Display registers updated */
+	FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001,
+
+	/* Bit 2 - FBC_GRPH_COMP_EN register updated */
+	FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002,
+	/* Bit 3 - FBC_SRC_SEL register updated */
+	FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004,
+	/* Bit 4 - FBC_MIN_COMPRESSION register updated */
+	FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008,
+	/* Bit 5 - FBC_ALPHA_COMP_EN register updated */
+	FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010,
+	/* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */
+	FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020,
+	/* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */
+	FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040,
+
+	/* Bit 24 - Memory write to region 0 defined by MC registers. */
+	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000,
+	/* Bit 25 - Memory write to region 1 defined by MC registers */
+	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000,
+	/* Bit 26 - Memory write to region 2 defined by MC registers */
+	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000,
+	/* Bit 27 - Memory write to region 3 defined by MC registers. */
+	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000,
+
+	/* Bit 28 - Memory write from any client other than MCIF */
+	FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000,
+	/* Bit 29 - CG statics screen signal is inactive */
+	FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000,
+};
+
+static uint32_t lpt_size_alignment(struct dce110_compressor *cp110)
+{
+	/*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */
+	return cp110->base.raw_size * cp110->base.banks_num *
+		cp110->base.dram_channels_num;
+}
+
+static uint32_t lpt_memory_control_config(struct dce110_compressor *cp110,
+	uint32_t lpt_control)
+{
+	/*LPT MC Config */
+	if (cp110->base.options.bits.LPT_MC_CONFIG == 1) {
+		/* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS):
+		 * 00 - 1 CHANNEL
+		 * 01 - 2 CHANNELS
+		 * 02 - 4 OR 6 CHANNELS
+		 * (Only for discrete GPU, N/A for CZ)
+		 * 03 - 8 OR 12 CHANNELS
+		 * (Only for discrete GPU, N/A for CZ) */
+		switch (cp110->base.dram_channels_num) {
+		case 2:
+			set_reg_field_value(
+				lpt_control,
+				1,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_PIPES);
+			break;
+		case 1:
+			set_reg_field_value(
+				lpt_control,
+				0,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_PIPES);
+			break;
+		default:
+			dal_logger_write(
+				cp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: Invalid LPT NUM_PIPES!!!",
+				__func__);
+			break;
+		}
+
+		/* The mapping for LPT NUM_BANKS is in
+		 * GRPH_CONTROL.GRPH_NUM_BANKS register field
+		 * Specifies the number of memory banks for tiling
+		 * purposes. Only applies to 2D and 3D tiling modes.
+		 * POSSIBLE VALUES:
+		 * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK
+		 * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK
+		 * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK
+		 * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */
+		switch (cp110->base.banks_num) {
+		case 16:
+			set_reg_field_value(
+				lpt_control,
+				3,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_BANKS);
+			break;
+		case 8:
+			set_reg_field_value(
+				lpt_control,
+				2,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_BANKS);
+			break;
+		case 4:
+			set_reg_field_value(
+				lpt_control,
+				1,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_BANKS);
+			break;
+		case 2:
+			set_reg_field_value(
+				lpt_control,
+				0,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_BANKS);
+			break;
+		default:
+			dal_logger_write(
+				cp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: Invalid LPT NUM_BANKS!!!",
+				__func__);
+			break;
+		}
+
+		/* The mapping is in DMIF_ADDR_CALC.
+		 * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for
+		 * Carrizo specifies the memory interleave per pipe.
+		 * It effectively specifies the location of pipe bits in
+		 * the memory address.
+		 * POSSIBLE VALUES:
+		 * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte
+		 * interleave
+		 * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte
+		 * interleave
+		 */
+		switch (cp110->base.channel_interleave_size) {
+		case 256: /*256B */
+			set_reg_field_value(
+				lpt_control,
+				0,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
+			break;
+		case 512: /*512B */
+			set_reg_field_value(
+				lpt_control,
+				1,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
+			break;
+		default:
+			dal_logger_write(
+				cp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: Invalid LPT INTERLEAVE_SIZE!!!",
+				__func__);
+			break;
+		}
+
+		/* The mapping for LOW_POWER_TILING_ROW_SIZE is in
+		 * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field
+		 * for Carrizo. Specifies the size of dram row in bytes.
+		 * This should match up with NOOFCOLS field in
+		 * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns).
+		 * This register DMIF_ADDR_CALC is not used by the
+		 * hardware as it is only used for addrlib assertions.
+		 * POSSIBLE VALUES:
+		 * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row
+		 * boundary
+		 * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row
+		 * boundary
+		 * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row
+		 * boundary */
+		switch (cp110->base.raw_size) {
+		case 4096: /*4 KB */
+			set_reg_field_value(
+				lpt_control,
+				2,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_ROW_SIZE);
+			break;
+		case 2048:
+			set_reg_field_value(
+				lpt_control,
+				1,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_ROW_SIZE);
+			break;
+		case 1024:
+			set_reg_field_value(
+				lpt_control,
+				0,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_ROW_SIZE);
+			break;
+		default:
+			dal_logger_write(
+				cp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: Invalid LPT ROW_SIZE!!!",
+				__func__);
+			break;
+		}
+	} else {
+		dal_logger_write(
+			cp110->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_CONTROLLER,
+			"%s: LPT MC Configuration is not provided",
+			__func__);
+	}
+
+	return lpt_control;
+}
+
+
+
+static bool is_source_bigger_than_epanel_size(
+	struct dce110_compressor *cp110,
+	uint32_t source_view_width,
+	uint32_t source_view_height)
+{
+	if (cp110->base.embedded_panel_h_size != 0 &&
+		cp110->base.embedded_panel_v_size != 0 &&
+		((source_view_width * source_view_height) >
+		(cp110->base.embedded_panel_h_size *
+			cp110->base.embedded_panel_v_size)))
+		return true;
+
+	return false;
+}
+
+static uint32_t align_to_chunks_number_per_line(
+	struct dce110_compressor *cp110,
+	uint32_t pixels)
+{
+	return 256 * ((pixels + 255) / 256);
+}
+
+static void wait_for_fbc_state_changed(
+	struct dce110_compressor *cp110,
+	bool enabled)
+{
+	uint8_t counter = 0;
+	uint32_t addr = mmFBC_STATUS;
+	uint32_t value;
+
+	while (counter < 10) {
+		value = dm_read_reg(cp110->base.ctx, addr);
+		if (get_reg_field_value(
+			value,
+			FBC_STATUS,
+			FBC_ENABLE_STATUS) == enabled)
+			break;
+		dm_delay_in_microseconds(cp110->base.ctx, 10);
+		counter++;
+	}
+
+	if (counter == 10) {
+		dal_logger_write(
+			cp110->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_CONTROLLER,
+			"%s: wait counter exceeded, changes to HW not applied",
+			__func__);
+	}
+}
+
+void dce110_compressor_power_up_fbc(struct compressor *compressor)
+{
+	uint32_t value;
+	uint32_t addr;
+
+	addr = mmFBC_CNTL;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
+	set_reg_field_value(value, 1, FBC_CNTL, FBC_EN);
+	set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE);
+	if (compressor->options.bits.CLK_GATING_DISABLED == 1) {
+		/* HW needs to do power measurement comparison. */
+		set_reg_field_value(
+			value,
+			0,
+			FBC_CNTL,
+			FBC_COMP_CLK_GATE_EN);
+	}
+	dm_write_reg(compressor->ctx, addr, value);
+
+	addr = mmFBC_COMP_MODE;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN);
+	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN);
+	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	addr = mmFBC_COMP_CNTL;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN);
+	dm_write_reg(compressor->ctx, addr, value);
+	/*FBC_MIN_COMPRESSION 0 ==> 2:1 */
+	/*                    1 ==> 4:1 */
+	/*                    2 ==> 8:1 */
+	/*                  0xF ==> 1:1 */
+	set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION);
+	dm_write_reg(compressor->ctx, addr, value);
+	compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1;
+
+	value = 0;
+	dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value);
+
+	value = 0xFFFFFF;
+	dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value);
+}
+
+void dce110_compressor_enable_fbc(
+	struct compressor *compressor,
+	uint32_t paths_num,
+	struct compr_addr_and_pitch_params *params)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+
+	if (compressor->options.bits.FBC_SUPPORT &&
+		(compressor->options.bits.DUMMY_BACKEND == 0) &&
+		(!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) &&
+		(!is_source_bigger_than_epanel_size(
+			cp110,
+			params->source_view_width,
+			params->source_view_height))) {
+
+		uint32_t addr;
+		uint32_t value;
+
+		/* Before enabling FBC first need to enable LPT if applicable
+		 * LPT state should always be changed (enable/disable) while FBC
+		 * is disabled */
+		if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) &&
+			(params->source_view_width *
+				params->source_view_height <=
+				dce11_one_lpt_channel_max_resolution)) {
+			dce110_compressor_enable_lpt(compressor);
+		}
+
+		addr = mmFBC_CNTL;
+		value = dm_read_reg(compressor->ctx, addr);
+		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
+		set_reg_field_value(
+			value,
+			params->inst,
+			FBC_CNTL, FBC_SRC_SEL);
+		dm_write_reg(compressor->ctx, addr, value);
+
+		/* Keep track of enum controller_id FBC is attached to */
+		compressor->is_enabled = true;
+		compressor->attached_inst = params->inst;
+		cp110->offsets = reg_offsets[params->inst - 1];
+
+		/*Toggle it as there is bug in HW */
+		set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
+		dm_write_reg(compressor->ctx, addr, value);
+		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
+		dm_write_reg(compressor->ctx, addr, value);
+
+		wait_for_fbc_state_changed(cp110, true);
+	}
+}
+
+void dce110_compressor_disable_fbc(struct compressor *compressor)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+
+	if (compressor->options.bits.FBC_SUPPORT &&
+		dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) {
+		uint32_t reg_data;
+		/* Turn off compression */
+		reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);
+		set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
+		dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);
+
+		/* Reset enum controller_id to undefined */
+		compressor->attached_inst = 0;
+		compressor->is_enabled = false;
+
+		/* Whenever disabling FBC make sure LPT is disabled if LPT
+		 * supported */
+		if (compressor->options.bits.LPT_SUPPORT)
+			dce110_compressor_disable_lpt(compressor);
+
+		wait_for_fbc_state_changed(cp110, false);
+	}
+}
+
+bool dce110_compressor_is_fbc_enabled_in_hw(
+	struct compressor *compressor,
+	uint32_t *inst)
+{
+	/* Check the hardware register */
+	uint32_t value;
+
+	value = dm_read_reg(compressor->ctx, mmFBC_STATUS);
+	if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) {
+		if (inst != NULL)
+			*inst = compressor->attached_inst;
+		return true;
+	}
+
+	value = dm_read_reg(compressor->ctx, mmFBC_MISC);
+	if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) {
+		value = dm_read_reg(compressor->ctx, mmFBC_CNTL);
+
+		if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) {
+			if (inst != NULL)
+				*inst =
+					compressor->attached_inst;
+			return true;
+		}
+	}
+	return false;
+}
+
+bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *compressor)
+{
+	/* Check the hardware register */
+	uint32_t value = dm_read_reg(compressor->ctx,
+		mmLOW_POWER_TILING_CONTROL);
+
+	return get_reg_field_value(
+		value,
+		LOW_POWER_TILING_CONTROL,
+		LOW_POWER_TILING_ENABLE);
+}
+
+void dce110_compressor_program_compressed_surface_address_and_pitch(
+	struct compressor *compressor,
+	struct compr_addr_and_pitch_params *params)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+	uint32_t value = 0;
+	uint32_t fbc_pitch = 0;
+	uint32_t compressed_surf_address_low_part =
+		compressor->compr_surface_address.addr.low_part;
+
+	/* Clear content first. */
+	dm_write_reg(
+		compressor->ctx,
+		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
+		0);
+	dm_write_reg(compressor->ctx,
+		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0);
+
+	if (compressor->options.bits.LPT_SUPPORT) {
+		uint32_t lpt_alignment = lpt_size_alignment(cp110);
+
+		if (lpt_alignment != 0) {
+			compressed_surf_address_low_part =
+				((compressed_surf_address_low_part
+					+ (lpt_alignment - 1)) / lpt_alignment)
+					* lpt_alignment;
+		}
+	}
+
+	/* Write address, HIGH has to be first. */
+	dm_write_reg(compressor->ctx,
+		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
+		compressor->compr_surface_address.addr.high_part);
+	dm_write_reg(compressor->ctx,
+		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS),
+		compressed_surf_address_low_part);
+
+	fbc_pitch = align_to_chunks_number_per_line(
+		cp110,
+		params->source_view_width);
+
+	if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
+		fbc_pitch = fbc_pitch / 8;
+	else
+		dal_logger_write(
+			compressor->ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_CONTROLLER,
+			"%s: Unexpected DCE11 compression ratio",
+			__func__);
+
+	/* Clear content first. */
+	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0);
+
+	/* Write FBC Pitch. */
+	set_reg_field_value(
+		value,
+		fbc_pitch,
+		GRPH_COMPRESS_PITCH,
+		GRPH_COMPRESS_PITCH);
+	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value);
+
+}
+
+void dce110_compressor_disable_lpt(struct compressor *compressor)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+	uint32_t value;
+	uint32_t addr;
+	uint32_t inx;
+
+	/* Disable all pipes LPT Stutter */
+	for (inx = 0; inx < 3; inx++) {
+		value =
+			dm_read_reg(
+				compressor->ctx,
+				DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
+		set_reg_field_value(
+			value,
+			0,
+			DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
+			STUTTER_ENABLE_NONLPTCH);
+		dm_write_reg(
+			compressor->ctx,
+			DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH),
+			value);
+	}
+	/* Disable Underlay pipe LPT Stutter */
+	addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		0,
+		DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
+		STUTTER_ENABLE_NONLPTCH);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Disable LPT */
+	addr = mmLOW_POWER_TILING_CONTROL;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		0,
+		LOW_POWER_TILING_CONTROL,
+		LOW_POWER_TILING_ENABLE);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Clear selection of Channel(s) containing Compressed Surface */
+	addr = mmGMCON_LPT_TARGET;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		0xFFFFFFFF,
+		GMCON_LPT_TARGET,
+		STCTRL_LPT_TARGET);
+	dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value);
+}
+
+void dce110_compressor_enable_lpt(struct compressor *compressor)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+	uint32_t value;
+	uint32_t addr;
+	uint32_t value_control;
+	uint32_t channels;
+
+	/* Enable LPT Stutter from Display pipe */
+	value = dm_read_reg(compressor->ctx,
+		DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
+		STUTTER_ENABLE_NONLPTCH);
+	dm_write_reg(compressor->ctx,
+		DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value);
+
+	/* Enable Underlay pipe LPT Stutter */
+	addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
+		STUTTER_ENABLE_NONLPTCH);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Selection of Channel(s) containing Compressed Surface: 0xfffffff
+	 * will disable LPT.
+	 * STCTRL_LPT_TARGETn corresponds to channel n. */
+	addr = mmLOW_POWER_TILING_CONTROL;
+	value_control = dm_read_reg(compressor->ctx, addr);
+	channels = get_reg_field_value(value_control,
+			LOW_POWER_TILING_CONTROL,
+			LOW_POWER_TILING_MODE);
+
+	addr = mmGMCON_LPT_TARGET;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		channels + 1, /* not mentioned in programming guide,
+				but follow DCE8.1 */
+		GMCON_LPT_TARGET,
+		STCTRL_LPT_TARGET);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Enable LPT */
+	addr = mmLOW_POWER_TILING_CONTROL;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		LOW_POWER_TILING_CONTROL,
+		LOW_POWER_TILING_ENABLE);
+	dm_write_reg(compressor->ctx, addr, value);
+}
+
+void dce110_compressor_program_lpt_control(
+	struct compressor *compressor,
+	struct compr_addr_and_pitch_params *params)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+	uint32_t rows_per_channel;
+	uint32_t lpt_alignment;
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+	uint32_t lpt_control = 0;
+
+	if (!compressor->options.bits.LPT_SUPPORT)
+		return;
+
+	lpt_control = dm_read_reg(compressor->ctx,
+		mmLOW_POWER_TILING_CONTROL);
+
+	/* POSSIBLE VALUES for Low Power Tiling Mode:
+	 * 00 - Use channel 0
+	 * 01 - Use Channel 0 and 1
+	 * 02 - Use Channel 0,1,2,3
+	 * 03 - reserved */
+	switch (compressor->lpt_channels_num) {
+	/* case 2:
+	 * Use Channel 0 & 1 / Not used for DCE 11 */
+	case 1:
+		/*Use Channel 0 for LPT for DCE 11 */
+		set_reg_field_value(
+			lpt_control,
+			0,
+			LOW_POWER_TILING_CONTROL,
+			LOW_POWER_TILING_MODE);
+		break;
+	default:
+		dal_logger_write(
+			compressor->ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_CONTROLLER,
+			"%s: Invalid selected DRAM channels for LPT!!!",
+			__func__);
+		break;
+	}
+
+	lpt_control = lpt_memory_control_config(cp110, lpt_control);
+
+	/* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on
+	 * FBC compressed surface pitch.
+	 * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height *
+	 * Surface Pitch) / (Row Size * Number of Channels *
+	 * Number of Banks)). */
+	rows_per_channel = 0;
+	lpt_alignment = lpt_size_alignment(cp110);
+	source_view_width =
+		align_to_chunks_number_per_line(
+			cp110,
+			params->source_view_width);
+	source_view_height = (params->source_view_height + 1) & (~0x1);
+
+	if (lpt_alignment != 0) {
+		rows_per_channel = source_view_width * source_view_height * 4;
+		rows_per_channel =
+			(rows_per_channel % lpt_alignment) ?
+				(rows_per_channel / lpt_alignment + 1) :
+				rows_per_channel / lpt_alignment;
+	}
+
+	set_reg_field_value(
+		lpt_control,
+		rows_per_channel,
+		LOW_POWER_TILING_CONTROL,
+		LOW_POWER_TILING_ROWS_PER_CHAN);
+
+	dm_write_reg(compressor->ctx,
+		mmLOW_POWER_TILING_CONTROL, lpt_control);
+}
+
+/*
+ * DCE 11 Frame Buffer Compression Implementation
+ */
+
+
+void dce110_compressor_set_fbc_invalidation_triggers(
+	struct compressor *compressor,
+	uint32_t fbc_trigger)
+{
+	/* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)
+	 * for DCE 11 regions cannot be used - does not work with S/G
+	 */
+	uint32_t addr = mmFBC_CLIENT_REGION_MASK;
+	uint32_t value = dm_read_reg(compressor->ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		FBC_CLIENT_REGION_MASK,
+		FBC_MEMORY_REGION_MASK);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Setup events when to clear all CSM entries (effectively marking
+	 * current compressed data invalid)
+	 * For DCE 11 CSM metadata 11111 means - "Not Compressed"
+	 * Used as the initial value of the metadata sent to the compressor
+	 * after invalidation, to indicate that the compressor should attempt
+	 * to compress all chunks on the current pass.  Also used when the chunk
+	 * is not successfully written to memory.
+	 * When this CSM value is detected, FBC reads from the uncompressed
+	 * buffer. Set events according to passed in value, these events are
+	 * valid for DCE11:
+	 *     - bit  0 - display register updated
+	 *     - bit 28 - memory write from any client except from MCIF
+	 *     - bit 29 - CG static screen signal is inactive
+	 * In addition, DCE11.1 also needs to set new DCE11.1 specific events
+	 * that are used to trigger invalidation on certain register changes,
+	 * for example enabling of Alpha Compression may trigger invalidation of
+	 * FBC once bit is set. These events are as follows:
+	 *      - Bit 2 - FBC_GRPH_COMP_EN register updated
+	 *      - Bit 3 - FBC_SRC_SEL register updated
+	 *      - Bit 4 - FBC_MIN_COMPRESSION register updated
+	 *      - Bit 5 - FBC_ALPHA_COMP_EN register updated
+	 *      - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated
+	 *      - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated
+	 */
+	addr = mmFBC_IDLE_FORCE_CLEAR_MASK;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		fbc_trigger |
+		FBC_IDLE_FORCE_GRPH_COMP_EN |
+		FBC_IDLE_FORCE_SRC_SEL_CHANGE |
+		FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE |
+		FBC_IDLE_FORCE_ALPHA_COMP_EN |
+		FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN |
+		FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF,
+		FBC_IDLE_FORCE_CLEAR_MASK,
+		FBC_IDLE_FORCE_CLEAR_MASK);
+	dm_write_reg(compressor->ctx, addr, value);
+}
+
+bool dce110_compressor_construct(struct dce110_compressor *compressor,
+	struct dc_context *ctx, struct adapter_service *as)
+{
+	struct embedded_panel_info panel_info;
+
+	compressor->base.options.bits.FBC_SUPPORT = true;
+	if (!(dal_adapter_service_is_feature_supported(
+		FEATURE_DISABLE_LPT_SUPPORT)))
+		compressor->base.options.bits.LPT_SUPPORT = true;
+	 /* For DCE 11 always use one DRAM channel for LPT */
+	compressor->base.lpt_channels_num = 1;
+
+	if (dal_adapter_service_is_feature_supported(FEATURE_DUMMY_FBC_BACKEND))
+		compressor->base.options.bits.DUMMY_BACKEND = true;
+
+	/* Check if this system has more than 1 DRAM channel; if only 1 then LPT
+	 * should not be supported */
+	if (compressor->base.memory_bus_width == 64)
+		compressor->base.options.bits.LPT_SUPPORT = false;
+
+	if (dal_adapter_service_is_feature_supported(
+		FEATURE_DISABLE_FBC_COMP_CLK_GATE))
+		compressor->base.options.bits.CLK_GATING_DISABLED = true;
+
+	compressor->base.ctx = ctx;
+	compressor->base.embedded_panel_h_size = 0;
+	compressor->base.embedded_panel_v_size = 0;
+	compressor->base.memory_bus_width =
+		dal_adapter_service_get_asic_vram_bit_width(as);
+	compressor->base.allocated_size = 0;
+	compressor->base.preferred_requested_size = 0;
+	compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID;
+	compressor->base.options.raw = 0;
+	compressor->base.banks_num = 0;
+	compressor->base.raw_size = 0;
+	compressor->base.channel_interleave_size = 0;
+	compressor->base.dram_channels_num = 0;
+	compressor->base.lpt_channels_num = 0;
+	compressor->base.attached_inst = 0;
+	compressor->base.is_enabled = false;
+
+	if (dal_adapter_service_get_embedded_panel_info(as,
+		&panel_info)) {
+		compressor->base.embedded_panel_h_size =
+			panel_info.lcd_timing.horizontal_addressable;
+		compressor->base.embedded_panel_v_size =
+			panel_info.lcd_timing.vertical_addressable;
+	}
+	return true;
+}
+
+struct compressor *dce110_compressor_create(struct dc_context *ctx,
+	struct adapter_service *as)
+{
+	struct dce110_compressor *cp110 =
+		dm_alloc(ctx, sizeof(struct dce110_compressor));
+
+	if (!cp110)
+		return NULL;
+
+	if (dce110_compressor_construct(cp110, ctx, as))
+		return &cp110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, cp110);
+	return NULL;
+}
+
+void dce110_compressor_destroy(struct compressor **compressor)
+{
+	dm_free((*compressor)->ctx, TO_DCE110_COMPRESSOR(*compressor));
+	*compressor = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h
new file mode 100644
index 000000000000..0beef2243d04
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h
@@ -0,0 +1,84 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_COMPRESSOR_DCE110_H__
+#define __DC_COMPRESSOR_DCE110_H__
+
+#include "../inc/compressor.h"
+
+#define TO_DCE110_COMPRESSOR(compressor)\
+	container_of(compressor, struct dce110_compressor, base)
+
+struct dce110_compressor_reg_offsets {
+	uint32_t dcp_offset;
+	uint32_t dmif_offset;
+};
+
+struct dce110_compressor {
+	struct compressor base;
+	struct dce110_compressor_reg_offsets offsets;
+};
+
+struct compressor *dce110_compressor_create(struct dc_context *ctx,
+	struct adapter_service *as);
+
+bool dce110_compressor_construct(struct dce110_compressor *cp110,
+	struct dc_context *ctx, struct adapter_service *as);
+
+void dce110_compressor_destroy(struct compressor **cp);
+
+/* FBC RELATED */
+void dce110_compressor_power_up_fbc(struct compressor *cp);
+
+void dce110_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num,
+	struct compr_addr_and_pitch_params *params);
+
+void dce110_compressor_disable_fbc(struct compressor *cp);
+
+void dce110_compressor_set_fbc_invalidation_triggers(struct compressor *cp,
+	uint32_t fbc_trigger);
+
+void dce110_compressor_program_compressed_surface_address_and_pitch(
+	struct compressor *cp,
+	struct compr_addr_and_pitch_params *params);
+
+bool dce110_compressor_get_required_compressed_surface_size(
+	struct compressor *cp,
+	struct fbc_input_info *input_info,
+	struct fbc_requested_compressed_size *size);
+
+bool dce110_compressor_is_fbc_enabled_in_hw(struct compressor *cp,
+	uint32_t *fbc_mapped_crtc_id);
+
+/* LPT RELATED */
+void dce110_compressor_enable_lpt(struct compressor *cp);
+
+void dce110_compressor_disable_lpt(struct compressor *cp);
+
+void dce110_compressor_program_lpt_control(struct compressor *cp,
+	struct compr_addr_and_pitch_params *params);
+
+bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *cp);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 18/29] drm/amd/dal: Add input pixel processing HW programming
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (16 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 17/29] drm/amd/dal: Add framebuffer compression " Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:19 ` [PATCH 19/29] drm/amd/dal: Add output " Harry Wentland
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Adds programming of cursor and input gamma.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c     |  65 ++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h     | 100 +++
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c  | 256 ++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c   | 872 +++++++++++++++++++++
 4 files changed, 1293 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
new file mode 100644
index 000000000000..6ab35272f979
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_ipp.h"
+
+static struct ipp_funcs funcs = {
+		.ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes,
+		.ipp_cursor_set_position = dce110_ipp_cursor_set_position,
+		.ipp_program_prescale = dce110_ipp_program_prescale,
+		.ipp_set_degamma = dce110_ipp_set_degamma,
+		.ipp_set_legacy_input_gamma_mode = dce110_ipp_set_legacy_input_gamma_mode,
+		.ipp_set_legacy_input_gamma_ramp = dce110_ipp_set_legacy_input_gamma_ramp,
+		.ipp_set_palette = dce110_ipp_set_palette,
+};
+
+bool dce110_ipp_construct(
+	struct dce110_ipp* ipp,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_ipp_reg_offsets *offset)
+{
+	ipp->base.ctx = ctx;
+
+	ipp->base.inst = inst;
+
+	ipp->offsets = *offset;
+
+	ipp->base.funcs = &funcs;
+
+	return true;
+}
+
+void dce110_ipp_destroy(struct input_pixel_processor **ipp)
+{
+	dm_free((*ipp)->ctx, TO_DCE110_IPP(*ipp));
+	*ipp = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
new file mode 100644
index 000000000000..709906face3f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_IPP_DCE110_H__
+#define __DC_IPP_DCE110_H__
+
+#include "inc/ipp.h"
+
+
+struct gamma_parameters;
+struct dev_c_lut;
+
+#define TO_DCE110_IPP(input_pixel_processor)\
+	container_of(input_pixel_processor, struct dce110_ipp, base)
+
+struct dce110_ipp_reg_offsets {
+	uint32_t dcp_offset;
+};
+
+struct dce110_ipp {
+	struct input_pixel_processor base;
+	struct dce110_ipp_reg_offsets offsets;
+	struct dev_c_lut saved_palette[RGB_256X3X16];
+};
+
+bool dce110_ipp_construct(
+	struct dce110_ipp* ipp,
+	struct dc_context *ctx,
+	enum controller_id id,
+	const struct dce110_ipp_reg_offsets *offset);
+
+void dce110_ipp_destroy(struct input_pixel_processor **ipp);
+
+/* CURSOR RELATED */
+bool dce110_ipp_cursor_set_position(
+	struct input_pixel_processor *ipp,
+	const struct dc_cursor_position *position);
+
+bool dce110_ipp_cursor_set_attributes(
+	struct input_pixel_processor *ipp,
+	const struct dc_cursor_attributes *attributes);
+
+/* DEGAMMA RELATED */
+bool dce110_ipp_set_degamma(
+	struct input_pixel_processor *ipp,
+	const struct gamma_parameters *params,
+	bool force_bypass);
+
+void dce110_ipp_program_prescale(
+	struct input_pixel_processor *ipp,
+	enum pixel_format pixel_format);
+
+void dce110_ipp_set_legacy_input_gamma_mode(
+		struct input_pixel_processor *ipp,
+		bool is_legacy);
+
+bool dce110_ipp_set_legacy_input_gamma_ramp(
+	struct input_pixel_processor *ipp,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params);
+
+bool dce110_ipp_set_palette(
+	struct input_pixel_processor *ipp,
+	const struct dev_c_lut *palette,
+	uint32_t start,
+	uint32_t length,
+	enum pixel_format surface_pixel_format);
+
+/*
+ * Helper functions to be resused in other ASICs
+ */
+void dce110_helper_select_lut(struct dce110_ipp *ipp110);
+
+void dce110_helper_program_black_white_offset(
+	struct dce110_ipp *ipp110,
+	enum pixel_format surface_pixel_format);
+
+#endif /*__DC_IPP_DCE110_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
new file mode 100644
index 000000000000..ef91f2db24e3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_ipp.h"
+
+#define CURSOR_COLOR_BLACK 0x00000000
+#define CURSOR_COLOR_WHITE 0xFFFFFFFF
+
+#define DCP_REG(reg)\
+	(reg + ipp110->offsets.dcp_offset)
+
+static void enable(
+	struct dce110_ipp *ipp110,
+	bool enable);
+
+static void lock(
+	struct dce110_ipp *ipp110,
+	bool enable);
+
+static void program_position(
+	struct dce110_ipp *ipp110,
+	uint32_t x,
+	uint32_t y);
+
+static bool program_control(
+	struct dce110_ipp *ipp110,
+	enum dc_cursor_color_format color_format,
+	bool enable_magnification,
+	bool inverse_transparent_clamping);
+
+static void program_hotspot(
+	struct dce110_ipp *ipp110,
+	uint32_t x,
+	uint32_t y);
+
+static void program_size(
+	struct dce110_ipp *ipp110,
+	uint32_t width,
+	uint32_t height);
+
+static void program_address(
+	struct dce110_ipp *ipp110,
+	PHYSICAL_ADDRESS_LOC address);
+
+
+bool dce110_ipp_cursor_set_position(
+	struct input_pixel_processor *ipp,
+	const struct dc_cursor_position *position)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	/* lock cursor registers */
+	lock(ipp110, true);
+
+	/* Flag passed in structure differentiates cursor enable/disable. */
+	/* Update if it differs from cached state. */
+	enable(ipp110, position->enable);
+
+	program_position(ipp110, position->x, position->y);
+
+	if (position->hot_spot_enable)
+		program_hotspot(
+				ipp110,
+				position->x_origin,
+				position->y_origin);
+
+	/* unlock cursor registers */
+	lock(ipp110, false);
+
+	return true;
+}
+
+bool dce110_ipp_cursor_set_attributes(
+	struct input_pixel_processor *ipp,
+	const struct dc_cursor_attributes *attributes)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+	/* Lock cursor registers */
+	lock(ipp110, true);
+
+	/* Program cursor control */
+	program_control(
+		ipp110,
+		attributes->color_format,
+		attributes->attribute_flags.bits.ENABLE_MAGNIFICATION,
+		attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING);
+
+	/* Program hot spot coordinates */
+	program_hotspot(ipp110, attributes->x_hot, attributes->y_hot);
+
+	/*
+	 * Program cursor size -- NOTE: HW spec specifies that HW register
+	 * stores size as (height - 1, width - 1)
+	 */
+	program_size(ipp110, attributes->width, attributes->height);
+
+	/* Program cursor surface address */
+	program_address(ipp110, attributes->address);
+
+	/* Unlock Cursor registers. */
+	lock(ipp110, false);
+
+	return true;
+}
+
+static void enable(
+	struct dce110_ipp *ipp110, bool enable)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_CONTROL);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, enable, CUR_CONTROL, CURSOR_EN);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static void lock(
+	struct dce110_ipp *ipp110, bool lock)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_UPDATE);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, lock, CUR_UPDATE, CURSOR_UPDATE_LOCK);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static void program_position(
+	struct dce110_ipp *ipp110,
+	uint32_t x,
+	uint32_t y)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_POSITION);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, x, CUR_POSITION, CURSOR_X_POSITION);
+	set_reg_field_value(value, y, CUR_POSITION, CURSOR_Y_POSITION);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static bool program_control(
+	struct dce110_ipp *ipp110,
+	enum dc_cursor_color_format color_format,
+	bool enable_magnification,
+	bool inverse_transparent_clamping)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_CONTROL);
+	uint32_t mode = 0;
+
+	switch (color_format) {
+	case CURSOR_MODE_MONO:
+		mode = 0;
+		break;
+	case CURSOR_MODE_COLOR_1BIT_AND:
+		mode = 1;
+		break;
+	case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
+		mode = 2;
+		break;
+	case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
+		mode = 3;
+		break;
+	default:
+		return false;
+	}
+
+	set_reg_field_value(value, mode, CUR_CONTROL, CURSOR_MODE);
+	set_reg_field_value(value, enable_magnification,
+			CUR_CONTROL, CURSOR_2X_MAGNIFY);
+	set_reg_field_value(value, inverse_transparent_clamping,
+			CUR_CONTROL, CUR_INV_TRANS_CLAMP);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+
+	if (color_format == CURSOR_MODE_MONO) {
+		addr = DCP_REG(mmCUR_COLOR1);
+		dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_BLACK);
+		addr = DCP_REG(mmCUR_COLOR2);
+		dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_WHITE);
+	}
+	return true;
+}
+
+static void program_hotspot(
+	struct dce110_ipp *ipp110,
+	uint32_t x,
+	uint32_t y)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_HOT_SPOT);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, x, CUR_HOT_SPOT, CURSOR_HOT_SPOT_X);
+	set_reg_field_value(value, y, CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static void program_size(
+	struct dce110_ipp *ipp110,
+	uint32_t width,
+	uint32_t height)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_SIZE);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, width, CUR_SIZE, CURSOR_WIDTH);
+	set_reg_field_value(value, height, CUR_SIZE, CURSOR_HEIGHT);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static void program_address(
+	struct dce110_ipp *ipp110,
+	PHYSICAL_ADDRESS_LOC address)
+{
+	uint32_t addr = DCP_REG(mmCUR_SURFACE_ADDRESS_HIGH);
+	/* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor
+	 * surface base address in byte. It is 4K byte aligned.
+	 * The correct way to program cursor surface address is to first write
+	 * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS */
+
+	dm_write_reg(ipp110->base.ctx, addr, address.high_part);
+
+	addr = DCP_REG(mmCUR_SURFACE_ADDRESS);
+	dm_write_reg(ipp110->base.ctx, addr, address.low_part);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c
new file mode 100644
index 000000000000..fcf65f119af4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c
@@ -0,0 +1,872 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+#include "include/fixed31_32.h"
+#include "basics/conversion.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_ipp.h"
+#include "gamma_types.h"
+
+#define DCP_REG(reg)\
+	(reg + ipp110->offsets.dcp_offset)
+
+enum {
+	MAX_INPUT_LUT_ENTRY = 256
+};
+
+/* CALCULATION OPERATIONS*/
+static void convert_256_lut_entries_to_gxo_format(
+	const struct gamma_ramp_rgb256x3x16 *lut,
+	struct dev_c_lut16 *gamma)
+{
+	uint32_t i = 0;
+
+	ASSERT(lut);
+	ASSERT(gamma);
+
+	do {
+		gamma->red = lut->red[i];
+		gamma->green = lut->green[i];
+		gamma->blue = lut->blue[i];
+
+		++gamma;
+		++i;
+	} while (i != MAX_INPUT_LUT_ENTRY);
+}
+
+static void convert_udx_gamma_entries_to_gxo_format(
+	const struct gamma_ramp_dxgi_1 *lut,
+	struct dev_c_lut16 *gamma)
+{
+	/* TODO here we deal with DXGI gamma table,
+	 * originally, values was expressed as 'float',
+	 * now values expressed as 'dal_fixed20_12'. */
+}
+
+/*PROTOTYPE DECLARATIONS*/
+static void set_lut_inc(
+	struct dce110_ipp *ipp110,
+	uint8_t inc,
+	bool is_float,
+	bool is_signed);
+
+static void program_black_offsets(
+	struct dce110_ipp *ipp110,
+	struct dev_c_lut16 *offset);
+
+static void program_white_offsets(
+	struct dce110_ipp *ipp110,
+	struct dev_c_lut16 *offset);
+
+static void program_lut_gamma(
+	struct dce110_ipp *ipp110,
+	const struct dev_c_lut16 *gamma,
+	const struct gamma_parameters *params);
+
+static void program_prescale(
+	struct dce110_ipp *ipp110,
+	enum pixel_format pixel_format);
+
+static void set_legacy_input_gamma_mode(
+	struct dce110_ipp *ipp110,
+	bool is_legacy);
+
+static bool set_legacy_input_gamma_ramp_rgb256x3x16(
+	struct dce110_ipp *ipp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params);
+
+static bool set_legacy_input_gamma_ramp_dxgi1(
+	struct dce110_ipp *ipp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params);
+
+static bool set_default_gamma(
+	struct dce110_ipp *ipp110,
+	enum pixel_format surface_pixel_format);
+
+static void set_degamma(
+	struct dce110_ipp *ipp110,
+	const struct gamma_parameters *params,
+	bool force_bypass);
+
+bool dce110_ipp_set_legacy_input_gamma_ramp(
+	struct input_pixel_processor *ipp,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	switch (gamma_ramp->type) {
+	case GAMMA_RAMP_RBG256X3X16:
+		return set_legacy_input_gamma_ramp_rgb256x3x16(
+				ipp110, gamma_ramp, params);
+	case GAMMA_RAMP_DXGI_1:
+		return set_legacy_input_gamma_ramp_dxgi1(
+				ipp110, gamma_ramp, params);
+	default:
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+}
+
+bool dce110_ipp_set_palette(
+	struct input_pixel_processor *ipp,
+	const struct dev_c_lut *palette,
+	uint32_t start,
+	uint32_t length,
+	enum pixel_format surface_pixel_format)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+	uint32_t i;
+
+	if (((start + length) > MAX_INPUT_LUT_ENTRY) || (NULL == palette)) {
+		BREAK_TO_DEBUGGER();
+		/* wrong input */
+		return false;
+	}
+
+	for (i = start; i < start + length; i++) {
+		ipp110->saved_palette[i] = palette[i];
+		ipp110->saved_palette[i] = palette[i];
+		ipp110->saved_palette[i] = palette[i];
+	}
+
+	return set_default_gamma(ipp110, surface_pixel_format);
+}
+
+bool dce110_ipp_set_degamma(
+	struct input_pixel_processor *ipp,
+	const struct gamma_parameters *params,
+	bool force_bypass)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	set_degamma(ipp110, params, force_bypass);
+
+	return true;
+}
+
+void dce110_ipp_program_prescale(
+	struct input_pixel_processor *ipp,
+	enum pixel_format pixel_format)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	program_prescale(ipp110, pixel_format);
+}
+
+void dce110_ipp_set_legacy_input_gamma_mode(
+		struct input_pixel_processor *ipp,
+		bool is_legacy)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	set_legacy_input_gamma_mode(ipp110, is_legacy);
+}
+
+static void set_lut_inc(
+	struct dce110_ipp *ipp110,
+	uint8_t inc,
+	bool is_float,
+	bool is_signed)
+{
+	const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL);
+
+	uint32_t value = dm_read_reg(ipp110->base.ctx, addr);
+
+	set_reg_field_value(
+		value,
+		inc,
+		DC_LUT_CONTROL,
+		DC_LUT_INC_R);
+
+	set_reg_field_value(
+		value,
+		inc,
+		DC_LUT_CONTROL,
+		DC_LUT_INC_G);
+
+	set_reg_field_value(
+		value,
+		inc,
+		DC_LUT_CONTROL,
+		DC_LUT_INC_B);
+
+	set_reg_field_value(
+		value,
+		is_float,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_R_FLOAT_POINT_EN);
+
+	set_reg_field_value(
+		value,
+		is_float,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_G_FLOAT_POINT_EN);
+
+	set_reg_field_value(
+		value,
+		is_float,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_B_FLOAT_POINT_EN);
+
+	set_reg_field_value(
+		value,
+		is_signed,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_R_SIGNED_EN);
+
+	set_reg_field_value(
+		value,
+		is_signed,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_G_SIGNED_EN);
+
+	set_reg_field_value(
+		value,
+		is_signed,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_B_SIGNED_EN);
+
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+void dce110_helper_select_lut(struct dce110_ipp *ipp110)
+{
+	uint32_t value = 0;
+
+	set_lut_inc(ipp110, 0, false, false);
+
+	{
+		const uint32_t addr = DCP_REG(mmDC_LUT_WRITE_EN_MASK);
+
+		value = dm_read_reg(ipp110->base.ctx, addr);
+
+		/* enable all */
+		set_reg_field_value(
+			value,
+			0x7,
+			DC_LUT_WRITE_EN_MASK,
+			DC_LUT_WRITE_EN_MASK);
+
+		dm_write_reg(ipp110->base.ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = DCP_REG(mmDC_LUT_RW_MODE);
+
+		value = dm_read_reg(ipp110->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_LUT_RW_MODE,
+			DC_LUT_RW_MODE);
+
+		dm_write_reg(ipp110->base.ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL);
+
+		value = dm_read_reg(ipp110->base.ctx, addr);
+
+		/* 00 - new u0.12 */
+		set_reg_field_value(
+			value,
+			3,
+			DC_LUT_CONTROL,
+			DC_LUT_DATA_R_FORMAT);
+
+		set_reg_field_value(
+			value,
+			3,
+			DC_LUT_CONTROL,
+			DC_LUT_DATA_G_FORMAT);
+
+		set_reg_field_value(
+			value,
+			3,
+			DC_LUT_CONTROL,
+			DC_LUT_DATA_B_FORMAT);
+
+		dm_write_reg(ipp110->base.ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = DCP_REG(mmDC_LUT_RW_INDEX);
+
+		value = dm_read_reg(ipp110->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_LUT_RW_INDEX,
+			DC_LUT_RW_INDEX);
+
+		dm_write_reg(ipp110->base.ctx, addr, value);
+	}
+}
+
+static void program_black_offsets(
+	struct dce110_ipp *ipp110,
+	struct dev_c_lut16 *offset)
+{
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_BLACK_OFFSET_RED),
+		offset->red);
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_BLACK_OFFSET_GREEN),
+		offset->green);
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_BLACK_OFFSET_BLUE),
+		offset->blue);
+}
+
+static void program_white_offsets(
+	struct dce110_ipp *ipp110,
+	struct dev_c_lut16 *offset)
+{
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_WHITE_OFFSET_RED),
+		offset->red);
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_WHITE_OFFSET_GREEN),
+		offset->green);
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_WHITE_OFFSET_BLUE),
+		offset->blue);
+}
+
+void dce110_helper_program_black_white_offset(
+	struct dce110_ipp *ipp110,
+	enum pixel_format surface_pixel_format)
+{
+	struct dev_c_lut16 black_offset;
+	struct dev_c_lut16 white_offset;
+
+	/* get black offset */
+
+	switch (surface_pixel_format) {
+	case PIXEL_FORMAT_FP16:
+		/* sRGB gamut, [0.0...1.0] */
+		black_offset.red = 0;
+		black_offset.green = 0;
+		black_offset.blue = 0;
+	break;
+
+	case PIXEL_FORMAT_ARGB2101010_XRBIAS:
+		/* [-1.0...3.0] */
+		black_offset.red = 0x100;
+		black_offset.green = 0x100;
+		black_offset.blue = 0x100;
+	break;
+
+	default:
+		black_offset.red = 0;
+		black_offset.green = 0;
+		black_offset.blue = 0;
+	}
+
+	/* get white offset */
+
+	switch (surface_pixel_format) {
+	case PIXEL_FORMAT_FP16:
+		white_offset.red = 0x3BFF;
+		white_offset.green = 0x3BFF;
+		white_offset.blue = 0x3BFF;
+	break;
+
+	case PIXEL_FORMAT_ARGB2101010_XRBIAS:
+		white_offset.red = 0x37E;
+		white_offset.green = 0x37E;
+		white_offset.blue = 0x37E;
+		break;
+
+	case PIXEL_FORMAT_ARGB8888:
+		white_offset.red = 0xFF;
+		white_offset.green = 0xFF;
+		white_offset.blue = 0xFF;
+		break;
+
+	default:
+		white_offset.red = 0x3FF;
+		white_offset.green = 0x3FF;
+		white_offset.blue = 0x3FF;
+	}
+
+	program_black_offsets(ipp110, &black_offset);
+	program_white_offsets(ipp110, &white_offset);
+}
+
+static void program_lut_gamma(
+	struct dce110_ipp *ipp110,
+	const struct dev_c_lut16 *gamma,
+	const struct gamma_parameters *params)
+{
+	uint32_t i = 0;
+	uint32_t value = 0;
+	uint32_t addr;
+
+	{
+		uint8_t max_tries = 10;
+		uint8_t counter = 0;
+
+		/* Power on LUT memory */
+		value = dm_read_reg(
+				ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL));
+
+		set_reg_field_value(
+			value,
+			1,
+			DCFE_MEM_PWR_CTRL,
+			DCP_REGAMMA_MEM_PWR_DIS);
+
+		dm_write_reg(
+			ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value);
+
+		while (counter < max_tries) {
+			value =
+				dm_read_reg(
+					ipp110->base.ctx,
+					DCP_REG(mmDCFE_MEM_PWR_STATUS));
+
+			if (get_reg_field_value(
+				value,
+				DCFE_MEM_PWR_STATUS,
+				DCP_REGAMMA_MEM_PWR_STATE) == 0)
+				break;
+
+			++counter;
+		}
+
+		if (counter == max_tries) {
+			dal_logger_write(ipp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: regamma lut was not powered on in a timely manner, programming still proceeds\n",
+				__func__);
+		}
+	}
+
+	dce110_helper_program_black_white_offset(ipp110, params->surface_pixel_format);
+
+	dce110_helper_select_lut(ipp110);
+
+	if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8) {
+		addr = DCP_REG(mmDC_LUT_SEQ_COLOR);
+
+		do {
+			struct dev_c_lut *index =
+				ipp110->saved_palette + i;
+
+			set_reg_field_value(
+				value,
+				gamma[index->red].red,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+
+			set_reg_field_value(
+				value,
+				gamma[index->green].green,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+
+			set_reg_field_value(
+				value,
+				gamma[index->blue].blue,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+			++i;
+		} while (i != RGB_256X3X16);
+	} else {
+		addr = DCP_REG(mmDC_LUT_SEQ_COLOR);
+
+		do {
+			set_reg_field_value(
+				value,
+				gamma[i].red,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+
+			set_reg_field_value(
+				value,
+				gamma[i].green,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+
+			set_reg_field_value(
+				value,
+				gamma[i].blue,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+			++i;
+		} while (i != RGB_256X3X16);
+	}
+
+	/*  we are done with DCP LUT memory; re-enable low power mode */
+	value = dm_read_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL));
+
+	set_reg_field_value(
+		value,
+		0,
+		DCFE_MEM_PWR_CTRL,
+		DCP_REGAMMA_MEM_PWR_DIS);
+
+	dm_write_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value);
+}
+
+static void program_prescale(
+	struct dce110_ipp *ipp110,
+	enum pixel_format pixel_format)
+{
+	uint32_t prescale_control;
+	uint32_t prescale_values_grph_r = 0;
+	uint32_t prescale_values_grph_g = 0;
+	uint32_t prescale_values_grph_b = 0;
+
+	uint32_t prescale_num;
+	uint32_t prescale_denom = 1;
+	uint16_t prescale_hw;
+	uint32_t bias_num = 0;
+	uint32_t bias_denom = 1;
+	uint16_t bias_hw;
+
+	const uint32_t addr_control = DCP_REG(mmPRESCALE_GRPH_CONTROL);
+
+	prescale_control = dm_read_reg(ipp110->base.ctx, addr_control);
+
+	set_reg_field_value(
+		prescale_control,
+		0,
+		PRESCALE_GRPH_CONTROL,
+		GRPH_PRESCALE_BYPASS);
+
+	switch (pixel_format) {
+	case PIXEL_FORMAT_RGB565:
+		prescale_num = 64;
+		prescale_denom = 63;
+	break;
+
+	case PIXEL_FORMAT_ARGB8888:
+		/* This function should only be called when using regamma
+		 * and bypassing legacy INPUT GAMMA LUT (function name is
+		 * misleading)
+		 */
+		prescale_num = 256;
+		prescale_denom = 255;
+	break;
+
+	case PIXEL_FORMAT_ARGB2101010:
+		prescale_num = 1024;
+		prescale_denom = 1023;
+	break;
+
+	case PIXEL_FORMAT_ARGB2101010_XRBIAS:
+		prescale_num = 1024;
+		prescale_denom = 510;
+		bias_num = 384;
+		bias_denom = 1024;
+	break;
+
+	case PIXEL_FORMAT_FP16:
+		prescale_num = 1;
+	break;
+
+	default:
+		prescale_num = 1;
+
+		set_reg_field_value(
+			prescale_control,
+			1,
+			PRESCALE_GRPH_CONTROL,
+			GRPH_PRESCALE_BYPASS);
+	}
+
+	prescale_hw = fixed_point_to_int_frac(
+		dal_fixed31_32_from_fraction(prescale_num, prescale_denom),
+		2, 13);
+
+	bias_hw = fixed_point_to_int_frac(
+		dal_fixed31_32_from_fraction(bias_num, bias_denom),
+		2, 13);
+
+
+	set_reg_field_value(
+		prescale_values_grph_r,
+		prescale_hw,
+		PRESCALE_VALUES_GRPH_R,
+		GRPH_PRESCALE_SCALE_R);
+
+	set_reg_field_value(
+		prescale_values_grph_r,
+		bias_hw,
+		PRESCALE_VALUES_GRPH_R,
+		GRPH_PRESCALE_BIAS_R);
+
+
+	set_reg_field_value(
+		prescale_values_grph_g,
+		prescale_hw,
+		PRESCALE_VALUES_GRPH_G,
+		GRPH_PRESCALE_SCALE_G);
+
+	set_reg_field_value(
+		prescale_values_grph_g,
+		bias_hw,
+		PRESCALE_VALUES_GRPH_G,
+		GRPH_PRESCALE_BIAS_G);
+
+
+	set_reg_field_value(
+		prescale_values_grph_b,
+		prescale_hw,
+		PRESCALE_VALUES_GRPH_B,
+		GRPH_PRESCALE_SCALE_B);
+
+	set_reg_field_value(
+		prescale_values_grph_b,
+		bias_hw,
+		PRESCALE_VALUES_GRPH_B,
+		GRPH_PRESCALE_BIAS_B);
+
+	dm_write_reg(ipp110->base.ctx,
+		addr_control, prescale_control);
+
+	{
+		dm_write_reg(ipp110->base.ctx,
+				DCP_REG(mmPRESCALE_VALUES_GRPH_R),
+				prescale_values_grph_r);
+	}
+
+	{
+		dm_write_reg(ipp110->base.ctx,
+				DCP_REG(mmPRESCALE_VALUES_GRPH_G),
+				prescale_values_grph_g);
+	}
+
+	{
+		dm_write_reg(ipp110->base.ctx,
+				DCP_REG(mmPRESCALE_VALUES_GRPH_B),
+				prescale_values_grph_b);
+	}
+}
+
+static void set_legacy_input_gamma_mode(
+	struct dce110_ipp *ipp110,
+	bool is_legacy)
+{
+	const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL);
+	uint32_t value = dm_read_reg(ipp110->base.ctx, addr);
+
+	set_reg_field_value(
+		value,
+		!is_legacy,
+		INPUT_GAMMA_CONTROL,
+		GRPH_INPUT_GAMMA_MODE);
+
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static bool set_legacy_input_gamma_ramp_rgb256x3x16(
+	struct dce110_ipp *ipp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct dev_c_lut16 *gamma16 =
+		dm_alloc(
+			ipp110->base.ctx,
+			sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY);
+
+	if (!gamma16)
+		return false;
+
+	convert_256_lut_entries_to_gxo_format(
+		&gamma_ramp->gamma_ramp_rgb256x3x16, gamma16);
+
+	if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) &&
+		(params->surface_pixel_format !=
+			PIXEL_FORMAT_ARGB2101010_XRBIAS) &&
+		(params->surface_pixel_format != PIXEL_FORMAT_FP16)) {
+		program_lut_gamma(ipp110, gamma16, params);
+		dm_free(ipp110->base.ctx, gamma16);
+		return true;
+	}
+
+	/* TODO process DirectX-specific formats*/
+	dm_free(ipp110->base.ctx, gamma16);
+	return false;
+}
+
+static bool set_legacy_input_gamma_ramp_dxgi1(
+	struct dce110_ipp *ipp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct dev_c_lut16 *gamma16 =
+		dm_alloc(
+			ipp110->base.ctx,
+			sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY);
+
+	if (!gamma16)
+		return false;
+
+	convert_udx_gamma_entries_to_gxo_format(
+		&gamma_ramp->gamma_ramp_dxgi1, gamma16);
+
+	if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) &&
+		(params->surface_pixel_format !=
+			PIXEL_FORMAT_ARGB2101010_XRBIAS) &&
+		(params->surface_pixel_format != PIXEL_FORMAT_FP16)) {
+		program_lut_gamma(ipp110, gamma16, params);
+		dm_free(ipp110->base.ctx, gamma16);
+		return true;
+	}
+
+	/* TODO process DirectX-specific formats*/
+	dm_free(ipp110->base.ctx, gamma16);
+	return false;
+}
+
+static bool set_default_gamma(
+	struct dce110_ipp *ipp110,
+	enum pixel_format surface_pixel_format)
+{
+	uint32_t i;
+
+	struct dev_c_lut16 *gamma16 = NULL;
+	struct gamma_parameters *params = NULL;
+
+	gamma16 = dm_alloc(
+			ipp110->base.ctx,
+			sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY);
+
+	if (!gamma16)
+		return false;
+
+	params = dm_alloc(ipp110->base.ctx, sizeof(*params));
+
+	if (!params) {
+		dm_free(ipp110->base.ctx, gamma16);
+		return false;
+	}
+
+	for (i = 0; i < MAX_INPUT_LUT_ENTRY; i++) {
+		gamma16[i].red = gamma16[i].green =
+			gamma16[i].blue = (uint16_t) (i << 8);
+	}
+
+	params->surface_pixel_format = surface_pixel_format;
+	params->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_HW;
+	params->degamma_adjust_type = GRAPHICS_DEGAMMA_ADJUST_HW;
+	params->selected_gamma_lut = GRAPHICS_GAMMA_LUT_REGAMMA;
+	params->disable_adjustments = false;
+
+	params->regamma.features.value = 0;
+
+	params->regamma.features.bits.GAMMA_RAMP_ARRAY = 0;
+	params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 1;
+	params->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 1;
+
+	for (i = 0; i < 3; i++) {
+		params->regamma.gamma_coeff.a0[i] = 31308;
+		params->regamma.gamma_coeff.a1[i] = 12920;
+		params->regamma.gamma_coeff.a2[i] = 55;
+		params->regamma.gamma_coeff.a3[i] = 55;
+		params->regamma.gamma_coeff.gamma[i] = 2400;
+
+	}
+
+	program_lut_gamma(ipp110, gamma16, params);
+
+	dm_free(ipp110->base.ctx, gamma16);
+	dm_free(ipp110->base.ctx, params);
+
+	return true;
+}
+
+static void set_degamma(
+	struct dce110_ipp *ipp110,
+	const struct gamma_parameters *params,
+	bool force_bypass)
+{
+	uint32_t value;
+	const uint32_t addr = DCP_REG(mmDEGAMMA_CONTROL);
+	uint32_t degamma_type =
+		params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB == 1 ?
+			1 : 2;
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+
+	/* if by pass - no degamma
+	 * when legacy and regamma LUT's we do degamma */
+	if (params->degamma_adjust_type == GRAPHICS_DEGAMMA_ADJUST_BYPASS ||
+		(params->surface_pixel_format == PIXEL_FORMAT_FP16 &&
+			params->selected_gamma_lut ==
+				GRAPHICS_GAMMA_LUT_REGAMMA))
+		degamma_type = 0;
+
+	if (force_bypass)
+		degamma_type = 0;
+
+	set_reg_field_value(
+		value,
+		degamma_type,
+		DEGAMMA_CONTROL,
+		GRPH_DEGAMMA_MODE);
+
+	set_reg_field_value(
+		value,
+		degamma_type,
+		DEGAMMA_CONTROL,
+		CURSOR_DEGAMMA_MODE);
+
+	set_reg_field_value(
+		value,
+		degamma_type,
+		DEGAMMA_CONTROL,
+		CURSOR2_DEGAMMA_MODE);
+
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 19/29] drm/amd/dal: Add output pixel processing HW programming
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (17 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 18/29] drm/amd/dal: Add input pixel processing " Harry Wentland
@ 2016-02-11 17:19 ` Harry Wentland
  2016-02-11 17:20 ` [PATCH 20/29] drm/amd/dal: Add transform & scaler " Harry Wentland
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:19 UTC (permalink / raw)
  To: dri-devel

Adds programming for color space conversion (CSC),
regamma, and formatter.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c     |  272 +++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h     |  143 ++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c |  904 +++++++
 .../drm/amd/dal/dc/dce110/dce110_opp_formatter.c   |  610 +++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2474 ++++++++++++++++++++
 5 files changed, 4403 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
new file mode 100644
index 000000000000..acb405e7b2e7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_opp.h"
+
+#include "gamma_types.h"
+
+enum {
+	MAX_LUT_ENTRY = 256,
+	MAX_NUMBER_OF_ENTRIES = 256
+};
+
+static void build_evenly_distributed_points(
+	struct gamma_pixel *points,
+	uint32_t numberof_points,
+	struct fixed31_32 max_value,
+	struct fixed31_32 divider1,
+	struct fixed31_32 divider2,
+	struct fixed31_32 divider3)
+{
+	struct gamma_pixel *p = points;
+	struct gamma_pixel *p_last = p + numberof_points - 1;
+
+	uint32_t i = 0;
+
+	do {
+		struct fixed31_32 value = dal_fixed31_32_div_int(
+			dal_fixed31_32_mul_int(max_value, i),
+			numberof_points - 1);
+
+		p->r = value;
+		p->g = value;
+		p->b = value;
+
+		++p;
+		++i;
+	} while (i != numberof_points);
+
+	p->r = dal_fixed31_32_div(p_last->r, divider1);
+	p->g = dal_fixed31_32_div(p_last->g, divider1);
+	p->b = dal_fixed31_32_div(p_last->b, divider1);
+
+	++p;
+
+	p->r = dal_fixed31_32_div(p_last->r, divider2);
+	p->g = dal_fixed31_32_div(p_last->g, divider2);
+	p->b = dal_fixed31_32_div(p_last->b, divider2);
+
+	++p;
+
+	p->r = dal_fixed31_32_div(p_last->r, divider3);
+	p->g = dal_fixed31_32_div(p_last->g, divider3);
+	p->b = dal_fixed31_32_div(p_last->b, divider3);
+}
+
+/*****************************************/
+/* Constructor, Destructor               */
+/*****************************************/
+
+struct opp_funcs funcs = {
+		.opp_map_legacy_and_regamma_hw_to_x_user = dce110_opp_map_legacy_and_regamma_hw_to_x_user,
+		.opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
+		.opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction,
+		.opp_program_clamping_and_pixel_encoding = dce110_opp_program_clamping_and_pixel_encoding,
+		.opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
+		.opp_set_csc_default = dce110_opp_set_csc_default,
+		.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
+		.opp_set_regamma = dce110_opp_set_regamma
+};
+
+bool dce110_opp_construct(struct dce110_opp *opp110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offsets)
+{
+
+	opp110->base.funcs = &funcs;
+
+	opp110->base.ctx = ctx;
+
+	opp110->base.inst = inst;
+
+	opp110->offsets = *offsets;
+
+	opp110->regamma.hw_points_num = 128;
+	opp110->regamma.coordinates_x = NULL;
+	opp110->regamma.rgb_resulted = NULL;
+	opp110->regamma.rgb_regamma = NULL;
+	opp110->regamma.coeff128 = NULL;
+	opp110->regamma.coeff128_oem = NULL;
+	opp110->regamma.coeff128_dx = NULL;
+	opp110->regamma.axis_x_256 = NULL;
+	opp110->regamma.axis_x_1025 = NULL;
+	opp110->regamma.rgb_oem = NULL;
+	opp110->regamma.rgb_user = NULL;
+	opp110->regamma.extra_points = 3;
+	opp110->regamma.use_half_points = false;
+	opp110->regamma.x_max1 = dal_fixed31_32_one;
+	opp110->regamma.x_max2 = dal_fixed31_32_from_int(2);
+	opp110->regamma.x_min = dal_fixed31_32_zero;
+	opp110->regamma.divider1 = dal_fixed31_32_from_fraction(3, 2);
+	opp110->regamma.divider2 = dal_fixed31_32_from_int(2);
+	opp110->regamma.divider3 = dal_fixed31_32_from_fraction(5, 2);
+
+	opp110->regamma.rgb_user = dm_alloc(
+		ctx,
+		sizeof(struct pwl_float_data) *
+		(DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points));
+	if (!opp110->regamma.rgb_user)
+		goto failure_1;
+
+	opp110->regamma.rgb_oem = dm_alloc(
+		ctx,
+		sizeof(struct pwl_float_data) *
+		(DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points));
+	if (!opp110->regamma.rgb_oem)
+		goto failure_2;
+
+	opp110->regamma.rgb_resulted = dm_alloc(
+		ctx,
+		sizeof(struct pwl_result_data) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.rgb_resulted)
+		goto failure_3;
+
+	opp110->regamma.rgb_regamma = dm_alloc(
+		ctx,
+		sizeof(struct pwl_float_data_ex) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.rgb_regamma)
+		goto failure_4;
+
+	opp110->regamma.coordinates_x = dm_alloc(
+		ctx,
+		sizeof(struct hw_x_point) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.coordinates_x)
+		goto failure_5;
+
+	opp110->regamma.axis_x_256 = dm_alloc(
+		ctx,
+		sizeof(struct gamma_pixel) *
+		(MAX_LUT_ENTRY + opp110->regamma.extra_points));
+	if (!opp110->regamma.axis_x_256)
+		goto failure_6;
+
+	opp110->regamma.axis_x_1025 = dm_alloc(
+		ctx,
+		sizeof(struct gamma_pixel) *
+		(DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points));
+	if (!opp110->regamma.axis_x_1025)
+		goto failure_7;
+
+	opp110->regamma.coeff128 = dm_alloc(
+		ctx,
+		sizeof(struct pixel_gamma_point) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.coeff128)
+		goto failure_8;
+
+	opp110->regamma.coeff128_oem = dm_alloc(
+		ctx,
+		sizeof(struct pixel_gamma_point) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.coeff128_oem)
+		goto failure_9;
+
+	opp110->regamma.coeff128_dx = dm_alloc(
+		ctx,
+		sizeof(struct pixel_gamma_point) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.coeff128_dx)
+		goto failure_10;
+
+	/* init palette */
+	{
+		uint32_t i = 0;
+
+		do {
+			opp110->regamma.saved_palette[i].red = (uint8_t)i;
+			opp110->regamma.saved_palette[i].green = (uint8_t)i;
+			opp110->regamma.saved_palette[i].blue = (uint8_t)i;
+
+			++i;
+		} while (i != MAX_LUT_ENTRY);
+	}
+
+	build_evenly_distributed_points(
+		opp110->regamma.axis_x_256,
+		MAX_LUT_ENTRY,
+		opp110->regamma.x_max1,
+		opp110->regamma.divider1,
+		opp110->regamma.divider2,
+		opp110->regamma.divider3);
+
+	build_evenly_distributed_points(
+		opp110->regamma.axis_x_1025,
+		DX_GAMMA_RAMP_MAX,
+		opp110->regamma.x_max1,
+		opp110->regamma.divider1,
+		opp110->regamma.divider2,
+		opp110->regamma.divider3);
+
+	return true;
+
+failure_10:
+	dm_free(ctx, opp110->regamma.coeff128_oem);
+failure_9:
+	dm_free(ctx, opp110->regamma.coeff128);
+failure_8:
+	dm_free(ctx, opp110->regamma.axis_x_1025);
+failure_7:
+	dm_free(ctx, opp110->regamma.axis_x_256);
+failure_6:
+	dm_free(ctx, opp110->regamma.coordinates_x);
+failure_5:
+	dm_free(ctx, opp110->regamma.rgb_regamma);
+failure_4:
+	dm_free(ctx, opp110->regamma.rgb_resulted);
+failure_3:
+	dm_free(ctx, opp110->regamma.rgb_oem);
+failure_2:
+	dm_free(ctx, opp110->regamma.rgb_user);
+failure_1:
+
+	return true;
+}
+
+void dce110_opp_destroy(struct output_pixel_processor **opp)
+{
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_dx);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_oem);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_1025);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_256);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coordinates_x);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_regamma);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_resulted);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_oem);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_user);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp));
+	*opp = NULL;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
new file mode 100644
index 000000000000..e53eb7413948
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
@@ -0,0 +1,143 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_OPP_DCE110_H__
+#define __DC_OPP_DCE110_H__
+
+#include "dc_types.h"
+#include "inc/opp.h"
+#include "gamma_types.h"
+
+struct gamma_parameters;
+
+#define FROM_DCE11_OPP(opp)\
+	container_of(opp, struct dce110_opp, base)
+
+enum dce110_opp_reg_type {
+	DCE110_OPP_REG_DCP = 0,
+	DCE110_OPP_REG_DCFE,
+	DCE110_OPP_REG_FMT,
+
+	DCE110_OPP_REG_MAX
+};
+
+struct dce110_regamma {
+	struct gamma_curve arr_curve_points[16];
+	struct curve_points arr_points[3];
+	uint32_t hw_points_num;
+	struct hw_x_point *coordinates_x;
+	struct pwl_result_data *rgb_resulted;
+
+	/* re-gamma curve */
+	struct pwl_float_data_ex *rgb_regamma;
+	/* coeff used to map user evenly distributed points
+	 * to our hardware points (predefined) for gamma 256 */
+	struct pixel_gamma_point *coeff128;
+	struct pixel_gamma_point *coeff128_oem;
+	/* coeff used to map user evenly distributed points
+	 * to our hardware points (predefined) for gamma 1025 */
+	struct pixel_gamma_point *coeff128_dx;
+	/* evenly distributed points, gamma 256 software points 0-255 */
+	struct gamma_pixel *axis_x_256;
+	/* evenly distributed points, gamma 1025 software points 0-1025 */
+	struct gamma_pixel *axis_x_1025;
+	/* OEM supplied gamma for regamma LUT */
+	struct pwl_float_data *rgb_oem;
+	/* user supplied gamma */
+	struct pwl_float_data *rgb_user;
+	struct dev_c_lut saved_palette[RGB_256X3X16];
+	uint32_t extra_points;
+	bool use_half_points;
+	struct fixed31_32 x_max1;
+	struct fixed31_32 x_max2;
+	struct fixed31_32 x_min;
+	struct fixed31_32 divider1;
+	struct fixed31_32 divider2;
+	struct fixed31_32 divider3;
+};
+
+/* OPP RELATED */
+#define TO_DCE110_OPP(opp)\
+	container_of(opp, struct dce110_opp, base)
+
+struct dce110_opp_reg_offsets {
+	uint32_t fmt_offset;
+	uint32_t dcp_offset;
+	uint32_t dcfe_offset;
+};
+
+struct dce110_opp {
+	struct output_pixel_processor base;
+	struct dce110_opp_reg_offsets offsets;
+	struct dce110_regamma regamma;
+};
+
+bool dce110_opp_construct(struct dce110_opp *opp110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offsets);
+
+void dce110_opp_destroy(struct output_pixel_processor **opp);
+
+/* REGAMMA RELATED */
+void dce110_opp_power_on_regamma_lut(
+	struct output_pixel_processor *opp,
+	bool power_on);
+
+bool dce110_opp_set_regamma(
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *ramp,
+	const struct gamma_parameters *params,
+	bool force_bypass);
+
+bool dce110_opp_map_legacy_and_regamma_hw_to_x_user(
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params);
+
+void dce110_opp_set_csc_adjustment(
+	struct output_pixel_processor *opp,
+	const struct grph_csc_adjustment *adjust);
+
+void dce110_opp_set_csc_default(
+	struct output_pixel_processor *opp,
+	const struct default_adjustment *default_adjust);
+
+/* FORMATTER RELATED */
+void dce110_opp_program_bit_depth_reduction(
+	struct output_pixel_processor *opp,
+	const struct bit_depth_reduction_params *params);
+
+void dce110_opp_program_clamping_and_pixel_encoding(
+	struct output_pixel_processor *opp,
+	const struct clamping_and_pixel_encoding_params *params);
+
+
+void dce110_opp_set_dyn_expansion(
+	struct output_pixel_processor *opp,
+	enum color_space color_sp,
+	enum dc_color_depth color_dpth,
+	enum signal_type signal);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
new file mode 100644
index 000000000000..8f651e9329bc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
@@ -0,0 +1,904 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dce110_opp.h"
+#include "basics/conversion.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#define DCP_REG(reg)\
+	(reg + opp110->offsets.dcp_offset)
+
+enum {
+	OUTPUT_CSC_MATRIX_SIZE = 12
+};
+
+struct out_csc_color_matrix {
+	enum color_space color_space;
+	uint16_t regval[OUTPUT_CSC_MATRIX_SIZE];
+};
+
+static const struct out_csc_color_matrix global_color_matrix[] = {
+{ COLOR_SPACE_SRGB_FULL_RANGE,
+	{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
+{ COLOR_SPACE_SRGB_LIMITED_RANGE,
+	{ 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
+{ COLOR_SPACE_YCBCR601,
+	{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
+		0xF6B9, 0xE00, 0x1000} },
+{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
+	0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
+/*  YOnly same as YCbCr709 but Y in Full range -To do. */
+{ COLOR_SPACE_YCBCR601_YONLY, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
+	0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
+{ COLOR_SPACE_YCBCR709_YONLY, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
+	0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
+};
+
+enum csc_color_mode {
+	/* 00 - BITS2:0 Bypass */
+	CSC_COLOR_MODE_GRAPHICS_BYPASS,
+	/* 01 - hard coded coefficient TV RGB */
+	CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
+	/* 04 - programmable OUTPUT CSC coefficient */
+	CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
+};
+
+static void program_color_matrix(
+	struct dce110_opp *opp110,
+	const struct out_csc_color_matrix *tbl_entry,
+	enum grph_color_adjust_option options)
+{
+	struct dc_context *ctx = opp110->base.ctx;
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[0],
+			OUTPUT_CSC_C11_C12,
+			OUTPUT_CSC_C11);
+
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[1],
+			OUTPUT_CSC_C11_C12,
+			OUTPUT_CSC_C12);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[2],
+			OUTPUT_CSC_C13_C14,
+			OUTPUT_CSC_C13);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[3],
+			OUTPUT_CSC_C13_C14,
+			OUTPUT_CSC_C14);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[4],
+			OUTPUT_CSC_C21_C22,
+			OUTPUT_CSC_C21);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[5],
+			OUTPUT_CSC_C21_C22,
+			OUTPUT_CSC_C22);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[6],
+			OUTPUT_CSC_C23_C24,
+			OUTPUT_CSC_C23);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[7],
+			OUTPUT_CSC_C23_C24,
+			OUTPUT_CSC_C24);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[8],
+			OUTPUT_CSC_C31_C32,
+			OUTPUT_CSC_C31);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[9],
+			OUTPUT_CSC_C31_C32,
+			OUTPUT_CSC_C32);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[10],
+			OUTPUT_CSC_C33_C34,
+			OUTPUT_CSC_C33);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[11],
+			OUTPUT_CSC_C33_C34,
+			OUTPUT_CSC_C34);
+
+		dm_write_reg(ctx, addr, value);
+	}
+}
+
+/*
+ * initialize_color_float_adj_reference_values
+ * This initialize display color adjust input from API to HW range for later
+ * calculation use. This is shared by all the display color adjustment.
+ * @param :
+ * @return None
+ */
+static void initialize_color_float_adj_reference_values(
+	const struct grph_csc_adjustment *adjust,
+	struct fixed31_32 *grph_cont,
+	struct fixed31_32 *grph_sat,
+	struct fixed31_32 *grph_bright,
+	struct fixed31_32 *sin_grph_hue,
+	struct fixed31_32 *cos_grph_hue)
+{
+	/* Hue adjustment could be negative. -45 ~ +45 */
+	struct fixed31_32 hue =
+		dal_fixed31_32_mul(
+			dal_fixed31_32_from_fraction(adjust->grph_hue, 180),
+			dal_fixed31_32_pi);
+
+	*sin_grph_hue = dal_fixed31_32_sin(hue);
+	*cos_grph_hue = dal_fixed31_32_cos(hue);
+
+	if (adjust->adjust_divider) {
+		*grph_cont =
+			dal_fixed31_32_from_fraction(
+				adjust->grph_cont,
+				adjust->adjust_divider);
+		*grph_sat =
+			dal_fixed31_32_from_fraction(
+				adjust->grph_sat,
+				adjust->adjust_divider);
+		*grph_bright =
+			dal_fixed31_32_from_fraction(
+				adjust->grph_bright,
+				adjust->adjust_divider);
+	} else {
+		*grph_cont = dal_fixed31_32_from_int(adjust->grph_cont);
+		*grph_sat = dal_fixed31_32_from_int(adjust->grph_sat);
+		*grph_bright = dal_fixed31_32_from_int(adjust->grph_bright);
+	}
+}
+
+static inline struct fixed31_32 fixed31_32_clamp(
+	struct fixed31_32 value,
+	int32_t min_numerator,
+	int32_t max_numerator,
+	int32_t denominator)
+{
+	return dal_fixed31_32_clamp(
+		value,
+		dal_fixed31_32_from_fraction(
+			min_numerator,
+			denominator),
+		dal_fixed31_32_from_fraction(
+			max_numerator,
+			denominator));
+}
+
+static void setup_reg_format(
+	struct fixed31_32 *coefficients,
+	uint16_t *reg_values)
+{
+	enum {
+		LENGTH = 12,
+		DENOMINATOR = 10000
+	};
+
+	static const int32_t min_numerator[] = {
+		-3 * DENOMINATOR,
+		-DENOMINATOR
+	};
+
+	static const int32_t max_numerator[] = {
+		DENOMINATOR,
+		DENOMINATOR
+	};
+
+	static const uint8_t integer_bits[] = { 2, 0 };
+
+	uint32_t i = 0;
+
+	do {
+		const uint32_t index = (i % 4) == 3;
+
+		reg_values[i] = fixed_point_to_int_frac(
+			fixed31_32_clamp(coefficients[(i + 8) % LENGTH],
+				min_numerator[index],
+				max_numerator[index],
+				DENOMINATOR),
+			integer_bits[index], 13);
+
+		++i;
+	} while (i != LENGTH);
+}
+
+/**
+ *****************************************************************************
+ *  Function: setup_adjustments
+ *  @note prepare to setup the values
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void setup_adjustments(const struct grph_csc_adjustment *adjust,
+	struct dc_csc_adjustments *adjustments)
+{
+	if (adjust->adjust_divider != 0) {
+		adjustments->brightness =
+			dal_fixed31_32_from_fraction(adjust->grph_bright,
+			adjust->adjust_divider);
+		adjustments->contrast =
+			dal_fixed31_32_from_fraction(adjust->grph_cont,
+			adjust->adjust_divider);
+		adjustments->saturation =
+			dal_fixed31_32_from_fraction(adjust->grph_sat,
+			adjust->adjust_divider);
+	} else {
+		adjustments->brightness =
+			dal_fixed31_32_from_fraction(adjust->grph_bright, 1);
+		adjustments->contrast =
+			dal_fixed31_32_from_fraction(adjust->grph_cont, 1);
+		adjustments->saturation =
+			dal_fixed31_32_from_fraction(adjust->grph_sat, 1);
+	}
+
+	/* convert degrees into radians */
+	adjustments->hue =
+		dal_fixed31_32_mul(
+			dal_fixed31_32_from_fraction(adjust->grph_hue, 180),
+			dal_fixed31_32_pi);
+}
+
+static void prepare_tv_rgb_ideal(
+	struct fixed31_32 *matrix)
+{
+	static const int32_t matrix_[] = {
+		85546875, 0, 0, 6250000,
+		0, 85546875, 0, 6250000,
+		0, 0, 85546875, 6250000
+	};
+
+	uint32_t i = 0;
+
+	do {
+		matrix[i] = dal_fixed31_32_from_fraction(
+			matrix_[i],
+			100000000);
+		++i;
+	} while (i != ARRAY_SIZE(matrix_));
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_rgb_adjustment_legacy
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and program color adjustments for sRGB color space
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void set_rgb_adjustment_legacy(
+	struct dce110_opp *opp110,
+	const struct grph_csc_adjustment *adjust)
+{
+	const struct fixed31_32 k1 =
+		dal_fixed31_32_from_fraction(701000, 1000000);
+	const struct fixed31_32 k2 =
+		dal_fixed31_32_from_fraction(236568, 1000000);
+	const struct fixed31_32 k3 =
+		dal_fixed31_32_from_fraction(-587000, 1000000);
+	const struct fixed31_32 k4 =
+		dal_fixed31_32_from_fraction(464432, 1000000);
+	const struct fixed31_32 k5 =
+		dal_fixed31_32_from_fraction(-114000, 1000000);
+	const struct fixed31_32 k6 =
+		dal_fixed31_32_from_fraction(-701000, 1000000);
+	const struct fixed31_32 k7 =
+		dal_fixed31_32_from_fraction(-299000, 1000000);
+	const struct fixed31_32 k8 =
+		dal_fixed31_32_from_fraction(-292569, 1000000);
+	const struct fixed31_32 k9 =
+		dal_fixed31_32_from_fraction(413000, 1000000);
+	const struct fixed31_32 k10 =
+		dal_fixed31_32_from_fraction(-92482, 1000000);
+	const struct fixed31_32 k11 =
+		dal_fixed31_32_from_fraction(-114000, 1000000);
+	const struct fixed31_32 k12 =
+		dal_fixed31_32_from_fraction(385051, 1000000);
+	const struct fixed31_32 k13 =
+		dal_fixed31_32_from_fraction(-299000, 1000000);
+	const struct fixed31_32 k14 =
+		dal_fixed31_32_from_fraction(886000, 1000000);
+	const struct fixed31_32 k15 =
+		dal_fixed31_32_from_fraction(-587000, 1000000);
+	const struct fixed31_32 k16 =
+		dal_fixed31_32_from_fraction(-741914, 1000000);
+	const struct fixed31_32 k17 =
+		dal_fixed31_32_from_fraction(886000, 1000000);
+	const struct fixed31_32 k18 =
+		dal_fixed31_32_from_fraction(-144086, 1000000);
+
+	const struct fixed31_32 luma_r =
+		dal_fixed31_32_from_fraction(299, 1000);
+	const struct fixed31_32 luma_g =
+		dal_fixed31_32_from_fraction(587, 1000);
+	const struct fixed31_32 luma_b =
+		dal_fixed31_32_from_fraction(114, 1000);
+
+	struct out_csc_color_matrix tbl_entry;
+	struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE];
+
+	struct fixed31_32 grph_cont;
+	struct fixed31_32 grph_sat;
+	struct fixed31_32 grph_bright;
+	struct fixed31_32 sin_grph_hue;
+	struct fixed31_32 cos_grph_hue;
+
+	initialize_color_float_adj_reference_values(
+		adjust, &grph_cont, &grph_sat,
+		&grph_bright, &sin_grph_hue, &cos_grph_hue);
+
+	/* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +
+	 * Sin(GrphHue) * K2)) */
+	/* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2) */
+	matrix[0] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k1),
+			dal_fixed31_32_mul(sin_grph_hue, k2));
+	/* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */
+	matrix[0] = dal_fixed31_32_mul(grph_sat, matrix[0]);
+	/* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)) */
+	matrix[0] = dal_fixed31_32_add(luma_r, matrix[0]);
+	/* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) *
+	 * K2)) */
+	matrix[0] = dal_fixed31_32_mul(grph_cont, matrix[0]);
+
+	/* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +
+	 * Sin(GrphHue) * K4)) */
+	/* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4) */
+	matrix[1] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k3),
+			dal_fixed31_32_mul(sin_grph_hue, k4));
+	/* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4) */
+	matrix[1] = dal_fixed31_32_mul(grph_sat, matrix[1]);
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)) */
+	matrix[1] = dal_fixed31_32_add(luma_g, matrix[1]);
+	/* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) *
+	 * K4)) */
+	matrix[1] = dal_fixed31_32_mul(grph_cont, matrix[1]);
+
+	/* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +
+	 * Sin(GrphHue) * K6)) */
+	/* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */
+	matrix[2] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k5),
+			dal_fixed31_32_mul(sin_grph_hue, k6));
+	/* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */
+	matrix[2] = dal_fixed31_32_mul(grph_sat, matrix[2]);
+	/* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */
+	matrix[2] = dal_fixed31_32_add(luma_b, matrix[2]);
+	/* GrphCont  * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) *
+	 * K6)) */
+	matrix[2] = dal_fixed31_32_mul(grph_cont, matrix[2]);
+
+	/* COEF_1_4 = GrphBright */
+	matrix[3] = grph_bright;
+
+	/* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +
+	 * Sin(GrphHue) * K8)) */
+	/* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8) */
+	matrix[4] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k7),
+			dal_fixed31_32_mul(sin_grph_hue, k8));
+	/* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8) */
+	matrix[4] = dal_fixed31_32_mul(grph_sat, matrix[4]);
+	/* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)) */
+	matrix[4] = dal_fixed31_32_add(luma_r, matrix[4]);
+	/* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) *
+	 * K8)) */
+	matrix[4] = dal_fixed31_32_mul(grph_cont, matrix[4]);
+
+	/* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +
+	 * Sin(GrphHue) * K10)) */
+	/* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */
+	matrix[5] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k9),
+			dal_fixed31_32_mul(sin_grph_hue, k10));
+	/* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */
+	matrix[5] = dal_fixed31_32_mul(grph_sat, matrix[5]);
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */
+	matrix[5] = dal_fixed31_32_add(luma_g, matrix[5]);
+	/* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) *
+	 * K10)) */
+	matrix[5] = dal_fixed31_32_mul(grph_cont, matrix[5]);
+
+	/*  COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +
+	 * Sin(GrphHue) * K12)) */
+	/* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */
+	matrix[6] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k11),
+			dal_fixed31_32_mul(sin_grph_hue, k12));
+	/* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */
+	matrix[6] = dal_fixed31_32_mul(grph_sat, matrix[6]);
+	/*  (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */
+	matrix[6] = dal_fixed31_32_add(luma_b, matrix[6]);
+	/* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) *
+	 * K12)) */
+	matrix[6] = dal_fixed31_32_mul(grph_cont, matrix[6]);
+
+	/* COEF_2_4 = GrphBright */
+	matrix[7] = grph_bright;
+
+	/* COEF_3_1 = GrphCont  * (LumaR + GrphSat * (Cos(GrphHue) * K13 +
+	 * Sin(GrphHue) * K14)) */
+	/* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
+	matrix[8] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k13),
+			dal_fixed31_32_mul(sin_grph_hue, k14));
+	/* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
+	matrix[8] = dal_fixed31_32_mul(grph_sat, matrix[8]);
+	/* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
+	matrix[8] = dal_fixed31_32_add(luma_r, matrix[8]);
+	/* GrphCont  * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) *
+	 * K14)) */
+	matrix[8] = dal_fixed31_32_mul(grph_cont, matrix[8]);
+
+	/* COEF_3_2    = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +
+	 * Sin(GrphHue) * K16)) */
+	/* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */
+	matrix[9] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k15),
+			dal_fixed31_32_mul(sin_grph_hue, k16));
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */
+	matrix[9] = dal_fixed31_32_mul(grph_sat, matrix[9]);
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */
+	matrix[9] = dal_fixed31_32_add(luma_g, matrix[9]);
+	 /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) *
+	  * K16)) */
+	matrix[9] = dal_fixed31_32_mul(grph_cont, matrix[9]);
+
+	/*  COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +
+	 * Sin(GrphHue) * K18)) */
+	/* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
+	matrix[10] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k17),
+			dal_fixed31_32_mul(sin_grph_hue, k18));
+	/*  GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
+	matrix[10] = dal_fixed31_32_mul(grph_sat, matrix[10]);
+	/* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
+	matrix[10] = dal_fixed31_32_add(luma_b, matrix[10]);
+	 /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) *
+	  * K18)) */
+	matrix[10] = dal_fixed31_32_mul(grph_cont, matrix[10]);
+
+	/*  COEF_3_4    = GrphBright */
+	matrix[11] = grph_bright;
+
+	tbl_entry.color_space = adjust->c_space;
+
+	convert_float_matrix(tbl_entry.regval, matrix, OUTPUT_CSC_MATRIX_SIZE);
+
+	program_color_matrix(
+		opp110, &tbl_entry, adjust->color_adjust_option);
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_rgb_limited_range_adjustment
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and program color adjustments for sRGB limited color space
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void set_rgb_limited_range_adjustment(
+	struct dce110_opp *opp110,
+	const struct grph_csc_adjustment *adjust)
+{
+	struct out_csc_color_matrix reg_matrix;
+	struct fixed31_32 change_matrix[OUTPUT_CSC_MATRIX_SIZE];
+	struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE];
+	struct dc_csc_adjustments adjustments;
+	struct fixed31_32 ideals[OUTPUT_CSC_MATRIX_SIZE];
+
+	prepare_tv_rgb_ideal(ideals);
+
+	setup_adjustments(adjust, &adjustments);
+
+	calculate_adjustments(ideals, &adjustments, matrix);
+
+	dm_memmove(change_matrix, matrix, sizeof(matrix));
+
+	/* from 1 -> 3 */
+	matrix[8] = change_matrix[0];
+	matrix[9] = change_matrix[1];
+	matrix[10] = change_matrix[2];
+	matrix[11] = change_matrix[3];
+
+	/* from 2 -> 1 */
+	matrix[0] = change_matrix[4];
+	matrix[1] = change_matrix[5];
+	matrix[2] = change_matrix[6];
+	matrix[3] = change_matrix[7];
+
+	/* from 3 -> 2 */
+	matrix[4] = change_matrix[8];
+	matrix[5] = change_matrix[9];
+	matrix[6] = change_matrix[10];
+	matrix[7] = change_matrix[11];
+
+	dm_memset(&reg_matrix, 0, sizeof(struct out_csc_color_matrix));
+
+	setup_reg_format(matrix, reg_matrix.regval);
+
+	program_color_matrix(opp110, &reg_matrix, GRPH_COLOR_MATRIX_SW);
+}
+
+static void prepare_yuv_ideal(
+	bool b601,
+	struct fixed31_32 *matrix)
+{
+	static const int32_t matrix_1[] = {
+		25578516, 50216016, 9752344, 6250000,
+		-14764391, -28985609, 43750000, 50000000,
+		43750000, -36635164, -7114836, 50000000
+	};
+
+	static const int32_t matrix_2[] = {
+		18187266, 61183125, 6176484, 6250000,
+		-10025059, -33724941, 43750000, 50000000,
+		43750000, -39738379, -4011621, 50000000
+	};
+
+	const int32_t *matrix_x = b601 ? matrix_1 : matrix_2;
+
+	uint32_t i = 0;
+
+	do {
+		matrix[i] = dal_fixed31_32_from_fraction(
+			matrix_x[i],
+			100000000);
+		++i;
+	} while (i != ARRAY_SIZE(matrix_1));
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_yuv_adjustment
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and program color adjustments for YUV  color spaces
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void set_yuv_adjustment(
+	struct dce110_opp *opp110,
+	const struct grph_csc_adjustment *adjust)
+{
+	bool b601 = (adjust->c_space == COLOR_SPACE_YPBPR601) ||
+		(adjust->c_space == COLOR_SPACE_YCBCR601) ||
+		(adjust->c_space == COLOR_SPACE_YCBCR601_YONLY);
+	struct out_csc_color_matrix reg_matrix;
+	struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE];
+	struct dc_csc_adjustments adjustments;
+	struct fixed31_32 ideals[OUTPUT_CSC_MATRIX_SIZE];
+
+	prepare_yuv_ideal(b601, ideals);
+
+	setup_adjustments(adjust, &adjustments);
+
+	if ((adjust->c_space == COLOR_SPACE_YCBCR601_YONLY) ||
+		(adjust->c_space == COLOR_SPACE_YCBCR709_YONLY))
+		calculate_adjustments_y_only(
+			ideals, &adjustments, matrix);
+	else
+		calculate_adjustments(
+			ideals, &adjustments, matrix);
+
+	dm_memset(&reg_matrix, 0, sizeof(struct out_csc_color_matrix));
+
+	setup_reg_format(matrix, reg_matrix.regval);
+
+	program_color_matrix(opp110, &reg_matrix, GRPH_COLOR_MATRIX_SW);
+}
+
+static bool configure_graphics_mode(
+	struct dce110_opp *opp110,
+	enum csc_color_mode config,
+	enum graphics_csc_adjust_type csc_adjust_type,
+	enum color_space color_space)
+{
+	struct dc_context *ctx = opp110->base.ctx;
+	uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		OUTPUT_CSC_CONTROL,
+		OUTPUT_CSC_GRPH_MODE);
+
+	if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
+		if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
+			set_reg_field_value(
+				value,
+				4,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+		} else {
+
+			switch (color_space) {
+			case COLOR_SPACE_SRGB_FULL_RANGE:
+				/* by pass */
+				set_reg_field_value(
+					value,
+					0,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			case COLOR_SPACE_SRGB_LIMITED_RANGE:
+				/* TV RGB */
+				set_reg_field_value(
+					value,
+					1,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			case COLOR_SPACE_YCBCR601:
+			case COLOR_SPACE_YPBPR601:
+			case COLOR_SPACE_YCBCR601_YONLY:
+				/* YCbCr601 */
+				set_reg_field_value(
+					value,
+					2,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			case COLOR_SPACE_YCBCR709:
+			case COLOR_SPACE_YPBPR709:
+			case COLOR_SPACE_YCBCR709_YONLY:
+				/* YCbCr709 */
+				set_reg_field_value(
+					value,
+					3,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			default:
+				return false;
+			}
+		}
+	} else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
+		switch (color_space) {
+		case COLOR_SPACE_SRGB_FULL_RANGE:
+			/* by pass */
+			set_reg_field_value(
+				value,
+				0,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		case COLOR_SPACE_SRGB_LIMITED_RANGE:
+			/* TV RGB */
+			set_reg_field_value(
+				value,
+				1,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		case COLOR_SPACE_YCBCR601:
+		case COLOR_SPACE_YPBPR601:
+		case COLOR_SPACE_YCBCR601_YONLY:
+			/* YCbCr601 */
+			set_reg_field_value(
+				value,
+				2,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		case COLOR_SPACE_YCBCR709:
+		case COLOR_SPACE_YPBPR709:
+		case COLOR_SPACE_YCBCR709_YONLY:
+			 /* YCbCr709 */
+			set_reg_field_value(
+				value,
+				3,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		default:
+			return false;
+		}
+
+	} else
+		/* by pass */
+		set_reg_field_value(
+			value,
+			0,
+			OUTPUT_CSC_CONTROL,
+			OUTPUT_CSC_GRPH_MODE);
+
+	addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
+	dm_write_reg(ctx, addr, value);
+
+	return true;
+}
+
+void dce110_opp_set_csc_adjustment(
+	struct output_pixel_processor *opp,
+	const struct grph_csc_adjustment *adjust)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+	enum csc_color_mode config =
+			CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
+
+	/* Apply color adjustments: brightness, saturation, hue, contrast and
+	 * CSC. No need for different color space routine, color space defines
+	 * the ideal values only, but keep original design to allow quick switch
+	 * to the old legacy routines */
+	switch (adjust->c_space) {
+	case COLOR_SPACE_SRGB_FULL_RANGE:
+		set_rgb_adjustment_legacy(opp110, adjust);
+		break;
+	case COLOR_SPACE_SRGB_LIMITED_RANGE:
+		set_rgb_limited_range_adjustment(
+			opp110, adjust);
+		break;
+	case COLOR_SPACE_YCBCR601:
+	case COLOR_SPACE_YCBCR709:
+	case COLOR_SPACE_YCBCR601_YONLY:
+	case COLOR_SPACE_YCBCR709_YONLY:
+	case COLOR_SPACE_YPBPR601:
+	case COLOR_SPACE_YPBPR709:
+		set_yuv_adjustment(opp110, adjust);
+		break;
+	default:
+		set_rgb_adjustment_legacy(opp110, adjust);
+		break;
+	}
+
+	/*  We did everything ,now program DxOUTPUT_CSC_CONTROL */
+	configure_graphics_mode(opp110, config, adjust->csc_adjust_type,
+		adjust->c_space);
+}
+
+void dce110_opp_set_csc_default(
+	struct output_pixel_processor *opp,
+	const struct default_adjustment *default_adjust)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+	enum csc_color_mode config =
+			CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
+
+	if (default_adjust->force_hw_default == false) {
+		const struct out_csc_color_matrix *elm;
+		/* currently parameter not in use */
+		enum grph_color_adjust_option option =
+			GRPH_COLOR_MATRIX_HW_DEFAULT;
+		uint32_t i;
+		/*
+		 * HW default false we program locally defined matrix
+		 * HW default true  we use predefined hw matrix and we
+		 * do not need to program matrix
+		 * OEM wants the HW default via runtime parameter.
+		 */
+		option = GRPH_COLOR_MATRIX_SW;
+
+		for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
+			elm = &global_color_matrix[i];
+			if (elm->color_space != default_adjust->color_space)
+				continue;
+			/* program the matrix with default values from this
+			 * file */
+			program_color_matrix(opp110, elm, option);
+			config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
+			break;
+		}
+	}
+
+	/* configure the what we programmed :
+	 * 1. Default values from this file
+	 * 2. Use hardware default from ROM_A and we do not need to program
+	 * matrix */
+
+	configure_graphics_mode(opp110, config,
+		default_adjust->csc_adjust_type,
+		default_adjust->color_space);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
new file mode 100644
index 000000000000..235b92e3af61
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
@@ -0,0 +1,610 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_opp.h"
+
+#define FMT_REG(reg)\
+	(reg + opp110->offsets.fmt_offset)
+
+/**
+ *	set_truncation
+ *	1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
+ *	2) enable truncation
+ *	3) HW remove 12bit FMT support for DCE11 power saving reason.
+ */
+static void set_truncation(
+		struct dce110_opp *opp110,
+		const struct bit_depth_reduction_params *params)
+{
+	uint32_t value = 0;
+	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+
+	/*Disable truncation*/
+	value = dm_read_reg(opp110->base.ctx, addr);
+	set_reg_field_value(value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
+	set_reg_field_value(value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
+	set_reg_field_value(value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+	/* no 10bpc trunc on DCE11*/
+	if (params->flags.TRUNCATE_ENABLED == 0 ||
+		params->flags.TRUNCATE_DEPTH == 2)
+		return;
+
+	/*Set truncation depth and Enable truncation*/
+	set_reg_field_value(value, 1,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
+	set_reg_field_value(value, params->flags.TRUNCATE_MODE,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
+	set_reg_field_value(value, params->flags.TRUNCATE_DEPTH,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+}
+
+/**
+ *	set_spatial_dither
+ *	1) set spatial dithering mode: pattern of seed
+ *	2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp
+ *	3) set random seed
+ *	4) set random mode
+ *		lfsr is reset every frame or not reset
+ *		RGB dithering method
+ *		0: RGB data are all dithered with x^28+x^3+1
+ *		1: R data is dithered with x^28+x^3+1
+ *		G data is dithered with x^28+X^9+1
+ *		B data is dithered with x^28+x^13+1
+ *		enable high pass filter or not
+ *	5) enable spatical dithering
+ */
+static void set_spatial_dither(
+	struct dce110_opp *opp110,
+	const struct bit_depth_reduction_params *params)
+{
+	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	uint32_t depth_cntl_value = 0;
+	uint32_t fmt_cntl_value = 0;
+	uint32_t dither_r_value = 0;
+	uint32_t dither_g_value = 0;
+	uint32_t dither_b_value = 0;
+
+	/*Disable spatial (random) dithering*/
+	depth_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE);
+
+	dm_write_reg(opp110->base.ctx, addr, depth_cntl_value);
+
+	/* no 10bpc on DCE11*/
+	if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
+		params->flags.SPATIAL_DITHER_DEPTH == 2)
+		return;
+
+	addr = FMT_REG(mmFMT_CONTROL);
+	fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+	/* only use FRAME_COUNTER_MAX if frameRandom == 1*/
+	if (params->flags.FRAME_RANDOM == 1) {
+		if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
+		params->flags.SPATIAL_DITHER_DEPTH == 1) {
+			set_reg_field_value(fmt_cntl_value, 15,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
+			set_reg_field_value(fmt_cntl_value, 2,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
+		} else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
+			set_reg_field_value(fmt_cntl_value, 3,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
+			set_reg_field_value(fmt_cntl_value, 1,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
+		} else
+			return;
+	} else {
+		set_reg_field_value(fmt_cntl_value, 0,
+			FMT_CONTROL,
+			FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
+		set_reg_field_value(fmt_cntl_value, 0,
+			FMT_CONTROL,
+			FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
+	}
+
+	dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
+
+	/*Set seed for random values for
+	 * spatial dithering for R,G,B channels*/
+	addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED);
+	set_reg_field_value(dither_r_value, params->r_seed_value,
+		FMT_DITHER_RAND_R_SEED,
+		FMT_RAND_R_SEED);
+	dm_write_reg(opp110->base.ctx, addr, dither_r_value);
+
+	addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED);
+	set_reg_field_value(dither_g_value,
+		params->g_seed_value,
+		FMT_DITHER_RAND_G_SEED,
+		FMT_RAND_G_SEED);
+	dm_write_reg(opp110->base.ctx, addr, dither_g_value);
+
+	addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED);
+	set_reg_field_value(dither_b_value, params->b_seed_value,
+		FMT_DITHER_RAND_B_SEED,
+		FMT_RAND_B_SEED);
+	dm_write_reg(opp110->base.ctx, addr, dither_b_value);
+
+	/* FMT_OFFSET_R_Cr  31:16 0x0 Setting the zero
+	 * offset for the R/Cr channel, lower 4LSB
+	 * is forced to zeros. Typically set to 0
+	 * RGB and 0x80000 YCbCr.
+	 */
+	/* FMT_OFFSET_G_Y   31:16 0x0 Setting the zero
+	 * offset for the G/Y  channel, lower 4LSB is
+	 * forced to zeros. Typically set to 0 RGB
+	 * and 0x80000 YCbCr.
+	 */
+	/* FMT_OFFSET_B_Cb  31:16 0x0 Setting the zero
+	 * offset for the B/Cb channel, lower 4LSB is
+	 * forced to zeros. Typically set to 0 RGB and
+	 * 0x80000 YCbCr.
+	 */
+
+	/*Set spatial dithering bit depth*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.SPATIAL_DITHER_DEPTH,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_SPATIAL_DITHER_DEPTH);
+
+	/* Set spatial dithering mode
+	 * (default is Seed patterrn AAAA...)
+	 */
+	set_reg_field_value(depth_cntl_value,
+		params->flags.SPATIAL_DITHER_MODE,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_SPATIAL_DITHER_MODE);
+
+	/*Reset only at startup*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.FRAME_RANDOM,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_RGB_RANDOM_ENABLE);
+
+	/*Set RGB data dithered with x^28+x^3+1*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.RGB_RANDOM,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_RGB_RANDOM_ENABLE);
+
+	/*Disable High pass filter*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.HIGHPASS_RANDOM,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_HIGHPASS_RANDOM_ENABLE);
+
+	/*Enable spatial dithering*/
+	set_reg_field_value(depth_cntl_value,
+		1,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_SPATIAL_DITHER_EN);
+
+	addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	dm_write_reg(opp110->base.ctx, addr, depth_cntl_value);
+
+}
+
+/**
+ *	SetTemporalDither (Frame Modulation)
+ *	1) set temporal dither depth
+ *	2) select pattern: from hard-coded pattern or programmable pattern
+ *	3) select optimized strips for BGR or RGB LCD sub-pixel
+ *	4) set s matrix
+ *	5) set t matrix
+ *	6) set grey level for 0.25, 0.5, 0.75
+ *	7) enable temporal dithering
+ */
+static void set_temporal_dither(
+	struct dce110_opp *opp110,
+	const struct bit_depth_reduction_params *params)
+{
+	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	uint32_t value;
+
+	/*Disable temporal (frame modulation) dithering first*/
+	value = dm_read_reg(opp110->base.ctx, addr);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_EN);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_RESET);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_OFFSET);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_DEPTH);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_LEVEL);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_25FRC_SEL);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_50FRC_SEL);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_75FRC_SEL);
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+	/* no 10bpc dither on DCE11*/
+	if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
+		params->flags.FRAME_MODULATION_DEPTH == 2)
+		return;
+
+	/* Set temporal dithering depth*/
+	set_reg_field_value(value,
+		params->flags.FRAME_MODULATION_DEPTH,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_DEPTH);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_RESET);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_OFFSET);
+
+	/*Select legacy pattern based on FRC and Temporal level*/
+	addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL);
+	dm_write_reg(opp110->base.ctx, addr, 0);
+	/*Set s matrix*/
+	addr = FMT_REG(
+		mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX);
+	dm_write_reg(opp110->base.ctx, addr, 0);
+	/*Set t matrix*/
+	addr = FMT_REG(
+		mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX);
+	dm_write_reg(opp110->base.ctx, addr, 0);
+
+	/*Select patterns for 0.25, 0.5 and 0.75 grey level*/
+	set_reg_field_value(value,
+		params->flags.TEMPORAL_LEVEL,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_LEVEL);
+
+	set_reg_field_value(value,
+		params->flags.FRC25,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_25FRC_SEL);
+
+	set_reg_field_value(value,
+		params->flags.FRC50,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_50FRC_SEL);
+
+	set_reg_field_value(value,
+		params->flags.FRC75,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_75FRC_SEL);
+
+	/*Enable bit reduction by temporal (frame modulation) dithering*/
+	set_reg_field_value(value,
+		1,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_EN);
+
+	addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+}
+
+/**
+ *	Set Clamping
+ *	1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
+ *		1 for 8 bpc
+ *		2 for 10 bpc
+ *		3 for 12 bpc
+ *		7 for programable
+ *	2) Enable clamp if Limited range requested
+ */
+static void set_clamping(
+	struct dce110_opp *opp110,
+	const struct clamping_and_pixel_encoding_params *params)
+{
+	uint32_t clamp_cntl_value = 0;
+	uint32_t red_clamp_value = 0;
+	uint32_t green_clamp_value = 0;
+	uint32_t blue_clamp_value = 0;
+	uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL);
+
+	clamp_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+
+	set_reg_field_value(clamp_cntl_value,
+		0,
+		FMT_CLAMP_CNTL,
+		FMT_CLAMP_DATA_EN);
+
+	set_reg_field_value(clamp_cntl_value,
+		0,
+		FMT_CLAMP_CNTL,
+		FMT_CLAMP_COLOR_FORMAT);
+
+	switch (params->clamping_level) {
+	case CLAMPING_FULL_RANGE:
+		break;
+
+	case CLAMPING_LIMITED_RANGE_8BPC:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		break;
+
+	case CLAMPING_LIMITED_RANGE_10BPC:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			2,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		break;
+	case CLAMPING_LIMITED_RANGE_12BPC:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			3,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		break;
+	case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			7,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		/*set the defaults*/
+		set_reg_field_value(red_clamp_value,
+			0x10,
+			FMT_CLAMP_COMPONENT_R,
+			FMT_CLAMP_LOWER_R);
+
+		set_reg_field_value(red_clamp_value,
+			0xFEF,
+			FMT_CLAMP_COMPONENT_R,
+			FMT_CLAMP_UPPER_R);
+
+		addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R);
+		dm_write_reg(opp110->base.ctx, addr, red_clamp_value);
+
+		set_reg_field_value(green_clamp_value,
+			0x10,
+			FMT_CLAMP_COMPONENT_G,
+			FMT_CLAMP_LOWER_G);
+
+		set_reg_field_value(green_clamp_value,
+			0xFEF,
+			FMT_CLAMP_COMPONENT_G,
+			FMT_CLAMP_UPPER_G);
+
+		addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G);
+		dm_write_reg(opp110->base.ctx, addr, green_clamp_value);
+
+		set_reg_field_value(blue_clamp_value,
+			0x10,
+			FMT_CLAMP_COMPONENT_B,
+			FMT_CLAMP_LOWER_B);
+
+		set_reg_field_value(blue_clamp_value,
+			0xFEF,
+			FMT_CLAMP_COMPONENT_B,
+			FMT_CLAMP_UPPER_B);
+
+		addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B);
+		dm_write_reg(opp110->base.ctx, addr, blue_clamp_value);
+
+		break;
+
+	default:
+		break;
+	}
+
+	addr = FMT_REG(mmFMT_CLAMP_CNTL);
+	/*Set clamp control*/
+	dm_write_reg(opp110->base.ctx, addr, clamp_cntl_value);
+
+}
+
+/**
+ *	set_pixel_encoding
+ *
+ *	Set Pixel Encoding
+ *		0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
+ *		1: YCbCr 4:2:2
+ */
+static void set_pixel_encoding(
+	struct dce110_opp *opp110,
+	const struct clamping_and_pixel_encoding_params *params)
+{
+	uint32_t fmt_cntl_value;
+	uint32_t addr = FMT_REG(mmFMT_CONTROL);
+
+	/*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/
+	fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+
+	set_reg_field_value(fmt_cntl_value,
+		0,
+		FMT_CONTROL,
+		FMT_PIXEL_ENCODING);
+
+	if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+		set_reg_field_value(fmt_cntl_value,
+			1,
+			FMT_CONTROL,
+			FMT_PIXEL_ENCODING);
+
+		/*00 - Pixels drop mode ,01 - Pixels average mode*/
+		set_reg_field_value(fmt_cntl_value,
+			0,
+			FMT_CONTROL,
+			FMT_SUBSAMPLING_MODE);
+
+		/*00 - Cb before Cr ,01 - Cr before Cb*/
+		set_reg_field_value(fmt_cntl_value,
+			0,
+			FMT_CONTROL,
+			FMT_SUBSAMPLING_ORDER);
+	}
+	dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
+
+}
+
+void dce110_opp_program_bit_depth_reduction(
+	struct output_pixel_processor *opp,
+	const struct bit_depth_reduction_params *params)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	set_truncation(opp110, params);
+	set_spatial_dither(opp110, params);
+	set_temporal_dither(opp110, params);
+}
+
+void dce110_opp_program_clamping_and_pixel_encoding(
+	struct output_pixel_processor *opp,
+	const struct clamping_and_pixel_encoding_params *params)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	set_clamping(opp110, params);
+	set_pixel_encoding(opp110, params);
+}
+
+void dce110_opp_set_dyn_expansion(
+	struct output_pixel_processor *opp,
+	enum color_space color_sp,
+	enum dc_color_depth color_dpth,
+	enum signal_type signal)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+	uint32_t value;
+	bool enable_dyn_exp = false;
+	uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL);
+
+	value = dm_read_reg(opp->ctx, addr);
+
+	set_reg_field_value(value, 0,
+		FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
+	set_reg_field_value(value, 0,
+		FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
+
+	/* From HW programming guide:
+		FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output
+		FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/
+	if (color_sp == COLOR_SPACE_SRGB_FULL_RANGE)
+		enable_dyn_exp = true;
+
+	/*00 - 10-bit -> 12-bit dynamic expansion*/
+	/*01 - 8-bit  -> 12-bit dynamic expansion*/
+	if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+		switch (color_dpth) {
+		case COLOR_DEPTH_888:
+			set_reg_field_value(value, enable_dyn_exp ? 1:0,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
+			set_reg_field_value(value, 1,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
+			break;
+		case COLOR_DEPTH_101010:
+			set_reg_field_value(value, enable_dyn_exp ? 1:0,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
+			set_reg_field_value(value, 0,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
+			break;
+		case COLOR_DEPTH_121212:
+			break;
+		default:
+			break;
+		}
+	}
+
+	dm_write_reg(opp->ctx, addr, value);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
new file mode 100644
index 000000000000..32cf57dd80d2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
@@ -0,0 +1,2474 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_opp.h"
+#include "gamma_types.h"
+
+#define DCP_REG(reg)\
+	(reg + opp110->offsets.dcp_offset)
+
+#define DCFE_REG(reg)\
+	(reg + opp110->offsets.dcfe_offset)
+
+enum {
+	MAX_PWL_ENTRY = 128,
+	MAX_REGIONS_NUMBER = 16
+
+};
+
+struct curve_config {
+	uint32_t offset;
+	int8_t segments[MAX_REGIONS_NUMBER];
+	int8_t begin;
+};
+
+/* BASE */
+static bool find_software_points(
+	struct dce110_opp *opp110,
+	struct fixed31_32 hw_point,
+	enum channel_name channel,
+	uint32_t *index_to_start,
+	uint32_t *index_left,
+	uint32_t *index_right,
+	enum hw_point_position *pos)
+{
+	const uint32_t max_number =
+			RGB_256X3X16 + opp110->regamma.extra_points;
+
+	struct fixed31_32 left, right;
+
+	uint32_t i = *index_to_start;
+
+	while (i < max_number) {
+		if (channel == CHANNEL_NAME_RED) {
+			left = opp110->
+					regamma.axis_x_256[i].r;
+
+			if (i < max_number - 1)
+				right = opp110->
+					regamma.axis_x_256[i + 1].r;
+			else
+				right = opp110->
+					regamma.axis_x_256[max_number - 1].r;
+		} else if (channel == CHANNEL_NAME_GREEN) {
+			left = opp110->regamma.axis_x_256[i].g;
+
+			if (i < max_number - 1)
+				right = opp110->
+					regamma.axis_x_256[i + 1].g;
+			else
+				right = opp110->
+					regamma.axis_x_256[max_number - 1].g;
+		} else {
+			left = opp110->regamma.axis_x_256[i].b;
+
+			if (i < max_number - 1)
+				right = opp110->
+					regamma.axis_x_256[i + 1].b;
+			else
+				right = opp110->
+					regamma.axis_x_256[max_number - 1].b;
+		}
+
+		if (dal_fixed31_32_le(left, hw_point) &&
+			dal_fixed31_32_le(hw_point, right)) {
+			*index_to_start = i;
+			*index_left = i;
+
+			if (i < max_number - 1)
+				*index_right = i + 1;
+			else
+				*index_right = max_number - 1;
+
+			*pos = HW_POINT_POSITION_MIDDLE;
+
+			return true;
+		} else if ((i == *index_to_start) &&
+			dal_fixed31_32_le(hw_point, left)) {
+			*index_to_start = i;
+			*index_left = i;
+			*index_right = i;
+
+			*pos = HW_POINT_POSITION_LEFT;
+
+			return true;
+		} else if ((i == max_number - 1) &&
+			dal_fixed31_32_le(right, hw_point)) {
+			*index_to_start = i;
+			*index_left = i;
+			*index_right = i;
+
+			*pos = HW_POINT_POSITION_RIGHT;
+
+			return true;
+		}
+
+		++i;
+	}
+
+	return false;
+}
+
+static bool find_software_points_dx(
+	struct dce110_opp *opp110,
+	struct fixed31_32 hw_point,
+	enum channel_name channel,
+	uint32_t *index_to_start,
+	uint32_t *index_left,
+	uint32_t *index_right,
+	enum hw_point_position *pos)
+{
+	const uint32_t max_number = DX_GAMMA_RAMP_MAX +
+					opp110->regamma.extra_points;
+
+	struct fixed31_32 left, right;
+
+	uint32_t i = *index_to_start;
+
+	while (i < max_number) {
+		if (channel == CHANNEL_NAME_RED) {
+			left = opp110->regamma.axis_x_1025[i].r;
+
+			if (i < DX_GAMMA_RAMP_MAX - 1)
+				right = opp110->
+					regamma.axis_x_1025[i + 1].r;
+			else
+				right = opp110->
+				regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].r;
+		} else if (channel == CHANNEL_NAME_GREEN) {
+			left = opp110->regamma.axis_x_1025[i].g;
+
+			if (i < DX_GAMMA_RAMP_MAX - 1)
+				right = opp110->
+					regamma.axis_x_1025[i + 1].g;
+			else
+				right = opp110->
+				regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].g;
+		} else {
+			left = opp110->regamma.axis_x_1025[i].b;
+
+			if (i < DX_GAMMA_RAMP_MAX - 1)
+				right = opp110->
+					regamma.axis_x_1025[i + 1].b;
+			else
+				right = opp110->
+				regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].b;
+		}
+
+		if (dal_fixed31_32_le(left, hw_point) &&
+			dal_fixed31_32_le(hw_point, right)) {
+			*index_to_start = i;
+			*index_left = i;
+
+			if (i < DX_GAMMA_RAMP_MAX - 1)
+				*index_right = i + 1;
+			else
+				*index_right = DX_GAMMA_RAMP_MAX - 1;
+
+			*pos = HW_POINT_POSITION_MIDDLE;
+
+			return true;
+		} else if ((i == *index_to_start) &&
+			dal_fixed31_32_le(hw_point, left)) {
+			*index_to_start = i;
+			*index_left = i;
+			*index_right = i;
+
+			*pos = HW_POINT_POSITION_LEFT;
+
+			return true;
+		} else if ((i == max_number - 1) &&
+			dal_fixed31_32_le(right, hw_point)) {
+			*index_to_start = i;
+			*index_left = i;
+			*index_right = i;
+
+			*pos = HW_POINT_POSITION_RIGHT;
+
+			return true;
+		}
+
+		++i;
+	}
+
+	return false;
+}
+
+static bool build_custom_gamma_mapping_coefficients_worker(
+	struct dce110_opp *opp110,
+	struct pixel_gamma_point *coeff,
+	enum channel_name channel,
+	uint32_t number_of_points,
+	enum pixel_format pixel_format)
+{
+	uint32_t i = 0;
+
+	while (i <= number_of_points) {
+		struct fixed31_32 coord_x;
+
+		uint32_t index_to_start = 0;
+		uint32_t index_left = 0;
+		uint32_t index_right = 0;
+
+		enum hw_point_position hw_pos;
+
+		struct gamma_point *point;
+
+		struct fixed31_32 left_pos;
+		struct fixed31_32 right_pos;
+
+		if (pixel_format == PIXEL_FORMAT_FP16)
+			coord_x = opp110->
+				regamma.coordinates_x[i].adjusted_x;
+		else if (channel == CHANNEL_NAME_RED)
+			coord_x = opp110->
+				regamma.coordinates_x[i].regamma_y_red;
+		else if (channel == CHANNEL_NAME_GREEN)
+			coord_x = opp110->
+				regamma.coordinates_x[i].regamma_y_green;
+		else
+			coord_x = opp110->
+				regamma.coordinates_x[i].regamma_y_blue;
+
+		if (!find_software_points(
+			opp110, coord_x, channel,
+			&index_to_start, &index_left, &index_right, &hw_pos)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (index_left >= RGB_256X3X16 +
+				opp110->regamma.extra_points) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (index_right >= RGB_256X3X16 +
+				opp110->regamma.extra_points) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (channel == CHANNEL_NAME_RED) {
+			point = &coeff[i].r;
+
+			left_pos = opp110->
+					regamma.axis_x_256[index_left].r;
+			right_pos = opp110->
+					regamma.axis_x_256[index_right].r;
+		} else if (channel == CHANNEL_NAME_GREEN) {
+			point = &coeff[i].g;
+
+			left_pos = opp110->
+					regamma.axis_x_256[index_left].g;
+			right_pos = opp110->
+					regamma.axis_x_256[index_right].g;
+		} else {
+			point = &coeff[i].b;
+
+			left_pos = opp110->
+					regamma.axis_x_256[index_left].b;
+			right_pos = opp110->
+					regamma.axis_x_256[index_right].b;
+		}
+
+		if (hw_pos == HW_POINT_POSITION_MIDDLE)
+			point->coeff = dal_fixed31_32_div(
+				dal_fixed31_32_sub(
+					coord_x,
+					left_pos),
+				dal_fixed31_32_sub(
+					right_pos,
+					left_pos));
+		else if (hw_pos == HW_POINT_POSITION_LEFT)
+			point->coeff = opp110->regamma.x_min;
+		else if (hw_pos == HW_POINT_POSITION_RIGHT)
+			point->coeff = opp110->regamma.x_max2;
+		else {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		point->left_index = index_left;
+		point->right_index = index_right;
+		point->pos = hw_pos;
+
+		++i;
+	}
+
+	return true;
+}
+
+static inline bool build_custom_gamma_mapping_coefficients(
+	struct dce110_opp *opp110,
+	enum channel_name channel,
+	uint32_t number_of_points,
+	enum pixel_format pixel_format)
+{
+	return build_custom_gamma_mapping_coefficients_worker(
+		opp110, opp110->regamma.coeff128, channel,
+		number_of_points, pixel_format);
+}
+
+static inline bool build_oem_custom_gamma_mapping_coefficients(
+	struct dce110_opp *opp110,
+	enum channel_name channel,
+	uint32_t number_of_points,
+	enum pixel_format pixel_format)
+{
+	return build_custom_gamma_mapping_coefficients_worker(
+		opp110, opp110->regamma.coeff128_oem, channel,
+		number_of_points, pixel_format);
+}
+
+static bool build_custom_dx_gamma_mapping_coefficients(
+	struct dce110_opp *opp110,
+	enum channel_name channel,
+	uint32_t number_of_points,
+	enum pixel_format pixel_format)
+{
+	uint32_t i = 0;
+
+	while (i <= number_of_points) {
+		struct fixed31_32 coord_x;
+
+		uint32_t index_to_start = 0;
+		uint32_t index_left = 0;
+		uint32_t index_right = 0;
+
+		enum hw_point_position hw_pos;
+
+		struct gamma_point *point;
+
+		struct fixed31_32 left_pos;
+		struct fixed31_32 right_pos;
+
+		if (pixel_format == PIXEL_FORMAT_FP16)
+			coord_x = opp110->
+			regamma.coordinates_x[i].adjusted_x;
+		else if (channel == CHANNEL_NAME_RED)
+			coord_x = opp110->
+			regamma.coordinates_x[i].regamma_y_red;
+		else if (channel == CHANNEL_NAME_GREEN)
+			coord_x = opp110->
+			regamma.coordinates_x[i].regamma_y_green;
+		else
+			coord_x = opp110->
+			regamma.coordinates_x[i].regamma_y_blue;
+
+		if (!find_software_points_dx(
+			opp110, coord_x, channel,
+			&index_to_start, &index_left, &index_right, &hw_pos)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (index_left >= DX_GAMMA_RAMP_MAX +
+				opp110->regamma.extra_points) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (index_right >= DX_GAMMA_RAMP_MAX +
+				opp110->regamma.extra_points) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (channel == CHANNEL_NAME_RED) {
+			point = &opp110->regamma.coeff128_dx[i].r;
+
+			left_pos = opp110->
+					regamma.axis_x_1025[index_left].r;
+			right_pos = opp110->
+					regamma.axis_x_1025[index_right].r;
+		} else if (channel == CHANNEL_NAME_GREEN) {
+			point = &opp110->regamma.coeff128_dx[i].g;
+
+			left_pos = opp110->
+					regamma.axis_x_1025[index_left].g;
+			right_pos = opp110->
+					regamma.axis_x_1025[index_right].g;
+		} else {
+			point = &opp110->regamma.coeff128_dx[i].b;
+
+			left_pos = opp110->
+					regamma.axis_x_1025[index_left].b;
+			right_pos = opp110->
+					regamma.axis_x_1025[index_right].b;
+		}
+
+		if (hw_pos == HW_POINT_POSITION_MIDDLE)
+			point->coeff = dal_fixed31_32_div(
+				dal_fixed31_32_sub(
+					coord_x,
+					left_pos),
+				dal_fixed31_32_sub(
+					right_pos,
+					left_pos));
+		else if (hw_pos == HW_POINT_POSITION_LEFT)
+			point->coeff = opp110->regamma.x_min;
+		else if (hw_pos == HW_POINT_POSITION_RIGHT)
+			point->coeff = opp110->regamma.x_max2;
+		else {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		point->left_index = index_left;
+		point->right_index = index_right;
+		point->pos = hw_pos;
+
+		++i;
+	}
+
+	return true;
+}
+
+static struct fixed31_32 calculate_mapped_value(
+	struct dce110_opp *opp110,
+	struct pwl_float_data *rgb,
+	const struct pixel_gamma_point *coeff,
+	enum channel_name channel,
+	uint32_t max_index)
+{
+	const struct gamma_point *point;
+
+	struct fixed31_32 result;
+
+	if (channel == CHANNEL_NAME_RED)
+		point = &coeff->r;
+	else if (channel == CHANNEL_NAME_GREEN)
+		point = &coeff->g;
+	else
+		point = &coeff->b;
+
+	if ((point->left_index < 0) || (point->left_index > max_index)) {
+		BREAK_TO_DEBUGGER();
+		return dal_fixed31_32_zero;
+	}
+
+	if ((point->right_index < 0) || (point->right_index > max_index)) {
+		BREAK_TO_DEBUGGER();
+		return dal_fixed31_32_zero;
+	}
+
+	if (point->pos == HW_POINT_POSITION_MIDDLE)
+		if (channel == CHANNEL_NAME_RED)
+			result = dal_fixed31_32_add(
+				dal_fixed31_32_mul(
+					point->coeff,
+					dal_fixed31_32_sub(
+						rgb[point->right_index].r,
+						rgb[point->left_index].r)),
+				rgb[point->left_index].r);
+		else if (channel == CHANNEL_NAME_GREEN)
+			result = dal_fixed31_32_add(
+				dal_fixed31_32_mul(
+					point->coeff,
+					dal_fixed31_32_sub(
+						rgb[point->right_index].g,
+						rgb[point->left_index].g)),
+				rgb[point->left_index].g);
+		else
+			result = dal_fixed31_32_add(
+				dal_fixed31_32_mul(
+					point->coeff,
+					dal_fixed31_32_sub(
+						rgb[point->right_index].b,
+						rgb[point->left_index].b)),
+				rgb[point->left_index].b);
+	else if (point->pos == HW_POINT_POSITION_LEFT) {
+		BREAK_TO_DEBUGGER();
+		result = opp110->regamma.x_min;
+	} else {
+		BREAK_TO_DEBUGGER();
+		result = opp110->regamma.x_max1;
+	}
+
+	return result;
+}
+
+static inline struct fixed31_32 calculate_regamma_user_mapped_value(
+	struct dce110_opp *opp110,
+	const struct pixel_gamma_point *coeff,
+	enum channel_name channel,
+	uint32_t max_index)
+{
+	return calculate_mapped_value(
+		opp110, opp110->regamma.rgb_oem,
+		coeff, channel, max_index);
+}
+
+static inline struct fixed31_32 calculate_user_mapped_value(
+	struct dce110_opp *opp110,
+	const struct pixel_gamma_point *coeff,
+	enum channel_name channel,
+	uint32_t max_index)
+{
+	return calculate_mapped_value(
+		opp110, opp110->regamma.rgb_user,
+		coeff, channel, max_index);
+}
+
+static inline struct fixed31_32 calculate_oem_mapped_value(
+	struct dce110_opp *opp110,
+	uint32_t index,
+	enum channel_name channel,
+	uint32_t max_index)
+{
+	return calculate_regamma_user_mapped_value(
+		opp110, opp110->regamma.coeff128_oem +
+		index, channel, max_index);
+}
+
+static void scale_oem_gamma(
+	struct dce110_opp *opp110,
+	const struct regamma_ramp *regamma_ramp)
+{
+	const uint16_t max_driver = 0xFFFF;
+	const uint16_t max_os = 0xFF00;
+
+	uint16_t scale = max_os;
+
+	uint32_t i;
+
+	struct pwl_float_data *rgb = opp110->regamma.rgb_oem;
+	struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1;
+
+	/* find OEM maximum */
+
+	i = 0;
+
+	do {
+		if ((regamma_ramp->gamma[i] > max_os) ||
+			(regamma_ramp->gamma[i + RGB_256X3X16] > max_os) ||
+			(regamma_ramp->gamma[i + 2 * RGB_256X3X16] > max_os)) {
+			scale = max_driver;
+			break;
+		}
+
+		++i;
+	} while (i != RGB_256X3X16);
+
+	/* scale */
+
+	i = 0;
+
+	do {
+		rgb->r = dal_fixed31_32_div_int(
+			dal_fixed31_32_from_int(
+				regamma_ramp->gamma[i]),
+			scale);
+		rgb->g = dal_fixed31_32_div_int(
+			dal_fixed31_32_from_int(
+				regamma_ramp->gamma[i + RGB_256X3X16]),
+			scale);
+		rgb->b = dal_fixed31_32_div_int(
+			dal_fixed31_32_from_int(
+				regamma_ramp->gamma[i + 2 * RGB_256X3X16]),
+			scale);
+
+		++rgb;
+		++i;
+	} while (i != RGB_256X3X16);
+
+	/* add 3 extra points, 2 physical plus 1 virtual */
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider1);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider1);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider1);
+
+	++rgb;
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider2);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider2);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider2);
+
+	++rgb;
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider3);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider3);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider3);
+}
+
+static inline void copy_rgb_regamma_to_coordinates_x(
+	struct dce110_opp *opp110)
+{
+	struct hw_x_point *coords = opp110->regamma.coordinates_x;
+	const struct pwl_float_data_ex *rgb_regamma =
+			opp110->regamma.rgb_regamma;
+
+	uint32_t i = 0;
+
+	while (i <= opp110->regamma.hw_points_num) {
+		coords->regamma_y_red = rgb_regamma->r;
+		coords->regamma_y_green = rgb_regamma->g;
+		coords->regamma_y_blue = rgb_regamma->b;
+
+		++coords;
+		++rgb_regamma;
+		++i;
+	}
+}
+
+static bool calculate_interpolated_hardware_curve(
+	struct dce110_opp *opp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct pwl_result_data *rgb_resulted =
+			opp110->regamma.rgb_resulted;
+
+	const struct pixel_gamma_point *coeff;
+	uint32_t max_entries = opp110->regamma.extra_points - 1;
+
+	uint32_t i = 0;
+
+	if (gamma_ramp->type == GAMMA_RAMP_RBG256X3X16) {
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		coeff = opp110->regamma.coeff128;
+		max_entries += RGB_256X3X16;
+	} else if (gamma_ramp->type == GAMMA_RAMP_DXGI_1) {
+		if (!build_custom_dx_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_dx_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_dx_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		coeff = opp110->regamma.coeff128_dx;
+		max_entries += DX_GAMMA_RAMP_MAX;
+	} else {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	while (i <= opp110->regamma.hw_points_num) {
+		rgb_resulted->red = calculate_user_mapped_value(
+			opp110, coeff, CHANNEL_NAME_RED, max_entries);
+		rgb_resulted->green = calculate_user_mapped_value(
+			opp110, coeff, CHANNEL_NAME_GREEN, max_entries);
+		rgb_resulted->blue = calculate_user_mapped_value(
+			opp110, coeff, CHANNEL_NAME_BLUE, max_entries);
+
+		++coeff;
+		++rgb_resulted;
+		++i;
+	}
+
+	return true;
+}
+
+static void map_standard_regamma_hw_to_x_user(
+	struct dce110_opp *opp110,
+	enum gamma_ramp_type type,
+	const struct gamma_parameters *params)
+{
+	struct pwl_result_data *rgb_resulted =
+			opp110->regamma.rgb_resulted;
+	const struct pwl_float_data_ex *rgb_regamma =
+			opp110->regamma.rgb_regamma;
+
+	uint32_t i = 0;
+
+	while (i <= opp110->regamma.hw_points_num) {
+		rgb_resulted->red = rgb_regamma->r;
+		rgb_resulted->green = rgb_regamma->g;
+		rgb_resulted->blue = rgb_regamma->b;
+
+		++rgb_resulted;
+		++rgb_regamma;
+		++i;
+	}
+}
+
+bool dce110_opp_map_legacy_and_regamma_hw_to_x_user(
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	if (params->regamma.features.bits.GAMMA_RAMP_ARRAY ||
+		params->regamma.features.bits.APPLY_DEGAMMA) {
+
+		const uint32_t max_entries =
+			RGB_256X3X16 + opp110->regamma.extra_points - 1;
+
+		const struct pixel_gamma_point *coeff =
+				opp110->regamma.coeff128;
+		struct pwl_result_data *rgb_resulted =
+				opp110->regamma.rgb_resulted;
+
+		uint32_t i = 0;
+
+		scale_oem_gamma(opp110, &params->regamma.regamma_ramp);
+
+		copy_rgb_regamma_to_coordinates_x(opp110);
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		while (i <= opp110->regamma.hw_points_num) {
+			rgb_resulted->red =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_RED, max_entries);
+			rgb_resulted->green =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_GREEN, max_entries);
+			rgb_resulted->blue =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_BLUE, max_entries);
+
+			++coeff;
+			++rgb_resulted;
+			++i;
+		}
+	} else
+		map_standard_regamma_hw_to_x_user(opp110,
+				gamma_ramp->type,
+				params);
+
+	return true;
+}
+
+static bool map_regamma_hw_to_x_user(
+	struct dce110_opp *opp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	/* setup to spare calculated ideal regamma values */
+	if (params->regamma.features.bits.GAMMA_RAMP_ARRAY ||
+		params->regamma.features.bits.APPLY_DEGAMMA) {
+
+		const uint32_t max_entries =
+			RGB_256X3X16 + opp110->regamma.extra_points - 1;
+
+		const struct pixel_gamma_point *coeff =
+				opp110->regamma.coeff128;
+		struct hw_x_point *coords =
+				opp110->regamma.coordinates_x;
+
+		uint32_t i = 0;
+
+		scale_oem_gamma(opp110, &params->regamma.regamma_ramp);
+
+		copy_rgb_regamma_to_coordinates_x(opp110);
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		while (i <= opp110->regamma.hw_points_num) {
+			coords->regamma_y_red =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_RED, max_entries);
+			coords->regamma_y_green =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_GREEN, max_entries);
+			coords->regamma_y_blue =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_BLUE, max_entries);
+
+			++coeff;
+			++coords;
+			++i;
+		}
+	} else {
+		copy_rgb_regamma_to_coordinates_x(opp110);
+	}
+
+	return calculate_interpolated_hardware_curve(opp110, gamma_ramp,
+		params);
+}
+
+static void build_regamma_coefficients(
+	const struct regamma_lut *regamma,
+	bool is_degamma_srgb,
+	struct gamma_coefficients *coefficients)
+{
+	/* sRGB should apply 2.4 */
+	static const int32_t numerator01[3] = { 31308, 31308, 31308 };
+	static const int32_t numerator02[3] = { 12920, 12920, 12920 };
+	static const int32_t numerator03[3] = { 55, 55, 55 };
+	static const int32_t numerator04[3] = { 55, 55, 55 };
+	static const int32_t numerator05[3] = { 2400, 2400, 2400 };
+
+	/* Non-sRGB should apply 2.2 */
+	static const int32_t numerator11[3] = { 180000, 180000, 180000 };
+	static const int32_t numerator12[3] = { 4500, 4500, 4500 };
+	static const int32_t numerator13[3] = { 99, 99, 99 };
+	static const int32_t numerator14[3] = { 99, 99, 99 };
+	static const int32_t numerator15[3] = { 2200, 2200, 2200 };
+
+	const int32_t *numerator1;
+	const int32_t *numerator2;
+	const int32_t *numerator3;
+	const int32_t *numerator4;
+	const int32_t *numerator5;
+
+	uint32_t i = 0;
+
+	if (!regamma->features.bits.GAMMA_RAMP_ARRAY) {
+		numerator1 = regamma->gamma_coeff.a0;
+		numerator2 = regamma->gamma_coeff.a1;
+		numerator3 = regamma->gamma_coeff.a2;
+		numerator4 = regamma->gamma_coeff.a3;
+		numerator5 = regamma->gamma_coeff.gamma;
+	} else if (is_degamma_srgb) {
+		numerator1 = numerator01;
+		numerator2 = numerator02;
+		numerator3 = numerator03;
+		numerator4 = numerator04;
+		numerator5 = numerator05;
+	} else {
+		numerator1 = numerator11;
+		numerator2 = numerator12;
+		numerator3 = numerator13;
+		numerator4 = numerator14;
+		numerator5 = numerator15;
+	}
+
+	do {
+		coefficients->a0[i] = dal_fixed31_32_from_fraction(
+			numerator1[i], 10000000);
+		coefficients->a1[i] = dal_fixed31_32_from_fraction(
+			numerator2[i], 1000);
+		coefficients->a2[i] = dal_fixed31_32_from_fraction(
+			numerator3[i], 1000);
+		coefficients->a3[i] = dal_fixed31_32_from_fraction(
+			numerator4[i], 1000);
+		coefficients->user_gamma[i] = dal_fixed31_32_from_fraction(
+			numerator5[i], 1000);
+
+		++i;
+	} while (i != ARRAY_SIZE(regamma->gamma_coeff.a0));
+}
+
+static struct fixed31_32 translate_from_linear_space(
+	struct fixed31_32 arg,
+	struct fixed31_32 a0,
+	struct fixed31_32 a1,
+	struct fixed31_32 a2,
+	struct fixed31_32 a3,
+	struct fixed31_32 gamma)
+{
+	const struct fixed31_32 one = dal_fixed31_32_from_int(1);
+
+	if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0)))
+		return dal_fixed31_32_sub(
+			a2,
+			dal_fixed31_32_mul(
+				dal_fixed31_32_add(
+					one,
+					a3),
+				dal_fixed31_32_pow(
+					dal_fixed31_32_neg(arg),
+					dal_fixed31_32_recip(gamma))));
+	else if (dal_fixed31_32_le(a0, arg))
+		return dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				dal_fixed31_32_add(
+					one,
+					a3),
+				dal_fixed31_32_pow(
+					arg,
+					dal_fixed31_32_recip(gamma))),
+			a2);
+	else
+		return dal_fixed31_32_mul(
+			arg,
+			a1);
+}
+
+static inline struct fixed31_32 translate_from_linear_space_ex(
+	struct fixed31_32 arg,
+	struct gamma_coefficients *coeff,
+	uint32_t color_index)
+{
+	return translate_from_linear_space(
+		arg,
+		coeff->a0[color_index],
+		coeff->a1[color_index],
+		coeff->a2[color_index],
+		coeff->a3[color_index],
+		coeff->user_gamma[color_index]);
+}
+
+static bool build_regamma_curve(
+	struct dce110_opp *opp110,
+	const struct gamma_parameters *params)
+{
+	struct pwl_float_data_ex *rgb = opp110->regamma.rgb_regamma;
+
+	uint32_t i;
+
+	struct gamma_coefficients coeff;
+
+	struct hw_x_point *coord_x =
+		opp110->regamma.coordinates_x;
+
+	build_regamma_coefficients(
+		&params->regamma,
+		params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB,
+		&coeff);
+
+	/* Use opp110->regamma.coordinates_x to retrieve
+	 * coordinates chosen base on given user curve (future task).
+	 * The x values are exponentially distributed and currently
+	 * it is hard-coded, the user curve shape is ignored.
+	 * The future task is to recalculate opp110-
+	 * regamma.coordinates_x based on input/user curve,
+	 * translation from 256/1025 to 128 pwl points.
+	 */
+
+	i = 0;
+
+	while (i != opp110->regamma.hw_points_num + 1) {
+		rgb->r = translate_from_linear_space_ex(
+			coord_x->adjusted_x, &coeff, 0);
+		rgb->g = translate_from_linear_space_ex(
+			coord_x->adjusted_x, &coeff, 1);
+		rgb->b = translate_from_linear_space_ex(
+			coord_x->adjusted_x, &coeff, 2);
+
+		++coord_x;
+		++rgb;
+		++i;
+	}
+
+	if (params->regamma.features.bits.GAMMA_RAMP_ARRAY &&
+			!params->regamma.features.bits.APPLY_DEGAMMA) {
+		const uint32_t max_entries =
+			RGB_256X3X16 + opp110->regamma.extra_points - 1;
+
+		/* interpolate between 256 input points and output 185 points */
+
+		scale_oem_gamma(opp110, &params->regamma.regamma_ramp);
+
+		if (!build_oem_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_oem_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_oem_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		i = 0;
+
+		while (i != opp110->regamma.hw_points_num + 1) {
+			rgb->r = calculate_oem_mapped_value(
+				opp110, i, CHANNEL_NAME_RED, max_entries);
+			rgb->g = calculate_oem_mapped_value(
+				opp110, i, CHANNEL_NAME_GREEN, max_entries);
+			rgb->b = calculate_oem_mapped_value(
+				opp110, i, CHANNEL_NAME_BLUE, max_entries);
+			++rgb;
+			++i;
+		}
+	}
+
+	return true;
+}
+
+static void build_new_custom_resulted_curve(
+	struct dce110_opp *opp110,
+	const struct gamma_parameters *params)
+{
+	struct pwl_result_data *rgb = opp110->regamma.rgb_resulted;
+	struct pwl_result_data *rgb_plus_1 = rgb + 1;
+
+	uint32_t i;
+
+	i = 0;
+
+	while (i != opp110->regamma.hw_points_num + 1) {
+		rgb->red = dal_fixed31_32_clamp(
+			rgb->red, opp110->regamma.x_min,
+			opp110->regamma.x_max1);
+		rgb->green = dal_fixed31_32_clamp(
+			rgb->green, opp110->regamma.x_min,
+			opp110->regamma.x_max1);
+		rgb->blue = dal_fixed31_32_clamp(
+			rgb->blue, opp110->regamma.x_min,
+			opp110->regamma.x_max1);
+
+		++rgb;
+		++i;
+	}
+
+	rgb = opp110->regamma.rgb_resulted;
+
+	i = 1;
+
+	while (i != opp110->regamma.hw_points_num + 1) {
+		if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
+			rgb_plus_1->red = rgb->red;
+		if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
+			rgb_plus_1->green = rgb->green;
+		if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
+			rgb_plus_1->blue = rgb->blue;
+
+		rgb->delta_red = dal_fixed31_32_sub(
+			rgb_plus_1->red,
+			rgb->red);
+		rgb->delta_green = dal_fixed31_32_sub(
+			rgb_plus_1->green,
+			rgb->green);
+		rgb->delta_blue = dal_fixed31_32_sub(
+			rgb_plus_1->blue,
+			rgb->blue);
+
+		++rgb_plus_1;
+		++rgb;
+		++i;
+	}
+}
+
+static bool rebuild_curve_configuration_magic(
+	struct dce110_opp *opp110)
+{
+	const struct fixed31_32 magic_number =
+		dal_fixed31_32_from_fraction(249, 1000);
+
+	struct fixed31_32 y_r;
+	struct fixed31_32 y_g;
+	struct fixed31_32 y_b;
+
+	struct fixed31_32 y1_min;
+	struct fixed31_32 y2_max;
+	struct fixed31_32 y3_max;
+
+	y_r = opp110->regamma.rgb_resulted[0].red;
+	y_g = opp110->regamma.rgb_resulted[0].green;
+	y_b = opp110->regamma.rgb_resulted[0].blue;
+
+	y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
+
+	opp110->regamma.arr_points[0].x =
+			opp110->regamma.coordinates_x[0].adjusted_x;
+	opp110->regamma.arr_points[0].y = y1_min;
+	opp110->regamma.arr_points[0].slope = dal_fixed31_32_div(
+		opp110->regamma.arr_points[0].y,
+		opp110->regamma.arr_points[0].x);
+
+	opp110->regamma.arr_points[1].x = dal_fixed31_32_add(
+		opp110->regamma.coordinates_x
+		[opp110->regamma.hw_points_num - 1].adjusted_x,
+		magic_number);
+
+	opp110->regamma.arr_points[2].x =
+			opp110->regamma.arr_points[1].x;
+
+	y_r = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num - 1].red;
+	y_g = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num - 1].green;
+	y_b = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num - 1].blue;
+
+	y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
+
+	opp110->regamma.arr_points[1].y = y2_max;
+
+	y_r = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num].red;
+	y_g = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num].green;
+	y_b = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num].blue;
+
+	y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
+
+	opp110->regamma.arr_points[2].y = y3_max;
+
+	opp110->regamma.arr_points[2].slope = dal_fixed31_32_one;
+
+	return true;
+}
+
+static bool build_custom_float(
+	struct fixed31_32 value,
+	const struct custom_float_format *format,
+	bool *negative,
+	uint32_t *mantissa,
+	uint32_t *exponenta)
+{
+	uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
+
+	const struct fixed31_32 mantissa_constant_plus_max_fraction =
+		dal_fixed31_32_from_fraction(
+			(1LL << (format->mantissa_bits + 1)) - 1,
+			1LL << format->mantissa_bits);
+
+	struct fixed31_32 mantiss;
+
+	if (dal_fixed31_32_eq(
+		value,
+		dal_fixed31_32_zero)) {
+		*negative = false;
+		*mantissa = 0;
+		*exponenta = 0;
+		return true;
+	}
+
+	if (dal_fixed31_32_lt(
+		value,
+		dal_fixed31_32_zero)) {
+		*negative = format->sign;
+		value = dal_fixed31_32_neg(value);
+	} else {
+		*negative = false;
+	}
+
+	if (dal_fixed31_32_lt(
+		value,
+		dal_fixed31_32_one)) {
+		uint32_t i = 1;
+
+		do {
+			value = dal_fixed31_32_shl(value, 1);
+			++i;
+		} while (dal_fixed31_32_lt(
+			value,
+			dal_fixed31_32_one));
+
+		--i;
+
+		if (exp_offset <= i) {
+			*mantissa = 0;
+			*exponenta = 0;
+			return true;
+		}
+
+		*exponenta = exp_offset - i;
+	} else if (dal_fixed31_32_le(
+		mantissa_constant_plus_max_fraction,
+		value)) {
+		uint32_t i = 1;
+
+		do {
+			value = dal_fixed31_32_shr(value, 1);
+			++i;
+		} while (dal_fixed31_32_lt(
+			mantissa_constant_plus_max_fraction,
+			value));
+
+		*exponenta = exp_offset + i - 1;
+	} else {
+		*exponenta = exp_offset;
+	}
+
+	mantiss = dal_fixed31_32_sub(
+		value,
+		dal_fixed31_32_one);
+
+	if (dal_fixed31_32_lt(
+			mantiss,
+			dal_fixed31_32_zero) ||
+		dal_fixed31_32_lt(
+			dal_fixed31_32_one,
+			mantiss))
+		mantiss = dal_fixed31_32_zero;
+	else
+		mantiss = dal_fixed31_32_shl(
+			mantiss,
+			format->mantissa_bits);
+
+	*mantissa = dal_fixed31_32_floor(mantiss);
+
+	return true;
+}
+
+static bool setup_custom_float(
+	const struct custom_float_format *format,
+	bool negative,
+	uint32_t mantissa,
+	uint32_t exponenta,
+	uint32_t *result)
+{
+	uint32_t i = 0;
+	uint32_t j = 0;
+
+	uint32_t value = 0;
+
+	/* verification code:
+	 * once calculation is ok we can remove it */
+
+	const uint32_t mantissa_mask =
+		(1 << (format->mantissa_bits + 1)) - 1;
+
+	const uint32_t exponenta_mask =
+		(1 << (format->exponenta_bits + 1)) - 1;
+
+	if (mantissa & ~mantissa_mask) {
+		BREAK_TO_DEBUGGER();
+		mantissa = mantissa_mask;
+	}
+
+	if (exponenta & ~exponenta_mask) {
+		BREAK_TO_DEBUGGER();
+		exponenta = exponenta_mask;
+	}
+
+	/* end of verification code */
+
+	while (i < format->mantissa_bits) {
+		uint32_t mask = 1 << i;
+
+		if (mantissa & mask)
+			value |= mask;
+
+		++i;
+	}
+
+	while (j < format->exponenta_bits) {
+		uint32_t mask = 1 << j;
+
+		if (exponenta & mask)
+			value |= mask << i;
+
+		++j;
+	}
+
+	if (negative && format->sign)
+		value |= 1 << (i + j);
+
+	*result = value;
+
+	return true;
+}
+
+static bool convert_to_custom_float_format(
+	struct fixed31_32 value,
+	const struct custom_float_format *format,
+	uint32_t *result)
+{
+	uint32_t mantissa;
+	uint32_t exponenta;
+	bool negative;
+
+	return build_custom_float(
+		value, format, &negative, &mantissa, &exponenta) &&
+	setup_custom_float(
+		format, negative, mantissa, exponenta, result);
+}
+
+static bool convert_to_custom_float_format_ex(
+	struct fixed31_32 value,
+	const struct custom_float_format *format,
+	struct custom_float_value *result)
+{
+	return build_custom_float(
+		value, format,
+		&result->negative, &result->mantissa, &result->exponenta) &&
+	setup_custom_float(
+		format, result->negative, result->mantissa, result->exponenta,
+		&result->value);
+}
+
+static bool convert_to_custom_float(
+	struct dce110_opp *opp110)
+{
+	struct custom_float_format fmt;
+
+	struct pwl_result_data *rgb = opp110->regamma.rgb_resulted;
+
+	uint32_t i = 0;
+
+	fmt.exponenta_bits = 6;
+	fmt.mantissa_bits = 12;
+	fmt.sign = true;
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[0].x,
+		&fmt,
+		&opp110->regamma.arr_points[0].custom_float_x)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[0].offset,
+		&fmt,
+		&opp110->regamma.arr_points[0].custom_float_offset)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[0].slope,
+		&fmt,
+		&opp110->regamma.arr_points[0].custom_float_slope)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	fmt.mantissa_bits = 10;
+	fmt.sign = false;
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[1].x,
+		&fmt,
+		&opp110->regamma.arr_points[1].custom_float_x)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[1].y,
+		&fmt,
+		&opp110->regamma.arr_points[1].custom_float_y)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[2].slope,
+		&fmt,
+		&opp110->regamma.arr_points[2].custom_float_slope)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	fmt.mantissa_bits = 12;
+	fmt.sign = true;
+
+	while (i != opp110->regamma.hw_points_num) {
+		if (!convert_to_custom_float_format(
+			rgb->red,
+			&fmt,
+			&rgb->red_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->green,
+			&fmt,
+			&rgb->green_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->blue,
+			&fmt,
+			&rgb->blue_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->delta_red,
+			&fmt,
+			&rgb->delta_red_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->delta_green,
+			&fmt,
+			&rgb->delta_green_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->delta_blue,
+			&fmt,
+			&rgb->delta_blue_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		++rgb;
+		++i;
+	}
+
+	return true;
+}
+
+static bool round_custom_float_6_12(
+	struct hw_x_point *x)
+{
+	struct custom_float_format fmt;
+
+	struct custom_float_value value;
+
+	fmt.exponenta_bits = 6;
+	fmt.mantissa_bits = 12;
+	fmt.sign = true;
+
+	if (!convert_to_custom_float_format_ex(
+		x->x, &fmt, &value))
+		return false;
+
+	x->adjusted_x = x->x;
+
+	if (value.mantissa) {
+		BREAK_TO_DEBUGGER();
+
+		return false;
+	}
+
+	return true;
+}
+
+static bool build_hw_curve_configuration(
+	const struct curve_config *curve_config,
+	struct gamma_curve *gamma_curve,
+	struct curve_points *curve_points,
+	struct hw_x_point *points,
+	uint32_t *number_of_points)
+{
+	const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments);
+
+	int8_t i;
+
+	uint8_t segments_calculation[8] = { 0 };
+
+	struct fixed31_32 region1 = dal_fixed31_32_zero;
+	struct fixed31_32 region2;
+	struct fixed31_32 increment;
+
+	uint32_t index = 0;
+	uint32_t segments = 0;
+	uint32_t max_number;
+
+	bool result = false;
+
+	if (!number_of_points) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	max_number = *number_of_points;
+
+	i = 0;
+
+	while (i != max_regions_number) {
+		gamma_curve[i].offset = 0;
+		gamma_curve[i].segments_num = 0;
+
+		++i;
+	}
+
+	i = 0;
+
+	while (i != max_regions_number) {
+		/* number should go in uninterruptible sequence */
+		if (curve_config->segments[i] == -1)
+			break;
+
+		ASSERT(curve_config->segments[i] >= 0);
+
+		segments += (1 << curve_config->segments[i]);
+
+		++i;
+	}
+
+	if (segments > max_number) {
+		BREAK_TO_DEBUGGER();
+	} else {
+		int32_t divisor;
+		uint32_t offset = 0;
+		int8_t begin = curve_config->begin;
+		int32_t region_number = 0;
+
+		i = begin;
+
+		while ((index < max_number) &&
+			(region_number < max_regions_number) &&
+			(i <= 1)) {
+			int32_t j = 0;
+
+			segments = curve_config->segments[region_number];
+			divisor = 1 << segments;
+
+			if (segments == -1) {
+				if (i > 0) {
+					region1 = dal_fixed31_32_shl(
+						dal_fixed31_32_one,
+						i - 1);
+					region2 = dal_fixed31_32_shl(
+						dal_fixed31_32_one,
+						i);
+				} else {
+					region1 = dal_fixed31_32_shr(
+						dal_fixed31_32_one,
+						-(i - 1));
+					region2 = dal_fixed31_32_shr(
+						dal_fixed31_32_one,
+						-i);
+				}
+
+				break;
+			}
+
+			if (i > -1) {
+				region1 = dal_fixed31_32_shl(
+					dal_fixed31_32_one,
+					i);
+				region2 = dal_fixed31_32_shl(
+					dal_fixed31_32_one,
+					i + 1);
+			} else {
+				region1 = dal_fixed31_32_shr(
+					dal_fixed31_32_one,
+					-i);
+				region2 = dal_fixed31_32_shr(
+					dal_fixed31_32_one,
+					-(i + 1));
+			}
+
+			gamma_curve[region_number].offset = offset;
+			gamma_curve[region_number].segments_num = segments;
+
+			offset += divisor;
+
+			++segments_calculation[segments];
+
+			increment = dal_fixed31_32_div_int(
+				dal_fixed31_32_sub(
+					region2,
+					region1),
+				divisor);
+
+			points[index].x = region1;
+
+			round_custom_float_6_12(points + index);
+
+			++index;
+			++region_number;
+
+			while ((index < max_number) && (j < divisor - 1)) {
+				region1 = dal_fixed31_32_add(
+					region1,
+					increment);
+
+				points[index].x = region1;
+				points[index].adjusted_x = region1;
+
+				++index;
+				++j;
+			}
+
+			++i;
+		}
+
+		points[index].x = region1;
+
+		round_custom_float_6_12(points + index);
+
+		*number_of_points = index;
+
+		result = true;
+	}
+
+	curve_points[0].x = points[0].adjusted_x;
+	curve_points[0].offset = dal_fixed31_32_zero;
+
+	curve_points[1].x = points[index - 1].adjusted_x;
+	curve_points[1].offset = dal_fixed31_32_zero;
+
+	curve_points[2].x = points[index].adjusted_x;
+	curve_points[2].offset = dal_fixed31_32_zero;
+
+	return result;
+}
+
+static bool setup_distribution_points(
+	struct dce110_opp *opp110)
+{
+	uint32_t hw_points_num = MAX_PWL_ENTRY * 2;
+
+	struct curve_config cfg;
+
+	cfg.offset = 0;
+
+		cfg.segments[0] = 3;
+		cfg.segments[1] = 4;
+		cfg.segments[2] = 4;
+		cfg.segments[3] = 4;
+		cfg.segments[4] = 4;
+		cfg.segments[5] = 4;
+		cfg.segments[6] = 4;
+		cfg.segments[7] = 4;
+		cfg.segments[8] = 5;
+		cfg.segments[9] = 5;
+		cfg.segments[10] = 0;
+		cfg.segments[11] = -1;
+		cfg.segments[12] = -1;
+		cfg.segments[13] = -1;
+		cfg.segments[14] = -1;
+		cfg.segments[15] = -1;
+
+	cfg.begin = -10;
+
+	if (!build_hw_curve_configuration(
+		&cfg, opp110->regamma.arr_curve_points,
+		opp110->regamma.arr_points,
+		opp110->regamma.coordinates_x, &hw_points_num)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	opp110->regamma.hw_points_num = hw_points_num;
+
+	return true;
+}
+
+
+/*
+ *****************************************************************************
+ *  Function: regamma_config_regions_and_segments
+ *
+ *     build regamma curve by using predefined hw points
+ *     uses interface parameters ,like EDID coeff.
+ *
+ * @param   : parameters   interface parameters
+ *  @return void
+ *
+ *  @note
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void regamma_config_regions_and_segments(
+	struct dce110_opp *opp110)
+{
+	struct gamma_curve *curve;
+	uint32_t value = 0;
+
+	{
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[0].custom_float_x,
+			REGAMMA_CNTLA_START_CNTL,
+			REGAMMA_CNTLA_EXP_REGION_START);
+
+		set_reg_field_value(
+			value,
+			0,
+			REGAMMA_CNTLA_START_CNTL,
+			REGAMMA_CNTLA_EXP_REGION_START_SEGMENT);
+
+		dm_write_reg(opp110->base.ctx,
+				DCP_REG(mmREGAMMA_CNTLA_START_CNTL),
+				value);
+	}
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[0].custom_float_slope,
+			REGAMMA_CNTLA_SLOPE_CNTL,
+			REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value);
+	}
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[1].custom_float_x,
+			REGAMMA_CNTLA_END_CNTL1,
+			REGAMMA_CNTLA_EXP_REGION_END);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value);
+	}
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[2].custom_float_slope,
+			REGAMMA_CNTLA_END_CNTL2,
+			REGAMMA_CNTLA_EXP_REGION_END_BASE);
+
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[1].custom_float_y,
+			REGAMMA_CNTLA_END_CNTL2,
+			REGAMMA_CNTLA_EXP_REGION_END_SLOPE);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value);
+	}
+
+	curve = opp110->regamma.arr_curve_points;
+
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS);
+
+		dm_write_reg(
+			opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_0_1),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_2_3),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_4_5),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_6_7),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_8_9),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_10_11),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_12_13),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_14_15),
+			value);
+	}
+}
+
+static void program_pwl(
+	struct dce110_opp *opp110,
+	const struct gamma_parameters *params)
+{
+	uint32_t value;
+
+	{
+		uint8_t max_tries = 10;
+		uint8_t counter = 0;
+
+		/* Power on LUT memory */
+		value = dm_read_reg(opp110->base.ctx,
+				DCFE_REG(mmDCFE_MEM_PWR_CTRL));
+
+		set_reg_field_value(
+			value,
+			1,
+			DCFE_MEM_PWR_CTRL,
+			DCP_REGAMMA_MEM_PWR_DIS);
+
+		dm_write_reg(opp110->base.ctx,
+				DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
+
+		while (counter < max_tries) {
+			value =
+				dm_read_reg(
+					opp110->base.ctx,
+					DCFE_REG(mmDCFE_MEM_PWR_STATUS));
+
+			if (get_reg_field_value(
+				value,
+				DCFE_MEM_PWR_STATUS,
+				DCP_REGAMMA_MEM_PWR_STATE) == 0)
+				break;
+
+			++counter;
+		}
+
+		if (counter == max_tries) {
+			dal_logger_write(opp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: regamma lut was not powered on "
+				"in a timely manner,"
+				" programming still proceeds\n",
+				__func__);
+		}
+	}
+
+	value = 0;
+
+	set_reg_field_value(
+		value,
+		7,
+		REGAMMA_LUT_WRITE_EN_MASK,
+		REGAMMA_LUT_WRITE_EN_MASK);
+
+	dm_write_reg(opp110->base.ctx,
+		DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value);
+	dm_write_reg(opp110->base.ctx,
+		DCP_REG(mmREGAMMA_LUT_INDEX), 0);
+
+	/* Program REGAMMA_LUT_DATA */
+	{
+		const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA);
+
+		uint32_t i = 0;
+
+		struct pwl_result_data *rgb =
+				opp110->regamma.rgb_resulted;
+
+		while (i != opp110->regamma.hw_points_num) {
+			dm_write_reg(opp110->base.ctx, addr, rgb->red_reg);
+			dm_write_reg(opp110->base.ctx, addr, rgb->green_reg);
+			dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg);
+
+			dm_write_reg(opp110->base.ctx, addr,
+				rgb->delta_red_reg);
+			dm_write_reg(opp110->base.ctx, addr,
+				rgb->delta_green_reg);
+			dm_write_reg(opp110->base.ctx, addr,
+				rgb->delta_blue_reg);
+
+			++rgb;
+			++i;
+		}
+	}
+
+	/*  we are done with DCP LUT memory; re-enable low power mode */
+	value = dm_read_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL));
+
+	set_reg_field_value(
+		value,
+		0,
+		DCFE_MEM_PWR_CTRL,
+		DCP_REGAMMA_MEM_PWR_DIS);
+
+	dm_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
+}
+
+void dce110_opp_power_on_regamma_lut(
+	struct output_pixel_processor *opp,
+	bool power_on)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	uint32_t value =
+		dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL));
+
+	set_reg_field_value(
+		value,
+		power_on,
+		DCFE_MEM_PWR_CTRL,
+		DCP_REGAMMA_MEM_PWR_DIS);
+
+	set_reg_field_value(
+		value,
+		power_on,
+		DCFE_MEM_PWR_CTRL,
+		DCP_LUT_MEM_PWR_DIS);
+
+	dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
+}
+
+static bool scale_gamma(
+	struct dce110_opp *opp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	const struct gamma_ramp_rgb256x3x16 *gamma;
+	bool use_palette = params->surface_pixel_format == PIXEL_FORMAT_INDEX8;
+
+	const uint16_t max_driver = 0xFFFF;
+	const uint16_t max_os = 0xFF00;
+
+	uint16_t scaler = max_os;
+
+	uint32_t i;
+
+	struct dev_c_lut *palette = opp110->regamma.saved_palette;
+
+	struct pwl_float_data *rgb = opp110->regamma.rgb_user;
+	struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1;
+
+	if (gamma_ramp->type == GAMMA_RAMP_RBG256X3X16)
+		gamma = &gamma_ramp->gamma_ramp_rgb256x3x16;
+	else
+		return false; /* invalid option */
+
+	i = 0;
+
+	do {
+		if ((gamma->red[i] > max_os) ||
+			(gamma->green[i] > max_os) ||
+			(gamma->blue[i] > max_os)) {
+			scaler = max_driver;
+			break;
+		}
+		++i;
+	} while (i != RGB_256X3X16);
+
+	i = 0;
+
+	if (use_palette)
+		do {
+			rgb->r = dal_fixed31_32_from_fraction(
+				gamma->red[palette->red], scaler);
+			rgb->g = dal_fixed31_32_from_fraction(
+				gamma->green[palette->green], scaler);
+			rgb->b = dal_fixed31_32_from_fraction(
+				gamma->blue[palette->blue], scaler);
+
+			++palette;
+			++rgb;
+			++i;
+		} while (i != RGB_256X3X16);
+	else
+		do {
+			rgb->r = dal_fixed31_32_from_fraction(
+				gamma->red[i], scaler);
+			rgb->g = dal_fixed31_32_from_fraction(
+				gamma->green[i], scaler);
+			rgb->b = dal_fixed31_32_from_fraction(
+				gamma->blue[i], scaler);
+
+			++rgb;
+			++i;
+		} while (i != RGB_256X3X16);
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider1);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider1);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider1);
+
+	++rgb;
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider2);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider2);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider2);
+
+	++rgb;
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider3);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider3);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider3);
+
+	return true;
+}
+
+
+static void configure_regamma_mode(
+	struct dce110_opp *opp110,
+	const struct gamma_parameters *params,
+	bool force_bypass)
+{
+	const uint32_t addr = DCP_REG(mmREGAMMA_CONTROL);
+
+	enum wide_gamut_regamma_mode mode =
+		WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A;
+
+	uint32_t value = dm_read_reg(opp110->base.ctx, addr);
+
+	if (force_bypass) {
+
+		set_reg_field_value(
+			value,
+			0,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+
+		dm_write_reg(opp110->base.ctx, addr, value);
+
+		return;
+	}
+
+	if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_BYPASS)
+		mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS;
+	else if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_HW) {
+		if (params->surface_pixel_format == PIXEL_FORMAT_FP16)
+			mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS;
+		else
+			mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24;
+	}
+
+	switch (mode) {
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS:
+		set_reg_field_value(
+			value,
+			0,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24:
+		set_reg_field_value(
+			value,
+			1,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22:
+		set_reg_field_value(
+			value,
+			2,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A:
+		set_reg_field_value(
+			value,
+			3,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B:
+		set_reg_field_value(
+			value,
+			4,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	default:
+		break;
+	}
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+}
+
+bool dce110_opp_set_regamma(
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *ramp,
+	const struct gamma_parameters *params,
+	bool force_bypass)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	if (force_bypass) {
+		configure_regamma_mode(opp110, params, true);
+	} else {
+		/* 1. Scale gamma to 0 - 1 to m_pRgbUser */
+		if (!scale_gamma(opp110, ramp, params)) {
+			ASSERT_CRITICAL(false);
+			/* invalid option */
+			return false;
+		}
+
+		/* 2. Configure regamma curve without analysis (future task) */
+		/*    and program the PWL regions and segments */
+		if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_SW ||
+			params->surface_pixel_format == PIXEL_FORMAT_FP16) {
+
+			/* 3. Setup x exponentially distributed points */
+			if (!setup_distribution_points(opp110)) {
+				ASSERT_CRITICAL(false);
+				/* invalid option */
+				return false;
+			}
+
+			/* 4. Build ideal regamma curve */
+			if (!build_regamma_curve(opp110, params)) {
+				ASSERT_CRITICAL(false);
+				/* invalid parameters or bug */
+				return false;
+			}
+
+			/* 5. Map user gamma (evenly distributed x points) to
+			 * new curve when x is y from ideal regamma , step 5 */
+			if (!map_regamma_hw_to_x_user(
+				opp110, ramp, params)) {
+				ASSERT_CRITICAL(false);
+				/* invalid parameters or bug */
+				return false;
+			}
+
+			/* 6.Build and verify resulted curve */
+			build_new_custom_resulted_curve(opp110, params);
+
+			/* 7. Build and translate x to hw format */
+			if (!rebuild_curve_configuration_magic(opp110)) {
+				ASSERT_CRITICAL(false);
+				/* invalid parameters or bug */
+				return false;
+			}
+
+			/* 8. convert all params to the custom float format */
+			if (!convert_to_custom_float(opp110)) {
+				ASSERT_CRITICAL(false);
+				/* invalid parameters or bug */
+				return false;
+			}
+
+			/* 9. program regamma curve configuration */
+			regamma_config_regions_and_segments(opp110);
+
+			/* 10. Program PWL */
+			program_pwl(opp110, params);
+		}
+
+		/*
+		 * 11. program regamma config
+		 */
+		configure_regamma_mode(opp110, params, false);
+	}
+	return true;
+}
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 20/29] drm/amd/dal: Add transform & scaler HW programming
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (18 preceding siblings ...)
  2016-02-11 17:19 ` [PATCH 19/29] drm/amd/dal: Add output " Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 17:20 ` [PATCH 21/29] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel

Adds scaler, viewport, gamut remap, and pixel depth programming.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c   |  91 +++
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.h   |  87 +++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.c | 851 +++++++++++++++++++++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.h |  51 ++
 .../drm/amd/dal/dc/dce110/dce110_transform_gamut.c | 296 +++++++
 .../drm/amd/dal/dc/dce110/dce110_transform_scl.c   | 818 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c  | 531 +++++++++++++
 7 files changed, 2725 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
new file mode 100644
index 000000000000..2654a965065d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dc_types.h"
+#include "core_types.h"
+
+#include "include/grph_object_id.h"
+#include "include/fixed31_32.h"
+#include "include/logger_interface.h"
+
+#include "dce110_transform.h"
+
+#include "dce110_transform_bit_depth.h"
+
+static struct transform_funcs dce110_transform_funcs = {
+	.transform_power_up =
+		dce110_transform_power_up,
+	.transform_set_scaler =
+		dce110_transform_set_scaler,
+	.transform_set_scaler_bypass =
+		dce110_transform_set_scaler_bypass,
+	.transform_update_viewport =
+		dce110_transform_update_viewport,
+	.transform_set_scaler_filter =
+		dce110_transform_set_scaler_filter,
+	.transform_set_gamut_remap =
+		dce110_transform_set_gamut_remap,
+	.transform_set_pixel_storage_depth =
+		dce110_transform_set_pixel_storage_depth,
+	.transform_get_current_pixel_storage_depth =
+		dce110_transform_get_current_pixel_storage_depth
+};
+
+/*****************************************/
+/* Constructor, Destructor               */
+/*****************************************/
+
+bool dce110_transform_construct(
+	struct dce110_transform *xfm110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *reg_offsets)
+{
+	xfm110->base.ctx = ctx;
+
+	xfm110->base.inst = inst;
+	xfm110->base.funcs = &dce110_transform_funcs;
+
+	xfm110->offsets = *reg_offsets;
+
+	xfm110->lb_pixel_depth_supported =
+			LB_PIXEL_DEPTH_18BPP |
+			LB_PIXEL_DEPTH_24BPP |
+			LB_PIXEL_DEPTH_30BPP;
+
+	return true;
+}
+
+bool dce110_transform_power_up(struct transform *xfm)
+{
+	return dce110_transform_power_up_line_buffer(xfm);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
new file mode 100644
index 000000000000..117aca337f9d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
@@ -0,0 +1,87 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TRANSFORM_DCE110_H__
+#define __DAL_TRANSFORM_DCE110_H__
+
+#include "inc/transform.h"
+#include "include/grph_csc_types.h"
+
+#define TO_DCE110_TRANSFORM(transform)\
+	container_of(transform, struct dce110_transform, base)
+
+struct dce110_transform_reg_offsets {
+	uint32_t scl_offset;
+	uint32_t dcfe_offset;
+	uint32_t dcp_offset;
+	uint32_t lb_offset;
+};
+
+struct dce110_transform {
+	struct transform base;
+	struct dce110_transform_reg_offsets offsets;
+
+	uint32_t lb_pixel_depth_supported;
+};
+
+bool dce110_transform_construct(struct dce110_transform *xfm110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *reg_offsets);
+
+bool dce110_transform_power_up(struct transform *xfm);
+
+/* SCALER RELATED */
+bool dce110_transform_set_scaler(
+	struct transform *xfm,
+	const struct scaler_data *data);
+
+void dce110_transform_set_scaler_bypass(struct transform *xfm);
+
+bool dce110_transform_update_viewport(
+	struct transform *xfm,
+	const struct rect *view_port,
+	bool is_fbc_attached);
+
+void dce110_transform_set_scaler_filter(
+	struct transform *xfm,
+	struct scaler_filter *filter);
+
+/* GAMUT RELATED */
+void dce110_transform_set_gamut_remap(
+	struct transform *xfm,
+	const struct grph_csc_adjustment *adjust);
+
+/* BIT DEPTH RELATED */
+bool dce110_transform_set_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth depth,
+	const struct bit_depth_reduction_params *bit_depth_params);
+
+bool dce110_transform_get_current_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth *depth);
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
new file mode 100644
index 000000000000..fb5ef6d2c859
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
@@ -0,0 +1,851 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_transform.h"
+#include "opp.h"
+#include "include/logger_interface.h"
+#include "include/fixed32_32.h"
+
+#define DCP_REG(reg)\
+	(reg + xfm110->offsets.dcp_offset)
+
+#define LB_REG(reg)\
+	(reg + xfm110->offsets.lb_offset)
+
+#define LB_TOTAL_NUMBER_OF_ENTRIES 1712
+#define LB_BITS_PER_ENTRY 144
+
+enum dcp_out_trunc_round_mode {
+	DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+	DCP_OUT_TRUNC_ROUND_MODE_ROUND
+};
+
+enum dcp_out_trunc_round_depth {
+	DCP_OUT_TRUNC_ROUND_DEPTH_14BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_13BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_12BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_11BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_10BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_9BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_8BIT
+};
+
+/*  defines the various methods of bit reduction available for use */
+enum dcp_bit_depth_reduction_mode {
+	DCP_BIT_DEPTH_REDUCTION_MODE_DITHER,
+	DCP_BIT_DEPTH_REDUCTION_MODE_ROUND,
+	DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE,
+	DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED,
+	DCP_BIT_DEPTH_REDUCTION_MODE_INVALID
+};
+
+enum dcp_spatial_dither_mode {
+	DCP_SPATIAL_DITHER_MODE_AAAA,
+	DCP_SPATIAL_DITHER_MODE_A_AA_A,
+	DCP_SPATIAL_DITHER_MODE_AABBAABB,
+	DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC,
+	DCP_SPATIAL_DITHER_MODE_INVALID
+};
+
+enum dcp_spatial_dither_depth {
+	DCP_SPATIAL_DITHER_DEPTH_30BPP,
+	DCP_SPATIAL_DITHER_DEPTH_24BPP
+};
+
+static bool set_clamp(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth);
+
+static bool set_round(
+	struct dce110_transform *xfm110,
+	enum dcp_out_trunc_round_mode mode,
+	enum dcp_out_trunc_round_depth depth);
+
+static bool set_dither(
+	struct dce110_transform *xfm110,
+	bool dither_enable,
+	enum dcp_spatial_dither_mode dither_mode,
+	enum dcp_spatial_dither_depth dither_depth,
+	bool frame_random_enable,
+	bool rgb_random_enable,
+	bool highpass_random_enable);
+
+/**
+ *******************************************************************************
+ * dce110_transform_bit_depth_reduction_program
+ *
+ * @brief
+ *     Programs the DCP bit depth reduction registers (Clamp, Round/Truncate,
+ *      Dither) for dce110
+ *
+ * @param depth : bit depth to set the clamp to (should match denorm)
+ *
+ * @return
+ *     true if succeeds.
+ *******************************************************************************
+ */
+static bool program_bit_depth_reduction(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth,
+	const struct bit_depth_reduction_params *bit_depth_params)
+{
+	enum dcp_bit_depth_reduction_mode depth_reduction_mode;
+	enum dcp_spatial_dither_mode spatial_dither_mode;
+	bool frame_random_enable;
+	bool rgb_random_enable;
+	bool highpass_random_enable;
+
+	if (depth > COLOR_DEPTH_121212) {
+		ASSERT_CRITICAL(false); /* Invalid clamp bit depth */
+		return false;
+	}
+
+	if (bit_depth_params->flags.SPATIAL_DITHER_ENABLED) {
+		depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DITHER;
+		frame_random_enable = true;
+		rgb_random_enable = true;
+		highpass_random_enable = true;
+
+	} else {
+		depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED;
+		frame_random_enable = false;
+		rgb_random_enable = false;
+		highpass_random_enable = false;
+	}
+
+	spatial_dither_mode = DCP_SPATIAL_DITHER_MODE_A_AA_A;
+
+	if (!set_clamp(xfm110, depth)) {
+		/* Failure in set_clamp() */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	switch (depth_reduction_mode) {
+	case DCP_BIT_DEPTH_REDUCTION_MODE_DITHER:
+		/*  Spatial Dither: Set round/truncate to bypass (12bit),
+		 *  enable Dither (30bpp) */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+			DCP_OUT_TRUNC_ROUND_DEPTH_12BIT);
+
+		set_dither(xfm110, true, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+	case DCP_BIT_DEPTH_REDUCTION_MODE_ROUND:
+		/*  Round: Enable round (10bit), disable Dither */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_ROUND,
+			DCP_OUT_TRUNC_ROUND_DEPTH_10BIT);
+
+		set_dither(xfm110, false, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+	case DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE: /*  Truncate */
+		/*  Truncate: Enable truncate (10bit), disable Dither */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+			DCP_OUT_TRUNC_ROUND_DEPTH_10BIT);
+
+		set_dither(xfm110, false, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+
+	case DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED: /*  Disabled */
+		/*  Truncate: Set round/truncate to bypass (12bit),
+		 * disable Dither */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+			DCP_OUT_TRUNC_ROUND_DEPTH_12BIT);
+
+		set_dither(xfm110, false, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+	default:
+		/* Invalid DCP Depth reduction mode */
+		ASSERT_CRITICAL(false);
+		break;
+	}
+
+	return true;
+}
+
+/**
+ *******************************************************************************
+ * set_clamp
+ *
+ * @param depth : bit depth to set the clamp to (should match denorm)
+ *
+ * @brief
+ *     Programs clamp according to panel bit depth.
+ *
+ * @return
+ *     true if succeeds
+ *
+ *******************************************************************************
+ */
+static bool set_clamp(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth)
+{
+	uint32_t clamp_max = 0;
+
+	/* At the clamp block the data will be MSB aligned, so we set the max
+	 * clamp accordingly.
+	 * For example, the max value for 6 bits MSB aligned (14 bit bus) would
+	 * be "11 1111 0000 0000" in binary, so 0x3F00.
+	 */
+	switch (depth) {
+	case COLOR_DEPTH_666:
+		/* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */
+		clamp_max = 0x3F00;
+		break;
+	case COLOR_DEPTH_888:
+		/* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */
+		clamp_max = 0x3FC0;
+		break;
+	case COLOR_DEPTH_101010:
+		/* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
+		clamp_max = 0x3FFC;
+		break;
+	case COLOR_DEPTH_121212:
+		/* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */
+		clamp_max = 0x3FFF;
+		break;
+	default:
+		ASSERT_CRITICAL(false); /* Invalid clamp bit depth */
+		return false;
+	}
+
+	{
+		uint32_t value = 0;
+		/*  always set min to 0 */
+			set_reg_field_value(
+			value,
+			0,
+			OUT_CLAMP_CONTROL_B_CB,
+			OUT_CLAMP_MIN_B_CB);
+
+		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_B_CB,
+			OUT_CLAMP_MAX_B_CB);
+
+		dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmOUT_CLAMP_CONTROL_B_CB),
+			value);
+	}
+
+	{
+		uint32_t value = 0;
+		/*  always set min to 0 */
+		set_reg_field_value(
+			value,
+			0,
+			OUT_CLAMP_CONTROL_G_Y,
+			OUT_CLAMP_MIN_G_Y);
+
+		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_G_Y,
+			OUT_CLAMP_MAX_G_Y);
+
+		dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmOUT_CLAMP_CONTROL_G_Y),
+			value);
+	}
+
+	{
+		uint32_t value = 0;
+		/*  always set min to 0 */
+		set_reg_field_value(
+			value,
+			0,
+			OUT_CLAMP_CONTROL_R_CR,
+			OUT_CLAMP_MIN_R_CR);
+
+		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_R_CR,
+			OUT_CLAMP_MAX_R_CR);
+
+		dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmOUT_CLAMP_CONTROL_R_CR),
+			value);
+	}
+
+	return true;
+}
+
+/**
+ *******************************************************************************
+ * set_round
+ *
+ * @brief
+ *     Programs Round/Truncate
+ *
+ * @param [in] mode  :round or truncate
+ * @param [in] depth :bit depth to round/truncate to
+ OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode
+ POSSIBLE VALUES:
+      00 - truncate to u0.12
+      01 - truncate to u0.11
+      02 - truncate to u0.10
+      03 - truncate to u0.9
+      04 - truncate to u0.8
+      05 - reserved
+      06 - truncate to u0.14
+      07 - truncate to u0.13		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_R_CR,
+			OUT_CLAMP_MAX_R_CR);
+      08 - round to u0.12
+      09 - round to u0.11
+      10 - round to u0.10
+      11 - round to u0.9
+      12 - round to u0.8
+      13 - reserved
+      14 - round to u0.14
+      15 - round to u0.13
+
+ * @return
+ *     true if succeeds.
+ *******************************************************************************
+ */
+static bool set_round(
+	struct dce110_transform *xfm110,
+	enum dcp_out_trunc_round_mode mode,
+	enum dcp_out_trunc_round_depth depth)
+{
+	uint32_t depth_bits = 0;
+	uint32_t mode_bit = 0;
+	/*  zero out all bits */
+	uint32_t value = 0;
+
+	/*  set up bit depth */
+	switch (depth) {
+	case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT:
+		depth_bits = 6;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT:
+		depth_bits = 7;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT:
+		depth_bits = 0;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT:
+		depth_bits = 1;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT:
+		depth_bits = 2;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT:
+		depth_bits = 3;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT:
+		depth_bits = 4;
+		break;
+	default:
+		/* Invalid dcp_out_trunc_round_depth */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	set_reg_field_value(
+		value,
+		depth_bits,
+		OUT_ROUND_CONTROL,
+		OUT_ROUND_TRUNC_MODE);
+
+	/*  set up round or truncate */
+	switch (mode) {
+	case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE:
+		mode_bit = 0;
+		break;
+	case DCP_OUT_TRUNC_ROUND_MODE_ROUND:
+		mode_bit = 1;
+		break;
+	default:
+		/* Invalid dcp_out_trunc_round_mode */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	depth_bits |= mode_bit << 3;
+
+	set_reg_field_value(
+		value,
+		depth_bits,
+		OUT_ROUND_CONTROL,
+		OUT_ROUND_TRUNC_MODE);
+
+	/*  write the register */
+	dm_write_reg(xfm110->base.ctx,
+				DCP_REG(mmOUT_ROUND_CONTROL),
+				value);
+
+	return true;
+}
+
+/**
+ *******************************************************************************
+ * set_dither
+ *
+ * @brief
+ *     Programs Dither
+ *
+ * @param [in] dither_enable        : enable dither
+ * @param [in] dither_mode           : dither mode to set
+ * @param [in] dither_depth          : bit depth to dither to
+ * @param [in] frame_random_enable    : enable frame random
+ * @param [in] rgb_random_enable      : enable rgb random
+ * @param [in] highpass_random_enable : enable highpass random
+ *
+ * @return
+ *     true if succeeds.
+ *******************************************************************************
+ */
+
+static bool set_dither(
+	struct dce110_transform *xfm110,
+	bool dither_enable,
+	enum dcp_spatial_dither_mode dither_mode,
+	enum dcp_spatial_dither_depth dither_depth,
+	bool frame_random_enable,
+	bool rgb_random_enable,
+	bool highpass_random_enable)
+{
+	uint32_t dither_depth_bits = 0;
+	uint32_t dither_mode_bits = 0;
+	/*  zero out all bits */
+	uint32_t value = 0;
+
+	/* set up the fields */
+	if (dither_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_SPATIAL_DITHER_EN);
+
+	switch (dither_mode) {
+	case DCP_SPATIAL_DITHER_MODE_AAAA:
+		dither_mode_bits = 0;
+		break;
+	case DCP_SPATIAL_DITHER_MODE_A_AA_A:
+		dither_mode_bits = 1;
+		break;
+	case DCP_SPATIAL_DITHER_MODE_AABBAABB:
+		dither_mode_bits = 2;
+		break;
+	case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC:
+		dither_mode_bits = 3;
+		break;
+	default:
+		/* Invalid dcp_spatial_dither_mode */
+		ASSERT_CRITICAL(false);
+		return false;
+
+	}
+	set_reg_field_value(
+		value,
+		dither_mode_bits,
+		DCP_SPATIAL_DITHER_CNTL,
+		DCP_SPATIAL_DITHER_MODE);
+
+	switch (dither_depth) {
+	case DCP_SPATIAL_DITHER_DEPTH_30BPP:
+		dither_depth_bits = 0;
+		break;
+	case DCP_SPATIAL_DITHER_DEPTH_24BPP:
+		dither_depth_bits = 1;
+		break;
+	default:
+		/* Invalid dcp_spatial_dither_depth */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	set_reg_field_value(
+		value,
+		dither_depth_bits,
+		DCP_SPATIAL_DITHER_CNTL,
+		DCP_SPATIAL_DITHER_DEPTH);
+
+	if (frame_random_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_FRAME_RANDOM_ENABLE);
+
+	if (rgb_random_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_RGB_RANDOM_ENABLE);
+
+	if (highpass_random_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_HIGHPASS_RANDOM_ENABLE);
+
+	/*  write the register */
+	dm_write_reg(xfm110->base.ctx,
+				DCP_REG(mmDCP_SPATIAL_DITHER_CNTL),
+				value);
+
+	return true;
+}
+
+bool dce110_transform_get_max_num_of_supported_lines(
+	struct dce110_transform *xfm110,
+	enum lb_pixel_depth depth,
+	uint32_t pixel_width,
+	uint32_t *lines)
+{
+	uint32_t pixels_per_entries = 0;
+	uint32_t max_pixels_supports = 0;
+
+	if (pixel_width == 0)
+		return false;
+
+	/* Find number of pixels that can fit into a single LB entry and
+	 * take floor of the value since we cannot store a single pixel
+	 * across multiple entries. */
+	switch (depth) {
+	case LB_PIXEL_DEPTH_18BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 18;
+		break;
+
+	case LB_PIXEL_DEPTH_24BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 24;
+		break;
+
+	case LB_PIXEL_DEPTH_30BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 30;
+		break;
+
+	case LB_PIXEL_DEPTH_36BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 36;
+		break;
+
+	default:
+		dal_logger_write(xfm110->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Invalid LB pixel depth",
+			__func__);
+		break;
+	}
+
+	if (pixels_per_entries == 0)
+		return false;
+
+	max_pixels_supports = pixels_per_entries * LB_TOTAL_NUMBER_OF_ENTRIES;
+
+	*lines = max_pixels_supports / pixel_width;
+	return true;
+}
+
+void dce110_transform_enable_alpha(
+	struct dce110_transform *xfm110,
+	bool enable)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value;
+	uint32_t addr = LB_REG(mmLB_DATA_FORMAT);
+
+	value = dm_read_reg(ctx, addr);
+
+	if (enable == 1)
+		set_reg_field_value(
+				value,
+				1,
+				LB_DATA_FORMAT,
+				ALPHA_EN);
+	else
+		set_reg_field_value(
+				value,
+				0,
+				LB_DATA_FORMAT,
+				ALPHA_EN);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static enum lb_pixel_depth translate_display_bpp_to_lb_depth(
+	uint32_t display_bpp)
+{
+	switch (display_bpp) {
+	case 18:
+		return LB_PIXEL_DEPTH_18BPP;
+	case 24:
+		return LB_PIXEL_DEPTH_24BPP;
+	case 36:
+	case 42:
+	case 48:
+		return LB_PIXEL_DEPTH_36BPP;
+	case 30:
+	default:
+		return LB_PIXEL_DEPTH_30BPP;
+	}
+}
+
+bool dce110_transform_get_next_lower_pixel_storage_depth(
+	struct dce110_transform *xfm110,
+	uint32_t display_bpp,
+	enum lb_pixel_depth depth,
+	enum lb_pixel_depth *lower_depth)
+{
+	enum lb_pixel_depth depth_req_by_display =
+		translate_display_bpp_to_lb_depth(display_bpp);
+	uint32_t current_required_depth = depth_req_by_display;
+	uint32_t current_depth = depth;
+
+	/* if required display depth < current we could go down, for example
+	 * from LB_PIXEL_DEPTH_30BPP to LB_PIXEL_DEPTH_24BPP
+	 */
+	if (current_required_depth < current_depth) {
+		current_depth = current_depth >> 1;
+		if (xfm110->lb_pixel_depth_supported & current_depth) {
+			*lower_depth = current_depth;
+			return true;
+		}
+	}
+	return false;
+}
+
+bool dce110_transform_is_prefetch_enabled(
+	struct dce110_transform *xfm110)
+{
+	uint32_t value = dm_read_reg(
+			xfm110->base.ctx, LB_REG(mmLB_DATA_FORMAT));
+
+	if (get_reg_field_value(value, LB_DATA_FORMAT, PREFETCH) == 1)
+		return true;
+
+	return false;
+}
+
+bool dce110_transform_get_current_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth *depth)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	uint32_t value = 0;
+
+	if (depth == NULL)
+		return false;
+
+	value = dm_read_reg(
+			xfm->ctx,
+			LB_REG(mmLB_DATA_FORMAT));
+
+	switch (get_reg_field_value(value, LB_DATA_FORMAT, PIXEL_DEPTH)) {
+	case 0:
+		*depth = LB_PIXEL_DEPTH_30BPP;
+		break;
+	case 1:
+		*depth = LB_PIXEL_DEPTH_24BPP;
+		break;
+	case 2:
+		*depth = LB_PIXEL_DEPTH_18BPP;
+		break;
+	case 3:
+		*depth = LB_PIXEL_DEPTH_36BPP;
+		break;
+	default:
+		dal_logger_write(xfm->ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Invalid LB pixel depth",
+			__func__);
+		*depth = LB_PIXEL_DEPTH_30BPP;
+		break;
+	}
+	return true;
+
+}
+
+static void set_denormalization(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth)
+{
+	uint32_t value = dm_read_reg(xfm110->base.ctx,
+			DCP_REG(mmDENORM_CONTROL));
+
+	switch (depth) {
+	case COLOR_DEPTH_666:
+		/* 63/64 for 6 bit output color depth */
+		set_reg_field_value(
+			value,
+			1,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_888:
+		/* Unity for 8 bit output color depth
+		 * because prescale is disabled by default */
+		set_reg_field_value(
+			value,
+			0,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_101010:
+		/* 1023/1024 for 10 bit output color depth */
+		set_reg_field_value(
+			value,
+			3,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_121212:
+		/* 4095/4096 for 12 bit output color depth */
+		set_reg_field_value(
+			value,
+			5,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_141414:
+	case COLOR_DEPTH_161616:
+	default:
+		/* not valid used case! */
+		break;
+	}
+
+	dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmDENORM_CONTROL),
+			value);
+
+}
+
+bool dce110_transform_set_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth depth,
+	const struct bit_depth_reduction_params *bit_depth_params)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool ret = true;
+	uint32_t value;
+	enum dc_color_depth color_depth;
+
+	value = dm_read_reg(
+			xfm->ctx,
+			LB_REG(mmLB_DATA_FORMAT));
+	switch (depth) {
+	case LB_PIXEL_DEPTH_18BPP:
+		color_depth = COLOR_DEPTH_666;
+		set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	case LB_PIXEL_DEPTH_24BPP:
+		color_depth = COLOR_DEPTH_888;
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	case LB_PIXEL_DEPTH_30BPP:
+		color_depth = COLOR_DEPTH_101010;
+		set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	case LB_PIXEL_DEPTH_36BPP:
+		color_depth = COLOR_DEPTH_121212;
+		set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	default:
+		ret = false;
+		break;
+	}
+
+	if (ret == true) {
+		set_denormalization(xfm110, color_depth);
+		ret = program_bit_depth_reduction(xfm110, color_depth,
+				bit_depth_params);
+
+		set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN);
+		dm_write_reg(
+				xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value);
+		if (!(xfm110->lb_pixel_depth_supported & depth)) {
+			/*we should use unsupported capabilities
+			 *  unless it is required by w/a*/
+			dal_logger_write(xfm->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"%s: Capability not supported",
+				__func__);
+		}
+	}
+
+	return ret;
+}
+
+/* LB_MEMORY_CONFIG
+ *  00 - Use all three pieces of memory
+ *  01 - Use only one piece of memory of total 720x144 bits
+ *  10 - Use two pieces of memory of total 960x144 bits
+ *  11 - reserved
+ *
+ * LB_MEMORY_SIZE
+ *  Total entries of LB memory.
+ *  This number should be larger than 960. The default value is 1712(0x6B0) */
+bool dce110_transform_power_up_line_buffer(struct transform *xfm)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	uint32_t value;
+
+	value = dm_read_reg(xfm110->base.ctx, LB_REG(mmLB_MEMORY_CTRL));
+
+	/*Use all three pieces of memory always*/
+	set_reg_field_value(value, 0, LB_MEMORY_CTRL, LB_MEMORY_CONFIG);
+	/*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
+	set_reg_field_value(value, LB_TOTAL_NUMBER_OF_ENTRIES, LB_MEMORY_CTRL,
+			LB_MEMORY_SIZE);
+
+	dm_write_reg(xfm110->base.ctx, LB_REG(mmLB_MEMORY_CTRL), value);
+
+	return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
new file mode 100644
index 000000000000..ff100cc7f30f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
@@ -0,0 +1,51 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_TRANSFORM_BIT_DEPTH_DCE110_H__
+#define __DC_TRANSFORM_BIT_DEPTH_DCE110_H__
+
+#include "dce110_transform.h"
+
+bool dce110_transform_power_up_line_buffer(struct transform *xfm);
+
+bool dce110_transform_get_max_num_of_supported_lines(
+	struct dce110_transform *xfm110,
+	enum lb_pixel_depth depth,
+	uint32_t pixel_width,
+	uint32_t *lines);
+
+void dce110_transform_enable_alpha(
+	struct dce110_transform *xfm110,
+	bool enable);
+
+bool dce110_transform_get_next_lower_pixel_storage_depth(
+	struct dce110_transform *xfm110,
+	uint32_t display_bpp,
+	enum lb_pixel_depth depth,
+	enum lb_pixel_depth *lower_depth);
+
+bool dce110_transform_is_prefetch_enabled(
+	struct dce110_transform *xfm110);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
new file mode 100644
index 000000000000..05309c9f9482
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
@@ -0,0 +1,296 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dce110_transform.h"
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "include/fixed31_32.h"
+#include "basics/conversion.h"
+#include "include/grph_object_id.h"
+
+enum {
+	GAMUT_MATRIX_SIZE = 12
+};
+
+#define DCP_REG(reg)\
+	(reg + xfm110->offsets.dcp_offset)
+
+#define DISP_BRIGHTNESS_DEFAULT_HW 0
+#define DISP_BRIGHTNESS_MIN_HW -25
+#define DISP_BRIGHTNESS_MAX_HW 25
+#define DISP_BRIGHTNESS_STEP_HW 1
+#define DISP_BRIGHTNESS_HW_DIVIDER 100
+
+#define DISP_HUE_DEFAULT_HW 0
+#define DISP_HUE_MIN_HW -30
+#define DISP_HUE_MAX_HW 30
+#define DISP_HUE_STEP_HW 1
+#define DISP_HUE_HW_DIVIDER 1
+
+#define DISP_CONTRAST_DEFAULT_HW 100
+#define DISP_CONTRAST_MIN_HW 50
+#define DISP_CONTRAST_MAX_HW 150
+#define DISP_CONTRAST_STEP_HW 1
+#define DISP_CONTRAST_HW_DIVIDER 100
+
+#define DISP_SATURATION_DEFAULT_HW 100
+#define DISP_SATURATION_MIN_HW 0
+#define DISP_SATURATION_MAX_HW 200
+#define DISP_SATURATION_STEP_HW 1
+#define DISP_SATURATION_HW_DIVIDER 100
+
+#define DISP_KELVIN_DEGRES_DEFAULT 6500
+#define DISP_KELVIN_DEGRES_MIN 4000
+#define DISP_KELVIN_DEGRES_MAX 10000
+#define DISP_KELVIN_DEGRES_STEP 100
+#define DISP_KELVIN_HW_DIVIDER 10000
+
+static void program_gamut_remap(
+	struct dce110_transform *xfm110,
+	const uint16_t *reg_val)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmGAMUT_REMAP_CONTROL);
+
+	/* the register controls ovl also */
+	value = dm_read_reg(ctx, addr);
+
+	if (reg_val) {
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C11_C12);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[0],
+				GAMUT_REMAP_C11_C12,
+				GAMUT_REMAP_C11);
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[1],
+				GAMUT_REMAP_C11_C12,
+				GAMUT_REMAP_C12);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C13_C14);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[2],
+				GAMUT_REMAP_C13_C14,
+				GAMUT_REMAP_C13);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[3],
+				GAMUT_REMAP_C13_C14,
+				GAMUT_REMAP_C14);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C21_C22);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[4],
+				GAMUT_REMAP_C21_C22,
+				GAMUT_REMAP_C21);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[5],
+				GAMUT_REMAP_C21_C22,
+				GAMUT_REMAP_C22);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C23_C24);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[6],
+				GAMUT_REMAP_C23_C24,
+				GAMUT_REMAP_C23);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[7],
+				GAMUT_REMAP_C23_C24,
+				GAMUT_REMAP_C24);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C31_C32);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[8],
+				GAMUT_REMAP_C31_C32,
+				GAMUT_REMAP_C31);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[9],
+				GAMUT_REMAP_C31_C32,
+				GAMUT_REMAP_C32);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C33_C34);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[10],
+				GAMUT_REMAP_C33_C34,
+				GAMUT_REMAP_C33);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[11],
+				GAMUT_REMAP_C33_C34,
+				GAMUT_REMAP_C34);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+
+		set_reg_field_value(
+			value,
+			1,
+			GAMUT_REMAP_CONTROL,
+			GRPH_GAMUT_REMAP_MODE);
+
+	} else
+		set_reg_field_value(
+			value,
+			0,
+			GAMUT_REMAP_CONTROL,
+			GRPH_GAMUT_REMAP_MODE);
+
+	addr = DCP_REG(mmGAMUT_REMAP_CONTROL);
+	dm_write_reg(ctx, addr, value);
+
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_gamut_remap
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and apply color temperature adjustment to in Rgb color space
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+void dce110_transform_set_gamut_remap(
+	struct transform *xfm,
+	const struct grph_csc_adjustment *adjust)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+
+	if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW ||
+		adjust->temperature_divider == 0)
+		program_gamut_remap(xfm110, NULL);
+	else {
+		struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE];
+		uint16_t arr_reg_val[GAMUT_MATRIX_SIZE];
+
+		arr_matrix[0] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[0],
+				adjust->temperature_divider);
+		arr_matrix[1] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[1],
+				adjust->temperature_divider);
+		arr_matrix[2] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[2],
+				adjust->temperature_divider);
+		arr_matrix[3] = dal_fixed31_32_zero;
+
+		arr_matrix[4] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[3],
+				adjust->temperature_divider);
+		arr_matrix[5] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[4],
+				adjust->temperature_divider);
+		arr_matrix[6] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[5],
+				adjust->temperature_divider);
+		arr_matrix[7] = dal_fixed31_32_zero;
+
+		arr_matrix[8] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[6],
+				adjust->temperature_divider);
+		arr_matrix[9] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[7],
+				adjust->temperature_divider);
+		arr_matrix[10] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[8],
+				adjust->temperature_divider);
+		arr_matrix[11] = dal_fixed31_32_zero;
+
+		convert_float_matrix(
+			arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE);
+
+		program_gamut_remap(xfm110, arr_reg_val);
+	}
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
new file mode 100644
index 000000000000..7c15a13cb9fc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
@@ -0,0 +1,818 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_transform.h"
+
+#define UP_SCALER_RATIO_MAX 16000
+#define DOWN_SCALER_RATIO_MAX 250
+#define SCALER_RATIO_DIVIDER 1000
+
+#define SCL_REG(reg)\
+	(reg + xfm110->offsets.scl_offset)
+
+#define DCFE_REG(reg)\
+	(reg + xfm110->offsets.dcfe_offset)
+
+static void disable_enhanced_sharpness(struct dce110_transform *xfm110)
+{
+	uint32_t  value;
+
+	value = dm_read_reg(xfm110->base.ctx,
+			SCL_REG(mmSCL_F_SHARP_CONTROL));
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_HF_SHARP_EN);
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_VF_SHARP_EN);
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_HF_SHARP_SCALE_FACTOR);
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_VF_SHARP_SCALE_FACTOR);
+
+	dm_write_reg(xfm110->base.ctx,
+			SCL_REG(mmSCL_F_SHARP_CONTROL), value);
+}
+
+/**
+* Function:
+* void setup_scaling_configuration
+*
+* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
+* Input:   data
+*
+* Output:
+   void
+*/
+static bool setup_scaling_configuration(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	if (data->taps.h_taps + data->taps.v_taps <= 2) {
+		dce110_transform_set_scaler_bypass(&xfm110->base);
+		return false;
+	}
+
+	{
+		addr = SCL_REG(mmSCL_MODE);
+		value = dm_read_reg(ctx, addr);
+
+		if (data->dal_pixel_format <= PIXEL_FORMAT_GRPH_END)
+			set_reg_field_value(value, 1, SCL_MODE, SCL_MODE);
+		else
+			set_reg_field_value(value, 2, SCL_MODE, SCL_MODE);
+
+		set_reg_field_value(value, 1, SCL_MODE, SCL_PSCL_EN);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		addr = SCL_REG(mmSCL_TAP_CONTROL);
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(value, data->taps.h_taps - 1,
+				SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
+
+		set_reg_field_value(value, data->taps.v_taps - 1,
+				SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		addr = SCL_REG(mmSCL_CONTROL);
+		value = dm_read_reg(ctx, addr);
+		 /* 1 - Replaced out of bound pixels with edge */
+		set_reg_field_value(value, 1, SCL_CONTROL, SCL_BOUNDARY_MODE);
+
+		/* 1 - Replaced out of bound pixels with the edge pixel. */
+		dm_write_reg(ctx, addr, value);
+	}
+
+	return true;
+}
+
+/**
+* Function:
+* void program_overscan
+*
+* Purpose: Programs overscan border
+* Input:   overscan
+*
+* Output:
+   void
+*/
+static void program_overscan(
+		struct dce110_transform *xfm110,
+		const struct overscan_info *overscan)
+{
+	uint32_t overscan_left_right = 0;
+	uint32_t overscan_top_bottom = 0;
+
+	set_reg_field_value(overscan_left_right, overscan->left,
+			EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
+
+	set_reg_field_value(overscan_left_right, overscan->right,
+			EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
+
+	set_reg_field_value(overscan_top_bottom, overscan->top,
+			EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
+
+	set_reg_field_value(overscan_top_bottom, overscan->bottom,
+			EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
+
+	dm_write_reg(xfm110->base.ctx,
+			SCL_REG(mmEXT_OVERSCAN_LEFT_RIGHT),
+			overscan_left_right);
+
+	dm_write_reg(xfm110->base.ctx,
+			SCL_REG(mmEXT_OVERSCAN_TOP_BOTTOM),
+			overscan_top_bottom);
+}
+
+static void program_two_taps_filter(
+	struct dce110_transform *xfm110,
+	bool enable,
+	bool vertical)
+{
+	uint32_t addr;
+	uint32_t value;
+	/* 1: Hard coded 2 tap filter
+	 * 0: Programmable 2 tap filter from coefficient RAM
+	 */
+	if (vertical) {
+		addr = SCL_REG(mmSCL_VERT_FILTER_CONTROL);
+		value = dm_read_reg(xfm110->base.ctx, addr);
+		set_reg_field_value(
+			value,
+			enable ? 1 : 0,
+				SCL_VERT_FILTER_CONTROL,
+				SCL_V_2TAP_HARDCODE_COEF_EN);
+
+	} else {
+		addr = SCL_REG(mmSCL_HORZ_FILTER_CONTROL);
+		value = dm_read_reg(xfm110->base.ctx, addr);
+		set_reg_field_value(
+			value,
+			enable ? 1 : 0,
+			SCL_HORZ_FILTER_CONTROL,
+			SCL_H_2TAP_HARDCODE_COEF_EN);
+	}
+
+	dm_write_reg(xfm110->base.ctx, addr, value);
+}
+
+static void set_coeff_update_complete(struct dce110_transform *xfm110)
+{
+	uint32_t value;
+	uint32_t addr = SCL_REG(mmSCL_UPDATE);
+
+	value = dm_read_reg(xfm110->base.ctx, addr);
+	set_reg_field_value(value, 1,
+			SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+}
+
+static void program_filter(
+	struct dce110_transform *xfm110,
+	enum ram_filter_type filter_type,
+	struct scaler_filter_params *scl_filter_params,
+	uint32_t *coeffs,
+	uint32_t coeffs_num)
+{
+	uint32_t phase = 0;
+	uint32_t array_idx = 0;
+	uint32_t pair = 0;
+
+	uint32_t taps_pairs = (scl_filter_params->taps + 1) / 2;
+	uint32_t phases_to_program = scl_filter_params->phases / 2 + 1;
+
+	uint32_t i;
+	uint32_t addr;
+	uint32_t select_addr;
+	uint32_t select;
+	uint32_t data;
+	/* We need to disable power gating on coeff memory to do programming */
+
+	uint32_t pwr_ctrl_orig;
+	uint32_t pwr_ctrl_off;
+
+	addr = DCFE_REG(mmDCFE_MEM_PWR_CTRL);
+	pwr_ctrl_orig = dm_read_reg(xfm110->base.ctx, addr);
+	pwr_ctrl_off = pwr_ctrl_orig;
+	set_reg_field_value(
+		pwr_ctrl_off,
+		1,
+		DCFE_MEM_PWR_CTRL,
+		SCL_COEFF_MEM_PWR_DIS);
+	dm_write_reg(xfm110->base.ctx, addr, pwr_ctrl_off);
+
+	addr = DCFE_REG(mmDCFE_MEM_PWR_STATUS);
+	/* Wait to disable gating: */
+	for (i = 0;
+		i < 10 &&
+		get_reg_field_value(
+			dm_read_reg(xfm110->base.ctx, addr),
+			DCFE_MEM_PWR_STATUS,
+			SCL_COEFF_MEM_PWR_STATE);
+		i++)
+		dm_delay_in_microseconds(xfm110->base.ctx, 1);
+
+	ASSERT(i < 10);
+
+	select_addr = SCL_REG(mmSCL_COEF_RAM_SELECT);
+	select = dm_read_reg(xfm110->base.ctx, select_addr);
+
+	set_reg_field_value(
+		select,
+		filter_type,
+		SCL_COEF_RAM_SELECT,
+		SCL_C_RAM_FILTER_TYPE);
+	set_reg_field_value(
+		select,
+		0,
+		SCL_COEF_RAM_SELECT,
+		SCL_C_RAM_TAP_PAIR_IDX);
+	set_reg_field_value(
+		select,
+		0,
+		SCL_COEF_RAM_SELECT,
+		SCL_C_RAM_PHASE);
+
+	data = 0;
+
+	for (phase = 0; phase < phases_to_program; phase++) {
+		/* we always program N/2 + 1 phases, total phases N, but N/2-1
+		 * are just mirror phase 0 is unique and phase N/2 is unique
+		 * if N is even
+		 */
+
+		set_reg_field_value(
+			select,
+			phase,
+			SCL_COEF_RAM_SELECT,
+			SCL_C_RAM_PHASE);
+
+		for (pair = 0; pair < taps_pairs; pair++) {
+			set_reg_field_value(
+				select,
+				pair,
+				SCL_COEF_RAM_SELECT,
+				SCL_C_RAM_TAP_PAIR_IDX);
+			dm_write_reg(xfm110->base.ctx, select_addr, select);
+
+			/* even tap write enable */
+			set_reg_field_value(
+				data,
+				1,
+				SCL_COEF_RAM_TAP_DATA,
+				SCL_C_RAM_EVEN_TAP_COEF_EN);
+			/* even tap data */
+			set_reg_field_value(
+				data,
+				coeffs[array_idx],
+				SCL_COEF_RAM_TAP_DATA,
+				SCL_C_RAM_EVEN_TAP_COEF);
+
+			/* if we have odd number of taps and the last pair is
+			 * here then we do not need to program
+			 */
+			if (scl_filter_params->taps % 2 &&
+				pair == taps_pairs - 1) {
+				/* odd tap write disable */
+				set_reg_field_value(
+					data,
+					0,
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF_EN);
+				set_reg_field_value(
+					data,
+					0,
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF);
+				array_idx += 1;
+			} else {
+				/* odd tap write enable */
+				set_reg_field_value(
+					data,
+					1,
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF_EN);
+				/* dbg_val: 0x1000 / sclFilterParams->taps; */
+				set_reg_field_value(
+					data,
+					coeffs[array_idx + 1],
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF);
+
+				array_idx += 2;
+			}
+
+			dm_write_reg(
+				xfm110->base.ctx,
+				SCL_REG(mmSCL_COEF_RAM_TAP_DATA),
+				data);
+		}
+	}
+
+	ASSERT(coeffs_num == array_idx);
+
+	/* reset the power gating register */
+	dm_write_reg(
+		xfm110->base.ctx,
+		DCFE_REG(mmDCFE_MEM_PWR_CTRL),
+		pwr_ctrl_orig);
+
+	set_coeff_update_complete(xfm110);
+}
+
+/*
+ *
+ * Populates an array with filter coefficients in 1.1.12 fixed point form
+*/
+static bool get_filter_coefficients(
+	struct dce110_transform *xfm110,
+	uint32_t taps,
+	uint32_t **data_tab,
+	uint32_t *data_size)
+{
+	uint32_t num = 0;
+	uint32_t i;
+	const struct fixed31_32 *filter =
+		dal_scaler_filter_get(
+			xfm110->base.filter,
+			data_tab,
+			&num);
+	uint32_t *data_row;
+
+	if (!filter) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+	data_row = *data_tab;
+
+	for (i = 0; i < num; ++i) {
+		/* req. format sign fixed 1.1.12, the values are always between
+		 * [-1; 1]
+		 *
+		 * Each phase is mirrored as follows :
+		 * 0 : Phase 0
+		 * 1 : Phase 1 or Phase 64 - 1 / 128 - 1
+		 * N : Phase N or Phase 64 - N / 128 - N
+		 *
+		 * Convert from Fixed31_32 to 1.1.12 by using floor on value
+		 * shifted by number of required fractional bits(12)
+		 */
+		struct fixed31_32 value = filter[i];
+
+		data_row[i] =
+			dal_fixed31_32_floor(dal_fixed31_32_shl(value, 12)) &
+			0x3FFC;
+	}
+	*data_size = num;
+
+	return true;
+}
+
+static bool program_multi_taps_filter(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	bool horizontal)
+{
+	struct scaler_filter_params filter_params;
+	enum ram_filter_type filter_type;
+	uint32_t src_size;
+	uint32_t dst_size;
+
+	uint32_t *filter_data = NULL;
+	uint32_t filter_data_size = 0;
+
+	/* 16 phases total for DCE11 */
+	filter_params.phases = 16;
+
+	if (horizontal) {
+		filter_params.taps = data->taps.h_taps;
+		filter_params.sharpness = data->h_sharpness;
+		filter_params.flags.bits.HORIZONTAL = 1;
+
+		src_size = data->viewport.width;
+		dst_size =
+			dal_fixed31_32_floor(
+				dal_fixed31_32_div(
+					dal_fixed31_32_from_int(
+						data->viewport.width),
+					data->ratios->horz));
+
+		filter_type = FILTER_TYPE_RGB_Y_HORIZONTAL;
+	} else {
+		filter_params.taps = data->taps.v_taps;
+		filter_params.sharpness = data->v_sharpness;
+		filter_params.flags.bits.HORIZONTAL = 0;
+
+		src_size = data->viewport.height;
+		dst_size =
+			dal_fixed31_32_floor(
+				dal_fixed31_32_div(
+					dal_fixed31_32_from_int(
+						data->viewport.height),
+					data->ratios->vert));
+
+		filter_type = FILTER_TYPE_RGB_Y_VERTICAL;
+	}
+
+	/* 1. Generate the coefficients */
+	if (!dal_scaler_filter_generate(
+		xfm110->base.filter,
+		&filter_params,
+		src_size,
+		dst_size))
+		return false;
+
+	/* 2. Convert coefficients to fixed point format 1.12 (note coeff.
+	 * could be negative(!) and  range is [ from -1 to 1 ]) */
+	if (!get_filter_coefficients(
+		xfm110,
+		filter_params.taps,
+		&filter_data,
+		&filter_data_size))
+		return false;
+
+	/* 3. Program the filter */
+	program_filter(
+		xfm110,
+		filter_type,
+		&filter_params,
+		filter_data,
+		filter_data_size);
+
+	/* 4. Program the alpha if necessary */
+	if (data->flags.bits.SHOULD_PROGRAM_ALPHA) {
+		if (horizontal)
+			filter_type = FILTER_TYPE_ALPHA_HORIZONTAL;
+		else
+			filter_type = FILTER_TYPE_ALPHA_VERTICAL;
+
+		program_filter(
+			xfm110,
+			filter_type,
+			&filter_params,
+			filter_data,
+			filter_data_size);
+	}
+
+	return true;
+}
+
+static void program_viewport(
+	struct dce110_transform *xfm110,
+	const struct rect *view_port)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+	uint32_t addr = 0;
+
+	addr = SCL_REG(mmVIEWPORT_START);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		view_port->x,
+		VIEWPORT_START,
+		VIEWPORT_X_START);
+	set_reg_field_value(
+		value,
+		view_port->y,
+		VIEWPORT_START,
+		VIEWPORT_Y_START);
+	dm_write_reg(ctx, addr, value);
+
+	addr = SCL_REG(mmVIEWPORT_SIZE);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		view_port->height,
+		VIEWPORT_SIZE,
+		VIEWPORT_HEIGHT);
+	set_reg_field_value(
+		value,
+		view_port->width,
+		VIEWPORT_SIZE,
+		VIEWPORT_WIDTH);
+	dm_write_reg(ctx, addr, value);
+
+	/* TODO: add stereo support */
+}
+
+static void calculate_inits(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	struct scl_ratios_inits *inits)
+{
+	struct fixed31_32 h_init;
+	struct fixed31_32 v_init;
+	struct fixed31_32 v_init_bot;
+
+	inits->bottom_enable = 0;
+	inits->h_int_scale_ratio =
+		dal_fixed31_32_u2d19(data->ratios->horz) << 5;
+	inits->v_int_scale_ratio =
+		dal_fixed31_32_u2d19(data->ratios->vert) << 5;
+
+	h_init =
+		dal_fixed31_32_div_int(
+			dal_fixed31_32_add(
+				data->ratios->horz,
+				dal_fixed31_32_from_int(data->taps.h_taps + 1)),
+				2);
+	inits->h_init.integer = dal_fixed31_32_floor(h_init);
+	inits->h_init.fraction = dal_fixed31_32_u0d19(h_init) << 5;
+
+	v_init =
+		dal_fixed31_32_div_int(
+			dal_fixed31_32_add(
+				data->ratios->vert,
+				dal_fixed31_32_from_int(data->taps.v_taps + 1)),
+				2);
+	inits->v_init.integer = dal_fixed31_32_floor(v_init);
+	inits->v_init.fraction = dal_fixed31_32_u0d19(v_init) << 5;
+
+	if (data->flags.bits.INTERLACED) {
+		v_init_bot =
+			dal_fixed31_32_add(
+				dal_fixed31_32_div_int(
+					dal_fixed31_32_add(
+						data->ratios->vert,
+						dal_fixed31_32_from_int(
+							data->taps.v_taps + 1)),
+					2),
+				data->ratios->vert);
+		inits->v_init_bottom.integer = dal_fixed31_32_floor(v_init_bot);
+		inits->v_init_bottom.fraction =
+			dal_fixed31_32_u0d19(v_init_bot) << 5;
+
+		inits->bottom_enable = 1;
+	}
+}
+
+static void program_scl_ratios_inits(
+	struct dce110_transform *xfm110,
+	struct scl_ratios_inits *inits)
+{
+	uint32_t addr = SCL_REG(mmSCL_HORZ_FILTER_SCALE_RATIO);
+	uint32_t value = 0;
+
+	set_reg_field_value(
+		value,
+		inits->h_int_scale_ratio,
+		SCL_HORZ_FILTER_SCALE_RATIO,
+		SCL_H_SCALE_RATIO);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	addr = SCL_REG(mmSCL_VERT_FILTER_SCALE_RATIO);
+	value = 0;
+	set_reg_field_value(
+		value,
+		inits->v_int_scale_ratio,
+		SCL_VERT_FILTER_SCALE_RATIO,
+		SCL_V_SCALE_RATIO);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	addr = SCL_REG(mmSCL_HORZ_FILTER_INIT);
+	value = 0;
+	set_reg_field_value(
+		value,
+		inits->h_init.integer,
+		SCL_HORZ_FILTER_INIT,
+		SCL_H_INIT_INT);
+	set_reg_field_value(
+		value,
+		inits->h_init.fraction,
+		SCL_HORZ_FILTER_INIT,
+		SCL_H_INIT_FRAC);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	addr = SCL_REG(mmSCL_VERT_FILTER_INIT);
+	value = 0;
+	set_reg_field_value(
+		value,
+		inits->v_init.integer,
+		SCL_VERT_FILTER_INIT,
+		SCL_V_INIT_INT);
+	set_reg_field_value(
+		value,
+		inits->v_init.fraction,
+		SCL_VERT_FILTER_INIT,
+		SCL_V_INIT_FRAC);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	if (inits->bottom_enable) {
+		addr = SCL_REG(mmSCL_VERT_FILTER_INIT_BOT);
+		value = 0;
+		set_reg_field_value(
+			value,
+			inits->v_init_bottom.integer,
+			SCL_VERT_FILTER_INIT_BOT,
+			SCL_V_INIT_INT_BOT);
+		set_reg_field_value(
+			value,
+			inits->v_init_bottom.fraction,
+			SCL_VERT_FILTER_INIT_BOT,
+			SCL_V_INIT_FRAC_BOT);
+		dm_write_reg(xfm110->base.ctx, addr, value);
+	}
+
+	addr = SCL_REG(mmSCL_AUTOMATIC_MODE_CONTROL);
+	value = 0;
+	set_reg_field_value(
+		value,
+		0,
+		SCL_AUTOMATIC_MODE_CONTROL,
+		SCL_V_CALC_AUTO_RATIO_EN);
+	set_reg_field_value(
+		value,
+		0,
+		SCL_AUTOMATIC_MODE_CONTROL,
+		SCL_H_CALC_AUTO_RATIO_EN);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+}
+
+static void get_viewport(
+		struct dce110_transform *xfm110,
+		struct rect *current_view_port)
+{
+	uint32_t value_start;
+	uint32_t value_size;
+
+	if (current_view_port == NULL)
+		return;
+
+	value_start = dm_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_START));
+	value_size = dm_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_SIZE));
+
+	current_view_port->x = get_reg_field_value(
+			value_start,
+			VIEWPORT_START,
+			VIEWPORT_X_START);
+	current_view_port->y = get_reg_field_value(
+			value_start,
+			VIEWPORT_START,
+			VIEWPORT_Y_START);
+	current_view_port->height = get_reg_field_value(
+			value_size,
+			VIEWPORT_SIZE,
+			VIEWPORT_HEIGHT);
+	current_view_port->width = get_reg_field_value(
+			value_size,
+			VIEWPORT_SIZE,
+			VIEWPORT_WIDTH);
+}
+
+
+bool dce110_transform_set_scaler(
+	struct transform *xfm,
+	const struct scaler_data *data)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool is_scaling_required;
+	struct dc_context *ctx = xfm->ctx;
+
+	{
+		uint32_t addr = SCL_REG(mmSCL_BYPASS_CONTROL);
+		uint32_t value = dm_read_reg(xfm->ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			SCL_BYPASS_CONTROL,
+			SCL_BYPASS_MODE);
+		dm_write_reg(xfm->ctx, addr, value);
+	}
+
+	disable_enhanced_sharpness(xfm110);
+
+	/* 3. Program overscan */
+	program_overscan(xfm110, &data->overscan);
+
+	/* 4. Program taps and configuration */
+	is_scaling_required = setup_scaling_configuration(xfm110, data);
+	if (is_scaling_required) {
+		/* 5. Calculate and program ratio, filter initialization */
+		struct scl_ratios_inits inits = { 0 };
+
+		calculate_inits(xfm110, data, &inits);
+
+		program_scl_ratios_inits(xfm110, &inits);
+
+		/* 6. Program vertical filters */
+		if (data->taps.v_taps > 2) {
+			program_two_taps_filter(xfm110, false, true);
+
+			if (!program_multi_taps_filter(xfm110, data, false)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed vertical taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter(xfm110, true, true);
+
+		/* 7. Program horizontal filters */
+		if (data->taps.h_taps > 2) {
+			program_two_taps_filter(xfm110, false, false);
+
+			if (!program_multi_taps_filter(xfm110, data, true)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed horizontal taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter(xfm110, true, false);
+	}
+
+	return true;
+}
+
+void dce110_transform_set_scaler_bypass(struct transform *xfm)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	uint32_t sclv_mode;
+
+	disable_enhanced_sharpness(xfm110);
+
+	sclv_mode = dm_read_reg(xfm->ctx, SCL_REG(mmSCL_MODE));
+	set_reg_field_value(sclv_mode, 0, SCL_MODE, SCL_MODE);
+	set_reg_field_value(sclv_mode, 0, SCL_MODE, SCL_PSCL_EN);
+	dm_write_reg(xfm->ctx, SCL_REG(mmSCL_MODE), sclv_mode);
+}
+
+bool dce110_transform_update_viewport(
+	struct transform *xfm,
+	const struct rect *view_port,
+	bool is_fbc_attached)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool program_req = false;
+	struct rect current_view_port;
+
+	if (view_port == NULL)
+		return program_req;
+
+	get_viewport(xfm110, &current_view_port);
+
+	if (current_view_port.x != view_port->x ||
+			current_view_port.y != view_port->y ||
+			current_view_port.height != view_port->height ||
+			current_view_port.width != view_port->width)
+		program_req = true;
+
+	if (program_req) {
+		/*underlay viewport is programmed with scaler
+		 *program_viewport function pointer is not exposed*/
+		program_viewport(xfm110, view_port);
+	}
+
+	return program_req;
+}
+
+void dce110_transform_set_scaler_filter(
+	struct transform *xfm,
+	struct scaler_filter *filter)
+{
+	xfm->filter = filter;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
new file mode 100644
index 000000000000..1968296bd596
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
@@ -0,0 +1,531 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_transform.h"
+
+#define NOT_IMPLEMENTED()  DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_CONTROLLER,\
+			"TRANSFORM SCALER:%s()\n", __func__)
+
+/*
+*****************************************************************************
+*  Function: calculateViewport
+*
+*  @brief
+*     Calculates all of the data required to set the viewport
+*
+*  @param [in]  pData:      scaler settings data
+*  @param [out] pLumaVp:    luma viewport information
+*  @param [out] pChromaVp:  chroma viewport information
+*  @param [out] srcResCx2:  source chroma resolution times 2  - for multi-taps
+*
+*****************************************************************************
+*/
+static void calculate_viewport(
+		const struct scaler_data *scl_data,
+		struct rect *luma_viewport,
+		struct rect *chroma_viewport)
+{
+	/*Do not set chroma vp for rgb444 pixel format*/
+	luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2;
+	luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2;
+	luma_viewport->width =
+		scl_data->viewport.width - scl_data->viewport.width % 2;
+	luma_viewport->height =
+		scl_data->viewport.height - scl_data->viewport.height % 2;
+
+
+	if (scl_data->dal_pixel_format == PIXEL_FORMAT_422BPP16) {
+		luma_viewport->width += luma_viewport->width % 2;
+
+		chroma_viewport->x = luma_viewport->x / 2;
+		chroma_viewport->width = luma_viewport->width / 2;
+	} else if (scl_data->dal_pixel_format == PIXEL_FORMAT_420BPP12) {
+		luma_viewport->height += luma_viewport->height % 2;
+		luma_viewport->width += luma_viewport->width % 2;
+		/*for 420 video chroma is 1/4 the area of luma, scaled
+		 *vertically and horizontally
+		 */
+		chroma_viewport->x = luma_viewport->x / 2;
+		chroma_viewport->y = luma_viewport->y / 2;
+		chroma_viewport->height = luma_viewport->height / 2;
+		chroma_viewport->width = luma_viewport->width / 2;
+	}
+}
+
+
+static void program_viewport(
+	struct dce110_transform *xfm110,
+	struct rect *luma_view_port,
+	struct rect *chroma_view_port)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+	uint32_t addr = 0;
+
+	if (luma_view_port->width != 0 && luma_view_port->height != 0) {
+		addr = mmSCLV_VIEWPORT_START;
+		value = 0;
+		set_reg_field_value(
+			value,
+			luma_view_port->x,
+			SCLV_VIEWPORT_START,
+			VIEWPORT_X_START);
+		set_reg_field_value(
+			value,
+			luma_view_port->y,
+			SCLV_VIEWPORT_START,
+			VIEWPORT_Y_START);
+		dm_write_reg(ctx, addr, value);
+
+		addr = mmSCLV_VIEWPORT_SIZE;
+		value = 0;
+		set_reg_field_value(
+			value,
+			luma_view_port->height,
+			SCLV_VIEWPORT_SIZE,
+			VIEWPORT_HEIGHT);
+		set_reg_field_value(
+			value,
+			luma_view_port->width,
+			SCLV_VIEWPORT_SIZE,
+			VIEWPORT_WIDTH);
+		dm_write_reg(ctx, addr, value);
+	}
+
+	if (chroma_view_port->width != 0 && chroma_view_port->height != 0) {
+		addr = mmSCLV_VIEWPORT_START_C;
+		value = 0;
+		set_reg_field_value(
+			value,
+			chroma_view_port->x,
+			SCLV_VIEWPORT_START_C,
+			VIEWPORT_X_START_C);
+		set_reg_field_value(
+			value,
+			chroma_view_port->y,
+			SCLV_VIEWPORT_START_C,
+			VIEWPORT_Y_START_C);
+		dm_write_reg(ctx, addr, value);
+
+		addr = mmSCLV_VIEWPORT_SIZE_C;
+		value = 0;
+		set_reg_field_value(
+			value,
+			chroma_view_port->height,
+			SCLV_VIEWPORT_SIZE_C,
+			VIEWPORT_HEIGHT_C);
+		set_reg_field_value(
+			value,
+			chroma_view_port->width,
+			SCLV_VIEWPORT_SIZE_C,
+			VIEWPORT_WIDTH_C);
+		dm_write_reg(ctx, addr, value);
+	}
+	/* TODO: add stereo support */
+}
+
+
+/* Until and For MPO video play story, to reduce time for implementation,
+ * below limits are applied for now: 2_TAPS only
+ * Use auto-calculated filter values
+ * Following routines will be empty for now:
+ *
+ * programSclRatiosInits -- calcualate scaler ratio manually
+ * calculateInits --- calcualate scaler ratio manually
+ * programFilter -- multi-taps
+ * GetOptimalNumberOfTaps -- will hard coded to 2 TAPS
+ * GetNextLowerNumberOfTaps -- will hard coded to 2TAPS
+ * validateRequestedScaleRatio - used by GetOptimalNumberOfTaps internally
+ */
+
+/**
+* Function:
+* void setup_scaling_configuration
+*
+* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
+* Input:   data
+*
+* Output:
+   void
+*/
+static bool setup_scaling_configuration(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data)
+{
+	bool is_scaling_needed = false;
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+
+	if (data->taps.h_taps + data->taps.v_taps > 2) {
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE);
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN);
+		is_scaling_needed = true;
+	} else {
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
+	}
+
+	if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
+		is_scaling_needed = true;
+	} else if (data->dal_pixel_format != PIXEL_FORMAT_420BPP12 &&
+		data->dal_pixel_format != PIXEL_FORMAT_422BPP16) {
+		set_reg_field_value(
+			value,
+			get_reg_field_value(value, SCLV_MODE, SCL_MODE),
+			SCLV_MODE,
+			SCL_MODE_C);
+		set_reg_field_value(
+			value,
+			get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN),
+			SCLV_MODE,
+			SCL_PSCL_EN_C);
+	} else {
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
+	}
+	dm_write_reg(ctx, mmSCLV_MODE, value);
+
+	{
+		value = dm_read_reg(ctx, mmSCLV_TAP_CONTROL);
+
+		set_reg_field_value(value, data->taps.h_taps - 1,
+				SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
+
+		set_reg_field_value(value, data->taps.v_taps - 1,
+				SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
+
+		set_reg_field_value(value, data->taps.h_taps_c - 1,
+				SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
+
+		set_reg_field_value(value, data->taps.v_taps_c - 1,
+				SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
+
+		dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
+	}
+
+	{
+		/* we can ignore this register because we are ok with hw
+		 * default 0 -- change to 1 according to dal2 code*/
+		value = dm_read_reg(ctx, mmSCLV_CONTROL);
+		 /* 0 - Replaced out of bound pixels with black pixel
+		  * (or any other required color) */
+		set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
+
+		/* 1 - Replaced out of bound pixels with the edge pixel. */
+		dm_write_reg(ctx, mmSCLV_CONTROL, value);
+	}
+
+	return is_scaling_needed;
+}
+
+/**
+* Function:
+* void program_overscan
+*
+* Purpose: Programs overscan border
+* Input:   overscan
+*
+* Output:
+   void
+*/
+static void program_overscan(
+		struct dce110_transform *xfm110,
+		const struct overscan_info *overscan)
+{
+	uint32_t overscan_left_right = 0;
+	uint32_t overscan_top_bottom = 0;
+
+	set_reg_field_value(overscan_left_right, overscan->left,
+		SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
+
+	set_reg_field_value(overscan_left_right, overscan->right,
+		SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
+
+	set_reg_field_value(overscan_top_bottom, overscan->top,
+		SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
+
+	set_reg_field_value(overscan_top_bottom, overscan->bottom,
+		SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
+			overscan_left_right);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
+			overscan_top_bottom);
+}
+/*
+static void setup_auto_scaling(struct dce110_transform *xfm110)
+{
+	uint32_t value = 0;
+	set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL,
+			SCL_V_CALC_AUTO_RATIO_EN);
+	set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL,
+			SCL_H_CALC_AUTO_RATIO_EN);
+	dal_write_reg(xfm->ctx,
+			xfm->regs[IDX_SCL_AUTOMATIC_MODE_CONTROL],
+			value);
+}
+*/
+
+static void program_two_taps_filter_horz(
+	struct dce110_transform *xfm110,
+	bool hardcode_coff)
+{
+	uint32_t value = 0;
+
+	if (hardcode_coff)
+		set_reg_field_value(
+				value,
+				1,
+				SCLV_HORZ_FILTER_CONTROL,
+				SCL_H_2TAP_HARDCODE_COEF_EN);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_HORZ_FILTER_CONTROL,
+			value);
+}
+
+static void program_two_taps_filter_vert(
+	struct dce110_transform *xfm110,
+	bool hardcode_coff)
+{
+	uint32_t value = 0;
+
+	if (hardcode_coff)
+		set_reg_field_value(value, 1, SCLV_VERT_FILTER_CONTROL,
+				SCL_V_2TAP_HARDCODE_COEF_EN);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_VERT_FILTER_CONTROL,
+			value);
+}
+
+static void set_coeff_update_complete(
+		struct dce110_transform *xfm110)
+{
+	/*TODO: Until now, only scaler bypass, up-scaler 2 -TAPS coeff auto
+	 * calculation are implemented. Coefficient RAM is not used
+	 * Do not check this flag yet
+	 */
+
+	/*uint32_t value;
+	uint32_t addr = xfm->regs[IDX_SCL_UPDATE];
+
+	value = dal_read_reg(xfm->ctx, addr);
+	set_reg_field_value(value, 0,
+			SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE);
+	dal_write_reg(xfm->ctx, addr, value);*/
+}
+
+static bool program_multi_taps_filter(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	bool horizontal)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+
+	NOT_IMPLEMENTED();
+	return false;
+}
+
+static void calculate_inits(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	struct sclv_ratios_inits *inits,
+	struct rect *luma_viewport,
+	struct rect *chroma_viewport)
+{
+	if (data->dal_pixel_format == PIXEL_FORMAT_420BPP12 ||
+		data->dal_pixel_format == PIXEL_FORMAT_422BPP16)
+		inits->chroma_enable = true;
+
+	/* TODO: implement rest of this function properly */
+	if (inits->chroma_enable) {
+		inits->h_int_scale_ratio_luma = 0x1000000;
+		inits->v_int_scale_ratio_luma = 0x1000000;
+		inits->h_int_scale_ratio_chroma = 0x800000;
+		inits->v_int_scale_ratio_chroma = 0x800000;
+	}
+}
+
+static void program_scl_ratios_inits(
+	struct dce110_transform *xfm110,
+	struct sclv_ratios_inits *inits)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		inits->h_int_scale_ratio_luma,
+		SCLV_HORZ_FILTER_SCALE_RATIO,
+		SCL_H_SCALE_RATIO);
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		inits->v_int_scale_ratio_luma,
+		SCLV_VERT_FILTER_SCALE_RATIO,
+		SCL_V_SCALE_RATIO);
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		inits->h_int_scale_ratio_chroma,
+		SCLV_HORZ_FILTER_SCALE_RATIO_C,
+		SCL_H_SCALE_RATIO_C);
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		inits->v_int_scale_ratio_chroma,
+		SCLV_VERT_FILTER_SCALE_RATIO_C,
+		SCL_V_SCALE_RATIO_C);
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_transform_underlay_set_scalerv_bypass(struct transform *xfm)
+{
+	uint32_t addr = mmSCLV_MODE;
+	uint32_t value = dm_read_reg(xfm->ctx, addr);
+
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
+	dm_write_reg(xfm->ctx, addr, value);
+}
+
+bool dce110_transform_underlay_is_scaling_enabled(struct transform *xfm)
+{
+	uint32_t value = dm_read_reg(xfm->ctx, mmSCLV_MODE);
+	uint8_t scl_mode = get_reg_field_value(value, SCLV_MODE, SCL_MODE);
+
+	return scl_mode == 0;
+}
+
+/* TODO: sync this one with DAL2 */
+bool dce110_transform_underlay_set_scaler(
+	struct transform *xfm,
+	const struct scaler_data *data)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool is_scaling_required;
+	struct rect luma_viewport = {0};
+	struct rect chroma_viewport = {0};
+	struct dc_context *ctx = xfm->ctx;
+
+	/* 1. Lock Scaler TODO: enable?*/
+	/*set_scaler_update_lock(xfm, true);*/
+
+	/* 2. Calculate viewport, viewport programming should happen after init
+	 * calculations as they may require an adjustment in the viewport.
+	 */
+
+	calculate_viewport(data, &luma_viewport, &chroma_viewport);
+
+	/* 3. Program overscan */
+	program_overscan(xfm110, &data->overscan);
+
+	/* 4. Program taps and configuration */
+	is_scaling_required = setup_scaling_configuration(xfm110, data);
+
+	if (is_scaling_required) {
+		/* 5. Calculate and program ratio, filter initialization */
+
+		struct sclv_ratios_inits inits = { 0 };
+
+		calculate_inits(
+			xfm110,
+			data,
+			&inits,
+			&luma_viewport,
+			&chroma_viewport);
+
+		program_scl_ratios_inits(xfm110, &inits);
+
+		/*scaler coeff of 2-TAPS use hardware auto calculated value*/
+
+		/* 6. Program vertical filters */
+		if (data->taps.v_taps > 2) {
+			program_two_taps_filter_vert(xfm110, false);
+
+			if (!program_multi_taps_filter(xfm110, data, false)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed vertical taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter_vert(xfm110, true);
+
+		/* 7. Program horizontal filters */
+		if (data->taps.h_taps > 2) {
+			program_two_taps_filter_horz(xfm110, false);
+
+			if (!program_multi_taps_filter(xfm110, data, true)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed horizontal taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter_horz(xfm110, true);
+	}
+
+	/* 8. Program the viewport */
+	if (data->flags.bits.SHOULD_PROGRAM_VIEWPORT)
+		program_viewport(xfm110, &luma_viewport, &chroma_viewport);
+
+	/* 9. Unlock the Scaler TODO: enable?*/
+	/* Every call to "set_scaler_update_lock(xfm, TRUE)"
+	 * must have a corresponding call to
+	 * "set_scaler_update_lock(xfm, FALSE)" */
+	/*set_scaler_update_lock(xfm, false);*/
+
+	/* TODO: investigate purpose/need of SHOULD_UNLOCK */
+	if (data->flags.bits.SHOULD_UNLOCK == false)
+		set_coeff_update_complete(xfm110);
+
+	return true;
+}
+
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 21/29] drm/amd/dal: Add Carrizo HW sequencer and resource
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (19 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 20/29] drm/amd/dal: Add transform & scaler " Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 17:20 ` [PATCH 22/29] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel

Adds dce110_resource and dce110_hw_sequencer files.

dce110_resource manages creation of HW resources, along with correct
ASIC register offset for each block.

dce110_hw_sequencers is responsible for programming HW sequences,
such as enable_stream, program_scaler, power_down_encoders, etc.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce110/Makefile         |   15 +
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 1658 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h    |   36 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c    | 1238 +++++++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.h    |   46 +
 5 files changed, 2993 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile
new file mode 100644
index 000000000000..ae9d2de92da2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the 'controller' sub-component of DAL.
+# It provides the control and status of HW CRTC block.
+
+DCE110 = dce110_ipp.o dce110_ipp_cursor.o \
+dce110_ipp_gamma.o dce110_link_encoder.o dce110_opp.o \
+dce110_opp_formatter.o dce110_opp_regamma.o dce110_stream_encoder.o \
+dce110_timing_generator.o dce110_transform.o dce110_transform_gamut.o \
+dce110_transform_scl.o dce110_transform_sclv.o dce110_opp_csc.o\
+dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \
+dce110_resource.o dce110_transform_bit_depth.o dce110_clock_source.o
+
+AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_DCE110)
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
new file mode 100644
index 000000000000..71fa7b1f8061
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
@@ -0,0 +1,1658 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "dc.h"
+#include "dc_bios_types.h"
+#include "core_types.h"
+#include "core_status.h"
+#include "resource.h"
+#include "hw_sequencer.h"
+#include "dm_helpers.h"
+#include "dce110_hw_sequencer.h"
+
+#include "gpu/dce110/dc_clock_gating_dce110.h"
+
+#include "timing_generator.h"
+#include "mem_input.h"
+#include "opp.h"
+#include "ipp.h"
+#include "transform.h"
+#include "stream_encoder.h"
+#include "link_encoder.h"
+#include "clock_source.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+struct dce110_hw_seq_reg_offsets {
+	uint32_t dcfe;
+	uint32_t blnd;
+	uint32_t crtc;
+};
+
+enum pipe_lock_control {
+	PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0,
+	PIPE_LOCK_CONTROL_BLENDER = 1 << 1,
+	PIPE_LOCK_CONTROL_SCL = 1 << 2,
+	PIPE_LOCK_CONTROL_SURFACE = 1 << 3,
+	PIPE_LOCK_CONTROL_MODE = 1 << 4
+};
+
+enum blender_mode {
+	BLENDER_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */
+	BLENDER_MODE_OTHER_PIPE, /* Data from other pipe only */
+	BLENDER_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */
+	BLENDER_MODE_STEREO
+};
+
+static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
+{
+	.dcfe = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.blnd = (mmBLND0_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+	.dcfe = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.blnd = (mmBLND1_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+	.dcfe = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.blnd = (mmBLND2_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+}
+};
+
+#define HW_REG_DCFE(reg, id)\
+	(reg + reg_offsets[id].dcfe)
+
+#define HW_REG_BLND(reg, id)\
+	(reg + reg_offsets[id].blnd)
+
+#define HW_REG_CRTC(reg, id)\
+	(reg + reg_offsets[id].crtc)
+
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+/***************************PIPE_CONTROL***********************************/
+static void dce110_enable_fe_clock(
+	struct dc_context *ctx, uint8_t controller_id, bool enable)
+{
+	uint32_t value = 0;
+	uint32_t addr;
+
+	/*TODO: proper offset*/
+	addr = HW_REG_DCFE(mmDCFE_CLOCK_CONTROL, controller_id);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		enable,
+		DCFE_CLOCK_CONTROL,
+		DCFE_CLOCK_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void dce110_init_pte(struct dc_context *ctx)
+{
+	uint32_t addr;
+	uint32_t value = 0;
+	uint32_t chunk_int = 0;
+	uint32_t chunk_mul = 0;
+
+	addr = mmUNP_DVMM_PTE_CONTROL;
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		DVMM_PTE_CONTROL,
+		DVMM_USE_SINGLE_PTE);
+
+	set_reg_field_value(
+		value,
+		1,
+		DVMM_PTE_CONTROL,
+		DVMM_PTE_BUFFER_MODE0);
+
+	set_reg_field_value(
+		value,
+		1,
+		DVMM_PTE_CONTROL,
+		DVMM_PTE_BUFFER_MODE1);
+
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmDVMM_PTE_REQ;
+	value = dm_read_reg(ctx, addr);
+
+	chunk_int = get_reg_field_value(
+		value,
+		DVMM_PTE_REQ,
+		HFLIP_PTEREQ_PER_CHUNK_INT);
+
+	chunk_mul = get_reg_field_value(
+		value,
+		DVMM_PTE_REQ,
+		HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
+
+	if (chunk_int != 0x4 || chunk_mul != 0x4) {
+
+		set_reg_field_value(
+			value,
+			255,
+			DVMM_PTE_REQ,
+			MAX_PTEREQ_TO_ISSUE);
+
+		set_reg_field_value(
+			value,
+			4,
+			DVMM_PTE_REQ,
+			HFLIP_PTEREQ_PER_CHUNK_INT);
+
+		set_reg_field_value(
+			value,
+			4,
+			DVMM_PTE_REQ,
+			HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
+
+		dm_write_reg(ctx, addr, value);
+	}
+}
+
+/* this is a workaround for hw bug - it is a trigger on r/w */
+static void trigger_write_crtc_h_blank_start_end(
+	struct dc_context *ctx,
+	uint8_t controller_id)
+{
+	uint32_t value;
+	uint32_t addr;
+
+	addr =  HW_REG_CRTC(mmCRTC_H_BLANK_START_END, controller_id);
+	value = dm_read_reg(ctx, addr);
+	dm_write_reg(ctx, addr, value);
+}
+
+static bool dce110_pipe_control_lock(
+	struct dc_context *ctx,
+	uint8_t controller_idx,
+	uint32_t control_mask,
+	bool lock)
+{
+	uint32_t addr = HW_REG_BLND(mmBLND_V_UPDATE_LOCK, controller_idx);
+	uint32_t value = dm_read_reg(ctx, addr);
+	bool need_to_wait = false;
+
+	if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_DCP_GRPH_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_SCL)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_SCL_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_SURFACE)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_DCP_GRPH_SURF_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_BLND_V_UPDATE_LOCK);
+		need_to_wait = true;
+	}
+
+	if (control_mask & PIPE_LOCK_CONTROL_MODE)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_V_UPDATE_LOCK_MODE);
+
+	dm_write_reg(ctx, addr, value);
+
+	if (!lock && need_to_wait) {
+		uint8_t counter = 0;
+		const uint8_t counter_limit = 100;
+		const uint16_t delay_us = 1000;
+
+		uint8_t pipe_pending;
+
+		addr = HW_REG_BLND(mmBLND_REG_UPDATE_STATUS,
+				controller_idx);
+
+		while (counter < counter_limit) {
+			value = dm_read_reg(ctx, addr);
+
+			pipe_pending = 0;
+
+			if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						BLND_BLNDC_UPDATE_PENDING);
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					BLND_BLNDO_UPDATE_PENDING);
+			}
+
+			if (control_mask & PIPE_LOCK_CONTROL_SCL) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						SCL_BLNDC_UPDATE_PENDING);
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						SCL_BLNDO_UPDATE_PENDING);
+			}
+			if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						DCP_BLNDC_GRPH_UPDATE_PENDING);
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						DCP_BLNDO_GRPH_UPDATE_PENDING);
+			}
+			if (control_mask & PIPE_LOCK_CONTROL_SURFACE) {
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					DCP_BLNDC_GRPH_SURF_UPDATE_PENDING);
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					DCP_BLNDO_GRPH_SURF_UPDATE_PENDING);
+			}
+
+			if (pipe_pending == 0)
+				break;
+
+			counter++;
+			dm_delay_in_microseconds(ctx, delay_us);
+		}
+
+		if (counter == counter_limit) {
+			dal_logger_write(
+				ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: wait for update exceeded (wait %d us)\n",
+				__func__,
+				counter * delay_us);
+			dal_logger_write(
+				ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: control %d, remain value %x\n",
+				__func__,
+				control_mask,
+				value);
+		} else {
+			/* OK. */
+		}
+	}
+
+	if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER))
+		trigger_write_crtc_h_blank_start_end(ctx, controller_idx);
+
+	return true;
+}
+
+static void dce110_set_blender_mode(
+	struct dc_context *ctx,
+	uint8_t controller_id,
+	uint32_t mode)
+{
+	uint32_t value;
+	uint32_t addr = HW_REG_BLND(mmBLND_CONTROL, controller_id);
+	uint32_t blnd_mode;
+	uint32_t feedthrough = 0;
+
+	switch (mode) {
+	case BLENDER_MODE_OTHER_PIPE:
+		feedthrough = 0;
+		blnd_mode = 1;
+		break;
+	case BLENDER_MODE_BLENDING:
+		feedthrough = 0;
+		blnd_mode = 2;
+		break;
+	case BLENDER_MODE_CURRENT_PIPE:
+	default:
+		feedthrough = 1;
+		blnd_mode = 0;
+		break;
+	}
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		feedthrough,
+		BLND_CONTROL,
+		BLND_FEEDTHROUGH_EN);
+
+	set_reg_field_value(
+		value,
+		blnd_mode,
+		BLND_CONTROL,
+		BLND_MODE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void dce110_crtc_switch_to_clk_src(
+				struct clock_source *clk_src, uint8_t crtc_inst)
+{
+	uint32_t pixel_rate_cntl_value;
+	uint32_t addr;
+
+	addr = mmCRTC0_PIXEL_RATE_CNTL + crtc_inst *
+			(mmCRTC1_PIXEL_RATE_CNTL - mmCRTC0_PIXEL_RATE_CNTL);
+
+	pixel_rate_cntl_value = dm_read_reg(clk_src->ctx, addr);
+
+	if (clk_src->id == CLOCK_SOURCE_ID_EXTERNAL)
+		set_reg_field_value(pixel_rate_cntl_value, 1,
+			CRTC0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE);
+	else {
+		set_reg_field_value(pixel_rate_cntl_value,
+				0,
+				CRTC0_PIXEL_RATE_CNTL,
+				DP_DTO0_ENABLE);
+
+		set_reg_field_value(pixel_rate_cntl_value,
+				clk_src->id - 1,
+				CRTC0_PIXEL_RATE_CNTL,
+				CRTC0_PIXEL_RATE_SOURCE);
+	}
+	dm_write_reg(clk_src->ctx, addr, pixel_rate_cntl_value);
+}
+/**************************************************************************/
+
+static void enable_display_pipe_clock_gating(
+	struct dc_context *ctx,
+	bool clock_gating)
+{
+	/*TODO*/
+}
+
+static bool dce110_enable_display_power_gating(
+	struct dc_context *ctx,
+	uint8_t controller_id,
+	struct dc_bios *dcb,
+	enum pipe_gating_control power_gating)
+{
+	enum bp_result bp_result = BP_RESULT_OK;
+	enum bp_pipe_control_action cntl;
+
+	if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
+		return true;
+
+	if (power_gating == PIPE_GATING_CONTROL_INIT)
+		cntl = ASIC_PIPE_INIT;
+	else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
+		cntl = ASIC_PIPE_ENABLE;
+	else
+		cntl = ASIC_PIPE_DISABLE;
+
+	if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0))
+		bp_result = dcb->funcs->enable_disp_power_gating(
+						dcb, controller_id + 1, cntl);
+
+	if (power_gating != PIPE_GATING_CONTROL_ENABLE)
+		dce110_init_pte(ctx);
+
+	if (bp_result == BP_RESULT_OK)
+		return true;
+	else
+		return false;
+}
+
+
+static bool set_gamma_ramp(
+	struct input_pixel_processor *ipp,
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *ramp,
+	const struct gamma_parameters *params)
+{
+	/*Power on LUT memory*/
+	opp->funcs->opp_power_on_regamma_lut(opp, true);
+
+
+	if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8 ||
+		params->selected_gamma_lut == GRAPHICS_GAMMA_LUT_LEGACY) {
+		/* do legacy DCP for 256 colors if we are requested to do so */
+		ipp->funcs->ipp_set_legacy_input_gamma_ramp(
+			ipp, ramp, params);
+
+		ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, true);
+
+		/* set bypass */
+		ipp->funcs->ipp_program_prescale(ipp, PIXEL_FORMAT_UNINITIALIZED);
+
+		ipp->funcs->ipp_set_degamma(ipp, params, true);
+
+		opp->funcs->opp_set_regamma(opp, ramp, params, true);
+	} else if (params->selected_gamma_lut ==
+			GRAPHICS_GAMMA_LUT_LEGACY_AND_REGAMMA) {
+		if (!opp->funcs->opp_map_legacy_and_regamma_hw_to_x_user(
+			opp, ramp, params)) {
+			BREAK_TO_DEBUGGER();
+			/* invalid parameters or bug */
+			return false;
+		}
+
+		/* do legacy DCP for 256 colors if we are requested to do so */
+		ipp->funcs->ipp_set_legacy_input_gamma_ramp(
+			ipp, ramp, params);
+
+		ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, true);
+
+		/* set bypass */
+		ipp->funcs->ipp_program_prescale(ipp, PIXEL_FORMAT_UNINITIALIZED);
+	} else {
+		ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, false);
+
+		ipp->funcs->ipp_program_prescale(ipp, params->surface_pixel_format);
+
+		/* Do degamma step : remove the given gamma value from FB.
+		 * For FP16 or no degamma do by pass */
+		ipp->funcs->ipp_set_degamma(ipp, params, false);
+
+		opp->funcs->opp_set_regamma(opp, ramp, params, false);
+	}
+
+	/*re-enable low power mode for LUT memory*/
+	opp->funcs->opp_power_on_regamma_lut(opp, false);
+
+	return true;
+}
+
+static enum dc_status bios_parser_crtc_source_select(
+		struct core_stream *stream)
+{
+	struct dc_bios *dcb;
+	/* call VBIOS table to set CRTC source for the HW
+	 * encoder block
+	 * note: video bios clears all FMT setting here. */
+	struct bp_crtc_source_select crtc_source_select = {0};
+	const struct core_sink *sink = stream->sink;
+
+	crtc_source_select.engine_id = stream->stream_enc->id;
+	crtc_source_select.controller_id = stream->controller_idx + 1;
+	/*TODO: Need to un-hardcode color depth, dp_audio and account for
+	 * the case where signal and sink signal is different (translator
+	 * encoder)*/
+	crtc_source_select.signal = sink->public.sink_signal;
+	crtc_source_select.enable_dp_audio = false;
+	crtc_source_select.sink_signal = sink->public.sink_signal;
+	crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
+
+	dcb = dal_adapter_service_get_bios_parser(sink->link->adapter_srv);
+
+	if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
+		dcb,
+		&crtc_source_select)) {
+		return DC_ERROR_UNEXPECTED;
+	}
+
+	return DC_OK;
+}
+
+static enum color_space surface_color_to_color_space(
+	struct plane_colorimetry *colorimetry)
+{
+	enum color_space color_space = COLOR_SPACE_UNKNOWN;
+
+	switch (colorimetry->color_space) {
+	case SURFACE_COLOR_SPACE_SRGB:
+	case SURFACE_COLOR_SPACE_XRRGB:
+		if (colorimetry->limited_range)
+			color_space = COLOR_SPACE_SRGB_LIMITED_RANGE;
+		else
+			color_space = COLOR_SPACE_SRGB_FULL_RANGE;
+		break;
+	case SURFACE_COLOR_SPACE_BT601:
+	case SURFACE_COLOR_SPACE_XVYCC_BT601:
+		color_space = COLOR_SPACE_YCBCR601;
+		break;
+	case SURFACE_COLOR_SPACE_BT709:
+	case SURFACE_COLOR_SPACE_XVYCC_BT709:
+		color_space = COLOR_SPACE_YCBCR709;
+		break;
+	}
+
+	return color_space;
+}
+
+/*******************************FMT**************************************/
+static void program_fmt(
+		struct output_pixel_processor *opp,
+		struct bit_depth_reduction_params *fmt_bit_depth,
+		struct clamping_and_pixel_encoding_params *clamping)
+{
+	/* dithering is affected by <CrtcSourceSelect>, hence should be
+	 * programmed afterwards */
+
+	opp->funcs->opp_program_bit_depth_reduction(
+		opp,
+		fmt_bit_depth);
+
+	opp->funcs->opp_program_clamping_and_pixel_encoding(
+		opp,
+		clamping);
+
+	return;
+}
+
+static void update_bios_scratch_critical_state(struct adapter_service *as,
+		bool state)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	dcb->funcs->set_scratch_critical_state(dcb, state);
+}
+
+static void update_info_frame(struct core_stream *stream)
+{
+	if (dc_is_hdmi_signal(stream->signal))
+		stream->stream_enc->funcs->update_hdmi_info_packets(
+			stream->stream_enc,
+			&stream->encoder_info_frame);
+	else if (dc_is_dp_signal(stream->signal))
+		stream->stream_enc->funcs->update_dp_info_packets(
+			stream->stream_enc,
+			&stream->encoder_info_frame);
+}
+
+
+static void enable_stream(struct core_stream *stream)
+{
+	enum lane_count lane_count =
+			stream->sink->link->cur_link_settings.lane_count;
+
+	struct dc_crtc_timing *timing = &stream->public.timing;
+	struct core_link *link = stream->sink->link;
+
+	/* 1. update AVI info frame (HDMI, DP)
+	 * we always need to update info frame
+	*/
+	uint32_t active_total_with_borders;
+	uint32_t early_control = 0;
+	struct timing_generator *tg = stream->tg;
+
+	update_info_frame(stream);
+	/* enable early control to avoid corruption on DP monitor*/
+	active_total_with_borders =
+			timing->h_addressable
+				+ timing->h_border_left
+				+ timing->h_border_right;
+
+	if (lane_count != 0)
+		early_control = active_total_with_borders % lane_count;
+
+	if (early_control == 0)
+		early_control = lane_count;
+
+	tg->funcs->set_early_control(tg, early_control);
+
+	/* enable audio only within mode set */
+	if (stream->audio != NULL) {
+		dal_audio_enable_output(
+			stream->audio,
+			stream->stream_enc->id,
+			stream->signal);
+	}
+
+	/* For MST, there are multiply stream go to only one link.
+	 * connect DIG back_end to front_end while enable_stream and
+	 * disconnect them during disable_stream
+	 * BY this, it is logic clean to separate stream and link */
+	 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
+			stream->stream_enc->id, true);
+
+}
+
+static void disable_stream(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+
+	if (dc_is_hdmi_signal(stream->signal))
+		stream->stream_enc->funcs->stop_hdmi_info_packets(
+			stream->stream_enc);
+
+	if (dc_is_dp_signal(stream->signal))
+		stream->stream_enc->funcs->stop_dp_info_packets(
+			stream->stream_enc);
+
+	if (stream->audio) {
+		/* mute audio */
+		dal_audio_mute(stream->audio, stream->stream_enc->id,
+				stream->signal);
+
+		/* TODO: notify audio driver for if audio modes list changed
+		 * add audio mode list change flag */
+		/* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
+		 * stream->stream_engine_id);
+		 */
+	}
+
+	/* blank at encoder level */
+	if (dc_is_dp_signal(stream->signal))
+		stream->stream_enc->funcs->dp_blank(stream->stream_enc);
+
+	link->link_enc->funcs->connect_dig_be_to_fe(
+			link->link_enc,
+			stream->stream_enc->id,
+			false);
+
+}
+
+static void unblank_stream(struct core_stream *stream,
+		struct link_settings *link_settings)
+{
+	struct encoder_unblank_param params = { { 0 } };
+
+	/* only 3 items below are used by unblank */
+	params.crtc_timing.pixel_clock =
+		stream->public.timing.pix_clk_khz;
+	params.link_settings.link_rate = link_settings->link_rate;
+	stream->stream_enc->funcs->dp_unblank(
+		stream->stream_enc, &params);
+}
+
+static enum color_space get_output_color_space(
+				const struct dc_crtc_timing *dc_crtc_timing)
+{
+	enum color_space color_space = COLOR_SPACE_SRGB_FULL_RANGE;
+
+	switch (dc_crtc_timing->pixel_encoding)	{
+	case PIXEL_ENCODING_YCBCR422:
+	case PIXEL_ENCODING_YCBCR444:
+	case PIXEL_ENCODING_YCBCR420:
+	{
+		if ((dc_crtc_timing->timing_standard ==
+			TIMING_STANDARD_CEA770) ||
+			(dc_crtc_timing->timing_standard ==
+				TIMING_STANDARD_CEA861)) {
+			if (dc_crtc_timing->pix_clk_khz > 27030) {
+				if (dc_crtc_timing->flags.Y_ONLY)
+					color_space =
+						COLOR_SPACE_YCBCR709_YONLY;
+				else
+					color_space = COLOR_SPACE_YCBCR709;
+			} else {
+				if (dc_crtc_timing->flags.Y_ONLY)
+					color_space =
+						COLOR_SPACE_YCBCR601_YONLY;
+				else
+					color_space = COLOR_SPACE_YCBCR601;
+			}
+		}
+	}
+	break;
+
+	default:
+		break;
+	}
+
+	return color_space;
+}
+
+static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx,
+		struct validate_context *context,
+		const struct dc *dc)
+{
+	struct core_stream *stream =
+			context->res_ctx.controller_ctx[controller_idx].stream;
+	struct output_pixel_processor *opp =
+		context->res_ctx.pool.opps[controller_idx];
+	bool timing_changed = context->res_ctx.controller_ctx[controller_idx]
+			.flags.timing_changed;
+	enum color_space color_space;
+
+	if (timing_changed) {
+		/* Must blank CRTC after disabling power gating and before any
+		 * programming, otherwise CRTC will be hung in bad state
+		 */
+		stream->tg->funcs->set_blank(stream->tg, true);
+
+		core_link_disable_stream(stream->sink->link, stream);
+
+		/*TODO: AUTO check if timing changed*/
+		if (false == stream->clock_source->funcs->program_pix_clk(
+				stream->clock_source,
+				&stream->pix_clk_params,
+				&stream->pll_settings)) {
+			BREAK_TO_DEBUGGER();
+			return DC_ERROR_UNEXPECTED;
+		}
+
+		stream->tg->funcs->program_timing(
+				stream->tg,
+				&stream->public.timing,
+				true);
+	}
+
+	/*TODO: mst support - use total stream count*/
+	stream->mi->funcs->mem_input_allocate_dmif_buffer(
+					stream->mi,
+					&stream->public.timing,
+					context->target_count);
+
+	if (timing_changed) {
+		if (false == stream->tg->funcs->enable_crtc(
+				stream->tg)) {
+			BREAK_TO_DEBUGGER();
+			return DC_ERROR_UNEXPECTED;
+		}
+	}
+
+	/* TODO: move to stream encoder */
+	if (stream->signal != SIGNAL_TYPE_VIRTUAL)
+		if (DC_OK != bios_parser_crtc_source_select(stream)) {
+			BREAK_TO_DEBUGGER();
+			return DC_ERROR_UNEXPECTED;
+		}
+
+	opp->funcs->opp_set_dyn_expansion(
+			opp,
+			COLOR_SPACE_YCBCR601,
+			stream->public.timing.display_color_depth,
+			stream->sink->public.sink_signal);
+
+	program_fmt(opp, &stream->bit_depth_params, &stream->clamping);
+
+	stream->sink->link->link_enc->funcs->setup(
+		stream->sink->link->link_enc,
+		stream->signal);
+
+	if (dc_is_dp_signal(stream->signal))
+		stream->stream_enc->funcs->dp_set_stream_attribute(
+			stream->stream_enc,
+			&stream->public.timing);
+
+	if (dc_is_hdmi_signal(stream->signal))
+		stream->stream_enc->funcs->hdmi_set_stream_attribute(
+			stream->stream_enc,
+			&stream->public.timing,
+			stream->audio != NULL);
+
+	if (dc_is_dvi_signal(stream->signal))
+		stream->stream_enc->funcs->dvi_set_stream_attribute(
+			stream->stream_enc,
+			&stream->public.timing,
+			(stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
+			true : false);
+
+	if (stream->audio != NULL) {
+		if (AUDIO_RESULT_OK != dal_audio_setup(
+				stream->audio,
+				&stream->audio_output,
+				&stream->public.audio_info)) {
+			BREAK_TO_DEBUGGER();
+			return DC_ERROR_UNEXPECTED;
+		}
+	}
+
+	/* Setup audio rate clock source */
+	if (stream->audio != NULL)
+		dal_audio_setup_audio_wall_dto(
+				stream->audio,
+				stream->signal,
+				&stream->audio_output.crtc_info,
+				&stream->audio_output.pll_info);
+
+	/* program blank color */
+	color_space = get_output_color_space(&stream->public.timing);
+	stream->tg->funcs->set_blank_color(
+			context->res_ctx.pool.timing_generators[controller_idx],
+			color_space);
+
+	if (timing_changed)
+		core_link_enable_stream(stream->sink->link, stream);
+
+	if (dc_is_dp_signal(stream->signal))
+		unblank_stream(stream, &stream->sink->link->cur_link_settings);
+
+	return DC_OK;
+}
+
+
+/******************************************************************************/
+
+static void power_down_encoders(struct dc *dc)
+{
+	int i;
+
+	for (i = 0; i < dc->link_count; i++) {
+		dc->links[i]->link_enc->funcs->disable_output(
+				dc->links[i]->link_enc, SIGNAL_TYPE_NONE);
+	}
+}
+
+static void power_down_controllers(struct dc *dc)
+{
+	int i;
+
+	for (i = 0; i < dc->res_pool.controller_count; i++) {
+		dc->res_pool.timing_generators[i]->funcs->disable_crtc(
+				dc->res_pool.timing_generators[i]);
+	}
+}
+
+static void power_down_clock_sources(struct dc *dc)
+{
+	int i;
+
+	for (i = 0; i < dc->res_pool.clk_src_count; i++) {
+		if (dc->res_pool.clock_sources[i]->funcs->cs_power_down(
+				dc->res_pool.clock_sources[i]) == false)
+			dm_error("Failed to power down pll! (clk src index=%d)\n", i);
+	}
+}
+
+static void power_down_all_hw_blocks(struct dc *dc)
+{
+	power_down_encoders(dc);
+
+	power_down_controllers(dc);
+
+	power_down_clock_sources(dc);
+}
+
+static void disable_vga_and_power_gate_all_controllers(
+		struct dc *dc)
+{
+	int i;
+	struct timing_generator *tg;
+	struct dc_bios *dcb;
+	struct dc_context *ctx;
+
+	dcb = dal_adapter_service_get_bios_parser(
+			dc->res_pool.adapter_srv);
+
+	for (i = 0; i < dc->res_pool.controller_count; i++) {
+		tg = dc->res_pool.timing_generators[i];
+		ctx = dc->ctx;
+
+		tg->funcs->disable_vga(tg);
+
+		/* Enable CLOCK gating for each pipe BEFORE controller
+		 * powergating. */
+		enable_display_pipe_clock_gating(ctx,
+				true);
+		dc->hwss.enable_display_power_gating(ctx, i, dcb,
+				PIPE_GATING_CONTROL_ENABLE);
+	}
+}
+
+/**
+ * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
+ *  1. Power down all DC HW blocks
+ *  2. Disable VGA engine on all controllers
+ *  3. Enable power gating for controller
+ *  4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
+ */
+static void enable_accelerated_mode(struct dc *dc)
+{
+	struct dc_bios *dcb;
+
+	dcb = dal_adapter_service_get_bios_parser(dc->res_pool.adapter_srv);
+
+	power_down_all_hw_blocks(dc);
+
+	disable_vga_and_power_gate_all_controllers(dc);
+
+	dcb->funcs->set_scratch_acc_mode_change(dcb);
+}
+
+#if 0
+static enum clocks_state get_required_clocks_state(
+	struct display_clock *display_clock,
+	struct state_dependent_clocks *req_state_dep_clks)
+{
+	enum clocks_state clocks_required_state;
+	enum clocks_state dp_link_required_state;
+	enum clocks_state overall_required_state;
+
+	clocks_required_state = dal_display_clock_get_required_clocks_state(
+			display_clock, req_state_dep_clks);
+
+	dp_link_required_state = CLOCKS_STATE_ULTRA_LOW;
+
+	/* overall required state is the max of required state for clocks
+	 * (pixel, display clock) and the required state for DP link. */
+	overall_required_state =
+		clocks_required_state > dp_link_required_state ?
+			clocks_required_state : dp_link_required_state;
+
+	/* return the min required state */
+	return overall_required_state;
+}
+
+static bool dc_pre_clock_change(
+		struct dc_context *ctx,
+		struct minimum_clocks_calculation_result *min_clk_in,
+		enum clocks_state required_clocks_state,
+		struct power_to_dal_info *output)
+{
+	struct dal_to_power_info input = {0};
+
+	input.min_deep_sleep_sclk = min_clk_in->min_deep_sleep_sclk;
+	input.min_mclk = min_clk_in->min_mclk_khz;
+	input.min_sclk = min_clk_in->min_sclk_khz;
+
+	switch (required_clocks_state) {
+	case CLOCKS_STATE_ULTRA_LOW:
+		input.required_clock = PP_CLOCKS_STATE_ULTRA_LOW;
+		break;
+	case CLOCKS_STATE_LOW:
+		input.required_clock = PP_CLOCKS_STATE_LOW;
+		break;
+	case CLOCKS_STATE_NOMINAL:
+		input.required_clock = PP_CLOCKS_STATE_NOMINAL;
+		break;
+	case CLOCKS_STATE_PERFORMANCE:
+		input.required_clock = PP_CLOCKS_STATE_PERFORMANCE;
+		break;
+	default:
+		input.required_clock = PP_CLOCKS_STATE_NOMINAL;
+		break;
+	}
+
+	if (!dc_service_pp_pre_dce_clock_change(ctx, &input, output)) {
+		dm_error("DC: dc_service_pp_pre_dce_clock_change failed!\n");
+		return false;
+	}
+
+	return true;
+}
+
+static bool dc_set_clocks_and_clock_state (
+		struct validate_context *context)
+{
+	struct power_to_dal_info output = {0};
+
+	struct display_clock *disp_clk = context->res_ctx.pool.display_clock;
+	struct dc_context *ctx = context->targets[0]->ctx;
+
+
+	if (!dc_pre_clock_change(
+			ctx,
+			&context->res_ctx.min_clocks,
+			get_required_clocks_state(
+					context->res_ctx.pool.display_clock,
+					&context->res_ctx.state_clocks),
+			&output)) {
+		/* "output" was not updated by PPLib.
+		 * DAL will use default values for set mode.
+		 *
+		 * Do NOT fail this call. */
+		return true;
+	}
+
+	/* PPLib accepted the "clock state" that we need, that means we
+	 * can store it as minimum state because PPLib guarantees not go below
+	 * that state.
+	 *
+	 * Update the clock state here (prior to setting Pixel clock,
+	 * or Display clock)
+	 **/
+	if (!dal_display_clock_set_min_clocks_state(
+			disp_clk, context->res_ctx.required_clocks_state)) {
+		BREAK_TO_DEBUGGER();
+		dm_error("DC: failed to set minimum clock state!\n");
+	}
+
+
+	/*bm_clk_info.max_mclk_khz = output.max_mclk;
+	bm_clk_info.min_mclk_khz = output.min_mclk;
+	bm_clk_info.max_sclk_khz = output.max_sclk;
+	bm_clk_info.min_sclk_khz = output.min_sclk;*/
+
+	/* Now let Bandwidth Manager know about values we got from PPLib. */
+	/*dal_bandwidth_manager_set_dynamic_clock_info(bw_mgr, &bm_clk_info);*/
+
+	return true;
+}
+#endif
+
+/**
+ * Call display_engine_clock_dce80 to perform the Dclk programming.
+ */
+static void set_display_clock(struct validate_context *context)
+{
+	/* Program the display engine clock.
+	 * Check DFS bypass mode support or not. DFSbypass feature is only when
+	 * BIOS GPU info table reports support. */
+
+	if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) {
+		/*TODO: set_display_clock_dfs_bypass(
+				hws,
+				path_set,
+				context->res_ctx.pool.display_clock,
+				context->res_ctx.min_clocks.min_dclk_khz);*/
+	} else
+		dal_display_clock_set_clock(context->res_ctx.pool.display_clock,
+				context->bw_results.dispclk_khz);
+
+	/* TODO: When changing display engine clock, DMCU WaitLoop must be
+	 * reconfigured in order to maintain the same delays within DMCU
+	 * programming sequences. */
+
+	/* TODO: Start GTC counter */
+}
+
+static void set_displaymarks(
+	const struct dc *dc, struct validate_context *context)
+{
+	uint8_t i, j;
+	uint8_t total_streams = 0;
+	uint8_t target_count = context->target_count;
+
+	for (i = 0; i < target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			stream->mi->funcs->mem_input_program_display_marks(
+				stream->mi,
+				context->bw_results
+				.nbp_state_change_wm_ns[total_streams],
+				context->bw_results
+					.stutter_exit_wm_ns[total_streams],
+				context->bw_results
+					.urgent_wm_ns[total_streams],
+				stream->public.timing.h_total,
+				stream->public.timing.pix_clk_khz,
+				1000 * dc->bw_vbios.blackout_duration
+								.value >> 24);
+			total_streams++;
+		}
+	}
+}
+
+static void set_safe_displaymarks(struct validate_context *context)
+{
+	uint8_t i, j;
+	uint8_t target_count = context->target_count;
+
+	for (i = 0; i < target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			stream->mi->funcs->mem_input_program_safe_display_marks(
+					stream->mi);
+		}
+	}
+}
+
+static void program_bw(struct dc *dc, struct validate_context *context)
+{
+	set_safe_displaymarks(context);
+	/*TODO: when pplib works*/
+	/*dc_set_clocks_and_clock_state(context);*/
+
+	dc->hwss.set_display_clock(context);
+	dc->hwss.set_displaymarks(dc, context);
+}
+
+static void switch_dp_clock_sources(
+	const struct dc *dc,
+	struct validate_context *val_context)
+{
+	uint8_t i, j;
+	for (i = 0; i < val_context->target_count; i++) {
+		struct core_target *target = val_context->targets[i];
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			if (dc_is_dp_signal(stream->signal)) {
+				struct clock_source *clk_src =
+					find_used_clk_src_for_sharing(
+							val_context, stream);
+
+				if (clk_src &&
+					clk_src != stream->clock_source) {
+					unreference_clock_source(
+							&val_context->res_ctx,
+							stream->clock_source);
+					stream->clock_source = clk_src;
+					reference_clock_source(
+						&val_context->res_ctx, clk_src);
+					dc->hwss.crtc_switch_to_clk_src(
+						clk_src, stream->opp->inst);
+				}
+			}
+		}
+	}
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+/*TODO: const validate_context*/
+static enum dc_status apply_ctx_to_hw(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	enum dc_status status;
+	uint8_t i;
+	struct resource_pool *pool = &context->res_ctx.pool;
+
+	update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
+			true);
+
+	for (i = 0; i < pool->controller_count; i++) {
+		struct controller_ctx *ctlr_ctx
+			= &context->res_ctx.controller_ctx[i];
+		struct dc_bios *dcb;
+
+		if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream)
+			continue;
+
+		dcb = dal_adapter_service_get_bios_parser(
+				context->res_ctx.pool.adapter_srv);
+
+		dc->hwss.enable_display_power_gating(
+				dc->ctx, i, dcb,
+				PIPE_GATING_CONTROL_DISABLE);
+	}
+
+	set_safe_displaymarks(context);
+	/*TODO: when pplib works*/
+	/*dc_set_clocks_and_clock_state(context);*/
+
+	if (context->bw_results.dispclk_khz
+		> dc->current_context.bw_results.dispclk_khz)
+		set_display_clock(context);
+
+	for (i = 0; i < pool->controller_count; i++) {
+		struct controller_ctx *ctlr_ctx
+			= &context->res_ctx.controller_ctx[i];
+		if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream)
+			continue;
+
+		status = apply_single_controller_ctx_to_hw(
+				i,
+				context,
+				dc);
+
+		if (DC_OK != status)
+			return status;
+	}
+	dc->hwss.set_displaymarks(dc, context);
+
+	update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
+			false);
+
+	switch_dp_clock_sources(dc, context);
+
+	return DC_OK;
+}
+
+
+/*******************************************************************************
+ * Front End programming
+ ******************************************************************************/
+
+static bool setup_line_buffer_pixel_depth(
+	const struct core_stream *stream,
+	enum lb_pixel_depth depth,
+	bool blank)
+{
+	enum lb_pixel_depth current_depth;
+
+	struct timing_generator *tg = stream->tg;
+	struct transform *xfm = stream->xfm;
+
+	if (!xfm->funcs->transform_get_current_pixel_storage_depth(
+		xfm,
+		&current_depth))
+		return false;
+
+	if (current_depth != depth) {
+		if (blank)
+			tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
+
+		return xfm->funcs->transform_set_pixel_storage_depth(xfm, depth,
+				&stream->bit_depth_params);
+	}
+
+	return false;
+}
+
+static void hw_sequencer_build_scaler_parameter_plane(
+		const struct core_stream *stream,
+		struct scaler_data *scaler_data)
+{
+	/*TODO: per pipe not per stream*/
+	/*TODO: get from feature from adapterservice*/
+	scaler_data->flags.bits.SHOW_COLOURED_BORDER = false;
+
+	scaler_data->flags.bits.SHOULD_PROGRAM_ALPHA = 1;
+
+	scaler_data->flags.bits.SHOULD_PROGRAM_VIEWPORT = 0;
+
+	scaler_data->flags.bits.SHOULD_UNLOCK = 0;
+
+	scaler_data->flags.bits.INTERLACED = 0;
+
+	scaler_data->dal_pixel_format = stream->format;
+
+	scaler_data->taps = stream->taps;
+
+	scaler_data->viewport = stream->viewport;
+
+	scaler_data->overscan = stream->overscan;
+
+	scaler_data->ratios = &stream->ratios;
+
+	/*TODO rotation and adjustment */
+	scaler_data->h_sharpness = 0;
+	scaler_data->v_sharpness = 0;
+
+}
+
+static void set_default_colors(
+				struct input_pixel_processor *ipp,
+				struct output_pixel_processor *opp,
+				enum pixel_format format,
+				enum color_space input_color_space,
+				enum color_space output_color_space,
+				enum dc_color_depth color_depth)
+{
+	struct default_adjustment default_adjust = { 0 };
+
+	default_adjust.force_hw_default = false;
+	default_adjust.color_space = output_color_space;
+	default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
+	default_adjust.surface_pixel_format = format;
+
+	/* display color depth */
+	default_adjust.color_depth = color_depth;
+
+	/* Lb color depth */
+	default_adjust.lb_color_depth = LB_PIXEL_DEPTH_24BPP;
+	/*dal_hw_sequencer_translate_to_lb_color_depth(
+			build_params->
+			line_buffer_params[path_id][plane_id].depth);*/
+
+	opp->funcs->opp_set_csc_default(opp, &default_adjust);
+}
+
+static void program_scaler(
+	uint8_t controller_idx,
+	struct timing_generator *tg,
+	struct transform *xfm,
+	const struct core_surface *surface,
+	const struct core_stream *stream)
+{
+	struct scaler_data scaler_data = { { 0 } };
+
+	hw_sequencer_build_scaler_parameter_plane(
+		stream,
+		&scaler_data);
+
+	setup_line_buffer_pixel_depth(
+		stream,
+		LB_PIXEL_DEPTH_24BPP,
+		false);
+
+	tg->funcs->set_overscan_blank_color(tg, surface->public.colorimetry.color_space);
+
+	xfm->funcs->transform_set_scaler(xfm, &scaler_data);
+
+	xfm->funcs->transform_update_viewport(
+			xfm,
+			&scaler_data.viewport,
+			false);
+}
+
+/**
+ * Program the Front End of the Pipe.
+ * The Back End was already programmed by Set Mode.
+ */
+static bool set_plane_config(
+	const struct dc *dc,
+	struct core_surface *surface,
+	struct core_target *target)
+{
+	const struct core_stream *core_stream =
+		DC_STREAM_TO_CORE(target->public.streams[0]);
+	const struct dc_crtc_timing *dc_crtc_timing =
+			&target->public.streams[0]->timing;
+	struct mem_input *mi = core_stream->mi;
+	struct input_pixel_processor *ipp = core_stream->ipp;
+	struct timing_generator *tg = core_stream->tg;
+	struct transform *xfm = core_stream->xfm;
+	struct output_pixel_processor *opp = core_stream->opp;
+	struct dc_context *ctx = core_stream->ctx;
+	uint8_t controller_idx = core_stream->controller_idx;
+
+	/* TODO: Clean up change, possibly change to use same type */
+	enum color_space input_color_space =
+					surface_color_to_color_space(&(surface->public.colorimetry));
+
+	dc->hwss.pipe_control_lock(
+			ctx,
+			controller_idx,
+			PIPE_LOCK_CONTROL_MODE,
+			false);
+
+	/* While a non-root controller is programmed we
+	 * have to lock the root controller. */
+	dc->hwss.pipe_control_lock(
+			ctx,
+			controller_idx,
+			PIPE_LOCK_CONTROL_GRAPHICS |
+			PIPE_LOCK_CONTROL_SCL |
+			PIPE_LOCK_CONTROL_BLENDER |
+			PIPE_LOCK_CONTROL_SURFACE,
+			true);
+
+	tg->funcs->program_timing(tg, dc_crtc_timing, false);
+
+	dc->hwss.enable_fe_clock(ctx, controller_idx, true);
+
+	set_default_colors(
+			ipp,
+			opp,
+			core_stream->format,
+			input_color_space,
+			get_output_color_space(dc_crtc_timing),
+			dc_crtc_timing->display_color_depth);
+
+	/* program Scaler */
+	program_scaler(
+		controller_idx, tg, xfm, surface, core_stream);
+
+	dc->hwss.set_blender_mode(
+			ctx,
+			controller_idx,
+			BLENDER_MODE_CURRENT_PIPE);
+
+	mi->funcs->mem_input_program_surface_config(
+			mi,
+			surface->public.format,
+			&surface->public.tiling_info,
+			&surface->public.plane_size,
+			surface->public.rotation);
+
+	dc->hwss.pipe_control_lock(
+			ctx,
+			controller_idx,
+			PIPE_LOCK_CONTROL_GRAPHICS |
+			PIPE_LOCK_CONTROL_SCL |
+			PIPE_LOCK_CONTROL_BLENDER |
+			PIPE_LOCK_CONTROL_SURFACE,
+			false);
+
+	return true;
+}
+
+static bool update_plane_address(
+	const struct dc *dc,
+	const struct core_surface *surface,
+	struct core_target *target)
+{
+	const struct core_stream *core_stream =
+		DC_STREAM_TO_CORE(target->public.streams[0]);
+	struct dc_context *ctx = core_stream->ctx;
+	struct mem_input *mi = core_stream->mi;
+	uint8_t controller_id = core_stream->controller_idx;
+
+	/* TODO: crtc should be per surface, NOT per-target */
+	dc->hwss.pipe_control_lock(
+		ctx,
+		controller_id,
+		PIPE_LOCK_CONTROL_SURFACE,
+		true);
+
+	if (false ==
+		core_stream->mi->funcs->mem_input_program_surface_flip_and_addr(
+		mi, &surface->public.address, surface->public.flip_immediate))
+		return false;
+
+	dc->hwss.pipe_control_lock(
+		ctx,
+		controller_id,
+		PIPE_LOCK_CONTROL_SURFACE,
+		false);
+
+	return true;
+}
+
+static void reset_single_stream_hw_ctx(
+		const struct dc *dc,
+		struct core_stream *stream,
+		struct validate_context *context)
+{
+	struct dc_bios *dcb;
+
+	dcb = dal_adapter_service_get_bios_parser(
+			context->res_ctx.pool.adapter_srv);
+	if (stream->audio) {
+		dal_audio_disable_output(stream->audio,
+				stream->stream_enc->id,
+				stream->signal);
+		stream->audio = NULL;
+	}
+
+	core_link_disable_stream(stream->sink->link, stream);
+
+	stream->tg->funcs->set_blank(stream->tg, true);
+	stream->tg->funcs->disable_crtc(stream->tg);
+	stream->mi->funcs->mem_input_deallocate_dmif_buffer(
+			stream->mi, context->target_count);
+	stream->xfm->funcs->transform_set_scaler_bypass(stream->xfm);
+	unreference_clock_source(&context->res_ctx, stream->clock_source);
+	dc->hwss.enable_display_power_gating(
+			stream->ctx, stream->controller_idx, dcb,
+			PIPE_GATING_CONTROL_ENABLE);
+}
+
+static void reset_hw_ctx(struct dc *dc,
+		struct validate_context *context,
+		uint8_t target_count)
+{
+	uint8_t i;
+	/* look up the targets that have been removed since last commit */
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		const struct core_target *core_target =
+			dc->current_context.targets[i];
+		struct core_stream *core_stream =
+			DC_STREAM_TO_CORE(core_target->public.streams[0]);
+		uint8_t controller_idx = core_stream->controller_idx;
+
+		if (context->res_ctx.controller_ctx[controller_idx].stream &&
+				!context->res_ctx.controller_ctx[controller_idx]
+				.flags.timing_changed)
+			continue;
+
+		reset_single_stream_hw_ctx(dc, core_stream, &dc->current_context);
+	}
+}
+
+static void power_down(struct dc *dc)
+{
+	power_down_all_hw_blocks(dc);
+	disable_vga_and_power_gate_all_controllers(dc);
+
+}
+
+static bool wait_for_reset_trigger_to_occur(
+	struct dc_context *dc_ctx,
+	struct timing_generator *tg)
+{
+	bool rc = false;
+
+	/* To avoid endless loop we wait at most
+	 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
+	const uint32_t frames_to_wait_on_triggered_reset = 10;
+	uint32_t i;
+
+	for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
+
+		if (!tg->funcs->is_counter_moving(tg)) {
+			DC_ERROR("TG counter is not moving!\n");
+			break;
+		}
+
+		if (tg->funcs->did_triggered_reset_occur(tg)) {
+			rc = true;
+			/* usually occurs at i=1 */
+			DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
+					i);
+			break;
+		}
+
+		/* Wait for one frame. */
+		tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
+		tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
+	}
+
+	if (false == rc)
+		DC_ERROR("GSL: Timeout on reset trigger!\n");
+
+	return rc;
+}
+
+/* Enable timing synchronization for a group of Timing Generators. */
+static void enable_timing_synchronization(
+	struct dc_context *dc_ctx,
+	uint32_t timing_generator_num,
+	struct timing_generator *tgs[])
+{
+	struct dcp_gsl_params gsl_params = { 0 };
+	struct trigger_params trigger_params;
+	uint32_t i;
+
+	DC_SYNC_INFO("GSL: Setting-up...\n");
+
+	gsl_params.gsl_group = SYNC_SOURCE_GSL_GROUP0;
+	gsl_params.gsl_purpose = DCP_GSL_PURPOSE_SURFACE_FLIP;
+
+	for (i = 0; i < timing_generator_num; i++) {
+		/* Designate a single TG in the group as a master.
+		 * Since HW doesn't care which one, we always assign
+		 * the 1st one in the group. */
+		gsl_params.timing_server = (0 == i ? true : false);
+
+		tgs[i]->funcs->setup_global_swap_lock(tgs[i], &gsl_params);
+	}
+
+	/* Reset slave controllers on master VSync */
+	DC_SYNC_INFO("GSL: enabling trigger-reset\n");
+	dm_memset(&trigger_params, 0, sizeof(trigger_params));
+
+	trigger_params.edge = TRIGGER_EDGE_DEFAULT;
+	trigger_params.source = SYNC_SOURCE_GSL_GROUP0;
+
+	for (i = 1 /* skip the master */; i < timing_generator_num; i++) {
+		tgs[i]->funcs->enable_reset_trigger(tgs[i], &trigger_params);
+
+		DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
+		wait_for_reset_trigger_to_occur(dc_ctx, tgs[i]);
+
+		/* Regardless of success of the wait above, remove the reset or
+		 * the driver will start timing out on Display requests. */
+		DC_SYNC_INFO("GSL: disabling trigger-reset.\n");
+		tgs[i]->funcs->disable_reset_trigger(tgs[i]);
+	}
+
+	/* GSL Vblank synchronization is a one time sync mechanism, assumption
+	 * is that the sync'ed displays will not drift out of sync over time*/
+	DC_SYNC_INFO("GSL: Restoring register states.\n");
+	for (i = 0; i < timing_generator_num; i++)
+		tgs[i]->funcs->tear_down_global_swap_lock(tgs[i]);
+
+	DC_SYNC_INFO("GSL: Set-up complete.\n");
+}
+
+static const struct hw_sequencer_funcs dce110_funcs = {
+	.apply_ctx_to_hw = apply_ctx_to_hw,
+	.reset_hw_ctx = reset_hw_ctx,
+	.set_plane_config = set_plane_config,
+	.update_plane_address = update_plane_address,
+	.set_gamma_ramp = set_gamma_ramp,
+	.power_down = power_down,
+	.enable_accelerated_mode = enable_accelerated_mode,
+	.enable_timing_synchronization = enable_timing_synchronization,
+	.program_bw = program_bw,
+	.enable_stream = enable_stream,
+	.disable_stream = disable_stream,
+	.enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
+	.crtc_switch_to_clk_src = dce110_crtc_switch_to_clk_src,
+	.enable_display_power_gating = dce110_enable_display_power_gating,
+	.enable_fe_clock = dce110_enable_fe_clock,
+	.pipe_control_lock = dce110_pipe_control_lock,
+	.set_blender_mode = dce110_set_blender_mode,
+	.clock_gating_power_up = dal_dc_clock_gating_dce110_power_up,/*todo*/
+	.set_display_clock = set_display_clock,
+	.set_displaymarks = set_displaymarks,
+};
+
+bool dce110_hw_sequencer_construct(struct dc *dc)
+{
+	dc->hwss = dce110_funcs;
+
+	return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
new file mode 100644
index 000000000000..def54df283d5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
@@ -0,0 +1,36 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HWSS_DCE110_H__
+#define __DC_HWSS_DCE110_H__
+
+#include "core_types.h"
+
+struct dc;
+
+bool dce110_hw_sequencer_construct(struct dc *dc);
+
+#endif /* __DC_HWSS_DCE110_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
new file mode 100644
index 000000000000..9e2b5d95a521
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
@@ -0,0 +1,1238 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "link_encoder.h"
+#include "stream_encoder.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+#include "../virtual/virtual_stream_encoder.h"
+#include "dce110/dce110_timing_generator.h"
+#include "dce110/dce110_link_encoder.h"
+#include "dce110/dce110_mem_input.h"
+#include "dce110/dce110_ipp.h"
+#include "dce110/dce110_transform.h"
+#include "dce110/dce110_stream_encoder.h"
+#include "dce110/dce110_opp.h"
+#include "dce110/dce110_clock_source.h"
+
+#include "dce/dce_11_0_d.h"
+
+#ifndef mmDP_DPHY_INTERNAL_CTRL
+	#define mmDP_DPHY_INTERNAL_CTRL 0x4aa7
+	#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7
+	#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7
+	#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7
+	#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7
+	#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7
+	#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7
+	#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7
+	#define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7
+	#define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7
+#endif
+
+enum dce110_clk_src_array_id {
+	DCE110_CLK_SRC_PLL0 = 0,
+	DCE110_CLK_SRC_PLL1,
+	DCE110_CLK_SRC_EXT,
+
+	DCE110_CLK_SRC_TOTAL
+};
+
+static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = {
+	{
+		.crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp =  (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp =  (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
+	}
+};
+
+static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = {
+	{
+		.dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE0_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE1_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE2_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	}
+};
+
+static const struct dce110_transform_reg_offsets dce110_xfm_offsets[] = {
+{
+	.scl_offset = (mmSCL0_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB0_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL1_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB1_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL2_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB2_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+}
+};
+
+static const struct dce110_ipp_reg_offsets dce110_ipp_reg_offsets[] = {
+{
+	.dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL),
+}
+};
+
+static const struct dce110_link_enc_bl_registers link_enc_bl_regs = {
+		.BL_PWM_CNTL = mmBL_PWM_CNTL,
+		.BL_PWM_GRP1_REG_LOCK = mmBL_PWM_GRP1_REG_LOCK,
+		.BL_PWM_PERIOD_CNTL = mmBL_PWM_PERIOD_CNTL,
+		.LVTMA_PWRSEQ_CNTL = mmLVTMA_PWRSEQ_CNTL,
+		.LVTMA_PWRSEQ_STATE = mmLVTMA_PWRSEQ_STATE
+};
+
+#define aux_regs(id)\
+[id] = {\
+	.AUX_CONTROL = mmDP_AUX ## id ## _AUX_CONTROL,\
+	.AUX_DPHY_RX_CONTROL0 = mmDP_AUX ## id ## _AUX_DPHY_RX_CONTROL0\
+}
+
+static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = {
+		aux_regs(0),
+		aux_regs(1),
+		aux_regs(2),
+		aux_regs(3),
+		aux_regs(4),
+		aux_regs(5)
+};
+
+#define link_regs(id)\
+[id] = {\
+	.DIG_BE_CNTL = mmDIG ## id ## _DIG_BE_CNTL,\
+	.DIG_BE_EN_CNTL = mmDIG ## id ## _DIG_BE_EN_CNTL,\
+	.DP_CONFIG = mmDP ## id ## _DP_CONFIG,\
+	.DP_DPHY_CNTL = mmDP ## id ## _DP_DPHY_CNTL,\
+	.DP_DPHY_INTERNAL_CTRL = mmDP ## id ## _DP_DPHY_INTERNAL_CTRL,\
+	.DP_DPHY_PRBS_CNTL = mmDP ## id ## _DP_DPHY_PRBS_CNTL,\
+	.DP_DPHY_SYM0 = mmDP ## id ## _DP_DPHY_SYM0,\
+	.DP_DPHY_SYM1 = mmDP ## id ## _DP_DPHY_SYM1,\
+	.DP_DPHY_SYM2 = mmDP ## id ## _DP_DPHY_SYM2,\
+	.DP_DPHY_TRAINING_PATTERN_SEL = mmDP ## id ## _DP_DPHY_TRAINING_PATTERN_SEL,\
+	.DP_LINK_CNTL = mmDP ## id ## _DP_LINK_CNTL,\
+	.DP_LINK_FRAMING_CNTL = mmDP ## id ## _DP_LINK_FRAMING_CNTL,\
+	.DP_MSE_SAT0 = mmDP ## id ## _DP_MSE_SAT0,\
+	.DP_MSE_SAT1 = mmDP ## id ## _DP_MSE_SAT1,\
+	.DP_MSE_SAT2 = mmDP ## id ## _DP_MSE_SAT2,\
+	.DP_MSE_SAT_UPDATE = mmDP ## id ## _DP_MSE_SAT_UPDATE,\
+	.DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\
+	.DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL\
+}
+
+static const struct dce110_link_enc_registers link_enc_regs[] = {
+		link_regs(0),
+		link_regs(1),
+		link_regs(2),
+		link_regs(3),
+		link_regs(4),
+		link_regs(5),
+		link_regs(6)
+};
+
+#define stream_enc_regs(id)\
+[id] = {\
+	.AFMT_AVI_INFO0 = mmDIG ## id ## _AFMT_AVI_INFO0,\
+	.AFMT_AVI_INFO1 = mmDIG ## id ## _AFMT_AVI_INFO1,\
+	.AFMT_AVI_INFO2 = mmDIG ## id ## _AFMT_AVI_INFO2,\
+	.AFMT_AVI_INFO3 = mmDIG ## id ## _AFMT_AVI_INFO3,\
+	.AFMT_GENERIC_0 = mmDIG ## id ## _AFMT_GENERIC_0,\
+	.AFMT_GENERIC_7 = mmDIG ## id ## _AFMT_GENERIC_7,\
+	.AFMT_GENERIC_HDR = mmDIG ## id ## _AFMT_GENERIC_HDR,\
+	.AFMT_INFOFRAME_CONTROL0 = mmDIG ## id ## _AFMT_INFOFRAME_CONTROL0,\
+	.AFMT_VBI_PACKET_CONTROL = mmDIG ## id ## _AFMT_VBI_PACKET_CONTROL,\
+	.DIG_FE_CNTL = mmDIG ## id ## _DIG_FE_CNTL,\
+	.DP_MSE_RATE_CNTL = mmDP ## id ## _DP_MSE_RATE_CNTL,\
+	.DP_MSE_RATE_UPDATE = mmDP ## id ## _DP_MSE_RATE_UPDATE,\
+	.DP_PIXEL_FORMAT = mmDP ## id ## _DP_PIXEL_FORMAT,\
+	.DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\
+	.DP_STEER_FIFO = mmDP ## id ## _DP_STEER_FIFO,\
+	.DP_VID_M = mmDP ## id ## _DP_VID_M,\
+	.DP_VID_N = mmDP ## id ## _DP_VID_N,\
+	.DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL,\
+	.DP_VID_TIMING = mmDP ## id ## _DP_VID_TIMING,\
+	.HDMI_CONTROL = mmDIG ## id ## _HDMI_CONTROL,\
+	.HDMI_GC = mmDIG ## id ## _HDMI_GC,\
+	.HDMI_GENERIC_PACKET_CONTROL0 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL0,\
+	.HDMI_GENERIC_PACKET_CONTROL1 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL1,\
+	.HDMI_INFOFRAME_CONTROL0 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL0,\
+	.HDMI_INFOFRAME_CONTROL1 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL1,\
+	.HDMI_VBI_PACKET_CONTROL = mmDIG ## id ## _HDMI_VBI_PACKET_CONTROL,\
+	.TMDS_CNTL = mmDIG ## id ## _TMDS_CNTL\
+}
+
+static const struct dce110_stream_enc_registers stream_enc_regs[] = {
+		stream_enc_regs(0),
+		stream_enc_regs(1),
+		stream_enc_regs(2),
+		stream_enc_regs(3),
+		stream_enc_regs(4),
+		stream_enc_regs(5),
+		stream_enc_regs(6)
+};
+
+
+/* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */
+static const struct dce110_opp_reg_offsets dce110_opp_reg_offsets[] = {
+{
+	.fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{
+	.fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+}
+};
+
+
+static const struct dce110_clk_src_reg_offsets dce110_clk_src_reg_offsets[] = {
+	{
+		.pll_cntl = mmBPHYC_PLL0_PLL_CNTL,
+		.pixclk_resync_cntl  = mmPIXCLK0_RESYNC_CNTL
+	},
+	{
+		.pll_cntl = mmBPHYC_PLL1_PLL_CNTL,
+		.pixclk_resync_cntl  = mmPIXCLK1_RESYNC_CNTL
+	}
+};
+
+static struct timing_generator *dce110_timing_generator_create(
+		struct adapter_service *as,
+		struct dc_context *ctx,
+		uint32_t instance,
+		const struct dce110_timing_generator_offsets *offsets)
+{
+	struct dce110_timing_generator *tg110 =
+		dm_alloc(ctx, sizeof(struct dce110_timing_generator));
+
+	if (!tg110)
+		return NULL;
+
+	if (dce110_timing_generator_construct(tg110, as, ctx, instance, offsets))
+		return &tg110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, tg110);
+	return NULL;
+}
+
+static struct stream_encoder *dce110_stream_encoder_create(
+	enum engine_id eng_id,
+	struct dc_context *ctx,
+	struct dc_bios *bp,
+	const struct dce110_stream_enc_registers *regs)
+{
+	struct dce110_stream_encoder *enc110 =
+		dm_alloc(ctx, sizeof(struct dce110_stream_encoder));
+
+	if (!enc110)
+		return NULL;
+
+	if (dce110_stream_encoder_construct(enc110, ctx, bp, eng_id, regs))
+		return &enc110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, enc110);
+	return NULL;
+}
+
+static struct mem_input *dce110_mem_input_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_mem_input_reg_offsets *offset)
+{
+	struct dce110_mem_input *mem_input110 =
+		dm_alloc(ctx, sizeof(struct dce110_mem_input));
+
+	if (!mem_input110)
+		return NULL;
+
+	if (dce110_mem_input_construct(mem_input110,
+			ctx, inst, offset))
+		return &mem_input110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, mem_input110);
+	return NULL;
+}
+
+static void dce110_transform_destroy(struct transform **xfm)
+{
+	dm_free((*xfm)->ctx, TO_DCE110_TRANSFORM(*xfm));
+	*xfm = NULL;
+}
+
+static struct transform *dce110_transform_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *offsets)
+{
+	struct dce110_transform *transform =
+		dm_alloc(ctx, sizeof(struct dce110_transform));
+
+	if (!transform)
+		return NULL;
+
+	if (dce110_transform_construct(transform, ctx, inst, offsets))
+		return &transform->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, transform);
+	return NULL;
+}
+
+static struct input_pixel_processor *dce110_ipp_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_ipp_reg_offsets *offsets)
+{
+	struct dce110_ipp *ipp =
+		dm_alloc(ctx, sizeof(struct dce110_ipp));
+
+	if (!ipp)
+		return NULL;
+
+	if (dce110_ipp_construct(ipp, ctx, inst, offsets))
+		return &ipp->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, ipp);
+	return NULL;
+}
+
+struct link_encoder *dce110_link_encoder_create(
+	const struct encoder_init_data *enc_init_data)
+{
+	struct dce110_link_encoder *enc110 =
+		dm_alloc(
+			enc_init_data->ctx,
+			sizeof(struct dce110_link_encoder));
+
+	if (!enc110)
+		return NULL;
+
+	if (dce110_link_encoder_construct(
+			enc110,
+			enc_init_data,
+			&link_enc_regs[enc_init_data->transmitter],
+			&link_enc_aux_regs[enc_init_data->channel - 1],
+			&link_enc_bl_regs))
+		return &enc110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(enc_init_data->ctx, enc110);
+	return NULL;
+}
+
+void dce110_link_encoder_destroy(struct link_encoder **enc)
+{
+	dm_free((*enc)->ctx, TO_DCE110_LINK_ENC(*enc));
+	*enc = NULL;
+}
+
+
+static struct output_pixel_processor *dce110_opp_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offsets)
+{
+	struct dce110_opp *opp =
+		dm_alloc(ctx, sizeof(struct dce110_opp));
+
+	if (!opp)
+		return NULL;
+
+	if (dce110_opp_construct(opp,
+			ctx, inst, offsets))
+		return &opp->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, opp);
+	return NULL;
+}
+
+struct clock_source *dce110_clock_source_create(
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_reg_offsets *offsets)
+{
+	struct dce110_clk_src *clk_src =
+		dm_alloc(ctx, sizeof(struct dce110_clk_src));
+
+	if (!clk_src)
+		return NULL;
+
+	if (dce110_clk_src_construct(clk_src, ctx, bios, id, offsets))
+		return &clk_src->base;
+
+	BREAK_TO_DEBUGGER();
+	return NULL;
+}
+
+void dce110_clock_source_destroy(struct clock_source **clk_src)
+{
+	dm_free((*clk_src)->ctx, TO_DCE110_CLK_SRC(*clk_src));
+	*clk_src = NULL;
+}
+
+void dce110_destruct_resource_pool(struct resource_pool *pool)
+{
+	unsigned int i;
+
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->opps[i] != NULL)
+			dce110_opp_destroy(&pool->opps[i]);
+
+		if (pool->transforms[i] != NULL)
+			dce110_transform_destroy(&pool->transforms[i]);
+
+		if (pool->ipps[i] != NULL)
+			dce110_ipp_destroy(&pool->ipps[i]);
+
+		if (pool->mis[i] != NULL) {
+			dm_free(pool->mis[i]->ctx,
+					TO_DCE110_MEM_INPUT(pool->mis[i]));
+			pool->mis[i] = NULL;
+		}
+
+		if (pool->timing_generators[i] != NULL)	{
+			dm_free(pool->timing_generators[i]->ctx, DCE110TG_FROM_TG(pool->timing_generators[i]));
+			pool->timing_generators[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		if (pool->stream_enc[i] != NULL)
+			dm_free(pool->stream_enc[i]->ctx,
+				DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+	}
+
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] != NULL) {
+			dce110_clock_source_destroy(&pool->clock_sources[i]);
+		}
+	}
+
+	for (i = 0; i < pool->audio_count; i++)	{
+		if (pool->audios[i] != NULL) {
+			dal_audio_destroy(&pool->audios[i]);
+		}
+	}
+
+	if (pool->display_clock != NULL) {
+		dal_display_clock_destroy(&pool->display_clock);
+	}
+
+	if (pool->scaler_filter != NULL) {
+		dal_scaler_filter_destroy(&pool->scaler_filter);
+	}
+	if (pool->irqs != NULL) {
+		dal_irq_service_destroy(&pool->irqs);
+	}
+
+	if (pool->adapter_srv != NULL) {
+		dal_adapter_service_destroy(&pool->adapter_srv);
+	}
+}
+
+static struct clock_source *find_first_free_pll(
+		struct resource_context *res_ctx)
+{
+	if (res_ctx->clock_source_ref_count[DCE110_CLK_SRC_PLL0] == 0) {
+		return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL0];
+	}
+	if (res_ctx->clock_source_ref_count[DCE110_CLK_SRC_PLL1] == 0) {
+		return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL1];
+	}
+
+	return 0;
+}
+
+static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
+{
+	switch (crtc_id) {
+	case CONTROLLER_ID_D0:
+		return DTO_SOURCE_ID0;
+	case CONTROLLER_ID_D1:
+		return DTO_SOURCE_ID1;
+	case CONTROLLER_ID_D2:
+		return DTO_SOURCE_ID2;
+	case CONTROLLER_ID_D3:
+		return DTO_SOURCE_ID3;
+	case CONTROLLER_ID_D4:
+		return DTO_SOURCE_ID4;
+	case CONTROLLER_ID_D5:
+		return DTO_SOURCE_ID5;
+	default:
+		return DTO_SOURCE_UNKNOWN;
+	}
+}
+
+static void build_audio_output(
+	const struct core_stream *stream,
+	struct audio_output *audio_output)
+{
+	audio_output->engine_id = stream->stream_enc->id;
+
+	audio_output->signal = stream->signal;
+
+	/* audio_crtc_info  */
+
+	audio_output->crtc_info.h_total =
+		stream->public.timing.h_total;
+
+	/* Audio packets are sent during actual CRTC blank physical signal, we
+	 * need to specify actual active signal portion */
+	audio_output->crtc_info.h_active =
+			stream->public.timing.h_addressable
+			+ stream->public.timing.h_border_left
+			+ stream->public.timing.h_border_right;
+
+	audio_output->crtc_info.v_active =
+			stream->public.timing.v_addressable
+			+ stream->public.timing.v_border_top
+			+ stream->public.timing.v_border_bottom;
+
+	audio_output->crtc_info.pixel_repetition = 1;
+
+	audio_output->crtc_info.interlaced =
+			stream->public.timing.flags.INTERLACE;
+
+	audio_output->crtc_info.refresh_rate =
+		(stream->public.timing.pix_clk_khz*1000)/
+		(stream->public.timing.h_total*stream->public.timing.v_total);
+
+	audio_output->crtc_info.color_depth =
+		stream->public.timing.display_color_depth;
+
+	audio_output->crtc_info.requested_pixel_clock =
+			stream->pix_clk_params.requested_pix_clk;
+
+	/* TODO - Investigate why calculated pixel clk has to be
+	 * requested pixel clk */
+	audio_output->crtc_info.calculated_pixel_clock =
+			stream->pix_clk_params.requested_pix_clk;
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
+			stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+		audio_output->pll_info.dp_dto_source_clock_in_khz =
+			dal_display_clock_get_dp_ref_clk_frequency(
+				stream->dis_clk);
+	}
+
+	audio_output->pll_info.feed_back_divider =
+			stream->pll_settings.feedback_divider;
+
+	audio_output->pll_info.dto_source =
+		translate_to_dto_source(
+			stream->controller_idx + 1);
+
+	/* TODO hard code to enable for now. Need get from stream */
+	audio_output->pll_info.ss_enabled = true;
+
+	audio_output->pll_info.ss_percentage =
+			stream->pll_settings.ss_percentage;
+}
+
+static void get_pixel_clock_parameters(
+	const struct core_stream *stream,
+	struct pixel_clk_params *pixel_clk_params)
+{
+	pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz;
+	pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
+	pixel_clk_params->signal_type = stream->sink->public.sink_signal;
+	pixel_clk_params->controller_id = stream->controller_idx + 1;
+	/* TODO: un-hardcode*/
+	pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
+		LINK_RATE_REF_FREQ_IN_KHZ;
+	pixel_clk_params->flags.ENABLE_SS = 0;
+	pixel_clk_params->color_depth =
+		stream->public.timing.display_color_depth;
+	pixel_clk_params->flags.DISPLAY_BLANKED = 1;
+}
+
+static enum dc_status build_stream_hw_param(struct core_stream *stream)
+{
+	/*TODO: unhardcode*/
+	stream->max_tmds_clk_from_edid_in_mhz = 0;
+	stream->max_hdmi_deep_color = COLOR_DEPTH_121212;
+	stream->max_hdmi_pixel_clock = 600000;
+
+	get_pixel_clock_parameters(stream, &stream->pix_clk_params);
+	stream->clock_source->funcs->get_pix_clk_dividers(
+		stream->clock_source,
+		&stream->pix_clk_params,
+		&stream->pll_settings);
+
+	build_audio_output(stream, &stream->audio_output);
+
+	return DC_OK;
+}
+
+static enum dc_status validate_mapped_resource(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	enum dc_status status = DC_OK;
+	uint8_t i, j;
+
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		if (context->target_flags[i].unchanged)
+			continue;
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct core_link *link = stream->sink->link;
+
+			if (!stream->tg->funcs->validate_timing(
+					stream->tg, &stream->public.timing))
+				return DC_FAIL_CONTROLLER_VALIDATE;
+
+			status = build_stream_hw_param(stream);
+
+			if (status != DC_OK)
+				return status;
+
+			if (!link->link_enc->funcs->validate_output_with_stream(
+					link->link_enc,
+					stream))
+				return DC_FAIL_ENC_VALIDATE;
+
+			/* TODO: validate audio ASIC caps, encoder */
+
+			status = dc_link_validate_mode_timing(stream->sink,
+					link,
+					&stream->public.timing);
+
+			if (status != DC_OK)
+				return status;
+
+			build_info_frame(stream);
+		}
+	}
+
+	return DC_OK;
+}
+
+enum dc_status dce110_validate_bandwidth(
+	const struct dc *dc,
+	struct validate_context *context)
+{
+	uint8_t i, j;
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	uint8_t number_of_displays = 0;
+	uint8_t max_htaps = 1;
+	uint8_t max_vtaps = 1;
+	bool all_displays_in_sync = true;
+	struct dc_crtc_timing prev_timing;
+
+	memset(&context->bw_mode_data, 0, sizeof(context->bw_mode_data));
+
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct bw_calcs_input_single_display *disp = &context->
+				bw_mode_data.displays_data[number_of_displays];
+
+			if (target->status.surface_count == 0) {
+				disp->graphics_scale_ratio = bw_int_to_fixed(1);
+				disp->graphics_h_taps = 2;
+				disp->graphics_v_taps = 2;
+
+				/* TODO: remove when bw formula accepts taps per
+				 * display
+				 */
+				if (max_vtaps < 2)
+					max_vtaps = 2;
+				if (max_htaps < 2)
+					max_htaps = 2;
+
+			} else {
+				disp->graphics_scale_ratio =
+					fixed31_32_to_bw_fixed(
+						stream->ratios.vert.value);
+				disp->graphics_h_taps = stream->taps.h_taps;
+				disp->graphics_v_taps = stream->taps.v_taps;
+
+				/* TODO: remove when bw formula accepts taps per
+				 * display
+				 */
+				if (max_vtaps < stream->taps.v_taps)
+					max_vtaps = stream->taps.v_taps;
+				if (max_htaps < stream->taps.h_taps)
+					max_htaps = stream->taps.h_taps;
+			}
+
+			disp->graphics_src_width =
+					stream->public.timing.h_addressable;
+			disp->graphics_src_height =
+					stream->public.timing.v_addressable;
+			disp->h_total = stream->public.timing.h_total;
+			disp->pixel_rate = bw_frc_to_fixed(
+				stream->public.timing.pix_clk_khz, 1000);
+
+			/*TODO: get from surface*/
+			disp->graphics_bytes_per_pixel = 4;
+			disp->graphics_tiling_mode = bw_def_tiled;
+
+			/* DCE11 defaults*/
+			disp->graphics_lb_bpc = 10;
+			disp->graphics_interlace_mode = false;
+			disp->fbc_enable = false;
+			disp->lpt_enable = false;
+			disp->graphics_stereo_mode = bw_def_mono;
+			disp->underlay_mode = bw_def_none;
+
+			/*All displays will be synchronized if timings are all
+			 * the same
+			 */
+			if (number_of_displays != 0 && all_displays_in_sync)
+				if (dm_memcmp(&prev_timing,
+					&stream->public.timing,
+					sizeof(struct dc_crtc_timing))!= 0)
+					all_displays_in_sync = false;
+			if (number_of_displays == 0)
+				prev_timing = stream->public.timing;
+
+			number_of_displays++;
+		}
+	}
+
+	/* TODO: remove when bw formula accepts taps per
+	 * display
+	 */
+	context->bw_mode_data.displays_data[0].graphics_v_taps = max_vtaps;
+	context->bw_mode_data.displays_data[0].graphics_h_taps = max_htaps;
+
+	context->bw_mode_data.number_of_displays = number_of_displays;
+	context->bw_mode_data.display_synchronization_enabled =
+							all_displays_in_sync;
+
+	dal_logger_write(
+		dc->ctx->logger,
+		LOG_MAJOR_BWM,
+		LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS,
+		"%s: start\n",
+		__func__);
+
+	if (!bw_calcs(
+			dc->ctx,
+			&dc->bw_dceip,
+			&dc->bw_vbios,
+			&context->bw_mode_data,
+			&context->bw_results))
+		result =  DC_FAIL_BANDWIDTH_VALIDATE;
+	else
+		result =  DC_OK;
+
+	if (result == DC_FAIL_BANDWIDTH_VALIDATE)
+		dal_logger_write(dc->ctx->logger,
+			LOG_MAJOR_BWM,
+			LOG_MINOR_BWM_MODE_VALIDATION,
+			"%s: Bandwidth validation failed!",
+			__func__);
+
+	if (dm_memcmp(&dc->current_context.bw_results,
+			&context->bw_results, sizeof(context->bw_results))) {
+		struct log_entry log_entry;
+		dal_logger_open(
+			dc->ctx->logger,
+			&log_entry,
+			LOG_MAJOR_BWM,
+			LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS);
+		dal_logger_append(&log_entry, "%s: finish, numDisplays: %d\n"
+			"nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
+			"stutMark_b: %d stutMark_a: %d\n",
+			__func__, number_of_displays,
+			context->bw_results.nbp_state_change_wm_ns[0].b_mark,
+			context->bw_results.nbp_state_change_wm_ns[0].a_mark,
+			context->bw_results.urgent_wm_ns[0].b_mark,
+			context->bw_results.urgent_wm_ns[0].a_mark,
+			context->bw_results.stutter_exit_wm_ns[0].b_mark,
+			context->bw_results.stutter_exit_wm_ns[0].a_mark);
+		dal_logger_append(&log_entry,
+			"nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
+			"stutMark_b: %d stutMark_a: %d\n",
+			context->bw_results.nbp_state_change_wm_ns[1].b_mark,
+			context->bw_results.nbp_state_change_wm_ns[1].a_mark,
+			context->bw_results.urgent_wm_ns[1].b_mark,
+			context->bw_results.urgent_wm_ns[1].a_mark,
+			context->bw_results.stutter_exit_wm_ns[1].b_mark,
+			context->bw_results.stutter_exit_wm_ns[1].a_mark);
+		dal_logger_append(&log_entry,
+			"nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
+			"stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n",
+			context->bw_results.nbp_state_change_wm_ns[2].b_mark,
+			context->bw_results.nbp_state_change_wm_ns[2].a_mark,
+			context->bw_results.urgent_wm_ns[2].b_mark,
+			context->bw_results.urgent_wm_ns[2].a_mark,
+			context->bw_results.stutter_exit_wm_ns[2].b_mark,
+			context->bw_results.stutter_exit_wm_ns[2].a_mark,
+			context->bw_results.stutter_mode_enable);
+		dal_logger_append(&log_entry,
+			"cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n"
+			"sclk: %d sclk_sleep: %d yclk: %d blackout_duration: %d\n",
+			context->bw_results.cpuc_state_change_enable,
+			context->bw_results.cpup_state_change_enable,
+			context->bw_results.nbp_state_change_enable,
+			context->bw_results.all_displays_in_sync,
+			context->bw_results.dispclk_khz,
+			context->bw_results.required_sclk,
+			context->bw_results.required_sclk_deep_sleep,
+			context->bw_results.required_yclk,
+			context->bw_results.required_blackout_duration_us);
+		dal_logger_close(&log_entry);
+	}
+	return result;
+}
+
+static void set_target_unchanged(
+		struct validate_context *context,
+		uint8_t target_idx)
+{
+	uint8_t i;
+	struct core_target *target = context->targets[target_idx];
+	context->target_flags[target_idx].unchanged = true;
+	for (i = 0; i < target->public.stream_count; i++) {
+		struct core_stream *core_stream =
+			DC_STREAM_TO_CORE(target->public.streams[i]);
+		uint8_t index = core_stream->controller_idx;
+		context->res_ctx.controller_ctx[index].flags.unchanged = true;
+	}
+}
+
+static enum dc_status map_clock_resources(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	uint8_t i, j;
+
+	/* mark resources used for targets that are already active */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (!context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			reference_clock_source(
+				&context->res_ctx,
+				stream->clock_source);
+		}
+	}
+
+	/* acquire new resources */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			if (dc_is_dp_signal(stream->signal)
+				|| stream->signal == SIGNAL_TYPE_VIRTUAL)
+				stream->clock_source = context->res_ctx.
+					pool.clock_sources[DCE110_CLK_SRC_EXT];
+			else
+				stream->clock_source =
+					find_used_clk_src_for_sharing(
+							context, stream);
+			if (stream->clock_source == NULL)
+				stream->clock_source =
+					find_first_free_pll(&context->res_ctx);
+
+			if (stream->clock_source == NULL)
+				return DC_NO_CLOCK_SOURCE_RESOURCE;
+
+			reference_clock_source(
+					&context->res_ctx,
+					stream->clock_source);
+		}
+	}
+
+	return DC_OK;
+}
+
+enum dc_status dce110_validate_with_context(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count,
+		struct validate_context *context)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	uint8_t i, j;
+	struct dc_context *dc_ctx = dc->ctx;
+
+	for (i = 0; i < set_count; i++) {
+		context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
+
+		for (j = 0; j < dc->current_context.target_count; j++)
+			if (dc->current_context.targets[j] == context->targets[i])
+				set_target_unchanged(context, i);
+
+		if (!context->target_flags[i].unchanged)
+			if (!logical_attach_surfaces_to_target(
+							(struct dc_surface **)set[i].surfaces,
+							set[i].surface_count,
+							&context->targets[i]->public)) {
+				DC_ERROR("Failed to attach surface to target!\n");
+				return DC_FAIL_ATTACH_SURFACES;
+			}
+	}
+
+	context->target_count = set_count;
+
+	context->res_ctx.pool = dc->res_pool;
+
+	result = map_resources(dc, context);
+
+	if (result == DC_OK)
+		result = map_clock_resources(dc, context);
+
+	if (result == DC_OK)
+		result = validate_mapped_resource(dc, context);
+
+	if (result == DC_OK)
+		build_scaling_params_for_context(dc, context);
+
+	if (result == DC_OK)
+		result = dce110_validate_bandwidth(dc, context);
+
+	return result;
+}
+
+static struct resource_funcs dce110_res_pool_funcs = {
+	.destruct = dce110_destruct_resource_pool,
+	.link_enc_create = dce110_link_encoder_create,
+	.link_enc_destroy = dce110_link_encoder_destroy,
+	.validate_with_context = dce110_validate_with_context,
+	.validate_bandwidth = dce110_validate_bandwidth
+};
+
+bool dce110_construct_resource_pool(
+	struct adapter_service *adapter_serv,
+	uint8_t num_virtual_links,
+	struct dc *dc,
+	struct resource_pool *pool)
+{
+	unsigned int i;
+	struct audio_init_data audio_init_data = { 0 };
+	struct dc_context *ctx = dc->ctx;
+	pool->adapter_srv = adapter_serv;
+	pool->funcs = &dce110_res_pool_funcs;
+
+	pool->stream_engines.engine.ENGINE_ID_DIGA = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGB = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGC = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGD = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGE = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGF = 1;
+
+	pool->clock_sources[DCE110_CLK_SRC_PLL0] = dce110_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_PLL0, &dce110_clk_src_reg_offsets[0]);
+	pool->clock_sources[DCE110_CLK_SRC_PLL1] = dce110_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_PLL1, &dce110_clk_src_reg_offsets[1]);
+	pool->clock_sources[DCE110_CLK_SRC_EXT] =  dce110_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_EXTERNAL, &dce110_clk_src_reg_offsets[0]);
+	pool->clk_src_count = DCE110_CLK_SRC_TOTAL;
+
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] == NULL) {
+			dm_error("DC: failed to create clock sources!\n");
+			BREAK_TO_DEBUGGER();
+			goto clk_src_create_fail;
+		}
+	}
+
+	pool->display_clock = dal_display_clock_dce110_create(ctx, adapter_serv);
+	if (pool->display_clock == NULL) {
+		dm_error("DC: failed to create display clock!\n");
+		BREAK_TO_DEBUGGER();
+		goto disp_clk_create_fail;
+	}
+
+	{
+		struct irq_service_init_data init_data;
+		init_data.ctx = dc->ctx;
+		pool->irqs = dal_irq_service_create(
+				dal_adapter_service_get_dce_version(
+					dc->res_pool.adapter_srv),
+				&init_data);
+		if (!pool->irqs)
+			goto irqs_create_fail;
+
+	}
+
+	pool->controller_count =
+		dal_adapter_service_get_func_controllers_num(adapter_serv);
+	pool->stream_enc_count = dal_adapter_service_get_stream_engines_num(
+			adapter_serv);
+	pool->scaler_filter = dal_scaler_filter_create(ctx);
+	if (pool->scaler_filter == NULL) {
+		BREAK_TO_DEBUGGER();
+		dm_error("DC: failed to create filter!\n");
+		goto filter_create_fail;
+	}
+
+	for (i = 0; i < pool->controller_count; i++) {
+		pool->timing_generators[i] = dce110_timing_generator_create(
+				adapter_serv, ctx, i, &dce110_tg_offsets[i]);
+		if (pool->timing_generators[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create tg!\n");
+			goto controller_create_fail;
+		}
+
+		pool->mis[i] = dce110_mem_input_create(ctx, i,
+				&dce110_mi_reg_offsets[i]);
+		if (pool->mis[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create memory input!\n");
+			goto controller_create_fail;
+		}
+
+		pool->ipps[i] = dce110_ipp_create(ctx, i, &dce110_ipp_reg_offsets[i]);
+		if (pool->ipps[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create input pixel processor!\n");
+			goto controller_create_fail;
+		}
+
+		pool->transforms[i] = dce110_transform_create(
+					ctx, i, &dce110_xfm_offsets[i]);
+		if (pool->transforms[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create transform!\n");
+			goto controller_create_fail;
+		}
+		pool->transforms[i]->funcs->transform_set_scaler_filter(
+				pool->transforms[i],
+				pool->scaler_filter);
+
+		pool->opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]);
+		if (pool->opps[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create output pixel processor!\n");
+			goto controller_create_fail;
+		}
+	}
+
+	audio_init_data.as = adapter_serv;
+	audio_init_data.ctx = ctx;
+	pool->audio_count = 0;
+	for (i = 0; i < pool->controller_count; i++) {
+		struct graphics_object_id obj_id;
+
+		obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i);
+		if (false == dal_graphics_object_id_is_valid(obj_id)) {
+			/* no more valid audio objects */
+			break;
+		}
+
+		audio_init_data.audio_stream_id = obj_id;
+		pool->audios[i] = dal_audio_create(&audio_init_data);
+		if (pool->audios[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create DPPs!\n");
+			goto audio_create_fail;
+		}
+		pool->audio_count++;
+	}
+
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		/* TODO: rework fragile code*/
+		if (pool->stream_engines.u_all & 1 << i) {
+			pool->stream_enc[i] = dce110_stream_encoder_create(
+				i, dc->ctx,
+				dal_adapter_service_get_bios_parser(
+					adapter_serv),
+				&stream_enc_regs[i]);
+			if (pool->stream_enc[i] == NULL) {
+				BREAK_TO_DEBUGGER();
+				dm_error("DC: failed to create stream_encoder!\n");
+				goto stream_enc_create_fail;
+			}
+		}
+	}
+
+	for (i = 0; i < num_virtual_links; i++) {
+		pool->stream_enc[pool->stream_enc_count] =
+			virtual_stream_encoder_create(
+				dc->ctx, dal_adapter_service_get_bios_parser(
+								adapter_serv));
+		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create stream_encoder!\n");
+			goto stream_enc_create_fail;
+		}
+		pool->stream_enc_count++;
+	}
+
+	return true;
+
+stream_enc_create_fail:
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		if (pool->stream_enc[i] != NULL)
+			dm_free(pool->stream_enc[i]->ctx,
+				DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+	}
+
+audio_create_fail:
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->audios[i] != NULL)
+			dal_audio_destroy(&pool->audios[i]);
+	}
+
+controller_create_fail:
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->opps[i] != NULL)
+			dce110_opp_destroy(&pool->opps[i]);
+
+		if (pool->transforms[i] != NULL)
+			dce110_transform_destroy(&pool->transforms[i]);
+
+		if (pool->ipps[i] != NULL)
+			dce110_ipp_destroy(&pool->ipps[i]);
+
+		if (pool->mis[i] != NULL) {
+			dm_free(pool->mis[i]->ctx,
+					TO_DCE110_MEM_INPUT(pool->mis[i]));
+			pool->mis[i] = NULL;
+		}
+
+		if (pool->timing_generators[i] != NULL)	{
+			dm_free(pool->timing_generators[i]->ctx,
+				DCE110TG_FROM_TG(pool->timing_generators[i]));
+			pool->timing_generators[i] = NULL;
+		}
+	}
+
+filter_create_fail:
+	dal_irq_service_destroy(&pool->irqs);
+
+irqs_create_fail:
+	dal_display_clock_destroy(&pool->display_clock);
+
+disp_clk_create_fail:
+clk_src_create_fail:
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] != NULL)
+			dce110_clock_source_destroy(&pool->clock_sources[i]);
+	}
+
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
new file mode 100644
index 000000000000..5d60df286835
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
@@ -0,0 +1,46 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_RESOURCE_DCE110_H__
+#define __DC_RESOURCE_DCE110_H__
+
+#include "core_types.h"
+
+struct adapter_service;
+struct dc;
+struct resource_pool;
+
+bool dce110_construct_resource_pool(
+	struct adapter_service *adapter_serv,
+	uint8_t num_virtual_links,
+	struct dc *dc,
+	struct resource_pool *pool);
+
+void dce110_destruct_resource_pool(struct resource_pool *pool);
+
+void dce110_link_encoder_destroy(struct link_encoder **enc);
+
+#endif /* __DC_RESOURCE_DCE110_H__ */
+
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 22/29] drm/amd/dal: Add Tonga/Fiji HW sequencer and resource
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (20 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 21/29] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 17:20 ` [PATCH 23/29] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel

Enables HW programming on Tonga and Fiji (DCE 10) ASICs. This
mostly re-uses DCE 11 programming code with minor exceptions
and using DCE 10 register offsets.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce100/Makefile         |   23 +
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.c    |  388 +++++++
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.h    |   36 +
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c    | 1134 ++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.h    |   43 +
 5 files changed, 1624 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/Makefile b/drivers/gpu/drm/amd/dal/dc/dce100/Makefile
new file mode 100644
index 000000000000..656c38e1b0f5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile for the 'controller' sub-component of DAL.
+# It provides the control and status of HW CRTC block.
+
+DCE100 = dce100_resource.o dce100_hw_sequencer.o
+
+AMD_DAL_DCE100 = $(addprefix $(AMDDALPATH)/dc/dce100/,$(DCE100))
+
+AMD_DAL_FILES += $(AMD_DAL_DCE100)
+
+
+###############################################################################
+# DCE 10x
+###############################################################################
+ifdef 0#CONFIG_DRM_AMD_DAL_DCE11_0
+TG_DCE100 = dce100_resource.o
+
+AMD_DAL_TG_DCE100 = $(addprefix \
+	$(AMDDALPATH)/dc/dce100/,$(TG_DCE100))
+
+AMD_DAL_FILES += $(AMD_DAL_TG_DCE100)
+endif
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
new file mode 100644
index 000000000000..82c5e155d91a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "dc.h"
+#include "core_dc.h"
+#include "core_types.h"
+#include "hw_sequencer.h"
+#include "dce100_hw_sequencer.h"
+#include "dce110/dce110_hw_sequencer.h"
+
+/* include DCE10 register header files */
+#include "dce/dce_10_0_d.h"
+#include "dce/dce_10_0_sh_mask.h"
+
+struct dce100_hw_seq_reg_offsets {
+	uint32_t blnd;
+	uint32_t crtc;
+};
+
+enum pipe_lock_control {
+	PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0,
+	PIPE_LOCK_CONTROL_BLENDER = 1 << 1,
+	PIPE_LOCK_CONTROL_SCL = 1 << 2,
+	PIPE_LOCK_CONTROL_SURFACE = 1 << 3,
+	PIPE_LOCK_CONTROL_MODE = 1 << 4
+};
+
+enum blender_mode {
+	BLENDER_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */
+	BLENDER_MODE_OTHER_PIPE, /* Data from other pipe only */
+	BLENDER_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */
+	BLENDER_MODE_STEREO
+};
+
+static const struct dce100_hw_seq_reg_offsets reg_offsets[] = {
+{
+	.blnd = (mmBLND0_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+	.blnd = (mmBLND1_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+	.blnd = (mmBLND2_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+}
+};
+
+#define HW_REG_BLND(reg, id)\
+	(reg + reg_offsets[id].blnd)
+
+#define HW_REG_CRTC(reg, id)\
+	(reg + reg_offsets[id].crtc)
+
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+/***************************PIPE_CONTROL***********************************/
+static void dce100_enable_fe_clock(
+	struct dc_context *ctx, uint8_t controller_id, bool enable)
+{
+	uint32_t value = 0;
+	uint32_t addr;
+
+	addr = HW_REG_CRTC(mmDCFE_CLOCK_CONTROL, controller_id);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		enable,
+		DCFE_CLOCK_CONTROL,
+		DCFE_CLOCK_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static bool dce100_pipe_control_lock(
+	struct dc_context *ctx,
+	uint8_t controller_idx,
+	uint32_t control_mask,
+	bool lock)
+{
+	uint32_t addr = HW_REG_BLND(mmBLND_V_UPDATE_LOCK, controller_idx);
+	uint32_t value = dm_read_reg(ctx, addr);
+	bool need_to_wait = false;
+
+	if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_DCP_GRPH_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_SCL)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_SCL_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_SURFACE)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_DCP_GRPH_SURF_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_BLND_V_UPDATE_LOCK);
+		need_to_wait = true;
+	}
+
+	if (control_mask & PIPE_LOCK_CONTROL_MODE)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_V_UPDATE_LOCK_MODE);
+
+	dm_write_reg(ctx, addr, value);
+
+	if (!lock && need_to_wait) {
+		uint8_t counter = 0;
+		const uint8_t counter_limit = 100;
+		const uint16_t delay_us = 1000;
+
+		uint8_t pipe_pending;
+
+		addr = HW_REG_BLND(mmBLND_REG_UPDATE_STATUS,
+				controller_idx);
+
+		while (counter < counter_limit) {
+			value = dm_read_reg(ctx, addr);
+
+			pipe_pending = 0;
+
+			if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						BLND_BLNDC_UPDATE_PENDING);
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					BLND_BLNDO_UPDATE_PENDING);
+			}
+
+			if (control_mask & PIPE_LOCK_CONTROL_SCL) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						SCL_BLNDC_UPDATE_PENDING);
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						SCL_BLNDO_UPDATE_PENDING);
+			}
+			if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						DCP_BLNDC_GRPH_UPDATE_PENDING);
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						DCP_BLNDO_GRPH_UPDATE_PENDING);
+			}
+			if (control_mask & PIPE_LOCK_CONTROL_SURFACE) {
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					DCP_BLNDC_GRPH_SURF_UPDATE_PENDING);
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					DCP_BLNDO_GRPH_SURF_UPDATE_PENDING);
+			}
+
+			if (pipe_pending == 0)
+				break;
+
+			counter++;
+			dm_delay_in_microseconds(ctx, delay_us);
+		}
+
+		if (counter == counter_limit) {
+			dal_logger_write(
+				ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: wait for update exceeded (wait %d us)\n",
+				__func__,
+				counter * delay_us);
+			dal_logger_write(
+				ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: control %d, remain value %x\n",
+				__func__,
+				control_mask,
+				value);
+		} else {
+			/* OK. */
+		}
+	}
+
+	return true;
+}
+
+static void dce100_set_blender_mode(
+	struct dc_context *ctx,
+	uint8_t controller_id,
+	uint32_t mode)
+{
+	uint32_t value;
+	uint32_t addr = HW_REG_BLND(mmBLND_CONTROL, controller_id);
+	uint32_t blnd_mode;
+	uint32_t feedthrough = 0;
+
+	switch (mode) {
+	case BLENDER_MODE_OTHER_PIPE:
+		feedthrough = 0;
+		blnd_mode = 1;
+		break;
+	case BLENDER_MODE_BLENDING:
+		feedthrough = 0;
+		blnd_mode = 2;
+		break;
+	case BLENDER_MODE_CURRENT_PIPE:
+	default:
+		feedthrough = 1;
+		blnd_mode = 0;
+		break;
+	}
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		feedthrough,
+		BLND_CONTROL,
+		BLND_FEEDTHROUGH_EN);
+
+	set_reg_field_value(
+		value,
+		blnd_mode,
+		BLND_CONTROL,
+		BLND_MODE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static bool dce100_enable_display_power_gating(
+	struct dc_context *ctx,
+	uint8_t controller_id,
+	struct dc_bios *dcb,
+	enum pipe_gating_control power_gating)
+{
+	enum bp_result bp_result = BP_RESULT_OK;
+	enum bp_pipe_control_action cntl;
+
+	if (power_gating == PIPE_GATING_CONTROL_INIT)
+		cntl = ASIC_PIPE_INIT;
+	else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
+		cntl = ASIC_PIPE_ENABLE;
+	else
+		cntl = ASIC_PIPE_DISABLE;
+
+	if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0))
+		bp_result = dcb->funcs->enable_disp_power_gating(
+						dcb, controller_id + 1, cntl);
+
+	if (bp_result == BP_RESULT_OK)
+		return true;
+	else
+		return false;
+}
+
+static void enable_hw_base_light_sleep(void)
+{
+	/* TODO: implement */
+}
+
+static void disable_sw_manual_control_light_sleep(void)
+{
+	/* TODO: implement */
+}
+
+static void enable_sw_manual_control_light_sleep(void)
+{
+	/* TODO: implement */
+}
+
+static void dal_dc_clock_gating_dce100_power_up(struct dc_context *ctx, bool enable)
+{
+	if (enable) {
+		enable_hw_base_light_sleep();
+		disable_sw_manual_control_light_sleep();
+	} else {
+		enable_sw_manual_control_light_sleep();
+	}
+}
+
+/**
+ * Call display_engine_clock_dce80 to perform the Dclk programming.
+ */
+static void set_display_clock(struct validate_context *context)
+{
+	/* Program the display engine clock.
+	 * Check DFS bypass mode support or not. DFSbypass feature is only when
+	 * BIOS GPU info table reports support. */
+
+	if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) {
+		/*TODO: set_display_clock_dfs_bypass(
+				hws,
+				path_set,
+				context->res_ctx.pool.display_clock,
+				context->res_ctx.min_clocks.min_dclk_khz);*/
+	} else
+		dal_display_clock_set_clock(context->res_ctx.pool.display_clock,
+				681000);
+
+	/* TODO: When changing display engine clock, DMCU WaitLoop must be
+	 * reconfigured in order to maintain the same delays within DMCU
+	 * programming sequences. */
+
+	/* TODO: Start GTC counter */
+}
+
+
+static void set_displaymarks(
+		const struct dc *dc, struct validate_context *context)
+{
+	/* Do nothing until we have proper bandwitdth calcs */
+}
+
+/**************************************************************************/
+
+bool dce100_hw_sequencer_construct(struct dc *dc)
+{
+	dce110_hw_sequencer_construct(dc);
+
+	/* TODO: dce80 is empty implementation at the moment*/
+	dc->hwss.clock_gating_power_up = dal_dc_clock_gating_dce100_power_up;
+
+	dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating;
+	dc->hwss.enable_fe_clock = dce100_enable_fe_clock;
+	dc->hwss.pipe_control_lock = dce100_pipe_control_lock;
+	dc->hwss.set_blender_mode = dce100_set_blender_mode;
+	dc->hwss.set_display_clock = set_display_clock;
+	dc->hwss.set_displaymarks = set_displaymarks;
+	return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
new file mode 100644
index 000000000000..0ce637e6bd85
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
@@ -0,0 +1,36 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HWSS_DCE100_H__
+#define __DC_HWSS_DCE100_H__
+
+#include "core_types.h"
+
+struct dc;
+
+bool dce100_hw_sequencer_construct(struct dc *dc);
+
+#endif /* __DC_HWSS_DCE100_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
new file mode 100644
index 000000000000..e67ba81f1c85
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
@@ -0,0 +1,1134 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "link_encoder.h"
+#include "stream_encoder.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+
+#include "../virtual/virtual_stream_encoder.h"
+#include "dce110/dce110_resource.h"
+#include "dce110/dce110_timing_generator.h"
+#include "dce110/dce110_link_encoder.h"
+#include "dce110/dce110_mem_input.h"
+#include "dce110/dce110_ipp.h"
+#include "dce110/dce110_transform.h"
+#include "dce110/dce110_stream_encoder.h"
+#include "dce110/dce110_opp.h"
+#include "dce110/dce110_clock_source.h"
+
+#include "dce/dce_10_0_d.h"
+
+#ifndef mmDP_DPHY_INTERNAL_CTRL
+	#define mmDP_DPHY_INTERNAL_CTRL 0x4aa7
+	#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7
+	#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7
+	#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7
+	#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7
+	#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7
+	#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7
+	#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7
+	#define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7
+	#define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7
+#endif
+
+enum dce100_clk_src_array_id {
+	DCE100_CLK_SRC_PLL0 = 0,
+	DCE100_CLK_SRC_PLL1,
+	DCE100_CLK_SRC_EXT,
+
+	DCE100_CLK_SRC_TOTAL
+};
+
+static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = {
+	{
+		.crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp =  (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp =  (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
+	}
+};
+
+static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = {
+	{
+		.dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE0_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE1_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE2_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE3_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE4_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE5_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	}
+};
+
+
+static const struct dce110_clk_src_reg_offsets dce100_clk_src_reg_offsets[] = {
+	{
+		.pll_cntl = mmBPHYC_PLL0_PLL_CNTL,
+		.pixclk_resync_cntl  = mmPIXCLK0_RESYNC_CNTL
+	},
+	{
+		.pll_cntl = mmBPHYC_PLL1_PLL_CNTL,
+		.pixclk_resync_cntl  = mmPIXCLK1_RESYNC_CNTL
+	}
+};
+
+static const struct dce110_transform_reg_offsets dce100_xfm_offsets[] = {
+{
+	.scl_offset = (mmSCL0_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB0_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL1_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB1_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL2_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB2_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{
+	.scl_offset = (mmSCL3_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB3_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL4_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB4_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL5_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB5_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+}
+};
+
+static const struct dce110_ipp_reg_offsets dce100_ipp_reg_offsets[] = {
+{
+	.dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL),
+}
+};
+
+
+static const struct dce110_link_enc_bl_registers link_enc_bl_regs = {
+		.BL_PWM_CNTL = mmBL_PWM_CNTL,
+		.BL_PWM_GRP1_REG_LOCK = mmBL_PWM_GRP1_REG_LOCK,
+		.BL_PWM_PERIOD_CNTL = mmBL_PWM_PERIOD_CNTL,
+		.LVTMA_PWRSEQ_CNTL = mmLVTMA_PWRSEQ_CNTL,
+		.LVTMA_PWRSEQ_STATE = mmLVTMA_PWRSEQ_STATE
+};
+
+#define aux_regs(id)\
+[id] = {\
+	.AUX_CONTROL = mmDP_AUX ## id ## _AUX_CONTROL,\
+	.AUX_DPHY_RX_CONTROL0 = mmDP_AUX ## id ## _AUX_DPHY_RX_CONTROL0\
+}
+
+static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = {
+	aux_regs(0),
+	aux_regs(1),
+	aux_regs(2),
+	aux_regs(3),
+	aux_regs(4),
+	aux_regs(5)
+};
+
+#define link_regs(id)\
+[id] = {\
+	.DIG_BE_CNTL = mmDIG ## id ## _DIG_BE_CNTL,\
+	.DIG_BE_EN_CNTL = mmDIG ## id ## _DIG_BE_EN_CNTL,\
+	.DP_CONFIG = mmDP ## id ## _DP_CONFIG,\
+	.DP_DPHY_CNTL = mmDP ## id ## _DP_DPHY_CNTL,\
+	.DP_DPHY_INTERNAL_CTRL = mmDP ## id ## _DP_DPHY_INTERNAL_CTRL,\
+	.DP_DPHY_PRBS_CNTL = mmDP ## id ## _DP_DPHY_PRBS_CNTL,\
+	.DP_DPHY_SYM0 = mmDP ## id ## _DP_DPHY_SYM0,\
+	.DP_DPHY_SYM1 = mmDP ## id ## _DP_DPHY_SYM1,\
+	.DP_DPHY_SYM2 = mmDP ## id ## _DP_DPHY_SYM2,\
+	.DP_DPHY_TRAINING_PATTERN_SEL = mmDP ## id ## _DP_DPHY_TRAINING_PATTERN_SEL,\
+	.DP_LINK_CNTL = mmDP ## id ## _DP_LINK_CNTL,\
+	.DP_LINK_FRAMING_CNTL = mmDP ## id ## _DP_LINK_FRAMING_CNTL,\
+	.DP_MSE_SAT0 = mmDP ## id ## _DP_MSE_SAT0,\
+	.DP_MSE_SAT1 = mmDP ## id ## _DP_MSE_SAT1,\
+	.DP_MSE_SAT2 = mmDP ## id ## _DP_MSE_SAT2,\
+	.DP_MSE_SAT_UPDATE = mmDP ## id ## _DP_MSE_SAT_UPDATE,\
+	.DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\
+	.DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL\
+}
+
+static const struct dce110_link_enc_registers link_enc_regs[] = {
+	link_regs(0),
+	link_regs(1),
+	link_regs(2),
+	link_regs(3),
+	link_regs(4),
+	link_regs(5),
+	link_regs(6)
+};
+
+#define stream_enc_regs(id)\
+[id] = {\
+	.AFMT_AVI_INFO0 = mmDIG ## id ## _AFMT_AVI_INFO0,\
+	.AFMT_AVI_INFO1 = mmDIG ## id ## _AFMT_AVI_INFO1,\
+	.AFMT_AVI_INFO2 = mmDIG ## id ## _AFMT_AVI_INFO2,\
+	.AFMT_AVI_INFO3 = mmDIG ## id ## _AFMT_AVI_INFO3,\
+	.AFMT_GENERIC_0 = mmDIG ## id ## _AFMT_GENERIC_0,\
+	.AFMT_GENERIC_7 = mmDIG ## id ## _AFMT_GENERIC_7,\
+	.AFMT_GENERIC_HDR = mmDIG ## id ## _AFMT_GENERIC_HDR,\
+	.AFMT_INFOFRAME_CONTROL0 = mmDIG ## id ## _AFMT_INFOFRAME_CONTROL0,\
+	.AFMT_VBI_PACKET_CONTROL = mmDIG ## id ## _AFMT_VBI_PACKET_CONTROL,\
+	.DIG_FE_CNTL = mmDIG ## id ## _DIG_FE_CNTL,\
+	.DP_MSE_RATE_CNTL = mmDP ## id ## _DP_MSE_RATE_CNTL,\
+	.DP_MSE_RATE_UPDATE = mmDP ## id ## _DP_MSE_RATE_UPDATE,\
+	.DP_PIXEL_FORMAT = mmDP ## id ## _DP_PIXEL_FORMAT,\
+	.DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\
+	.DP_STEER_FIFO = mmDP ## id ## _DP_STEER_FIFO,\
+	.DP_VID_M = mmDP ## id ## _DP_VID_M,\
+	.DP_VID_N = mmDP ## id ## _DP_VID_N,\
+	.DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL,\
+	.DP_VID_TIMING = mmDP ## id ## _DP_VID_TIMING,\
+	.HDMI_CONTROL = mmDIG ## id ## _HDMI_CONTROL,\
+	.HDMI_GC = mmDIG ## id ## _HDMI_GC,\
+	.HDMI_GENERIC_PACKET_CONTROL0 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL0,\
+	.HDMI_GENERIC_PACKET_CONTROL1 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL1,\
+	.HDMI_INFOFRAME_CONTROL0 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL0,\
+	.HDMI_INFOFRAME_CONTROL1 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL1,\
+	.HDMI_VBI_PACKET_CONTROL = mmDIG ## id ## _HDMI_VBI_PACKET_CONTROL,\
+	.TMDS_CNTL = mmDIG ## id ## _TMDS_CNTL\
+}
+
+static const struct dce110_stream_enc_registers stream_enc_regs[] = {
+	stream_enc_regs(0),
+	stream_enc_regs(1),
+	stream_enc_regs(2),
+	stream_enc_regs(3),
+	stream_enc_regs(4),
+	stream_enc_regs(5),
+	stream_enc_regs(6)
+};
+
+#define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03
+
+static const struct dce110_opp_reg_offsets dce100_opp_reg_offsets[] = {
+{
+	.fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT_CONTROL),
+	.dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{
+	.fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+}
+};
+
+
+static struct timing_generator *dce100_timing_generator_create(
+		struct adapter_service *as,
+		struct dc_context *ctx,
+		uint32_t instance,
+		const struct dce110_timing_generator_offsets *offsets)
+{
+	struct dce110_timing_generator *tg110 =
+		dm_alloc(ctx, sizeof(struct dce110_timing_generator));
+
+	if (!tg110)
+		return NULL;
+
+	if (dce110_timing_generator_construct(tg110, as, ctx, instance,
+			offsets))
+		return &tg110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, tg110);
+	return NULL;
+}
+
+static struct stream_encoder *dce100_stream_encoder_create(
+	enum engine_id eng_id,
+	struct dc_context *ctx,
+	struct dc_bios *bp,
+	const struct dce110_stream_enc_registers *regs)
+{
+	struct dce110_stream_encoder *enc110 =
+		dm_alloc(ctx, sizeof(struct dce110_stream_encoder));
+
+	if (!enc110)
+		return NULL;
+
+	if (dce110_stream_encoder_construct(enc110, ctx, bp, eng_id, regs))
+		return &enc110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, enc110);
+	return NULL;
+}
+
+static struct mem_input *dce100_mem_input_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_mem_input_reg_offsets *offset)
+{
+	struct dce110_mem_input *mem_input110 =
+		dm_alloc(ctx, sizeof(struct dce110_mem_input));
+
+	if (!mem_input110)
+		return NULL;
+
+	if (dce110_mem_input_construct(mem_input110,
+			ctx, inst, offset))
+		return &mem_input110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, mem_input110);
+	return NULL;
+}
+
+static void dce100_transform_destroy(struct transform **xfm)
+{
+	dm_free((*xfm)->ctx, TO_DCE110_TRANSFORM(*xfm));
+	*xfm = NULL;
+}
+
+static struct transform *dce100_transform_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *offsets)
+{
+	struct dce110_transform *transform =
+		dm_alloc(ctx, sizeof(struct dce110_transform));
+
+	if (!transform)
+		return NULL;
+
+	if (dce110_transform_construct(transform, ctx, inst, offsets))
+		return &transform->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, transform);
+	return NULL;
+}
+
+static struct input_pixel_processor *dce100_ipp_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_ipp_reg_offsets *offsets)
+{
+	struct dce110_ipp *ipp =
+		dm_alloc(ctx, sizeof(struct dce110_ipp));
+
+	if (!ipp)
+		return NULL;
+
+	if (dce110_ipp_construct(ipp, ctx, inst, offsets))
+		return &ipp->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, ipp);
+	return NULL;
+}
+
+struct link_encoder *dce100_link_encoder_create(
+	const struct encoder_init_data *enc_init_data)
+{
+	struct dce110_link_encoder *enc110 =
+		dm_alloc(
+			enc_init_data->ctx,
+			sizeof(struct dce110_link_encoder));
+
+	if (!enc110)
+		return NULL;
+
+	if (dce110_link_encoder_construct(
+			enc110,
+			enc_init_data,
+			&link_enc_regs[enc_init_data->transmitter],
+			&link_enc_aux_regs[enc_init_data->channel - 1],
+			&link_enc_bl_regs))
+		return &enc110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(enc_init_data->ctx, enc110);
+	return NULL;
+}
+
+
+struct output_pixel_processor *dce100_opp_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offset)
+{
+	struct dce110_opp *opp =
+		dm_alloc(ctx, sizeof(struct dce110_opp));
+
+	if (!opp)
+		return NULL;
+
+	if (dce110_opp_construct(opp,
+			ctx, inst, offset))
+		return &opp->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, opp);
+	return NULL;
+}
+
+
+void dce100_opp_destroy(struct output_pixel_processor **opp)
+{
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_dx);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_oem);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_1025);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_256);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coordinates_x);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_regamma);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_resulted);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_oem);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_user);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp));
+	*opp = NULL;
+}
+
+struct clock_source *dce100_clock_source_create(
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_reg_offsets *offsets)
+{
+	struct dce110_clk_src *clk_src =
+		dm_alloc(ctx, sizeof(struct dce110_clk_src));
+
+	if (!clk_src)
+		return NULL;
+
+	if (dce110_clk_src_construct(clk_src, ctx, bios, id, offsets))
+		return &clk_src->base;
+
+	BREAK_TO_DEBUGGER();
+	return NULL;
+}
+
+void dce100_clock_source_destroy(struct clock_source **clk_src)
+{
+	dm_free((*clk_src)->ctx, TO_DCE110_CLK_SRC(*clk_src));
+	*clk_src = NULL;
+}
+
+void dce100_destruct_resource_pool(struct resource_pool *pool)
+{
+	unsigned int i;
+
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->opps[i] != NULL)
+			dce100_opp_destroy(&pool->opps[i]);
+
+		if (pool->transforms[i] != NULL)
+			dce100_transform_destroy(&pool->transforms[i]);
+
+		if (pool->ipps[i] != NULL)
+			dce110_ipp_destroy(&pool->ipps[i]);
+
+		if (pool->mis[i] != NULL) {
+			dm_free(pool->mis[i]->ctx,
+					TO_DCE110_MEM_INPUT(pool->mis[i]));
+			pool->mis[i] = NULL;
+		}
+
+		if (pool->timing_generators[i] != NULL)	{
+			dm_free(pool->timing_generators[i]->ctx,
+					DCE110TG_FROM_TG(pool->timing_generators[i]));
+			pool->timing_generators[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		if (pool->stream_enc[i] != NULL)
+			dm_free(pool->stream_enc[i]->ctx,
+				DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+	}
+
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] != NULL)
+			dce100_clock_source_destroy(&pool->clock_sources[i]);
+	}
+
+	for (i = 0; i < pool->audio_count; i++)	{
+		if (pool->audios[i] != NULL)
+			dal_audio_destroy(&pool->audios[i]);
+	}
+
+	if (pool->display_clock != NULL)
+		dal_display_clock_destroy(&pool->display_clock);
+
+	if (pool->scaler_filter != NULL)
+		dal_scaler_filter_destroy(&pool->scaler_filter);
+
+	if (pool->irqs != NULL)
+		dal_irq_service_destroy(&pool->irqs);
+
+	if (pool->adapter_srv != NULL)
+		dal_adapter_service_destroy(&pool->adapter_srv);
+}
+
+static struct clock_source *find_first_free_pll(
+		struct resource_context *res_ctx)
+{
+	if (res_ctx->clock_source_ref_count[DCE100_CLK_SRC_PLL0] == 0)
+		return res_ctx->pool.clock_sources[DCE100_CLK_SRC_PLL0];
+
+	if (res_ctx->clock_source_ref_count[DCE100_CLK_SRC_PLL1] == 0)
+		return res_ctx->pool.clock_sources[DCE100_CLK_SRC_PLL1];
+
+	return 0;
+}
+
+static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
+{
+	switch (crtc_id) {
+	case CONTROLLER_ID_D0:
+		return DTO_SOURCE_ID0;
+	case CONTROLLER_ID_D1:
+		return DTO_SOURCE_ID1;
+	case CONTROLLER_ID_D2:
+		return DTO_SOURCE_ID2;
+	case CONTROLLER_ID_D3:
+		return DTO_SOURCE_ID3;
+	case CONTROLLER_ID_D4:
+		return DTO_SOURCE_ID4;
+	case CONTROLLER_ID_D5:
+		return DTO_SOURCE_ID5;
+	default:
+		return DTO_SOURCE_UNKNOWN;
+	}
+}
+
+static void build_audio_output(
+	const struct core_stream *stream,
+	struct audio_output *audio_output)
+{
+	audio_output->engine_id = stream->stream_enc->id;
+
+	audio_output->signal = stream->signal;
+
+	/* audio_crtc_info  */
+
+	audio_output->crtc_info.h_total =
+		stream->public.timing.h_total;
+
+	/*
+	 * Audio packets are sent during actual CRTC blank physical signal, we
+	 * need to specify actual active signal portion
+	 */
+	audio_output->crtc_info.h_active =
+			stream->public.timing.h_addressable
+			+ stream->public.timing.h_border_left
+			+ stream->public.timing.h_border_right;
+
+	audio_output->crtc_info.v_active =
+			stream->public.timing.v_addressable
+			+ stream->public.timing.v_border_top
+			+ stream->public.timing.v_border_bottom;
+
+	audio_output->crtc_info.pixel_repetition = 1;
+
+	audio_output->crtc_info.interlaced =
+			stream->public.timing.flags.INTERLACE;
+
+	audio_output->crtc_info.refresh_rate =
+		(stream->public.timing.pix_clk_khz*1000)/
+		(stream->public.timing.h_total*stream->public.timing.v_total);
+
+	audio_output->crtc_info.color_depth =
+		stream->public.timing.display_color_depth;
+
+	audio_output->crtc_info.requested_pixel_clock =
+			stream->pix_clk_params.requested_pix_clk;
+
+	/*
+	 * TODO - Investigate why calculated pixel clk has to be
+	 * requested pixel clk
+	 */
+	audio_output->crtc_info.calculated_pixel_clock =
+			stream->pix_clk_params.requested_pix_clk;
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
+			stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+		audio_output->pll_info.dp_dto_source_clock_in_khz =
+			dal_display_clock_get_dp_ref_clk_frequency(
+				stream->dis_clk);
+	}
+
+	audio_output->pll_info.feed_back_divider =
+			stream->pll_settings.feedback_divider;
+
+	audio_output->pll_info.dto_source =
+		translate_to_dto_source(
+			stream->controller_idx + 1);
+
+	/* TODO hard code to enable for now. Need get from stream */
+	audio_output->pll_info.ss_enabled = true;
+
+	audio_output->pll_info.ss_percentage =
+			stream->pll_settings.ss_percentage;
+}
+
+static void get_pixel_clock_parameters(
+	const struct core_stream *stream,
+	struct pixel_clk_params *pixel_clk_params)
+{
+	pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz;
+	pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
+	pixel_clk_params->signal_type = stream->sink->public.sink_signal;
+	pixel_clk_params->controller_id = stream->controller_idx + 1;
+	/* TODO: un-hardcode*/
+	pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
+		LINK_RATE_REF_FREQ_IN_KHZ;
+	pixel_clk_params->flags.ENABLE_SS = 0;
+	pixel_clk_params->color_depth =
+		stream->public.timing.display_color_depth;
+	pixel_clk_params->flags.DISPLAY_BLANKED = 1;
+}
+
+static enum dc_status build_stream_hw_param(struct core_stream *stream)
+{
+	/*TODO: unhardcode*/
+	stream->max_tmds_clk_from_edid_in_mhz = 0;
+	stream->max_hdmi_deep_color = COLOR_DEPTH_121212;
+	stream->max_hdmi_pixel_clock = 600000;
+
+	get_pixel_clock_parameters(stream, &stream->pix_clk_params);
+	stream->clock_source->funcs->get_pix_clk_dividers(
+		stream->clock_source,
+		&stream->pix_clk_params,
+		&stream->pll_settings);
+
+	build_audio_output(stream, &stream->audio_output);
+
+	return DC_OK;
+}
+
+static enum dc_status validate_mapped_resource(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	enum dc_status status = DC_OK;
+	uint8_t i, j;
+
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (context->target_flags[i].unchanged)
+			continue;
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct core_link *link = stream->sink->link;
+
+			if (!stream->tg->funcs->validate_timing(
+					stream->tg, &stream->public.timing))
+				return DC_FAIL_CONTROLLER_VALIDATE;
+
+			if (stream->signal == SIGNAL_TYPE_VIRTUAL)
+				return status;
+
+			status = build_stream_hw_param(stream);
+
+			if (status != DC_OK)
+				return status;
+
+			if (!link->link_enc->funcs->validate_output_with_stream(
+					link->link_enc,
+					stream))
+				return DC_FAIL_ENC_VALIDATE;
+
+			/* TODO: validate audio ASIC caps, encoder */
+
+			status = dc_link_validate_mode_timing(stream->sink,
+					link,
+					&stream->public.timing);
+
+			if (status != DC_OK)
+				return status;
+
+			build_info_frame(stream);
+		}
+	}
+
+	return DC_OK;
+}
+
+enum dc_status dce100_validate_bandwidth(
+	const struct dc *dc,
+	struct validate_context *context)
+{
+	/* TODO implement when needed */
+
+	return DC_OK;
+}
+
+static void set_target_unchanged(
+		struct validate_context *context,
+		uint8_t target_idx)
+{
+	uint8_t i;
+	struct core_target *target = context->targets[target_idx];
+
+	context->target_flags[target_idx].unchanged = true;
+	for (i = 0; i < target->public.stream_count; i++) {
+		struct core_stream *core_stream =
+			DC_STREAM_TO_CORE(target->public.streams[i]);
+		uint8_t index = core_stream->controller_idx;
+
+		context->res_ctx.controller_ctx[index].flags.unchanged = true;
+	}
+}
+
+static enum dc_status map_clock_resources(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	uint8_t i, j;
+
+	/* mark resources used for targets that are already active */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (!context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			reference_clock_source(
+				&context->res_ctx,
+				stream->clock_source);
+		}
+	}
+
+	/* acquire new resources */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			if (dc_is_dp_signal(stream->signal)
+				|| stream->signal == SIGNAL_TYPE_VIRTUAL)
+				stream->clock_source = context->res_ctx.
+					pool.clock_sources[DCE100_CLK_SRC_EXT];
+			else
+				stream->clock_source =
+					find_used_clk_src_for_sharing(
+							context, stream);
+			if (stream->clock_source == NULL)
+				stream->clock_source =
+					find_first_free_pll(&context->res_ctx);
+
+			if (stream->clock_source == NULL)
+				return DC_NO_CLOCK_SOURCE_RESOURCE;
+
+			reference_clock_source(
+					&context->res_ctx,
+					stream->clock_source);
+		}
+	}
+
+	return DC_OK;
+}
+
+enum dc_status dce100_validate_with_context(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count,
+		struct validate_context *context)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	uint8_t i, j;
+	struct dc_context *dc_ctx = dc->ctx;
+
+	for (i = 0; i < set_count; i++) {
+		context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
+
+		for (j = 0; j < dc->current_context.target_count; j++)
+			if (dc->current_context.targets[j] == context->targets[i])
+				set_target_unchanged(context, i);
+
+		if (!context->target_flags[i].unchanged)
+			if (!logical_attach_surfaces_to_target(
+					(struct dc_surface **)set[i].surfaces,
+					set[i].surface_count,
+					&context->targets[i]->public)) {
+				DC_ERROR("Failed to attach surface to target!\n");
+				return DC_FAIL_ATTACH_SURFACES;
+			}
+	}
+
+	context->target_count = set_count;
+
+	context->res_ctx.pool = dc->res_pool;
+
+	result = map_resources(dc, context);
+
+	if (result == DC_OK)
+		result = map_clock_resources(dc, context);
+
+	if (result == DC_OK)
+		result = validate_mapped_resource(dc, context);
+
+	if (result == DC_OK)
+		build_scaling_params_for_context(dc, context);
+
+	if (result == DC_OK)
+		result = dce100_validate_bandwidth(dc, context);
+
+	return result;
+}
+
+static struct resource_funcs dce100_res_pool_funcs = {
+	.destruct = dce100_destruct_resource_pool,
+	.link_enc_create = dce100_link_encoder_create,
+	.link_enc_destroy = dce110_link_encoder_destroy,
+	.validate_with_context = dce100_validate_with_context,
+	.validate_bandwidth = dce100_validate_bandwidth
+};
+
+bool dce100_construct_resource_pool(
+	struct adapter_service *adapter_serv,
+	uint8_t num_virtual_links,
+	struct dc *dc,
+	struct resource_pool *pool)
+{
+	unsigned int i;
+	struct audio_init_data audio_init_data = { 0 };
+	struct dc_context *ctx = dc->ctx;
+
+	pool->adapter_srv = adapter_serv;
+	pool->funcs = &dce100_res_pool_funcs;
+
+	pool->stream_engines.engine.ENGINE_ID_DIGA = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGB = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGC = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGD = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGE = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGF = 1;
+
+	pool->clock_sources[DCE100_CLK_SRC_PLL0] = dce100_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_PLL0, &dce100_clk_src_reg_offsets[0]);
+	pool->clock_sources[DCE100_CLK_SRC_PLL1] = dce100_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_PLL1, &dce100_clk_src_reg_offsets[1]);
+	pool->clock_sources[DCE100_CLK_SRC_EXT] =  dce100_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_EXTERNAL, &dce100_clk_src_reg_offsets[0]);
+	pool->clk_src_count = DCE100_CLK_SRC_TOTAL;
+
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] == NULL) {
+			dm_error("DC: failed to create clock sources!\n");
+			BREAK_TO_DEBUGGER();
+			goto clk_src_create_fail;
+		}
+	}
+
+	pool->display_clock = dal_display_clock_dce110_create(ctx, adapter_serv);
+	if (pool->display_clock == NULL) {
+		dm_error("DC: failed to create display clock!\n");
+		BREAK_TO_DEBUGGER();
+		goto disp_clk_create_fail;
+	}
+
+	{
+		struct irq_service_init_data init_data;
+
+		init_data.ctx = dc->ctx;
+		pool->irqs = dal_irq_service_create(
+				dal_adapter_service_get_dce_version(
+					dc->res_pool.adapter_srv),
+				&init_data);
+		if (!pool->irqs)
+			goto irqs_create_fail;
+
+	}
+
+	pool->controller_count =
+		dal_adapter_service_get_func_controllers_num(adapter_serv);
+	pool->stream_enc_count = dal_adapter_service_get_stream_engines_num(
+			adapter_serv);
+	pool->scaler_filter = dal_scaler_filter_create(ctx);
+	if (pool->scaler_filter == NULL) {
+		BREAK_TO_DEBUGGER();
+		dm_error("DC: failed to create filter!\n");
+		goto filter_create_fail;
+	}
+
+	for (i = 0; i < pool->controller_count; i++) {
+		pool->timing_generators[i] = dce100_timing_generator_create(
+				adapter_serv, ctx, i, &dce100_tg_offsets[i]);
+		if (pool->timing_generators[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create tg!\n");
+			goto controller_create_fail;
+		}
+
+		pool->mis[i] = dce100_mem_input_create(ctx, i,
+				&dce100_mi_reg_offsets[i]);
+		if (pool->mis[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create memory input!\n");
+			goto controller_create_fail;
+		}
+
+		pool->ipps[i] = dce100_ipp_create(ctx, i,
+				&dce100_ipp_reg_offsets[i]);
+		if (pool->ipps[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create input pixel processor!\n");
+			goto controller_create_fail;
+		}
+
+		pool->transforms[i] = dce100_transform_create(
+					ctx, i, &dce100_xfm_offsets[i]);
+		if (pool->transforms[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create transform!\n");
+			goto controller_create_fail;
+		}
+		pool->transforms[i]->funcs->transform_set_scaler_filter(
+				pool->transforms[i],
+				pool->scaler_filter);
+
+		pool->opps[i] = dce100_opp_create(ctx, i, &dce100_opp_reg_offsets[i]);
+		if (pool->opps[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create output pixel processor!\n");
+			goto controller_create_fail;
+		}
+	}
+
+	audio_init_data.as = adapter_serv;
+	audio_init_data.ctx = ctx;
+	pool->audio_count = 0;
+	for (i = 0; i < pool->controller_count; i++) {
+		struct graphics_object_id obj_id;
+
+		obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i);
+		if (false == dal_graphics_object_id_is_valid(obj_id)) {
+			/* no more valid audio objects */
+			break;
+		}
+
+		audio_init_data.audio_stream_id = obj_id;
+		pool->audios[i] = dal_audio_create(&audio_init_data);
+		if (pool->audios[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create DPPs!\n");
+			goto audio_create_fail;
+		}
+		pool->audio_count++;
+	}
+
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		/* TODO: rework fragile code*/
+		if (pool->stream_engines.u_all & 1 << i) {
+			pool->stream_enc[i] = dce100_stream_encoder_create(
+				i, dc->ctx,
+				dal_adapter_service_get_bios_parser(
+					adapter_serv),
+				&stream_enc_regs[i]);
+			if (pool->stream_enc[i] == NULL) {
+				BREAK_TO_DEBUGGER();
+				dm_error("DC: failed to create stream_encoder!\n");
+				goto stream_enc_create_fail;
+			}
+		}
+	}
+
+	for (i = 0; i < num_virtual_links; i++) {
+		pool->stream_enc[pool->stream_enc_count] =
+			virtual_stream_encoder_create(
+				dc->ctx, dal_adapter_service_get_bios_parser(
+								adapter_serv));
+		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create stream_encoder!\n");
+			goto stream_enc_create_fail;
+		}
+		pool->stream_enc_count++;
+	}
+
+	return true;
+
+stream_enc_create_fail:
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		if (pool->stream_enc[i] != NULL)
+			dm_free(pool->stream_enc[i]->ctx,
+				DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+	}
+
+audio_create_fail:
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->audios[i] != NULL)
+			dal_audio_destroy(&pool->audios[i]);
+	}
+
+controller_create_fail:
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->opps[i] != NULL)
+			dce100_opp_destroy(&pool->opps[i]);
+
+		if (pool->transforms[i] != NULL)
+			dce100_transform_destroy(&pool->transforms[i]);
+
+		if (pool->ipps[i] != NULL)
+			dce110_ipp_destroy(&pool->ipps[i]);
+
+		if (pool->mis[i] != NULL) {
+			dm_free(pool->mis[i]->ctx,
+					TO_DCE110_MEM_INPUT(pool->mis[i]));
+			pool->mis[i] = NULL;
+		}
+
+		if (pool->timing_generators[i] != NULL)	{
+			dm_free(pool->timing_generators[i]->ctx,
+				DCE110TG_FROM_TG(pool->timing_generators[i]));
+			pool->timing_generators[i] = NULL;
+		}
+	}
+
+filter_create_fail:
+	dal_irq_service_destroy(&pool->irqs);
+
+irqs_create_fail:
+	dal_display_clock_destroy(&pool->display_clock);
+
+disp_clk_create_fail:
+clk_src_create_fail:
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] != NULL)
+			dce100_clock_source_destroy(&pool->clock_sources[i]);
+	}
+
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h
new file mode 100644
index 000000000000..2a23d864831f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h
@@ -0,0 +1,43 @@
+/*
+* Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DCE100_RESOURCE_H_
+#define DCE100_RESOURCE_H_
+
+struct adapter_service;
+struct dc;
+struct resource_pool;
+struct dc_validation_set;
+
+
+bool dce100_construct_resource_pool(
+	struct adapter_service *adapter_serv,
+	uint8_t num_virtual_links,
+	struct dc *dc,
+	struct resource_pool *pool);
+
+void dce100_destruct_resource_pool(struct resource_pool *pool);
+
+#endif /* DCE100_RESOURCE_H_ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 23/29] drm/amd/dal: Add empty encoder programming for virtual HW
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (21 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 22/29] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 17:20 ` [PATCH 24/29] drm/amd/dal: Add display core Harry Wentland
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel

Adds empty encoder HW programming functions to support
enablement of virtual pipes (i.e. pipes without actual
display output).

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/virtual/Makefile        |   9 ++
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.c  | 133 +++++++++++++++++++++
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.h  |  35 ++++++
 .../amd/dal/dc/virtual/virtual_stream_encoder.c    | 124 +++++++++++++++++++
 .../amd/dal/dc/virtual/virtual_stream_encoder.h    |  39 ++++++
 5 files changed, 340 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h

diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/Makefile b/drivers/gpu/drm/amd/dal/dc/virtual/Makefile
new file mode 100644
index 000000000000..0e2cbc0bb532
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the virtual sub-component of DAL.
+# It provides the control and status of HW CRTC block.
+
+VIRTUAL = virtual_link_encoder.o virtual_stream_encoder.o
+
+AMD_DAL_VIRTUAL = $(addprefix $(AMDDALPATH)/dc/virtual/,$(VIRTUAL))
+
+AMD_DAL_FILES += $(AMD_DAL_VIRTUAL)
diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
new file mode 100644
index 000000000000..ade443d79c02
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services_types.h"
+
+#include "virtual_link_encoder.h"
+
+#define VIRTUAL_MAX_PIXEL_CLK_IN_KHZ 600000
+
+static bool virtual_link_encoder_validate_output_with_stream(
+	struct link_encoder *enc,
+	struct core_stream *stream) { return true; }
+
+static void virtual_link_encoder_hw_init(struct link_encoder *enc) {}
+
+static void virtual_link_encoder_setup(
+	struct link_encoder *enc,
+	enum signal_type signal) {}
+
+static void virtual_link_encoder_enable_tmds_output(
+	struct link_encoder *enc,
+	enum clock_source_id clock_source,
+	enum dc_color_depth color_depth,
+	bool hdmi,
+	bool dual_link,
+	uint32_t pixel_clock) {}
+
+static void virtual_link_encoder_enable_dp_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source) {}
+
+static void virtual_link_encoder_enable_dp_mst_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source) {}
+
+static void virtual_link_encoder_disable_output(
+	struct link_encoder *link_enc,
+	enum signal_type signal) {}
+
+static void virtual_link_encoder_dp_set_lane_settings(
+	struct link_encoder *enc,
+	const struct link_training_settings *link_settings) {}
+
+static void virtual_link_encoder_dp_set_phy_pattern(
+	struct link_encoder *enc,
+	const struct encoder_set_dp_phy_pattern_param *param) {}
+
+static void virtual_link_encoder_update_mst_stream_allocation_table(
+	struct link_encoder *enc,
+	const struct link_mst_stream_allocation_table *table) {}
+
+static void virtual_link_encoder_set_lcd_backlight_level(
+	struct link_encoder *enc,
+	uint32_t level) {}
+
+static void virtual_link_encoder_edp_backlight_control(
+	struct link_encoder *enc,
+	bool enable) {}
+
+static void virtual_link_encoder_edp_power_control(
+	struct link_encoder *enc,
+	bool power_up) {}
+
+static void virtual_link_encoder_connect_dig_be_to_fe(
+	struct link_encoder *enc,
+	enum engine_id engine,
+	bool connect) {}
+
+static struct link_encoder_funcs virtual_lnk_enc_funcs = {
+	.validate_output_with_stream =
+		virtual_link_encoder_validate_output_with_stream,
+	.hw_init = virtual_link_encoder_hw_init,
+	.setup = virtual_link_encoder_setup,
+	.enable_tmds_output = virtual_link_encoder_enable_tmds_output,
+	.enable_dp_output = virtual_link_encoder_enable_dp_output,
+	.enable_dp_mst_output = virtual_link_encoder_enable_dp_mst_output,
+	.disable_output = virtual_link_encoder_disable_output,
+	.dp_set_lane_settings = virtual_link_encoder_dp_set_lane_settings,
+	.dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern,
+	.update_mst_stream_allocation_table =
+		virtual_link_encoder_update_mst_stream_allocation_table,
+	.set_lcd_backlight_level = virtual_link_encoder_set_lcd_backlight_level,
+	.backlight_control = virtual_link_encoder_edp_backlight_control,
+	.power_control = virtual_link_encoder_edp_power_control,
+	.connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe
+};
+
+bool virtual_link_encoder_construct(
+	struct link_encoder *enc, const struct encoder_init_data *init_data)
+{
+	enc->funcs = &virtual_lnk_enc_funcs;
+	enc->ctx = init_data->ctx;
+	enc->id = init_data->encoder;
+
+	enc->hpd_source = init_data->hpd_source;
+	enc->connector = init_data->connector;
+
+	enc->adapter_service = init_data->adapter_service;
+
+	enc->transmitter = init_data->transmitter;
+
+	enc->features.max_pixel_clock = VIRTUAL_MAX_PIXEL_CLK_IN_KHZ;
+
+	enc->output_signals = SIGNAL_TYPE_VIRTUAL;
+
+	enc->preferred_engine = ENGINE_ID_VIRTUAL;
+
+	return true;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
new file mode 100644
index 000000000000..c34bd0421c9b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_VIRTUAL_LINK_ENCODER_H__
+#define __DC_VIRTUAL_LINK_ENCODER_H__
+
+#include "inc/link_encoder.h"
+
+bool virtual_link_encoder_construct(
+	struct link_encoder *enc, const struct encoder_init_data *init_data);
+
+
+#endif /* __DC_VIRTUAL_LINK_ENCODER_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
new file mode 100644
index 000000000000..4f5271bec369
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "virtual_stream_encoder.h"
+
+static void virtual_stream_encoder_dp_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing) {}
+
+static void virtual_stream_encoder_hdmi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool enable_audio) {}
+
+static void virtual_stream_encoder_dvi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool is_dual_link) {}
+
+static void virtual_stream_encoder_set_mst_bandwidth(
+	struct stream_encoder *enc,
+	struct fixed31_32 avg_time_slots_per_mtp) {}
+
+static void virtual_stream_encoder_update_hdmi_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame) {}
+
+static void virtual_stream_encoder_stop_hdmi_info_packets(
+	struct stream_encoder *enc) {}
+
+static void virtual_stream_encoder_update_dp_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame) {}
+
+static void virtual_stream_encoder_stop_dp_info_packets(
+	struct stream_encoder *enc) {}
+
+static void virtual_stream_encoder_dp_blank(
+	struct stream_encoder *enc) {}
+
+static void virtual_stream_encoder_dp_unblank(
+	struct stream_encoder *enc,
+	const struct encoder_unblank_param *param) {}
+
+static struct stream_encoder_funcs virtual_str_enc_funcs = {
+	.dp_set_stream_attribute =
+		virtual_stream_encoder_dp_set_stream_attribute,
+	.hdmi_set_stream_attribute =
+		virtual_stream_encoder_hdmi_set_stream_attribute,
+	.dvi_set_stream_attribute =
+		virtual_stream_encoder_dvi_set_stream_attribute,
+	.set_mst_bandwidth =
+		virtual_stream_encoder_set_mst_bandwidth,
+	.update_hdmi_info_packets =
+		virtual_stream_encoder_update_hdmi_info_packets,
+	.stop_hdmi_info_packets =
+		virtual_stream_encoder_stop_hdmi_info_packets,
+	.update_dp_info_packets =
+		virtual_stream_encoder_update_dp_info_packets,
+	.stop_dp_info_packets =
+		virtual_stream_encoder_stop_dp_info_packets,
+	.dp_blank =
+		virtual_stream_encoder_dp_blank,
+	.dp_unblank =
+		virtual_stream_encoder_dp_unblank,
+};
+
+bool virtual_stream_encoder_construct(
+	struct stream_encoder *enc,
+	struct dc_context *ctx,
+	struct dc_bios *bp)
+{
+	if (!enc)
+		return false;
+	if (!bp)
+		return false;
+
+	enc->funcs = &virtual_str_enc_funcs;
+	enc->ctx = ctx;
+	enc->id = ENGINE_ID_VIRTUAL;
+	enc->bp = bp;
+
+	return true;
+}
+
+struct stream_encoder *virtual_stream_encoder_create(
+	struct dc_context *ctx, struct dc_bios *bp)
+{
+	struct stream_encoder *enc = dm_alloc(ctx, sizeof(*enc));
+
+	if (!enc)
+		return NULL;
+
+	if (virtual_stream_encoder_construct(enc, ctx, bp))
+		return enc;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, enc);
+	return NULL;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h
new file mode 100644
index 000000000000..dce8425ea88e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_VIRTUAL_STREAM_ENCODER_H__
+#define __DC_VIRTUAL_STREAM_ENCODER_H__
+
+#include "inc/stream_encoder.h"
+
+struct stream_encoder *virtual_stream_encoder_create(
+	struct dc_context *ctx, struct dc_bios *bp);
+
+bool virtual_stream_encoder_construct(
+	struct stream_encoder *enc,
+	struct dc_context *ctx,
+	struct dc_bios *bp);
+
+#endif /* __DC_VIRTUAL_STREAM_ENCODER_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 24/29] drm/amd/dal: Add display core
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (22 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 23/29] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 17:20 ` [PATCH 25/29] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel

Adds a logical representation of our hardware. Provides ability to
- dc_validate_resources - validate a display configuration
- dc_commit_targets - commit a display configuration
- dc_commit_surfaces_to_target - update surfaces
- dc_link_detect - detect displays at link
- dc_resume - resume display HW
- dc_interrupt_set/ack - set and ack interrupts
- etc.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/Makefile               |   28 +
 drivers/gpu/drm/amd/dal/dc/core/dc.c              |  932 +++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c |   56 +
 drivers/gpu/drm/amd/dal/dc/core/dc_link.c         | 1644 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c     | 1151 ++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c      | 1728 +++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c    |  201 +++
 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c     | 1243 +++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c         |  116 ++
 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c       |  188 +++
 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c      |  123 ++
 drivers/gpu/drm/amd/dal/dc/core/dc_target.c       |  548 +++++++
 12 files changed, 7958 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_target.c

diff --git a/drivers/gpu/drm/amd/dal/dc/Makefile b/drivers/gpu/drm/amd/dal/dc/Makefile
new file mode 100644
index 000000000000..aed26eec81f9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/Makefile
@@ -0,0 +1,28 @@
+#
+# Makefile for Display Core (dc) component.
+#
+
+DC_LIBS = adapter asic_capability audio basics bios calcs \
+gpio gpu i2caux irq virtual
+
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+DC_LIBS += dce110
+endif
+
+ifdef CONFIG_DRM_AMD_DAL_DCE10_0
+DC_LIBS += dce100
+endif
+
+AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/dc/,$(DC_LIBS)))
+
+include $(AMD_DC)
+
+DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_target.o dc_sink.o dc_stream.o \
+dc_hw_sequencer.o dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o
+
+AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE))
+
+AMD_DAL_FILES += $(AMD_DISPLAY_CORE)
+
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c
new file mode 100644
index 000000000000..0b8f158c0ec2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ */
+
+#include "dm_services.h"
+
+#include "dc.h"
+
+#include "core_status.h"
+#include "core_types.h"
+#include "hw_sequencer.h"
+
+#include "resource.h"
+
+#include "adapter_service_interface.h"
+#include "clock_source.h"
+#include "dc_bios_types.h"
+
+#include "bandwidth_calcs.h"
+#include "include/irq_service_interface.h"
+#include "transform.h"
+#include "timing_generator.h"
+#include "virtual/virtual_link_encoder.h"
+
+#include "link_hwss.h"
+#include "link_encoder.h"
+
+#include "dc_link_ddc.h"
+
+/*******************************************************************************
+ * Private structures
+ ******************************************************************************/
+
+struct dc_target_sync_report {
+	uint32_t h_count;
+	uint32_t v_count;
+};
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static void destroy_links(struct dc *dc)
+{
+	uint32_t i;
+
+	for (i = 0; i < dc->link_count; i++) {
+		if (NULL != dc->links[i])
+			link_destroy(&dc->links[i]);
+	}
+}
+
+static bool create_links(struct dc *dc, const struct dc_init_data *init_params)
+{
+	int i;
+	int connectors_num;
+	struct dc_bios *dcb;
+
+	dc->link_count = 0;
+
+	dcb = dal_adapter_service_get_bios_parser(init_params->adapter_srv);
+
+	connectors_num = dcb->funcs->get_connectors_number(dcb);
+
+	if (connectors_num > ENUM_ID_COUNT) {
+		dm_error(
+			"DC: Number of connectors %d exceeds maximum of %d!\n",
+			connectors_num,
+			ENUM_ID_COUNT);
+		return false;
+	}
+
+	if (connectors_num == 0 && init_params->num_virtual_links == 0) {
+		dm_error("DC: Number of connectors can not be zero!\n");
+		return false;
+	}
+
+	dm_output_to_console(
+		"DC: %s: connectors_num: physical:%d, virtual:%d\n",
+		__func__,
+		connectors_num,
+		init_params->num_virtual_links);
+
+	for (i = 0; i < connectors_num; i++) {
+		struct link_init_data link_init_params = {0};
+		struct core_link *link;
+
+		link_init_params.ctx = init_params->ctx;
+		link_init_params.adapter_srv = init_params->adapter_srv;
+		link_init_params.connector_index = i;
+		link_init_params.link_index = dc->link_count;
+		link_init_params.dc = dc;
+		link = link_create(&link_init_params);
+
+		if (link) {
+			dc->links[dc->link_count] = link;
+			link->dc = dc;
+			++dc->link_count;
+		} else {
+			dm_error("DC: failed to create link!\n");
+		}
+	}
+
+	for (i = 0; i < init_params->num_virtual_links; i++) {
+		struct core_link *link = dm_alloc(
+			dc->ctx,
+			sizeof(*link));
+		struct encoder_init_data enc_init = {0};
+
+		if (link == NULL) {
+			BREAK_TO_DEBUGGER();
+			goto failed_alloc;
+		}
+
+		link->adapter_srv = init_params->adapter_srv;
+		link->ctx = init_params->ctx;
+		link->dc = dc;
+		link->public.connector_signal = SIGNAL_TYPE_VIRTUAL;
+		link->link_id.type = OBJECT_TYPE_CONNECTOR;
+		link->link_id.id = CONNECTOR_ID_VIRTUAL;
+		link->link_id.enum_id = ENUM_ID_1;
+		link->link_enc = dm_alloc(
+			dc->ctx,
+			sizeof(*link->link_enc));
+
+		enc_init.adapter_service = init_params->adapter_srv;
+		enc_init.ctx = init_params->ctx;
+		enc_init.channel = CHANNEL_ID_UNKNOWN;
+		enc_init.hpd_source = HPD_SOURCEID_UNKNOWN;
+		enc_init.transmitter = TRANSMITTER_UNKNOWN;
+		enc_init.connector = link->link_id;
+		enc_init.encoder.type = OBJECT_TYPE_ENCODER;
+		enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL;
+		enc_init.encoder.enum_id = ENUM_ID_1;
+		virtual_link_encoder_construct(link->link_enc, &enc_init);
+
+		link->public.link_index = dc->link_count;
+		dc->links[dc->link_count] = link;
+		dc->link_count++;
+	}
+
+	return true;
+
+failed_alloc:
+	return false;
+}
+
+
+static void init_hw(struct dc *dc)
+{
+	int i;
+	struct dc_bios *bp;
+	struct transform *xfm;
+
+	bp = dal_adapter_service_get_bios_parser(dc->res_pool.adapter_srv);
+	for(i = 0; i < dc->res_pool.controller_count; i++) {
+		xfm = dc->res_pool.transforms[i];
+
+		dc->hwss.enable_display_power_gating(
+				dc->ctx, i, bp,
+				PIPE_GATING_CONTROL_INIT);
+		dc->hwss.enable_display_power_gating(
+				dc->ctx, i, bp,
+				PIPE_GATING_CONTROL_DISABLE);
+
+		xfm->funcs->transform_power_up(xfm);
+		dc->hwss.enable_display_pipe_clock_gating(
+			dc->ctx,
+			true);
+	}
+
+	dc->hwss.clock_gating_power_up(dc->ctx, false);
+	bp->funcs->power_up(bp);
+	/***************************************/
+
+	for (i = 0; i < dc->link_count; i++) {
+		/****************************************/
+		/* Power up AND update implementation according to the
+		 * required signal (which may be different from the
+		 * default signal on connector). */
+		struct core_link *link = dc->links[i];
+		link->link_enc->funcs->hw_init(link->link_enc);
+	}
+
+	for(i = 0; i < dc->res_pool.controller_count; i++) {
+		struct timing_generator *tg = dc->res_pool.timing_generators[i];
+
+		tg->funcs->disable_vga(tg);
+
+		/* Blank controller using driver code instead of
+		 * command table. */
+		tg->funcs->set_blank(tg, true);
+	}
+
+	for(i = 0; i < dc->res_pool.audio_count; i++) {
+		struct audio *audio = dc->res_pool.audios[i];
+
+		if (dal_audio_power_up(audio) != AUDIO_RESULT_OK)
+			dm_error("Failed audio power up!\n");
+	}
+
+}
+
+static struct adapter_service *create_as(
+		struct dc_init_data *dc_init_data,
+		const struct dal_init_data *init)
+{
+	struct adapter_service *as = NULL;
+	struct as_init_data init_data;
+
+	dm_memset(&init_data, 0, sizeof(init_data));
+
+	init_data.ctx = dc_init_data->ctx;
+
+	/* BIOS parser init data */
+	init_data.bp_init_data.ctx = dc_init_data->ctx;
+	init_data.bp_init_data.bios = init->asic_id.atombios_base_address;
+
+	/* HW init data */
+	init_data.hw_init_data.chip_id = init->asic_id.chip_id;
+	init_data.hw_init_data.chip_family = init->asic_id.chip_family;
+	init_data.hw_init_data.pci_revision_id = init->asic_id.pci_revision_id;
+	init_data.hw_init_data.fake_paths_num = init->asic_id.fake_paths_num;
+	init_data.hw_init_data.feature_flags = init->asic_id.feature_flags;
+	init_data.hw_init_data.hw_internal_rev = init->asic_id.hw_internal_rev;
+	init_data.hw_init_data.runtime_flags = init->asic_id.runtime_flags;
+	init_data.hw_init_data.vram_width = init->asic_id.vram_width;
+	init_data.hw_init_data.vram_type = init->asic_id.vram_type;
+
+	/* bdf is BUS,DEVICE,FUNCTION*/
+	init_data.bdf_info = init->bdf_info;
+
+	init_data.display_param = &init->display_param;
+	init_data.vbios_override = init->vbios_override;
+	init_data.dce_environment = init->dce_environment;
+
+	as = dal_adapter_service_create(&init_data);
+
+	return as;
+}
+
+static void bw_calcs_data_update_from_pplib(struct dc *dc)
+{
+	struct dc_pp_clock_levels clks = {0};
+
+	/*do system clock*/
+	dm_pp_get_clock_levels_by_type(
+			dc->ctx,
+			DC_PP_CLOCK_TYPE_ENGINE_CLK,
+			&clks);
+	/* convert all the clock fro kHz to fix point mHz */
+	dc->bw_vbios.high_sclk = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels-1], 1000);
+	dc->bw_vbios.mid_sclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels>>1], 1000);
+	dc->bw_vbios.low_sclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[0], 1000);
+
+	/*do display clock*/
+	dm_pp_get_clock_levels_by_type(
+			dc->ctx,
+			DC_PP_CLOCK_TYPE_DISPLAY_CLK,
+			&clks);
+
+	dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels-1], 1000);
+	dc->bw_vbios.mid_voltage_max_dispclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels>>1], 1000);
+	dc->bw_vbios.low_voltage_max_dispclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[0], 1000);
+
+	/*do memory clock*/
+	dm_pp_get_clock_levels_by_type(
+			dc->ctx,
+			DC_PP_CLOCK_TYPE_MEMORY_CLK,
+			&clks);
+
+	dc->bw_vbios.low_yclk = bw_frc_to_fixed(
+		clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000);
+	dc->bw_vbios.mid_yclk = bw_frc_to_fixed(
+		clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER,
+		1000);
+	dc->bw_vbios.high_yclk = bw_frc_to_fixed(
+		clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER,
+		1000);
+}
+
+static bool construct(struct dc *dc, const struct dal_init_data *init_params)
+{
+	struct dal_logger *logger;
+	/* Tempory code
+	 * TODO: replace dal_init_data with dc_init_data when dal is removed
+	 */
+	struct dc_init_data dc_init_data = {0};
+
+	/* Create dc context */
+	/* A temp dc context is used only to allocate the memory for actual
+	 * dc context */
+	struct dc_context ctx = {0};
+	ctx.cgs_device = init_params->cgs_device;
+	ctx.dc = dc;
+
+	dc_init_data.ctx = dm_alloc(&ctx, sizeof(*dc_init_data.ctx));
+	if (!dc_init_data.ctx) {
+		dm_error("%s: failed to create ctx\n", __func__);
+		goto ctx_fail;
+	}
+	dc_init_data.ctx->driver_context = init_params->driver;
+	dc_init_data.ctx->cgs_device = init_params->cgs_device;
+	dc_init_data.num_virtual_links = init_params->num_virtual_links;
+	dc_init_data.ctx->dc = dc;
+
+	/* Create logger */
+	logger = dal_logger_create(dc_init_data.ctx);
+
+	if (!logger) {
+		/* can *not* call logger. call base driver 'print error' */
+		dm_error("%s: failed to create Logger!\n", __func__);
+		goto logger_fail;
+	}
+	dc_init_data.ctx->logger = logger;
+
+	/* Create adapter service */
+	dc_init_data.adapter_srv = create_as(&dc_init_data, init_params);
+
+	if (!dc_init_data.adapter_srv) {
+		dm_error("%s: create_as() failed!\n", __func__);
+		goto as_fail;
+	}
+
+	/* Initialize HW controlled by Adapter Service */
+	if (false == dal_adapter_service_initialize_hw_data(
+			dc_init_data.adapter_srv)) {
+		dm_error("%s: dal_adapter_service_initialize_hw_data()"\
+				"  failed!\n", __func__);
+		/* Note that AS exist, so have to destroy it.*/
+		goto as_fail;
+	}
+
+	dc->ctx = dc_init_data.ctx;
+
+	dc->ctx->dce_environment = dal_adapter_service_get_dce_environment(
+			dc_init_data.adapter_srv);
+
+	/* Create hardware sequencer */
+	if (!dc_construct_hw_sequencer(dc_init_data.adapter_srv, dc))
+		goto hwss_fail;
+
+	if (!dc_construct_resource_pool(
+		dc_init_data.adapter_srv, dc, dc_init_data.num_virtual_links))
+		goto construct_resource_fail;
+
+	if (!create_links(dc, &dc_init_data))
+		goto create_links_fail;
+
+	bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios);
+
+	bw_calcs_data_update_from_pplib(dc);
+
+	return true;
+
+	/**** error handling here ****/
+construct_resource_fail:
+create_links_fail:
+as_fail:
+	dal_logger_destroy(&dc_init_data.ctx->logger);
+logger_fail:
+hwss_fail:
+	dm_free(&ctx, dc_init_data.ctx);
+ctx_fail:
+	return false;
+}
+
+static void destruct(struct dc *dc)
+{
+	destroy_links(dc);
+	dc->res_pool.funcs->destruct(&dc->res_pool);
+	dal_logger_destroy(&dc->ctx->logger);
+	dm_free(dc->ctx, dc->ctx);
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+struct dc *dc_create(const struct dal_init_data *init_params)
+ {
+	struct dc_context ctx = {
+		.driver_context = init_params->driver,
+		.cgs_device = init_params->cgs_device
+	};
+	struct dc *dc = dm_alloc(&ctx, sizeof(*dc));
+
+	if (NULL == dc)
+		goto alloc_fail;
+
+	ctx.dc = dc;
+	if (false == construct(dc, init_params))
+		goto construct_fail;
+
+	/*TODO: separate HW and SW initialization*/
+	init_hw(dc);
+
+	return dc;
+
+construct_fail:
+	dm_free(&ctx, dc);
+
+alloc_fail:
+	return NULL;
+}
+
+void dc_destroy(struct dc **dc)
+{
+	struct dc_context ctx = *(*dc)->ctx;
+	destruct(*dc);
+	dm_free(&ctx, *dc);
+	*dc = NULL;
+}
+
+bool dc_validate_resources(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	struct validate_context *context;
+
+	context = dm_alloc(dc->ctx, sizeof(struct validate_context));
+	if(context == NULL)
+		goto context_alloc_fail;
+
+	result = dc->res_pool.funcs->validate_with_context(
+						dc, set, set_count, context);
+
+	dm_free(dc->ctx, context);
+context_alloc_fail:
+
+	return (result == DC_OK);
+
+}
+
+static void program_timing_sync(
+		struct dc_context *dc_ctx,
+		struct validate_context *ctx)
+{
+	uint8_t i;
+	uint8_t j;
+	uint8_t group_size = 0;
+	uint8_t tg_count = ctx->res_ctx.pool.controller_count;
+	struct timing_generator *tg_set[3];
+
+	for (i = 0; i < tg_count; i++) {
+		if (!ctx->res_ctx.controller_ctx[i].stream)
+			continue;
+
+		tg_set[0] = ctx->res_ctx.pool.timing_generators[i];
+		group_size = 1;
+
+		/* Add tg to the set, search rest of the tg's for ones with
+		 * same timing, add all tgs with same timing to the group
+		 */
+		for (j = i + 1; j < tg_count; j++) {
+			if (!ctx->res_ctx.controller_ctx[j].stream)
+				continue;
+
+			if (is_same_timing(
+				&ctx->res_ctx.controller_ctx[j].stream->public
+								.timing,
+				&ctx->res_ctx.controller_ctx[i].stream->public
+								.timing)) {
+				tg_set[group_size] =
+					ctx->res_ctx.pool.timing_generators[j];
+				group_size++;
+			}
+		}
+
+		/* Right now we limit to one timing sync group so if one is
+		 * found we break. A group has to be more than one tg.*/
+		if (group_size > 1)
+			break;
+	}
+
+	if(group_size > 1) {
+		dc_ctx->dc->hwss.enable_timing_synchronization(dc_ctx, group_size, tg_set);
+	}
+}
+
+static bool targets_changed(
+		struct dc *dc,
+		struct dc_target *targets[],
+		uint8_t target_count)
+{
+	uint8_t i;
+
+	if (target_count != dc->current_context.target_count)
+		return true;
+
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		if (&dc->current_context.targets[i]->public != targets[i])
+			return true;
+	}
+
+	return false;
+}
+
+bool dc_commit_targets(
+	struct dc *dc,
+	struct dc_target *targets[],
+	uint8_t target_count)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	struct validate_context *context;
+	struct dc_validation_set set[4];
+	uint8_t i;
+
+	if (false == targets_changed(dc, targets, target_count))
+		return DC_OK;
+
+	dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_INTERFACE_TRACE,
+				LOG_MINOR_COMPONENT_DC,
+				"%s: %d targets\n",
+				__func__,
+				target_count);
+
+	for (i = 0; i < target_count; i++) {
+		struct dc_target *target = targets[i];
+
+		dc_target_log(target,
+				dc->ctx->logger,
+				LOG_MAJOR_INTERFACE_TRACE,
+				LOG_MINOR_COMPONENT_DC);
+
+		set[i].target = targets[i];
+		set[i].surface_count = 0;
+
+	}
+
+	context = dm_alloc(dc->ctx, sizeof(struct validate_context));
+	if (context == NULL)
+		goto context_alloc_fail;
+
+	result = dc->res_pool.funcs->validate_with_context(dc, set, target_count, context);
+	if (result != DC_OK){
+		BREAK_TO_DEBUGGER();
+		goto fail;
+	}
+
+	pplib_apply_safe_state(dc);
+
+	if (!dal_adapter_service_is_in_accelerated_mode(
+						dc->res_pool.adapter_srv)) {
+		dc->hwss.enable_accelerated_mode(dc);
+	}
+
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		/*TODO: optimize this to happen only when necessary*/
+		dc_target_disable_memory_requests(
+				&dc->current_context.targets[i]->public);
+	}
+
+	if (result == DC_OK) {
+		dc->hwss.reset_hw_ctx(dc, context, target_count);
+
+		if (context->target_count > 0)
+			result = dc->hwss.apply_ctx_to_hw(dc, context);
+	}
+
+	for (i = 0; i < context->target_count; i++) {
+		struct dc_target *dc_target = &context->targets[i]->public;
+		if (context->targets[i]->status.surface_count > 0)
+			dc_target_enable_memory_requests(dc_target);
+	}
+
+	/* Release old targets */
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		dc_target_release(
+				&dc->current_context.targets[i]->public);
+		dc->current_context.targets[i] = NULL;
+	}
+	/* Retain new targets*/
+	for (i = 0; i < context->target_count; i++) {
+		dc_target_retain(&context->targets[i]->public);
+	}
+
+	dc->current_context = *context;
+
+	program_timing_sync(dc->ctx, context);
+
+	pplib_apply_display_requirements(dc, context);
+
+	/* TODO: disable unused plls*/
+fail:
+	dm_free(dc->ctx, context);
+
+context_alloc_fail:
+	return (result == DC_OK);
+}
+
+uint8_t dc_get_current_target_count(const struct dc *dc)
+{
+	return dc->current_context.target_count;
+}
+
+struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i)
+{
+	if (i < dc->current_context.target_count)
+		return &dc->current_context.targets[i]->public;
+	return NULL;
+}
+
+const struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index)
+{
+	return &dc->links[link_index]->public;
+}
+
+const struct graphics_object_id dc_get_link_id_at_index(
+	struct dc *dc, uint32_t link_index)
+{
+	return dc->links[link_index]->link_id;
+}
+
+const struct ddc_service *dc_get_ddc_at_index(
+	struct dc *dc, uint32_t link_index)
+{
+	return dc->links[link_index]->ddc;
+}
+
+const enum dc_irq_source dc_get_hpd_irq_source_at_index(
+	struct dc *dc, uint32_t link_index)
+{
+	return dc->links[link_index]->public.irq_source_hpd;
+}
+
+const struct audio **dc_get_audios(struct dc *dc)
+{
+	return (const struct audio **)dc->res_pool.audios;
+}
+
+void dc_get_caps(const struct dc *dc, struct dc_caps *caps)
+{
+	caps->max_targets = dc->res_pool.controller_count;
+	caps->max_links = dc->link_count;
+	caps->max_audios = dc->res_pool.audio_count;
+}
+
+void dc_flip_surface_addrs(struct dc* dc,
+		const struct dc_surface *const surfaces[],
+		struct dc_flip_addrs flip_addrs[],
+		uint32_t count)
+{
+	uint8_t i;
+	for (i = 0; i < count; i++) {
+		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
+		/*
+		 * TODO figure out a good way to keep track of address. Until
+		 * then we'll have to awkwardly bypass the "const" surface.
+		 */
+		surface->public.address = flip_addrs[i].address;
+		surface->public.flip_immediate = flip_addrs[i].flip_immediate;
+
+		dc->hwss.update_plane_address(
+			dc,
+			surface,
+			DC_TARGET_TO_CORE(surface->status.dc_target));
+	}
+}
+
+enum dc_irq_source dc_interrupt_to_irq_source(
+		struct dc *dc,
+		uint32_t src_id,
+		uint32_t ext_id)
+{
+	return dal_irq_service_to_irq_source(dc->res_pool.irqs, src_id, ext_id);
+}
+
+
+void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable)
+{
+	dal_irq_service_set(dc->res_pool.irqs, src, enable);
+}
+
+void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
+{
+	dal_irq_service_ack(dc->res_pool.irqs, src);
+}
+
+const struct dc_target *dc_get_target_on_irq_source(
+		const struct dc *dc,
+		enum dc_irq_source src)
+{
+	uint8_t i, j;
+	uint8_t crtc_idx;
+
+	switch (src) {
+	case DC_IRQ_SOURCE_VUPDATE1:
+	case DC_IRQ_SOURCE_VUPDATE2:
+	case DC_IRQ_SOURCE_VUPDATE3:
+	case DC_IRQ_SOURCE_VUPDATE4:
+	case DC_IRQ_SOURCE_VUPDATE5:
+	case DC_IRQ_SOURCE_VUPDATE6:
+		crtc_idx = src - DC_IRQ_SOURCE_VUPDATE1;
+		break;
+	case DC_IRQ_SOURCE_PFLIP1:
+	case DC_IRQ_SOURCE_PFLIP2:
+	case DC_IRQ_SOURCE_PFLIP3:
+	case DC_IRQ_SOURCE_PFLIP4:
+	case DC_IRQ_SOURCE_PFLIP5:
+	case DC_IRQ_SOURCE_PFLIP6:
+	case DC_IRQ_SOURCE_PFLIP_UNDERLAY0:
+		crtc_idx = src - DC_IRQ_SOURCE_PFLIP1;
+		break;
+	default:
+		dm_error("%s: invalid irq source: %d\n!" ,__func__, src);
+		return NULL;
+	}
+
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		struct core_target *target = dc->current_context.targets[i];
+
+		struct dc_target *dc_target;
+
+		if (NULL == target) {
+			dm_error("%s: 'dc_target' is NULL for irq source: %d\n!",
+					__func__, src);
+			continue;
+		}
+
+		dc_target = &target->public;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			const struct core_stream *stream =
+				DC_STREAM_TO_CORE(dc_target->streams[j]);
+			const uint8_t controller_idx = stream->controller_idx;
+
+			if (controller_idx == crtc_idx)
+				return dc_target;
+		}
+	}
+
+	return NULL;
+}
+
+void dc_set_power_state(
+	struct dc *dc,
+	enum dc_acpi_cm_power_state power_state,
+	enum dc_video_power_state video_power_state)
+{
+	dc->previous_power_state = dc->current_power_state;
+	dc->current_power_state = video_power_state;
+
+	switch (power_state) {
+	case DC_ACPI_CM_POWER_STATE_D0:
+		init_hw(dc);
+		break;
+	default:
+		/* NULL means "reset/release all DC targets" */
+		dc_commit_targets(dc, NULL, 0);
+
+		dc->hwss.power_down(dc);
+		break;
+	}
+
+}
+
+void dc_resume(const struct dc *dc)
+{
+	uint32_t i;
+
+	for (i = 0; i < dc->link_count; i++)
+		core_link_resume(dc->links[i]);
+}
+
+bool dc_read_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size)
+{
+	struct core_link *link =
+			DC_LINK_TO_LINK(dc_get_link_at_index(dc, link_index));
+
+	enum ddc_result r = dal_ddc_service_read_dpcd_data(
+			link->ddc,
+			address,
+			data,
+			size);
+	return r == DDC_RESULT_SUCESSFULL;
+}
+
+bool dc_write_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t size)
+{
+	struct core_link *link =
+			DC_LINK_TO_LINK(dc_get_link_at_index(dc, link_index));
+
+	enum ddc_result r = dal_ddc_service_write_dpcd_data(
+			link->ddc,
+			address,
+			data,
+			size);
+	return r == DDC_RESULT_SUCESSFULL;
+}
+
+bool dc_link_add_remote_sink(const struct dc_link *link, struct dc_sink *sink)
+{
+	struct core_link *core_link = DC_LINK_TO_LINK(link);
+	struct dc_link *dc_link = &core_link->public;
+
+	if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	dc_link->remote_sinks[link->sink_count] = sink;
+	dc_link->sink_count++;
+
+	return true;
+}
+
+void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink)
+{
+	struct core_link *core_link = DC_LINK_TO_LINK(link);
+	struct dc_link *dc_link = &core_link->public;
+
+	dc_link->local_sink = sink;
+
+	if (sink == NULL) {
+		dc_link->sink_count = 0;
+		dc_link->type = dc_connection_none;
+	} else {
+		dc_link->sink_count = 1;
+		dc_link->type = dc_connection_single;
+	}
+}
+
+void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink)
+{
+	int i;
+	struct core_link *core_link = DC_LINK_TO_LINK(link);
+	struct dc_link *dc_link = &core_link->public;
+
+	if (!link->sink_count) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	for (i = 0; i < dc_link->sink_count; i++) {
+		if (dc_link->remote_sinks[i] == sink) {
+			dc_sink_release(sink);
+			dc_link->remote_sinks[i] = NULL;
+
+			/* shrink array to remove empty place */
+			while (i < dc_link->sink_count - 1) {
+				dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1];
+				i++;
+			}
+
+			dc_link->sink_count--;
+			return;
+		}
+	}
+}
+
+uint8_t dc_get_dig_index(const struct dc_stream *stream)
+{
+
+	struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
+
+	switch (core_stream->stream_enc->id) {
+	case ENGINE_ID_DIGA:
+		return 0;
+	case ENGINE_ID_DIGB:
+		return 1;
+	case ENGINE_ID_DIGC:
+		return 2;
+	case ENGINE_ID_DIGD:
+		return 3;
+	case ENGINE_ID_DIGE:
+		return 4;
+	case ENGINE_ID_DIGF:
+		return 5;
+	case ENGINE_ID_DIGG:
+		return 6;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+enum gpio_ddc_line dc_get_ddc_line(
+		const struct dc_stream *stream)
+{
+
+	struct core_sink *core_sink = DC_SINK_TO_CORE(stream->sink);
+	struct ddc *ddc_line = dal_ddc_service_get_ddc_pin(
+			core_sink->link->ddc);
+
+	return dal_ddc_get_line(ddc_line);
+}
+
+enum signal_type dc_get_display_signal(
+		const struct dc_stream *stream)
+{
+	return stream->sink->sink_signal;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
new file mode 100644
index 000000000000..db4f1313e056
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "core_types.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce100/dce100_hw_sequencer.h"
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/dce110_hw_sequencer.h"
+#endif
+
+bool dc_construct_hw_sequencer(
+				struct adapter_service *adapter_serv,
+				struct dc *dc)
+{
+	enum dce_version dce_ver = dal_adapter_service_get_dce_version(adapter_serv);
+
+	switch (dce_ver)
+	{
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dce100_hw_sequencer_construct(dc);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dce110_hw_sequencer_construct(dc);
+#endif
+	default:
+		break;
+	}
+
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
new file mode 100644
index 000000000000..b0ef028ad0fc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
@@ -0,0 +1,1644 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "dc.h"
+#include "core_dc.h"
+#include "adapter_service_interface.h"
+#include "grph_object_id.h"
+#include "gpio_service_interface.h"
+#include "core_status.h"
+#include "dc_link_dp.h"
+#include "dc_link_ddc.h"
+#include "link_hwss.h"
+#include "stream_encoder.h"
+#include "link_encoder.h"
+#include "hw_sequencer.h"
+#include "fixed31_32.h"
+
+
+#define LINK_INFO(...) \
+	dal_logger_write(dc_ctx->logger, \
+		LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_HOTPLUG, \
+		__VA_ARGS__)
+
+
+/*******************************************************************************
+ * Private structures
+ ******************************************************************************/
+
+enum {
+	LINK_RATE_REF_FREQ_IN_MHZ = 27,
+	PEAK_FACTOR_X1000 = 1006
+};
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static void destruct(struct core_link *link)
+{
+	if (link->ddc)
+		dal_ddc_service_destroy(&link->ddc);
+
+	if(link->link_enc)
+		link->ctx->dc->res_pool.funcs->link_enc_destroy(&link->link_enc);
+}
+
+/*
+ *  Function: program_hpd_filter
+ *
+ *  @brief
+ *     Programs HPD filter on associated HPD line
+ *
+ *  @param [in] delay_on_connect_in_ms: Connect filter timeout
+ *  @param [in] delay_on_disconnect_in_ms: Disconnect filter timeout
+ *
+ *  @return
+ *     true on success, false otherwise
+ */
+static bool program_hpd_filter(
+	const struct core_link *link)
+{
+	bool result = false;
+
+	struct irq *hpd;
+
+	int delay_on_connect_in_ms = 0;
+	int delay_on_disconnect_in_ms = 0;
+
+	/* Verify feature is supported */
+	switch (link->public.connector_signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		/* Program hpd filter */
+		delay_on_connect_in_ms = 500;
+		delay_on_disconnect_in_ms = 100;
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		/* Program hpd filter to allow DP signal to settle */
+		delay_on_connect_in_ms = 20;
+		delay_on_disconnect_in_ms = 0;
+		break;
+	case SIGNAL_TYPE_LVDS:
+	case SIGNAL_TYPE_EDP:
+	default:
+		/* Don't program hpd filter */
+		return false;
+	}
+
+	/* Obtain HPD handle */
+	hpd = dal_adapter_service_obtain_hpd_irq(
+		link->adapter_srv, link->link_id);
+
+	if (!hpd)
+		return result;
+
+	/* Setup HPD filtering */
+	if (dal_irq_open(hpd) == GPIO_RESULT_OK) {
+		struct gpio_hpd_config config;
+
+		config.delay_on_connect = delay_on_connect_in_ms;
+		config.delay_on_disconnect = delay_on_disconnect_in_ms;
+
+		dal_irq_setup_hpd_filter(hpd, &config);
+
+		dal_irq_close(hpd);
+
+		result = true;
+	} else {
+		ASSERT_CRITICAL(false);
+	}
+
+	/* Release HPD handle */
+	dal_adapter_service_release_irq(link->adapter_srv, hpd);
+
+	return result;
+}
+
+static bool detect_sink(struct core_link *link, enum dc_connection_type *type)
+{
+	uint32_t is_hpd_high = 0;
+	struct irq *hpd_pin;
+
+	/* todo: may need to lock gpio access */
+	hpd_pin = dal_adapter_service_obtain_hpd_irq(
+			link->adapter_srv,
+			link->link_id);
+	if (hpd_pin == NULL)
+		goto hpd_gpio_failure;
+
+	dal_irq_open(hpd_pin);
+	dal_irq_get_value(hpd_pin, &is_hpd_high);
+	dal_irq_close(hpd_pin);
+	dal_adapter_service_release_irq(
+		link->adapter_srv,
+		hpd_pin);
+
+	if (is_hpd_high) {
+		*type = dc_connection_single;
+		/* TODO: need to do the actual detection */
+	} else {
+		*type = dc_connection_none;
+	}
+
+	return true;
+
+hpd_gpio_failure:
+	return false;
+}
+
+
+enum ddc_transaction_type get_ddc_transaction_type(
+		enum signal_type sink_signal)
+{
+	enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE;
+
+
+	switch (sink_signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_LVDS:
+	case SIGNAL_TYPE_RGB:
+		transaction_type = DDC_TRANSACTION_TYPE_I2C;
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_EDP:
+		transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		/* MST does not use I2COverAux, but there is the
+		 * SPECIAL use case for "immediate dwnstrm device
+		 * access" (EPR#370830). */
+		transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+		break;
+
+	default:
+		break;
+	}
+
+
+	return transaction_type;
+}
+
+static enum signal_type get_basic_signal_type(
+	struct graphics_object_id encoder,
+	struct graphics_object_id downstream)
+{
+	if (downstream.type == OBJECT_TYPE_CONNECTOR) {
+		switch (downstream.id) {
+		case CONNECTOR_ID_SINGLE_LINK_DVII:
+			switch (encoder.id) {
+			case ENCODER_ID_INTERNAL_DAC1:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+			case ENCODER_ID_INTERNAL_DAC2:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+				return SIGNAL_TYPE_RGB;
+			default:
+				return SIGNAL_TYPE_DVI_SINGLE_LINK;
+			}
+		break;
+		case CONNECTOR_ID_DUAL_LINK_DVII:
+		{
+			switch (encoder.id) {
+			case ENCODER_ID_INTERNAL_DAC1:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+			case ENCODER_ID_INTERNAL_DAC2:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+				return SIGNAL_TYPE_RGB;
+			default:
+				return SIGNAL_TYPE_DVI_DUAL_LINK;
+			}
+		}
+		break;
+		case CONNECTOR_ID_SINGLE_LINK_DVID:
+			return SIGNAL_TYPE_DVI_SINGLE_LINK;
+		case CONNECTOR_ID_DUAL_LINK_DVID:
+			return SIGNAL_TYPE_DVI_DUAL_LINK;
+		case CONNECTOR_ID_VGA:
+			return SIGNAL_TYPE_RGB;
+		case CONNECTOR_ID_HDMI_TYPE_A:
+			return SIGNAL_TYPE_HDMI_TYPE_A;
+		case CONNECTOR_ID_LVDS:
+			return SIGNAL_TYPE_LVDS;
+		case CONNECTOR_ID_DISPLAY_PORT:
+			return SIGNAL_TYPE_DISPLAY_PORT;
+		case CONNECTOR_ID_EDP:
+			return SIGNAL_TYPE_EDP;
+		default:
+			return SIGNAL_TYPE_NONE;
+		}
+	} else if (downstream.type == OBJECT_TYPE_ENCODER) {
+		switch (downstream.id) {
+		case ENCODER_ID_EXTERNAL_NUTMEG:
+		case ENCODER_ID_EXTERNAL_TRAVIS:
+			return SIGNAL_TYPE_DISPLAY_PORT;
+		default:
+			return SIGNAL_TYPE_NONE;
+		}
+	}
+
+	return SIGNAL_TYPE_NONE;
+}
+
+/*
+ * @brief
+ * Check whether there is a dongle on DP connector
+ */
+static bool is_dp_sink_present(struct core_link *link)
+{
+	enum gpio_result gpio_result;
+	uint32_t clock_pin = 0;
+	uint32_t data_pin = 0;
+
+	struct ddc *ddc;
+
+	enum connector_id connector_id =
+		dal_graphics_object_id_get_connector_id(link->link_id);
+
+	bool present =
+		((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
+		(connector_id == CONNECTOR_ID_EDP));
+
+	ddc = dal_adapter_service_obtain_ddc(link->adapter_srv, link->link_id);
+
+	if (!ddc)
+		return present;
+
+	/* Open GPIO and set it to I2C mode */
+	/* Note: this GpioMode_Input will be converted
+	 * to GpioConfigType_I2cAuxDualMode in GPIO component,
+	 * which indicates we need additional delay */
+
+	if (GPIO_RESULT_OK != dal_ddc_open(
+		ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
+		dal_adapter_service_release_ddc(link->adapter_srv, ddc);
+
+		return present;
+	}
+
+	/* Read GPIO: DP sink is present if both clock and data pins are zero */
+	/* [anaumov] in DAL2, there was no check for GPIO failure */
+
+	gpio_result = dal_ddc_get_clock(ddc, &clock_pin);
+	ASSERT(gpio_result == GPIO_RESULT_OK);
+
+	if (gpio_result == GPIO_RESULT_OK)
+		if (link->link_enc->features.flags.bits.
+						DP_SINK_DETECT_POLL_DATA_PIN)
+			gpio_result = dal_ddc_get_data(ddc, &data_pin);
+
+	present = (gpio_result == GPIO_RESULT_OK) && !(clock_pin || data_pin);
+
+	dal_ddc_close(ddc);
+
+	dal_adapter_service_release_ddc(link->adapter_srv, ddc);
+
+	return present;
+}
+
+/*
+ * @brief
+ * Detect output sink type
+ */
+static enum signal_type link_detect_sink(struct core_link *link)
+{
+	enum signal_type result = get_basic_signal_type(
+		link->link_enc->id, link->link_id);
+
+	/* Internal digital encoder will detect only dongles
+	 * that require digital signal */
+
+	/* Detection mechanism is different
+	 * for different native connectors.
+	 * LVDS connector supports only LVDS signal;
+	 * PCIE is a bus slot, the actual connector needs to be detected first;
+	 * eDP connector supports only eDP signal;
+	 * HDMI should check straps for audio */
+
+	/* PCIE detects the actual connector on add-on board */
+
+	if (link->link_id.id == CONNECTOR_ID_PCIE) {
+		/* ZAZTODO implement PCIE add-on card detection */
+	}
+
+	switch (link->link_id.id) {
+	case CONNECTOR_ID_HDMI_TYPE_A: {
+		/* check audio support:
+		 * if native HDMI is not supported, switch to DVI */
+		union audio_support audio_support =
+			dal_adapter_service_get_audio_support(
+				link->adapter_srv);
+
+		if (!audio_support.bits.HDMI_AUDIO_NATIVE)
+			if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A)
+				result = SIGNAL_TYPE_DVI_SINGLE_LINK;
+	}
+	break;
+	case CONNECTOR_ID_DISPLAY_PORT: {
+
+		/* Check whether DP signal detected: if not -
+		 * we assume signal is DVI; it could be corrected
+		 * to HDMI after dongle detection */
+		if (!is_dp_sink_present(link))
+			result = SIGNAL_TYPE_DVI_SINGLE_LINK;
+	}
+	break;
+	default:
+	break;
+	}
+
+	return result;
+}
+
+static enum signal_type decide_signal_from_strap_and_dongle_type(
+		enum display_dongle_type dongle_type,
+		union audio_support *audio_support)
+{
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+
+	switch (dongle_type) {
+	case DISPLAY_DONGLE_DP_HDMI_DONGLE:
+		if (audio_support->bits.HDMI_AUDIO_ON_DONGLE)
+			signal =  SIGNAL_TYPE_HDMI_TYPE_A;
+		else
+			signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	case DISPLAY_DONGLE_DP_DVI_DONGLE:
+		signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE:
+		if (audio_support->bits.HDMI_AUDIO_NATIVE)
+			signal =  SIGNAL_TYPE_HDMI_TYPE_A;
+		else
+			signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	default:
+		signal = SIGNAL_TYPE_NONE;
+		break;
+	}
+
+	return signal;
+}
+
+static enum signal_type dp_passive_dongle_detection(
+		struct ddc_service *ddc,
+		struct display_sink_capability *sink_cap,
+		union audio_support *audio_support)
+{
+	/* TODO:These 2 functions should be protected for upstreaming purposes
+	 * in case hackers want to save 10 cents hdmi license fee
+	 */
+	dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
+						ddc, sink_cap);
+	return decide_signal_from_strap_and_dongle_type(
+			sink_cap->dongle_type,
+			audio_support);
+}
+
+static void link_disconnect_sink(struct core_link *link)
+{
+	if (link->public.local_sink) {
+		dc_sink_release(link->public.local_sink);
+		link->public.local_sink = NULL;
+	}
+
+	link->dpcd_sink_count = 0;
+}
+
+static enum dc_edid_status read_edid(
+	struct core_link *link,
+	struct core_sink *sink)
+{
+	uint32_t edid_retry = 3;
+	enum dc_edid_status edid_status;
+
+	/* some dongles read edid incorrectly the first time,
+	 * do check sum and retry to make sure read correct edid.
+	 */
+	do {
+		sink->public.dc_edid.length =
+				dal_ddc_service_edid_query(link->ddc);
+
+		if (0 == sink->public.dc_edid.length)
+			return EDID_NO_RESPONSE;
+
+		dal_ddc_service_get_edid_buf(link->ddc,
+				sink->public.dc_edid.raw_edid);
+		edid_status = dm_helpers_parse_edid_caps(
+				sink->ctx,
+				&sink->public.dc_edid,
+				&sink->public.edid_caps);
+		--edid_retry;
+		if (edid_status == EDID_BAD_CHECKSUM)
+			dal_logger_write(link->ctx->logger,
+					LOG_MAJOR_WARNING,
+					LOG_MINOR_DETECTION_EDID_PARSER,
+					"Bad EDID checksum, retry remain: %d\n",
+					edid_retry);
+	} while (edid_status == EDID_BAD_CHECKSUM && edid_retry > 0);
+
+	return edid_status;
+}
+
+static void detect_dp(
+	struct core_link *link,
+	struct display_sink_capability *sink_caps,
+	bool *converter_disable_audio,
+	union audio_support *audio_support,
+	bool boot)
+{
+	sink_caps->signal = link_detect_sink(link);
+	sink_caps->transaction_type =
+		get_ddc_transaction_type(sink_caps->signal);
+
+	if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
+		sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
+		detect_dp_sink_caps(link);
+
+		/* DP active dongles */
+		if (is_dp_active_dongle(link)) {
+			if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
+				link->public.type = dc_connection_none;
+				/*
+				 * active dongle unplug processing for short irq
+				 */
+				link_disconnect_sink(link);
+				return;
+			}
+
+			if (link->dpcd_caps.dongle_type !=
+			DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
+				*converter_disable_audio = true;
+			}
+		}
+		if (is_mst_supported(link)) {
+			sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
+
+			/*
+			 * This call will initiate MST topology discovery. Which
+			 * will detect MST ports and add new DRM connector DRM
+			 * framework. Then read EDID via remote i2c over aux. In
+			 * the end, will notify DRM detect result and save EDID
+			 * into DRM framework.
+			 *
+			 * .detect is called by .fill_modes.
+			 * .fill_modes is called by user mode ioctl
+			 * DRM_IOCTL_MODE_GETCONNECTOR.
+			 *
+			 * .get_modes is called by .fill_modes.
+			 *
+			 * call .get_modes, AMDGPU DM implementation will create
+			 * new dc_sink and add to dc_link. For long HPD plug
+			 * in/out, MST has its own handle.
+			 *
+			 * Therefore, just after dc_create, link->sink is not
+			 * created for MST until user mode app calls
+			 * DRM_IOCTL_MODE_GETCONNECTOR.
+			 *
+			 * Need check ->sink usages in case ->sink = NULL
+			 * TODO: s3 resume check
+			 */
+
+			if (dm_helpers_dp_mst_start_top_mgr(
+				link->ctx,
+				&link->public, boot)) {
+				link->public.type = dc_connection_mst_branch;
+			} else {
+				/* MST not supported */
+				sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
+			}
+		}
+	} else {
+		/* DP passive dongles */
+		sink_caps->signal = dp_passive_dongle_detection(link->ddc,
+				sink_caps,
+				audio_support);
+	}
+}
+
+bool dc_link_detect(const struct dc_link *dc_link, bool boot)
+{
+	struct core_link *link = DC_LINK_TO_LINK(dc_link);
+	struct dc_sink_init_data sink_init_data = { 0 };
+	struct display_sink_capability sink_caps = { 0 };
+	uint8_t i;
+	bool converter_disable_audio = false;
+	union audio_support audio_support =
+		dal_adapter_service_get_audio_support(
+			link->adapter_srv);
+	enum dc_edid_status edid_status;
+	struct dc_context *dc_ctx = link->ctx;
+	struct dc_sink *dc_sink;
+	struct core_sink *sink = NULL;
+	enum dc_connection_type new_connection_type = dc_connection_none;
+
+	if (link->public.connector_signal == SIGNAL_TYPE_VIRTUAL)
+		return false;
+
+	if (false == detect_sink(link, &new_connection_type)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	link_disconnect_sink(link);
+
+	if (new_connection_type != dc_connection_none) {
+		link->public.type = new_connection_type;
+
+		/* From Disconnected-to-Connected. */
+		switch (link->public.connector_signal) {
+		case SIGNAL_TYPE_HDMI_TYPE_A: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			if (audio_support.bits.HDMI_AUDIO_NATIVE)
+				sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+			else
+				sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+			break;
+		}
+
+		case SIGNAL_TYPE_DVI_SINGLE_LINK: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+			break;
+		}
+
+		case SIGNAL_TYPE_DVI_DUAL_LINK: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+			break;
+		}
+
+		case SIGNAL_TYPE_EDP: {
+			detect_dp_sink_caps(link);
+			sink_caps.transaction_type =
+				DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+			sink_caps.signal = SIGNAL_TYPE_EDP;
+			break;
+		}
+
+		case SIGNAL_TYPE_DISPLAY_PORT: {
+			detect_dp(
+				link,
+				&sink_caps,
+				&converter_disable_audio,
+				&audio_support, boot);
+
+			/* Active dongle downstream unplug */
+			if (link->public.type == dc_connection_none)
+				return true;
+
+			if (link->public.type == dc_connection_mst_branch) {
+				LINK_INFO("link=%d, mst branch is now Connected\n",
+					link->public.link_index);
+				return false;
+			}
+
+			break;
+		}
+
+		default:
+			DC_ERROR("Invalid connector type! signal:%d\n",
+				link->public.connector_signal);
+			return false;
+		} /* switch() */
+
+		if (link->dpcd_caps.sink_count.bits.SINK_COUNT)
+			link->dpcd_sink_count = link->dpcd_caps.sink_count.
+					bits.SINK_COUNT;
+			else
+				link->dpcd_sink_count = 1;
+
+
+		dal_ddc_service_set_transaction_type(
+						link->ddc,
+						sink_caps.transaction_type);
+
+		sink_init_data.link = &link->public;
+		sink_init_data.sink_signal = sink_caps.signal;
+		sink_init_data.dongle_max_pix_clk =
+			sink_caps.max_hdmi_pixel_clock;
+		sink_init_data.converter_disable_audio =
+			converter_disable_audio;
+
+		dc_sink = dc_sink_create(&sink_init_data);
+		if (!dc_sink) {
+			DC_ERROR("Failed to create sink!\n");
+			return false;
+		}
+
+		sink = DC_SINK_TO_CORE(dc_sink);
+		link->public.local_sink = &sink->public;
+
+		edid_status = read_edid(link, sink);
+
+		switch (edid_status) {
+		case EDID_BAD_CHECKSUM:
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_DETECTION_EDID_PARSER,
+				"EDID checksum invalid.\n");
+			break;
+		case EDID_NO_RESPONSE:
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_DETECTION_EDID_PARSER,
+				"No EDID read.\n");
+			return false;
+
+		default:
+			break;
+		}
+
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_DETECTION,
+			LOG_MINOR_DETECTION_EDID_PARSER,
+			"%s: "
+			"manufacturer_id = %X, "
+			"product_id = %X, "
+			"serial_number = %X, "
+			"manufacture_week = %d, "
+			"manufacture_year = %d, "
+			"display_name = %s, "
+			"speaker_flag = %d, "
+			"audio_mode_count = %d\n",
+			__func__,
+			sink->public.edid_caps.manufacturer_id,
+			sink->public.edid_caps.product_id,
+			sink->public.edid_caps.serial_number,
+			sink->public.edid_caps.manufacture_week,
+			sink->public.edid_caps.manufacture_year,
+			sink->public.edid_caps.display_name,
+			sink->public.edid_caps.speaker_flags,
+			sink->public.edid_caps.audio_mode_count);
+
+		for (i = 0; i < sink->public.edid_caps.audio_mode_count; i++) {
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_DETECTION,
+				LOG_MINOR_DETECTION_EDID_PARSER,
+				"%s: mode number = %d, "
+				"format_code = %d, "
+				"channel_count = %d, "
+				"sample_rate = %d, "
+				"sample_size = %d\n",
+				__func__,
+				i,
+				sink->public.edid_caps.audio_modes[i].format_code,
+				sink->public.edid_caps.audio_modes[i].channel_count,
+				sink->public.edid_caps.audio_modes[i].sample_rate,
+				sink->public.edid_caps.audio_modes[i].sample_size);
+		}
+
+	} else {
+		/* From Connected-to-Disconnected. */
+		if (link->public.type == dc_connection_mst_branch) {
+			LINK_INFO("link=%d, mst branch is now Disconnected\n",
+				link->public.link_index);
+			dm_helpers_dp_mst_stop_top_mgr(link->ctx, &link->public);
+		}
+
+		link->public.type = dc_connection_none;
+		sink_caps.signal = SIGNAL_TYPE_NONE;
+	}
+
+	LINK_INFO("link=%d, dc_sink_in=%p is now %s\n",
+		link->public.link_index, &sink->public,
+		(sink_caps.signal == SIGNAL_TYPE_NONE ?
+			"Disconnected":"Connected"));
+
+	return true;
+}
+
+static enum hpd_source_id get_hpd_line(
+		struct core_link *link,
+		struct adapter_service *as)
+{
+	struct irq *hpd;
+	enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN;
+
+	hpd = dal_adapter_service_obtain_hpd_irq(as, link->link_id);
+
+	if (hpd) {
+		switch (dal_irq_get_source(hpd)) {
+		case DC_IRQ_SOURCE_HPD1:
+			hpd_id = HPD_SOURCEID1;
+		break;
+		case DC_IRQ_SOURCE_HPD2:
+			hpd_id = HPD_SOURCEID2;
+		break;
+		case DC_IRQ_SOURCE_HPD3:
+			hpd_id = HPD_SOURCEID3;
+		break;
+		case DC_IRQ_SOURCE_HPD4:
+			hpd_id = HPD_SOURCEID4;
+		break;
+		case DC_IRQ_SOURCE_HPD5:
+			hpd_id = HPD_SOURCEID5;
+		break;
+		case DC_IRQ_SOURCE_HPD6:
+			hpd_id = HPD_SOURCEID6;
+		break;
+		default:
+			BREAK_TO_DEBUGGER();
+		break;
+		}
+
+		dal_adapter_service_release_irq(as, hpd);
+	}
+
+	return hpd_id;
+}
+
+static enum channel_id get_ddc_line(struct core_link *link, struct adapter_service *as)
+{
+	struct ddc *ddc;
+	enum channel_id channel = CHANNEL_ID_UNKNOWN;
+
+	ddc = dal_adapter_service_obtain_ddc(as, link->link_id);
+
+	if (ddc) {
+		switch (dal_ddc_get_line(ddc)) {
+		case GPIO_DDC_LINE_DDC1:
+			channel = CHANNEL_ID_DDC1;
+			break;
+		case GPIO_DDC_LINE_DDC2:
+			channel = CHANNEL_ID_DDC2;
+			break;
+		case GPIO_DDC_LINE_DDC3:
+			channel = CHANNEL_ID_DDC3;
+			break;
+		case GPIO_DDC_LINE_DDC4:
+			channel = CHANNEL_ID_DDC4;
+			break;
+		case GPIO_DDC_LINE_DDC5:
+			channel = CHANNEL_ID_DDC5;
+			break;
+		case GPIO_DDC_LINE_DDC6:
+			channel = CHANNEL_ID_DDC6;
+			break;
+		case GPIO_DDC_LINE_DDC_VGA:
+			channel = CHANNEL_ID_DDC_VGA;
+			break;
+		case GPIO_DDC_LINE_I2C_PAD:
+			channel = CHANNEL_ID_I2C_PAD;
+			break;
+		default:
+			BREAK_TO_DEBUGGER();
+			break;
+		}
+
+		dal_adapter_service_release_ddc(as, ddc);
+	}
+
+	return channel;
+}
+
+static enum transmitter translate_encoder_to_transmitter(
+	struct graphics_object_id encoder)
+{
+	switch (encoder.id) {
+	case ENCODER_ID_INTERNAL_UNIPHY:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_A;
+		case ENUM_ID_2:
+			return TRANSMITTER_UNIPHY_B;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_INTERNAL_UNIPHY1:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_C;
+		case ENUM_ID_2:
+			return TRANSMITTER_UNIPHY_D;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_INTERNAL_UNIPHY2:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_E;
+		case ENUM_ID_2:
+			return TRANSMITTER_UNIPHY_F;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_INTERNAL_UNIPHY3:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_G;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_EXTERNAL_NUTMEG:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_NUTMEG_CRT;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_EXTERNAL_TRAVIS:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_TRAVIS_CRT;
+		case ENUM_ID_2:
+			return TRANSMITTER_TRAVIS_LCD;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	default:
+		return TRANSMITTER_UNKNOWN;
+	}
+}
+
+
+static bool construct(
+	struct core_link *link,
+	const struct link_init_data *init_params)
+{
+	uint8_t i;
+	struct adapter_service *as = init_params->adapter_srv;
+	struct irq *hpd_gpio = NULL;
+	struct ddc_service_init_data ddc_service_init_data = { 0 };
+	struct dc_context *dc_ctx = init_params->ctx;
+	struct encoder_init_data enc_init_data = { 0 };
+	struct integrated_info info = {{{ 0 }}};
+
+	link->dc = init_params->dc;
+	link->adapter_srv = as;
+	link->ctx = dc_ctx;
+	link->public.link_index = init_params->link_index;
+
+	link->link_id = dal_adapter_service_get_connector_obj_id(
+			as,
+			init_params->connector_index);
+
+	if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
+		dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d!\n",
+				__func__, init_params->connector_index);
+		goto create_fail;
+	}
+
+	switch (link->link_id.id) {
+	case CONNECTOR_ID_HDMI_TYPE_A:
+		link->public.connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
+		break;
+	case CONNECTOR_ID_SINGLE_LINK_DVID:
+	case CONNECTOR_ID_SINGLE_LINK_DVII:
+		link->public.connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	case CONNECTOR_ID_DUAL_LINK_DVID:
+	case CONNECTOR_ID_DUAL_LINK_DVII:
+		link->public.connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+		break;
+	case CONNECTOR_ID_DISPLAY_PORT:
+		link->public.connector_signal =	SIGNAL_TYPE_DISPLAY_PORT;
+		hpd_gpio = dal_adapter_service_obtain_hpd_irq(
+					as,
+					link->link_id);
+
+		if (hpd_gpio != NULL) {
+			link->public.irq_source_hpd_rx =
+					dal_irq_get_rx_source(hpd_gpio);
+			dal_adapter_service_release_irq(
+					as, hpd_gpio);
+		}
+
+		break;
+	case CONNECTOR_ID_EDP:
+		link->public.connector_signal = SIGNAL_TYPE_EDP;
+		hpd_gpio = dal_adapter_service_obtain_hpd_irq(
+					as,
+					link->link_id);
+
+		if (hpd_gpio != NULL) {
+			link->public.irq_source_hpd_rx =
+					dal_irq_get_rx_source(hpd_gpio);
+			dal_adapter_service_release_irq(
+					as, hpd_gpio);
+		}
+		break;
+	default:
+		dal_logger_write(dc_ctx->logger,
+			LOG_MAJOR_WARNING, LOG_MINOR_TM_LINK_SRV,
+			"Unsupported Connector type:%d!\n", link->link_id.id);
+		goto create_fail;
+	}
+
+	/* TODO: #DAL3 Implement id to str function.*/
+	LINK_INFO("Connector[%d] description:"
+			"signal %d\n",
+			init_params->connector_index,
+			link->public.connector_signal);
+
+	hpd_gpio = dal_adapter_service_obtain_hpd_irq(as, link->link_id);
+
+	if (hpd_gpio != NULL) {
+		link->public.irq_source_hpd = dal_irq_get_source(hpd_gpio);
+		dal_adapter_service_release_irq(as, hpd_gpio);
+	}
+
+	ddc_service_init_data.as = as;
+	ddc_service_init_data.ctx = link->ctx;
+	ddc_service_init_data.id = link->link_id;
+	link->ddc = dal_ddc_service_create(&ddc_service_init_data);
+
+	if (NULL == link->ddc) {
+		DC_ERROR("Failed to create ddc_service!\n");
+		goto create_fail;
+	}
+
+	enc_init_data.adapter_service = as;
+	enc_init_data.ctx = dc_ctx;
+	enc_init_data.encoder = dal_adapter_service_get_src_obj(
+							as, link->link_id, 0);
+	enc_init_data.connector = link->link_id;
+	enc_init_data.channel = get_ddc_line(link, as);
+	enc_init_data.hpd_source = get_hpd_line(link, as);
+	enc_init_data.transmitter =
+			translate_encoder_to_transmitter(enc_init_data.encoder);
+	link->link_enc = dc_ctx->dc->res_pool.funcs->link_enc_create(
+								&enc_init_data);
+
+	if( link->link_enc == NULL) {
+		DC_ERROR("Failed to create link encoder!\n");
+		goto create_fail;
+	}
+
+	dal_adapter_service_get_integrated_info(as, &info);
+
+	for (i = 0; ; i++) {
+		if (!dal_adapter_service_get_device_tag(
+				as, link->link_id, i, &link->device_tag)) {
+			DC_ERROR("Failed to find device tag!\n");
+			goto create_fail;
+		}
+
+		/* Look for device tag that matches connector signal,
+		 * CRT for rgb, LCD for other supported signal tyes
+		 */
+		if (!dal_adapter_service_is_device_id_supported(
+						as, link->device_tag.dev_id))
+			continue;
+		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT
+			&& link->public.connector_signal != SIGNAL_TYPE_RGB)
+			continue;
+		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD
+			&& link->public.connector_signal == SIGNAL_TYPE_RGB)
+			continue;
+		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_WIRELESS
+			&& link->public.connector_signal != SIGNAL_TYPE_WIRELESS)
+			continue;
+		break;
+	}
+
+	/* Look for channel mapping corresponding to connector and device tag */
+	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
+		struct external_display_path *path =
+			&info.ext_disp_conn_info.path[i];
+		if (path->device_connector_id.enum_id == link->link_id.enum_id
+			&& path->device_connector_id.id == link->link_id.id
+			&& path->device_connector_id.type == link->link_id.type
+			&& path->device_acpi_enum
+					== link->device_tag.acpi_device) {
+			link->ddi_channel_mapping = path->channel_mapping;
+			break;
+		}
+	}
+
+	/*
+	 * TODO check if GPIO programmed correctly
+	 *
+	 * If GPIO isn't programmed correctly HPD might not rise or drain
+	 * fast enough, leading to bounces.
+	 */
+	program_hpd_filter(link);
+
+	return true;
+
+create_fail:
+	return false;
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+struct core_link *link_create(const struct link_init_data *init_params)
+{
+	struct core_link *link =
+			dm_alloc(init_params->ctx, sizeof(*link));
+
+	if (NULL == link)
+		goto alloc_fail;
+
+	if (false == construct(link, init_params))
+		goto construct_fail;
+
+	return link;
+
+construct_fail:
+	dm_free(init_params->ctx, link);
+
+alloc_fail:
+	return NULL;
+}
+
+void link_destroy(struct core_link **link)
+{
+	destruct(*link);
+	dm_free((*link)->ctx, *link);
+	*link = NULL;
+}
+
+static void dpcd_configure_panel_mode(
+	struct core_link *link,
+	enum dp_panel_mode panel_mode)
+{
+	union dpcd_edp_config edp_config_set;
+	bool panel_mode_edp = false;
+
+	dm_memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
+
+	if (DP_PANEL_MODE_DEFAULT != panel_mode) {
+
+		switch (panel_mode) {
+		case DP_PANEL_MODE_EDP:
+		case DP_PANEL_MODE_SPECIAL:
+			panel_mode_edp = true;
+			break;
+
+		default:
+			break;
+		}
+
+		/*set edp panel mode in receiver*/
+		core_link_read_dpcd(
+			link,
+			DPCD_ADDRESS_EDP_CONFIG_SET,
+			&edp_config_set.raw,
+			sizeof(edp_config_set.raw));
+
+		if (edp_config_set.bits.PANEL_MODE_EDP
+			!= panel_mode_edp) {
+			enum ddc_result result = DDC_RESULT_UNKNOWN;
+
+			edp_config_set.bits.PANEL_MODE_EDP =
+			panel_mode_edp;
+			result = core_link_write_dpcd(
+				link,
+				DPCD_ADDRESS_EDP_CONFIG_SET,
+				&edp_config_set.raw,
+				sizeof(edp_config_set.raw));
+
+			ASSERT(result == DDC_RESULT_SUCESSFULL);
+		}
+	}
+	dal_logger_write(link->ctx->logger, LOG_MAJOR_DETECTION,
+			LOG_MINOR_DETECTION_DP_CAPS,
+			"Link: %d eDP panel mode supported: %d "
+			"eDP panel mode enabled: %d \n",
+			link->public.link_index,
+			link->dpcd_caps.panel_mode_edp,
+			panel_mode_edp);
+}
+
+static enum dc_status enable_link_dp(struct core_stream *stream)
+{
+	enum dc_status status;
+	bool skip_video_pattern;
+	struct core_link *link = stream->sink->link;
+	struct link_settings link_settings = {0};
+	enum dp_panel_mode panel_mode;
+
+	/* get link settings for video mode timing */
+	decide_link_settings(stream, &link_settings);
+	dp_enable_link_phy(
+		stream->sink->link,
+		stream->signal,
+		&link_settings);
+
+	panel_mode = dp_get_panel_mode(link);
+	dpcd_configure_panel_mode(link, panel_mode);
+
+	skip_video_pattern = true;
+
+	if (link_settings.link_rate == LINK_RATE_LOW)
+			skip_video_pattern = false;
+
+	if (perform_link_training(link, &link_settings, skip_video_pattern)) {
+		link->cur_link_settings = link_settings;
+		status = DC_OK;
+	}
+	else
+		status = DC_ERROR_UNEXPECTED;
+
+	return status;
+}
+
+static enum dc_status enable_link_dp_mst(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+
+	/* sink signal type after MST branch is MST. Multiple MST sinks
+	 * share one link. Link DP PHY is enable or training only once.
+	 */
+	if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
+		return DC_OK;
+
+	return enable_link_dp(stream);
+}
+
+static void enable_link_hdmi(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+
+	/* enable video output */
+	/* here we need to specify that encoder output settings
+	 * need to be calculated as for the set mode,
+	 * it will lead to querying dynamic link capabilities
+	 * which should be done before enable output */
+	uint32_t normalized_pix_clk = stream->public.timing.pix_clk_khz;
+	switch (stream->public.timing.display_color_depth) {
+	case COLOR_DEPTH_888:
+		break;
+	case COLOR_DEPTH_101010:
+		normalized_pix_clk = (normalized_pix_clk * 30) / 24;
+		break;
+	case COLOR_DEPTH_121212:
+		normalized_pix_clk = (normalized_pix_clk * 36) / 24;
+		break;
+	case COLOR_DEPTH_161616:
+		normalized_pix_clk = (normalized_pix_clk * 48) / 24;
+		break;
+	default:
+		break;
+	}
+
+	if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		dal_ddc_service_write_scdc_data(
+			stream->sink->link->ddc,
+			normalized_pix_clk,
+			stream->public.timing.flags.LTE_340MCSC_SCRAMBLE);
+
+	dm_memset(&stream->sink->link->cur_link_settings, 0,
+			sizeof(struct link_settings));
+
+	link->link_enc->funcs->enable_tmds_output(
+			link->link_enc,
+			stream->clock_source->id,
+			stream->public.timing.display_color_depth,
+			stream->signal == SIGNAL_TYPE_HDMI_TYPE_A,
+			stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK,
+			stream->public.timing.pix_clk_khz);
+
+	if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		dal_ddc_service_read_scdc_data(link->ddc);
+}
+
+/****************************enable_link***********************************/
+static enum dc_status enable_link(struct core_stream *stream)
+{
+	enum dc_status status = DC_ERROR_UNEXPECTED;
+	switch (stream->signal) {
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_EDP:
+		status = enable_link_dp(stream);
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		status = enable_link_dp_mst(stream);
+		dm_sleep_in_milliseconds(stream->ctx, 200);
+		break;
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		enable_link_hdmi(stream);
+		status = DC_OK;
+		break;
+	case SIGNAL_TYPE_VIRTUAL:
+		status = DC_OK;
+		break;
+	default:
+		break;
+	}
+
+	if (stream->audio && status == DC_OK) {
+		/* notify audio driver for audio modes of monitor */
+		dal_audio_enable_azalia_audio_jack_presence(stream->audio,
+				stream->stream_enc->id);
+
+		/* un-mute audio */
+		dal_audio_unmute(stream->audio, stream->stream_enc->id,
+				stream->signal);
+	}
+
+	return status;
+}
+
+static void disable_link(struct core_stream *stream)
+{
+	/* TODO  dp_set_hw_test_pattern */
+
+	/* here we need to specify that encoder output settings
+	 * need to be calculated as for the set mode,
+	 * it will lead to querying dynamic link capabilities
+	 * which should be done before enable output */
+
+	if (dc_is_dp_signal(stream->signal)) {
+		/* SST DP, eDP */
+		if (dc_is_dp_sst_signal(stream->signal))
+			dp_disable_link_phy(
+					stream->sink->link, stream->signal);
+		else {
+			dp_disable_link_phy_mst(
+					stream->sink->link, stream);
+		}
+	} else {
+		struct link_encoder *encoder =
+				stream->sink->link->link_enc;
+
+		encoder->funcs->disable_output(encoder, stream->signal);
+	}
+}
+
+enum dc_status dc_link_validate_mode_timing(
+		const struct core_sink *sink,
+		struct core_link *link,
+		const struct dc_crtc_timing *timing)
+{
+	uint32_t max_pix_clk = sink->dongle_max_pix_clk;
+
+	if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk)
+		return DC_EXCEED_DONGLE_MAX_CLK;
+
+	switch (sink->public.sink_signal) {
+		case SIGNAL_TYPE_DISPLAY_PORT:
+			if(!dp_validate_mode_timing(
+					link,
+					timing))
+				return DC_NO_DP_LINK_BANDWIDTH;
+			break;
+
+		default:
+			break;
+	}
+
+	return DC_OK;
+}
+
+bool dc_link_set_backlight_level(const struct dc_link *public, uint32_t level)
+{
+	struct core_link *link = DC_LINK_TO_CORE(public);
+	struct dc_context *ctx = link->ctx;
+
+	dal_logger_write(ctx->logger, LOG_MAJOR_BACKLIGHT,
+			LOG_MINOR_BACKLIGHT_INTERFACE,
+			"New Backlight level: %d (0x%X)\n", level, level);
+
+	link->link_enc->funcs->set_lcd_backlight_level(link->link_enc, level);
+
+	return true;
+}
+
+void core_link_resume(struct core_link *link)
+{
+	if (link->public.connector_signal != SIGNAL_TYPE_VIRTUAL)
+		program_hpd_filter(link);
+}
+
+static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream)
+{
+	struct link_settings *link_settings =
+			&stream->sink->link->cur_link_settings;
+	uint32_t link_rate_in_mbps =
+			link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ;
+	struct fixed31_32 mbps = dal_fixed31_32_from_int(
+			link_rate_in_mbps * link_settings->lane_count);
+
+	return dal_fixed31_32_div_int(mbps, 54);
+}
+
+static int get_color_depth(struct core_stream *stream)
+{
+	switch (stream->pix_clk_params.color_depth) {
+	case COLOR_DEPTH_666: return 6;
+	case COLOR_DEPTH_888: return 8;
+	case COLOR_DEPTH_101010: return 10;
+	case COLOR_DEPTH_121212: return 12;
+	case COLOR_DEPTH_141414: return 14;
+	case COLOR_DEPTH_161616: return 16;
+	default: return 0;
+	}
+}
+
+static struct fixed31_32 get_pbn_from_timing(struct core_stream *stream)
+{
+	uint32_t bpc;
+	uint64_t kbps;
+	struct fixed31_32 peak_kbps;
+	uint32_t numerator;
+	uint32_t denominator;
+
+	bpc = get_color_depth(stream);
+	kbps = stream->pix_clk_params.requested_pix_clk * bpc * 3;
+
+	/*
+	 * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
+	 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
+	 * common multiplier to render an integer PBN for all link rate/lane
+	 * counts combinations
+	 * calculate
+	 * peak_kbps *= (1006/1000)
+	 * peak_kbps *= (64/54)
+	 * peak_kbps *= 8    convert to bytes
+	 */
+
+	numerator = 64 * PEAK_FACTOR_X1000;
+	denominator = 54 * 8 * 1000 * 1000;
+	kbps *= numerator;
+	peak_kbps = dal_fixed31_32_from_fraction(kbps, denominator);
+
+	return peak_kbps;
+}
+
+static void update_mst_stream_alloc_table(
+	struct core_link *link,
+	struct core_stream *stream,
+	const struct dp_mst_stream_allocation_table *proposed_table)
+{
+	struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = {
+			{ 0 } };
+	struct link_mst_stream_allocation *dc_alloc;
+
+	int i;
+	int j;
+
+	/* if DRM proposed_table has more than one new payload */
+	ASSERT(proposed_table->stream_count -
+			link->mst_stream_alloc_table.stream_count < 2);
+
+	/* copy proposed_table to core_link, add stream encoder */
+	for (i = 0; i < proposed_table->stream_count; i++) {
+
+		for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) {
+			dc_alloc =
+			&link->mst_stream_alloc_table.stream_allocations[j];
+
+			if (dc_alloc->vcp_id ==
+				proposed_table->stream_allocations[i].vcp_id) {
+
+				work_table[i] = *dc_alloc;
+				break; /* exit j loop */
+			}
+		}
+
+		/* new vcp_id */
+		if (j == link->mst_stream_alloc_table.stream_count) {
+			work_table[i].vcp_id =
+				proposed_table->stream_allocations[i].vcp_id;
+			work_table[i].slot_count =
+				proposed_table->stream_allocations[i].slot_count;
+			work_table[i].stream_enc = stream->stream_enc;
+		}
+	}
+
+	/* update link->mst_stream_alloc_table with work_table */
+	link->mst_stream_alloc_table.stream_count =
+			proposed_table->stream_count;
+	for (i = 0; i < MAX_CONTROLLER_NUM; i++)
+		link->mst_stream_alloc_table.stream_allocations[i] =
+				work_table[i];
+}
+
+/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table
+ * because stream_encoder is not exposed to dm
+ */
+static enum dc_status allocate_mst_payload(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+	struct link_encoder *link_encoder = link->link_enc;
+	struct stream_encoder *stream_encoder = stream->stream_enc;
+	struct dp_mst_stream_allocation_table proposed_table = {0};
+	struct fixed31_32 avg_time_slots_per_mtp;
+	struct fixed31_32 pbn;
+	struct fixed31_32 pbn_per_slot;
+	uint8_t i;
+
+	/* enable_link_dp_mst already check link->enabled_stream_count
+	 * and stream is in link->stream[]. This is called during set mode,
+	 * stream_enc is available.
+	 */
+
+	/* get calculate VC payload for stream: stream_alloc */
+	dm_helpers_dp_mst_write_payload_allocation_table(
+		stream->ctx,
+		&stream->public,
+		&proposed_table,
+		true);
+
+	update_mst_stream_alloc_table(link, stream, &proposed_table);
+
+	dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_MST,
+			LOG_MINOR_MST_PROGRAMMING,
+			"%s  "
+			"stream_count: %d: \n ",
+			__func__,
+			link->mst_stream_alloc_table.stream_count);
+
+	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
+		dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_MST,
+		LOG_MINOR_MST_PROGRAMMING,
+		"stream_enc[%d]: 0x%x      "
+		"stream[%d].vcp_id: %d      "
+		"stream[%d].slot_count: %d\n",
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
+	}
+
+	ASSERT(proposed_table.stream_count > 0);
+
+	/*
+	 * temporary fix. Unplug of MST chain happened (two displays),
+	 * table is empty on first reset mode, and cause 0 division in
+	 * avg_time_slots_per_mtp calculation
+	 */
+
+	/* to be removed or debugged */
+	if (proposed_table.stream_count == 0)
+		return DC_OK;
+
+	/* program DP source TX for payload */
+	link_encoder->funcs->update_mst_stream_allocation_table(
+		link_encoder,
+		&link->mst_stream_alloc_table);
+
+	/* send down message */
+	dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+			stream->ctx,
+			&stream->public);
+
+	dm_helpers_dp_mst_send_payload_allocation(
+			stream->ctx,
+			&stream->public,
+			true);
+
+	/* slot X.Y for only current stream */
+	pbn_per_slot = get_pbn_per_slot(stream);
+	pbn = get_pbn_from_timing(stream);
+	avg_time_slots_per_mtp = dal_fixed31_32_div(pbn, pbn_per_slot);
+
+
+
+	stream_encoder->funcs->set_mst_bandwidth(
+		stream_encoder,
+		avg_time_slots_per_mtp);
+
+	return DC_OK;
+
+}
+
+static enum dc_status deallocate_mst_payload(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+	struct link_encoder *link_encoder = link->link_enc;
+	struct stream_encoder *stream_encoder = stream->stream_enc;
+	struct dp_mst_stream_allocation_table proposed_table = {0};
+	struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0);
+	uint8_t i;
+	bool mst_mode = (link->public.type == dc_connection_mst_branch);
+
+	/* deallocate_mst_payload is called before disable link. When mode or
+	 * disable/enable monitor, new stream is created which is not in link
+	 * stream[] yet. For this, payload is not allocated yet, so de-alloc
+	 * should not done. For new mode set, map_resources will get engine
+	 * for new stream, so stream_enc->id should be validated until here.
+	 */
+
+	/* slot X.Y */
+	stream_encoder->funcs->set_mst_bandwidth(
+		stream_encoder,
+		avg_time_slots_per_mtp);
+
+	/* TODO: which component is responsible for remove payload table? */
+	if (mst_mode)
+		dm_helpers_dp_mst_write_payload_allocation_table(
+				stream->ctx,
+				&stream->public,
+				&proposed_table,
+				false);
+
+	update_mst_stream_alloc_table(link, stream, &proposed_table);
+
+	dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_MST,
+			LOG_MINOR_MST_PROGRAMMING,
+			"%s"
+			"stream_count: %d: ",
+			__func__,
+			link->mst_stream_alloc_table.stream_count);
+
+	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
+		dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_MST,
+		LOG_MINOR_MST_PROGRAMMING,
+		"stream_enc[%d]: 0x%x      "
+		"stream[%d].vcp_id: %d      "
+		"stream[%d].slot_count: %d\n",
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
+	}
+
+	link_encoder->funcs->update_mst_stream_allocation_table(
+		link_encoder,
+		&link->mst_stream_alloc_table);
+
+	if (mst_mode) {
+		dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+			stream->ctx,
+			&stream->public);
+
+		dm_helpers_dp_mst_send_payload_allocation(
+			stream->ctx,
+			&stream->public,
+			false);
+	}
+
+	return DC_OK;
+}
+
+void core_link_enable_stream(
+		struct core_link *link,
+		struct core_stream *stream)
+{
+	struct dc *dc = stream->ctx->dc;
+
+	if (DC_OK != enable_link(stream)) {
+			BREAK_TO_DEBUGGER();
+			return;
+	}
+
+	dc->hwss.enable_stream(stream);
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+		allocate_mst_payload(stream);
+}
+
+void core_link_disable_stream(
+		struct core_link *link,
+		struct core_stream *stream)
+{
+	struct dc *dc = stream->ctx->dc;
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+		deallocate_mst_payload(stream);
+
+	dc->hwss.disable_stream(stream);
+
+	disable_link(stream);
+
+}
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
new file mode 100644
index 000000000000..62b8c264a593
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
@@ -0,0 +1,1151 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/adapter_service_interface.h"
+#include "include/ddc_service_types.h"
+#include "include/grph_object_id.h"
+#include "include/dpcd_defs.h"
+#include "include/logger_interface.h"
+#include "include/vector.h"
+
+#include "dc_link_ddc.h"
+
+#define AUX_POWER_UP_WA_DELAY 500
+#define I2C_OVER_AUX_DEFER_WA_DELAY 70
+
+/* CV smart dongle slave address for retrieving supported HDTV modes*/
+#define CV_SMART_DONGLE_ADDRESS 0x20
+/* DVI-HDMI dongle slave address for retrieving dongle signature*/
+#define DVI_HDMI_DONGLE_ADDRESS 0x68
+static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G";
+struct dvi_hdmi_dongle_signature_data {
+	int8_t vendor[3];/* "AMD" */
+	uint8_t version[2];
+	uint8_t size;
+	int8_t id[11];/* "6140063500G"*/
+};
+/* DP-HDMI dongle slave address for retrieving dongle signature*/
+#define DP_HDMI_DONGLE_ADDRESS 0x40
+static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
+#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04
+
+struct dp_hdmi_dongle_signature_data {
+	int8_t id[15];/* "DP-HDMI ADAPTOR"*/
+	uint8_t eot;/* end of transmition '\x4' */
+};
+
+/* Address range from 0x00 to 0x1F.*/
+#define DP_ADAPTOR_TYPE2_SIZE 0x20
+#define DP_ADAPTOR_TYPE2_REG_ID 0x10
+#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D
+/* Identifies adaptor as Dual-mode adaptor */
+#define DP_ADAPTOR_TYPE2_ID 0xA0
+/* MHz*/
+#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600
+/* MHz*/
+#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25
+/* kHZ*/
+#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000
+/* kHZ*/
+#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000
+
+#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW
+
+enum edid_read_result {
+	EDID_READ_RESULT_EDID_MATCH = 0,
+	EDID_READ_RESULT_EDID_MISMATCH,
+	EDID_READ_RESULT_CHECKSUM_READ_ERR,
+	EDID_READ_RESULT_VENDOR_READ_ERR
+};
+
+/* SCDC Address defines (HDMI 2.0)*/
+#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3
+#define HDMI_SCDC_ADDRESS  0x54
+#define HDMI_SCDC_SINK_VERSION 0x01
+#define HDMI_SCDC_SOURCE_VERSION 0x02
+#define HDMI_SCDC_UPDATE_0 0x10
+#define HDMI_SCDC_TMDS_CONFIG 0x20
+#define HDMI_SCDC_SCRAMBLER_STATUS 0x21
+#define HDMI_SCDC_CONFIG_0 0x30
+#define HDMI_SCDC_STATUS_FLAGS 0x40
+#define HDMI_SCDC_ERR_DETECT 0x50
+#define HDMI_SCDC_TEST_CONFIG 0xC0
+
+
+union hdmi_scdc_update_read_data {
+	uint8_t byte[2];
+	struct {
+		uint8_t STATUS_UPDATE:1;
+		uint8_t CED_UPDATE:1;
+		uint8_t RR_TEST:1;
+		uint8_t RESERVED:5;
+		uint8_t RESERVED2:8;
+	} fields;
+};
+
+union hdmi_scdc_status_flags_data {
+	uint8_t byte[2];
+	struct {
+		uint8_t CLOCK_DETECTED:1;
+		uint8_t CH0_LOCKED:1;
+		uint8_t CH1_LOCKED:1;
+		uint8_t CH2_LOCKED:1;
+		uint8_t RESERVED:4;
+		uint8_t RESERVED2:8;
+	} fields;
+};
+
+union hdmi_scdc_ced_data {
+	uint8_t byte[7];
+	struct {
+		uint8_t CH0_8LOW:8;
+		uint8_t CH0_7HIGH:7;
+		uint8_t CH0_VALID:1;
+		uint8_t CH1_8LOW:8;
+		uint8_t CH1_7HIGH:7;
+		uint8_t CH1_VALID:1;
+		uint8_t CH2_8LOW:8;
+		uint8_t CH2_7HIGH:7;
+		uint8_t CH2_VALID:1;
+		uint8_t CHECKSUM:8;
+	} fields;
+};
+
+union hdmi_scdc_test_config_Data {
+	uint8_t byte;
+	struct {
+		uint8_t TEST_READ_REQUEST_DELAY:7;
+		uint8_t TEST_READ_REQUEST: 1;
+	} fields;
+};
+
+
+
+union ddc_wa {
+	struct {
+		uint32_t DP_SKIP_POWER_OFF:1;
+		uint32_t DP_AUX_POWER_UP_WA_DELAY:1;
+	} bits;
+	uint32_t raw;
+};
+
+struct ddc_flags {
+	uint8_t EDID_QUERY_DONE_ONCE:1;
+	uint8_t IS_INTERNAL_DISPLAY:1;
+	uint8_t FORCE_READ_REPEATED_START:1;
+	uint8_t EDID_STRESS_READ:1;
+
+};
+
+struct ddc_service {
+	struct ddc *ddc_pin;
+	struct ddc_flags flags;
+	union ddc_wa wa;
+	enum ddc_transaction_type transaction_type;
+	enum display_dongle_type dongle_type;
+	struct dp_receiver_id_info dp_receiver_id_info;
+	struct adapter_service *as;
+	struct dc_context *ctx;
+
+	uint32_t address;
+	uint32_t edid_buf_len;
+	uint8_t edid_buf[MAX_EDID_BUFFER_SIZE];
+};
+
+struct i2c_payloads {
+	struct vector payloads;
+};
+
+struct aux_payloads {
+	struct vector payloads;
+};
+
+struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count)
+{
+	struct i2c_payloads *payloads;
+
+	payloads = dm_alloc(ctx, sizeof(struct i2c_payloads));
+
+	if (!payloads)
+		return NULL;
+
+	if (dal_vector_construct(
+		&payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
+		return payloads;
+
+	dm_free(ctx, payloads);
+	return NULL;
+
+}
+
+struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
+{
+	return (struct i2c_payload *)p->payloads.container;
+}
+
+uint32_t  dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
+{
+	return p->payloads.count;
+}
+
+void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p)
+{
+	if (!p || !*p)
+		return;
+	dal_vector_destruct(&(*p)->payloads);
+	dm_free((*p)->payloads.ctx, *p);
+	*p = NULL;
+
+}
+
+struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count)
+{
+	struct aux_payloads *payloads;
+
+	payloads = dm_alloc(ctx, sizeof(struct aux_payloads));
+
+	if (!payloads)
+		return NULL;
+
+	if (dal_vector_construct(
+		&payloads->payloads, ctx, count, sizeof(struct aux_payloads)))
+		return payloads;
+
+	dm_free(ctx, payloads);
+	return NULL;
+}
+
+struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p)
+{
+	return (struct aux_payload *)p->payloads.container;
+}
+
+uint32_t  dal_ddc_aux_payloads_get_count(struct aux_payloads *p)
+{
+	return p->payloads.count;
+}
+
+
+void dal_ddc_aux_payloads_destroy(struct aux_payloads **p)
+{
+	if (!p || !*p)
+		return;
+
+	dal_vector_destruct(&(*p)->payloads);
+	dm_free((*p)->payloads.ctx, *p);
+	*p = NULL;
+}
+
+#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+void dal_ddc_i2c_payloads_add(
+	struct i2c_payloads *payloads,
+	uint32_t address,
+	uint32_t len,
+	uint8_t *data,
+	bool write)
+{
+	uint32_t payload_size = EDID_SEGMENT_SIZE;
+	uint32_t pos;
+
+	for (pos = 0; pos < len; pos += payload_size) {
+		struct i2c_payload payload = {
+			.write = write,
+			.address = address,
+			.length = DDC_MIN(payload_size, len - pos),
+			.data = data + pos };
+		dal_vector_append(&payloads->payloads, &payload);
+	}
+
+}
+
+void dal_ddc_aux_payloads_add(
+	struct aux_payloads *payloads,
+	uint32_t address,
+	uint32_t len,
+	uint8_t *data,
+	bool write)
+{
+	uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE;
+	uint32_t pos;
+
+	for (pos = 0; pos < len; pos += payload_size) {
+		struct aux_payload payload = {
+			.i2c_over_aux = true,
+			.write = write,
+			.address = address,
+			.length = DDC_MIN(payload_size, len - pos),
+			.data = data + pos };
+		dal_vector_append(&payloads->payloads, &payload);
+	}
+}
+
+
+static bool construct(
+	struct ddc_service *ddc_service,
+	struct ddc_service_init_data *init_data)
+{
+	enum connector_id connector_id =
+		dal_graphics_object_id_get_connector_id(init_data->id);
+
+	ddc_service->ctx = init_data->ctx;
+	ddc_service->as = init_data->as;
+	ddc_service->ddc_pin = dal_adapter_service_obtain_ddc(
+			init_data->as, init_data->id);
+
+	ddc_service->flags.EDID_QUERY_DONE_ONCE = false;
+
+	ddc_service->flags.FORCE_READ_REPEATED_START =
+		dal_adapter_service_is_feature_supported(
+			FEATURE_DDC_READ_FORCE_REPEATED_START);
+
+	ddc_service->flags.EDID_STRESS_READ =
+			dal_adapter_service_is_feature_supported(
+				FEATURE_EDID_STRESS_READ);
+
+
+	ddc_service->flags.IS_INTERNAL_DISPLAY =
+		connector_id == CONNECTOR_ID_EDP ||
+		connector_id == CONNECTOR_ID_LVDS;
+
+	ddc_service->wa.raw = 0;
+	return true;
+}
+
+struct ddc_service *dal_ddc_service_create(
+	struct ddc_service_init_data *init_data)
+{
+	struct ddc_service *ddc_service;
+
+	ddc_service = dm_alloc(init_data->ctx, sizeof(struct ddc_service));
+
+	if (!ddc_service)
+		return NULL;
+
+	if (construct(ddc_service, init_data))
+		return ddc_service;
+
+	dm_free(init_data->ctx, ddc_service);
+	return NULL;
+}
+
+static void destruct(struct ddc_service *ddc)
+{
+	if (ddc->ddc_pin)
+		dal_adapter_service_release_ddc(ddc->as, ddc->ddc_pin);
+}
+
+void dal_ddc_service_destroy(struct ddc_service **ddc)
+{
+	if (!ddc || !*ddc) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+	destruct(*ddc);
+	dm_free((*ddc)->ctx, *ddc);
+	*ddc = NULL;
+}
+
+enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc)
+{
+	return DDC_SERVICE_TYPE_CONNECTOR;
+}
+
+void dal_ddc_service_set_transaction_type(
+	struct ddc_service *ddc,
+	enum ddc_transaction_type type)
+{
+	ddc->transaction_type = type;
+}
+
+bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc)
+{
+	switch (ddc->transaction_type) {
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+void ddc_service_set_dongle_type(struct ddc_service *ddc,
+		enum display_dongle_type dongle_type)
+{
+	ddc->dongle_type = dongle_type;
+}
+
+static uint32_t defer_delay_converter_wa(
+	struct ddc_service *ddc,
+	uint32_t defer_delay)
+{
+	struct dp_receiver_id_info dp_rec_info = {0};
+
+	if (dal_ddc_service_get_dp_receiver_id_info(ddc, &dp_rec_info) &&
+		(dp_rec_info.branch_id == DP_BRANCH_DEVICE_ID_4) &&
+		!dm_strncmp(dp_rec_info.branch_name,
+			DP_DVI_CONVERTER_ID_4,
+			sizeof(dp_rec_info.branch_name)))
+		return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ?
+			defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY;
+
+	return defer_delay;
+
+}
+
+#define DP_TRANSLATOR_DELAY 5
+
+static uint32_t get_defer_delay(struct ddc_service *ddc)
+{
+	uint32_t defer_delay = 0;
+
+	switch (ddc->transaction_type) {
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
+		if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) ||
+			(DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) ||
+			(DISPLAY_DONGLE_DP_HDMI_CONVERTER ==
+				ddc->dongle_type)) {
+
+			defer_delay = DP_TRANSLATOR_DELAY;
+
+			defer_delay =
+				defer_delay_converter_wa(ddc, defer_delay);
+
+		} else /*sink has a delay different from an Active Converter*/
+			defer_delay = 0;
+		break;
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
+		defer_delay = DP_TRANSLATOR_DELAY;
+		break;
+	default:
+		break;
+	}
+	return defer_delay;
+}
+
+static bool i2c_read(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t *buffer,
+	uint32_t len)
+{
+	uint8_t offs_data = 0;
+	struct i2c_payload payloads[2] = {
+		{
+		.write = true,
+		.address = address,
+		.length = 1,
+		.data = &offs_data },
+		{
+		.write = false,
+		.address = address,
+		.length = len,
+		.data = buffer } };
+
+	struct i2c_command command = {
+		.payloads = payloads,
+		.number_of_payloads = 2,
+		.engine = DDC_I2C_COMMAND_ENGINE,
+		.speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) };
+
+	return dal_i2caux_submit_i2c_command(
+		dal_adapter_service_get_i2caux(ddc->as),
+		ddc->ddc_pin,
+		&command);
+}
+
+static uint8_t aux_read_edid_block(
+	struct ddc_service *ddc,
+	uint8_t address,
+	uint8_t index,
+	uint8_t *buf)
+{
+	struct aux_command cmd = {
+		.payloads = NULL,
+		.number_of_payloads = 0,
+		.defer_delay = get_defer_delay(ddc),
+		.max_defer_write_retry = 0 };
+
+	uint8_t retrieved = 0;
+	uint8_t base_offset =
+		(index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE;
+	uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT;
+
+	for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE;
+		retrieved += DEFAULT_AUX_MAX_DATA_SIZE) {
+
+		uint8_t offset = base_offset + retrieved;
+
+		struct aux_payload payloads[3] = {
+			{
+			.i2c_over_aux = true,
+			.write = true,
+			.address = DDC_EDID_SEGMENT_ADDRESS,
+			.length = 1,
+			.data = &segment },
+			{
+			.i2c_over_aux = true,
+			.write = true,
+			.address = address,
+			.length = 1,
+			.data = &offset },
+			{
+			.i2c_over_aux = true,
+			.write = false,
+			.address = address,
+			.length = DEFAULT_AUX_MAX_DATA_SIZE,
+			.data = &buf[retrieved] } };
+
+		if (segment == 0) {
+			cmd.payloads = &payloads[1];
+			cmd.number_of_payloads = 2;
+		} else {
+			cmd.payloads = payloads;
+			cmd.number_of_payloads = 3;
+		}
+
+		if (!dal_i2caux_submit_aux_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd))
+			/* cannot read, break*/
+			break;
+	}
+
+	/* Reset segment to 0. Needed by some panels */
+	if (0 != segment) {
+		struct aux_payload payloads[1] = { {
+			.i2c_over_aux = true,
+			.write = true,
+			.address = DDC_EDID_SEGMENT_ADDRESS,
+			.length = 1,
+			.data = &segment } };
+		bool result = false;
+
+		segment = 0;
+
+		cmd.number_of_payloads = ARRAY_SIZE(payloads);
+		cmd.payloads = payloads;
+
+		result = dal_i2caux_submit_aux_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd);
+
+		if (false == result)
+			dal_logger_write(
+				ddc->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE,
+				"%s: Writing of EDID Segment (0x30) failed!\n",
+				__func__);
+	}
+
+	return retrieved;
+}
+
+static uint8_t i2c_read_edid_block(
+	struct ddc_service *ddc,
+	uint8_t address,
+	uint8_t index,
+	uint8_t *buf)
+{
+	bool ret = false;
+	uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) *
+		DDC_EDID_BLOCK_SIZE;
+	uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT;
+
+	struct i2c_command cmd = {
+		.payloads = NULL,
+		.number_of_payloads = 0,
+		.engine = DDC_I2C_COMMAND_ENGINE,
+		.speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) };
+
+	struct i2c_payload payloads[3] = {
+		{
+		.write = true,
+		.address = DDC_EDID_SEGMENT_ADDRESS,
+		.length = 1,
+		.data = &segment },
+		{
+		.write = true,
+		.address = address,
+		.length = 1,
+		.data = &offset },
+		{
+		.write = false,
+		.address = address,
+		.length = DDC_EDID_BLOCK_SIZE,
+		.data = buf } };
+/*
+ * Some I2C engines don't handle stop/start between write-offset and read-data
+ * commands properly. For those displays, we have to force the newer E-DDC
+ * behavior of repeated-start which can be enabled by runtime parameter. */
+/* Originally implemented for OnLive using NXP receiver chip */
+
+	if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) {
+		/* base block, use use DDC2B, submit as 2 commands */
+		cmd.payloads = &payloads[1];
+		cmd.number_of_payloads = 1;
+
+		if (dal_i2caux_submit_i2c_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd)) {
+
+			cmd.payloads = &payloads[2];
+			cmd.number_of_payloads = 1;
+
+			ret = dal_i2caux_submit_i2c_command(
+				dal_adapter_service_get_i2caux(ddc->as),
+				ddc->ddc_pin,
+				&cmd);
+		}
+
+	} else {
+		/*
+		 * extension block use E-DDC, submit as 1 command
+		 * or if repeated-start is forced by runtime parameter
+		 */
+		if (segment != 0) {
+			/* include segment offset in command*/
+			cmd.payloads = payloads;
+			cmd.number_of_payloads = 3;
+		} else {
+			/* we are reading first segment,
+			 * segment offset is not required */
+			cmd.payloads = &payloads[1];
+			cmd.number_of_payloads = 2;
+		}
+
+		ret = dal_i2caux_submit_i2c_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd);
+	}
+
+	return ret ? DDC_EDID_BLOCK_SIZE : 0;
+}
+
+static uint32_t query_edid_block(
+	struct ddc_service *ddc,
+	uint8_t address,
+	uint8_t index,
+	uint8_t *buf,
+	uint32_t size)
+{
+	uint32_t size_retrieved = 0;
+
+	if (size < DDC_EDID_BLOCK_SIZE)
+		return 0;
+
+	if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
+
+		ASSERT(index < 2);
+		size_retrieved =
+			aux_read_edid_block(ddc, address, index, buf);
+	} else {
+		size_retrieved =
+			i2c_read_edid_block(ddc, address, index, buf);
+	}
+
+	return size_retrieved;
+}
+
+#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261
+#define DDC_TEST_ACK_ADDRESS 0x260
+#define DDC_DPCD_EDID_TEST_ACK 0x04
+#define DDC_DPCD_EDID_TEST_MASK 0x04
+#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218
+
+/* AG TODO GO throug DM callback here like for DPCD */
+
+static void write_dp_edid_checksum(
+	struct ddc_service *ddc,
+	uint8_t checksum)
+{
+	uint8_t dpcd_data;
+
+	dal_ddc_service_read_dpcd_data(
+		ddc,
+		DDC_DPCD_TEST_REQUEST_ADDRESS,
+		&dpcd_data,
+		1);
+
+	if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) {
+
+		dal_ddc_service_write_dpcd_data(
+			ddc,
+			DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS,
+			&checksum,
+			1);
+
+		dpcd_data = DDC_DPCD_EDID_TEST_ACK;
+
+		dal_ddc_service_write_dpcd_data(
+			ddc,
+			DDC_TEST_ACK_ADDRESS,
+			&dpcd_data,
+			1);
+	}
+}
+
+uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc)
+{
+	uint32_t bytes_read = 0;
+	uint32_t ext_cnt = 0;
+
+	uint8_t address;
+	uint32_t i;
+
+	for (address = DDC_EDID_ADDRESS_START;
+		address <= DDC_EDID_ADDRESS_END; ++address) {
+
+		bytes_read = query_edid_block(
+			ddc,
+			address,
+			0,
+			ddc->edid_buf,
+			sizeof(ddc->edid_buf) - bytes_read);
+
+		if (bytes_read != DDC_EDID_BLOCK_SIZE)
+			continue;
+
+		/* get the number of ext blocks*/
+		ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET];
+
+		/* EDID 2.0, need to read 1 more block because EDID2.0 is
+		 * 256 byte in size*/
+		if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] ==
+			DDC_EDID_20_SIGNATURE)
+				ext_cnt = 1;
+
+		for (i = 0; i < ext_cnt; i++) {
+			/* read additional ext blocks accordingly */
+			bytes_read += query_edid_block(
+					ddc,
+					address,
+					i+1,
+					&ddc->edid_buf[bytes_read],
+					sizeof(ddc->edid_buf) - bytes_read);
+		}
+
+		/*this is special code path for DP compliance*/
+		if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type)
+			write_dp_edid_checksum(
+				ddc,
+				ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) +
+				DDC_EDID1X_CHECKSUM_OFFSET]);
+
+		/*remembers the address where we fetch the EDID from
+		 * for later signature check use */
+		ddc->address = address;
+
+		break;/* already read edid, done*/
+	}
+
+	ddc->edid_buf_len = bytes_read;
+	return bytes_read;
+}
+
+uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc)
+{
+	return ddc->edid_buf_len;
+}
+
+void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf)
+{
+	dm_memmove(edid_buf,
+			ddc->edid_buf, ddc->edid_buf_len);
+}
+
+void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
+	struct ddc_service *ddc,
+	struct display_sink_capability *sink_cap)
+{
+	uint8_t i;
+	bool is_valid_hdmi_signature;
+	enum display_dongle_type *dongle = &sink_cap->dongle_type;
+	uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE];
+	bool is_type2_dongle = false;
+	struct dp_hdmi_dongle_signature_data *dongle_signature;
+
+	/* Assume we have no valid DP passive dongle connected */
+	*dongle = DISPLAY_DONGLE_NONE;
+	sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
+
+	/* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
+	if (!i2c_read(
+		ddc,
+		DP_HDMI_DONGLE_ADDRESS,
+		type2_dongle_buf,
+		sizeof(type2_dongle_buf))) {
+		dal_logger_write(ddc->ctx->logger,
+			LOG_MAJOR_DCS,
+			LOG_MINOR_DCS_DONGLE_DETECTION,
+			"Detected DP-DVI dongle.\n");
+		*dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
+		sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
+		return;
+	}
+
+	/* Check if Type 2 dongle.*/
+	if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID)
+		is_type2_dongle = true;
+
+	dongle_signature =
+		(struct dp_hdmi_dongle_signature_data *)type2_dongle_buf;
+
+	is_valid_hdmi_signature = true;
+
+	/* Check EOT */
+	if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) {
+		is_valid_hdmi_signature = false;
+	}
+
+	/* Check signature */
+	for (i = 0; i < sizeof(dongle_signature->id); ++i) {
+		/* If its not the right signature,
+		 * skip mismatch in subversion byte.*/
+		if (dongle_signature->id[i] !=
+			dp_hdmi_dongle_signature_str[i] && i != 3) {
+
+			if (is_type2_dongle) {
+				is_valid_hdmi_signature = false;
+				break;
+			}
+
+		}
+	}
+
+	if (is_type2_dongle) {
+		uint32_t max_tmds_clk =
+			type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK];
+
+		max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2;
+
+		if (0 == max_tmds_clk ||
+				max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK ||
+				max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) {
+			dal_logger_write(ddc->ctx->logger,
+				LOG_MAJOR_DCS,
+				LOG_MINOR_DCS_DONGLE_DETECTION,
+				"Invalid Maximum TMDS clock");
+			*dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
+		} else {
+			if (is_valid_hdmi_signature == true) {
+				*dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
+				dal_logger_write(ddc->ctx->logger,
+					LOG_MAJOR_DCS,
+					LOG_MINOR_DCS_DONGLE_DETECTION,
+					"Detected Type 2 DP-HDMI Maximum TMDS "
+					"clock, max TMDS clock: %d MHz",
+					max_tmds_clk);
+			} else {
+				*dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
+				dal_logger_write(ddc->ctx->logger,
+					LOG_MAJOR_DCS,
+					LOG_MINOR_DCS_DONGLE_DETECTION,
+					"Detected Type 2 DP-HDMI (no valid HDMI"
+					" signature) Maximum TMDS clock, max "
+					"TMDS clock: %d MHz",
+					max_tmds_clk);
+			}
+
+			/* Multiply by 1000 to convert to kHz. */
+			sink_cap->max_hdmi_pixel_clock =
+				max_tmds_clk * 1000;
+		}
+
+	} else {
+		if (is_valid_hdmi_signature == true) {
+			dal_logger_write(ddc->ctx->logger,
+				LOG_MAJOR_DCS,
+				LOG_MINOR_DCS_DONGLE_DETECTION,
+				"Detected Type 1 DP-HDMI dongle.\n");
+			*dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
+		} else {
+			dal_logger_write(ddc->ctx->logger,
+				LOG_MAJOR_DCS,
+				LOG_MINOR_DCS_DONGLE_DETECTION,
+				"Detected Type 1 DP-HDMI dongle (no valid HDMI "
+				"signature).\n");
+
+			*dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
+		}
+	}
+
+	return;
+}
+
+enum {
+	DP_SINK_CAP_SIZE =
+		DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1
+};
+
+bool dal_ddc_service_query_ddc_data(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t *write_buf,
+	uint32_t write_size,
+	uint8_t *read_buf,
+	uint32_t read_size)
+{
+	bool ret;
+	uint32_t payload_size =
+		dal_ddc_service_is_in_aux_transaction_mode(ddc) ?
+			DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE;
+
+	uint32_t write_payloads =
+		(write_size + payload_size - 1) / payload_size;
+
+	uint32_t read_payloads =
+		(read_size + payload_size - 1) / payload_size;
+
+	uint32_t payloads_num = write_payloads + read_payloads;
+
+	if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE)
+		return false;
+
+	/*TODO: len of payload data for i2c and aux is uint8!!!!,
+	 *  but we want to read 256 over i2c!!!!*/
+	if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
+
+		struct aux_payloads *payloads =
+			dal_ddc_aux_payloads_create(ddc->ctx, payloads_num);
+
+		struct aux_command command = {
+			.payloads = dal_ddc_aux_payloads_get(payloads),
+			.number_of_payloads = 0,
+			.defer_delay = get_defer_delay(ddc),
+			.max_defer_write_retry = 0 };
+
+		dal_ddc_aux_payloads_add(
+			payloads, address, write_size, write_buf, true);
+
+		dal_ddc_aux_payloads_add(
+			payloads, address, read_size, read_buf, false);
+
+		command.number_of_payloads =
+			dal_ddc_aux_payloads_get_count(payloads);
+
+		ret = dal_i2caux_submit_aux_command(
+				dal_adapter_service_get_i2caux(ddc->as),
+				ddc->ddc_pin,
+				&command);
+
+		dal_ddc_aux_payloads_destroy(&payloads);
+
+	} else {
+		struct i2c_payloads *payloads =
+			dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
+
+		struct i2c_command command = {
+			.payloads = dal_ddc_i2c_payloads_get(payloads),
+			.number_of_payloads = 0,
+			.engine = DDC_I2C_COMMAND_ENGINE,
+			.speed =
+				dal_adapter_service_get_sw_i2c_speed(ddc->as) };
+
+		dal_ddc_i2c_payloads_add(
+			payloads, address, write_size, write_buf, true);
+
+		dal_ddc_i2c_payloads_add(
+			payloads, address, read_size, read_buf, false);
+
+		command.number_of_payloads =
+			dal_ddc_i2c_payloads_get_count(payloads);
+
+		ret = dal_i2caux_submit_i2c_command(
+				dal_adapter_service_get_i2caux(ddc->as),
+				ddc->ddc_pin,
+				&command);
+
+		dal_ddc_i2c_payloads_destroy(&payloads);
+	}
+
+	return ret;
+}
+
+bool dal_ddc_service_get_dp_receiver_id_info(
+	struct ddc_service *ddc,
+	struct dp_receiver_id_info *info)
+{
+	if (!info)
+		return false;
+
+	*info = ddc->dp_receiver_id_info;
+	return true;
+}
+
+enum ddc_result dal_ddc_service_read_dpcd_data(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t len)
+{
+	struct aux_payload read_payload = {
+		.i2c_over_aux = false,
+		.write = false,
+		.address = address,
+		.length = len,
+		.data = data,
+	};
+	struct aux_command command = {
+		.payloads = &read_payload,
+		.number_of_payloads = 1,
+		.defer_delay = 0,
+		.max_defer_write_retry = 0,
+	};
+
+	if (len > DEFAULT_AUX_MAX_DATA_SIZE) {
+		BREAK_TO_DEBUGGER();
+		return DDC_RESULT_FAILED_INVALID_OPERATION;
+	}
+
+	if (dal_i2caux_submit_aux_command(
+		dal_adapter_service_get_i2caux(ddc->as),
+		ddc->ddc_pin,
+		&command))
+		return DDC_RESULT_SUCESSFULL;
+
+	return DDC_RESULT_FAILED_OPERATION;
+}
+
+enum ddc_result dal_ddc_service_write_dpcd_data(
+	struct ddc_service *ddc,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t len)
+{
+	struct aux_payload write_payload = {
+		.i2c_over_aux = false,
+		.write = true,
+		.address = address,
+		.length = len,
+		.data = (uint8_t *)data,
+	};
+	struct aux_command command = {
+		.payloads = &write_payload,
+		.number_of_payloads = 1,
+		.defer_delay = 0,
+		.max_defer_write_retry = 0,
+	};
+
+	if (len > DEFAULT_AUX_MAX_DATA_SIZE) {
+		BREAK_TO_DEBUGGER();
+		return DDC_RESULT_FAILED_INVALID_OPERATION;
+	}
+
+	if (dal_i2caux_submit_aux_command(
+		dal_adapter_service_get_i2caux(ddc->as),
+		ddc->ddc_pin,
+		&command))
+		return DDC_RESULT_SUCESSFULL;
+
+	return DDC_RESULT_FAILED_OPERATION;
+}
+
+/*test only function*/
+void dal_ddc_service_set_ddc_pin(
+	struct ddc_service *ddc_service,
+	struct ddc *ddc)
+{
+	ddc_service->ddc_pin = ddc;
+}
+
+struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service)
+{
+	return ddc_service->ddc_pin;
+}
+
+
+void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service)
+{
+	dm_memset(&ddc_service->dp_receiver_id_info,
+		0, sizeof(struct dp_receiver_id_info));
+}
+
+void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service,
+		uint32_t pix_clk,
+		bool lte_340_scramble)
+{
+	bool over_340_mhz = pix_clk > 340000 ? 1 : 0;
+	uint8_t slave_address = HDMI_SCDC_ADDRESS;
+	uint8_t offset = HDMI_SCDC_SINK_VERSION;
+	uint8_t sink_version = 0;
+	uint8_t write_buffer[2] = {0};
+	/*Lower than 340 Scramble bit from SCDC caps*/
+
+	dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
+			sizeof(offset), &sink_version, sizeof(sink_version));
+	if (sink_version == 1) {
+		/*Source Version = 1*/
+		write_buffer[0] = HDMI_SCDC_SOURCE_VERSION;
+		write_buffer[1] = 1;
+		dal_ddc_service_query_ddc_data(ddc_service, slave_address,
+				write_buffer, sizeof(write_buffer), NULL, 0);
+		/*Read Request from SCDC caps*/
+	}
+	write_buffer[0] = HDMI_SCDC_TMDS_CONFIG;
+
+	if (over_340_mhz) {
+		write_buffer[1] = 3;
+	} else if (lte_340_scramble) {
+		write_buffer[1] = 1;
+	} else {
+		write_buffer[1] = 0;
+	}
+	dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer,
+			sizeof(write_buffer), NULL, 0);
+}
+
+void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service)
+{
+	uint8_t slave_address = HDMI_SCDC_ADDRESS;
+	uint8_t offset = HDMI_SCDC_TMDS_CONFIG;
+	uint8_t tmds_config = 0;
+
+	dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
+			sizeof(offset), &tmds_config, sizeof(tmds_config));
+	if (tmds_config & 0x1) {
+		union hdmi_scdc_status_flags_data status_data = { {0} };
+		uint8_t scramble_status = 0;
+
+		offset = HDMI_SCDC_SCRAMBLER_STATUS;
+		dal_ddc_service_query_ddc_data(ddc_service, slave_address,
+				&offset, sizeof(offset), &scramble_status,
+				sizeof(scramble_status));
+		offset = HDMI_SCDC_STATUS_FLAGS;
+		dal_ddc_service_query_ddc_data(ddc_service, slave_address,
+				&offset, sizeof(offset), status_data.byte,
+				sizeof(status_data.byte));
+	}
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
new file mode 100644
index 000000000000..742ab756cb48
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
@@ -0,0 +1,1728 @@
+/* Copyright 2015 Advanced Micro Devices, Inc. */
+#include "dm_services.h"
+#include "dc.h"
+#include "dc_link_dp.h"
+#include "dm_helpers.h"
+
+#include "inc/core_types.h"
+#include "link_hwss.h"
+#include "dc_link_ddc.h"
+#include "core_status.h"
+#include "dpcd_defs.h"
+
+/* maximum pre emphasis level allowed for each voltage swing level*/
+static const enum pre_emphasis voltage_swing_to_pre_emphasis[] = {
+		PRE_EMPHASIS_LEVEL3,
+		PRE_EMPHASIS_LEVEL2,
+		PRE_EMPHASIS_LEVEL1,
+		PRE_EMPHASIS_DISABLED };
+
+enum {
+	POST_LT_ADJ_REQ_LIMIT = 6,
+	POST_LT_ADJ_REQ_TIMEOUT = 200
+};
+
+enum {
+	LINK_TRAINING_MAX_RETRY_COUNT = 5,
+	/* to avoid infinite loop where-in the receiver
+	 * switches between different VS
+	 */
+	LINK_TRAINING_MAX_CR_RETRY = 100
+};
+
+static const struct link_settings link_training_fallback_table[] = {
+/* 2160 Mbytes/sec*/
+{ LANE_COUNT_FOUR, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED },
+/* 1080 Mbytes/sec*/
+{ LANE_COUNT_FOUR, LINK_RATE_HIGH, LINK_SPREAD_DISABLED },
+/* 648 Mbytes/sec*/
+{ LANE_COUNT_FOUR, LINK_RATE_LOW, LINK_SPREAD_DISABLED },
+/* 1080 Mbytes/sec*/
+{ LANE_COUNT_TWO, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED },
+/* 540 Mbytes/sec*/
+{ LANE_COUNT_TWO, LINK_RATE_HIGH, LINK_SPREAD_DISABLED },
+/* 324 Mbytes/sec*/
+{ LANE_COUNT_TWO, LINK_RATE_LOW, LINK_SPREAD_DISABLED },
+/* 540 Mbytes/sec*/
+{ LANE_COUNT_ONE, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED },
+/* 270 Mbytes/sec*/
+{ LANE_COUNT_ONE, LINK_RATE_HIGH, LINK_SPREAD_DISABLED },
+/* 162 Mbytes/sec*/
+{ LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED } };
+
+static void wait_for_training_aux_rd_interval(
+	struct core_link* link,
+	uint32_t default_wait_in_micro_secs)
+{
+	uint8_t training_rd_interval;
+
+	/* overwrite the delay if rev > 1.1*/
+	if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
+		/* DP 1.2 or later - retrieve delay through
+		 * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */
+		core_link_read_dpcd(
+			link,
+			DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL,
+			&training_rd_interval,
+			sizeof(training_rd_interval));
+		default_wait_in_micro_secs = training_rd_interval ?
+			(training_rd_interval * 4000) :
+			default_wait_in_micro_secs;
+	}
+
+	dm_delay_in_microseconds(link->ctx, default_wait_in_micro_secs);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n wait = %d\n",
+		__func__,
+		default_wait_in_micro_secs);
+}
+
+static void dpcd_set_training_pattern(
+	struct core_link* link,
+	union dpcd_training_pattern dpcd_pattern)
+{
+	core_link_write_dpcd(
+		link,
+		DPCD_ADDRESS_TRAINING_PATTERN_SET,
+		&dpcd_pattern.raw,
+		1);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x pattern = %x\n",
+		__func__,
+		DPCD_ADDRESS_TRAINING_PATTERN_SET,
+		dpcd_pattern.bits.TRAINING_PATTERN_SET);
+}
+
+static void dpcd_set_link_settings(
+	struct core_link* link,
+	const struct link_training_settings *lt_settings)
+{
+	uint8_t rate = (uint8_t)
+	(lt_settings->link_settings.link_rate);
+
+	union down_spread_ctrl downspread = {{0}};
+	union lane_count_set lane_count_set = {{0}};
+	uint8_t link_set_buffer[2];
+
+
+	downspread.raw = (uint8_t)
+	(lt_settings->link_settings.link_spread);
+
+	lane_count_set.bits.LANE_COUNT_SET =
+	lt_settings->link_settings.lane_count;
+
+	lane_count_set.bits.ENHANCED_FRAMING = 1;
+
+	lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
+		link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
+
+	link_set_buffer[0] = rate;
+	link_set_buffer[1] = lane_count_set.raw;
+
+	core_link_write_dpcd(link, DPCD_ADDRESS_LINK_BW_SET,
+	link_set_buffer, 2);
+	core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL,
+	&downspread.raw, sizeof(downspread));
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
+		__func__,
+		DPCD_ADDRESS_LINK_BW_SET,
+		lt_settings->link_settings.link_rate,
+		DPCD_ADDRESS_LANE_COUNT_SET,
+		lt_settings->link_settings.lane_count,
+		DPCD_ADDRESS_DOWNSPREAD_CNTL,
+		lt_settings->link_settings.link_spread);
+
+}
+
+static enum dpcd_training_patterns
+	hw_training_pattern_to_dpcd_training_pattern(
+	struct core_link* link,
+	enum hw_dp_training_pattern pattern)
+{
+	enum dpcd_training_patterns dpcd_tr_pattern =
+	DPCD_TRAINING_PATTERN_VIDEOIDLE;
+
+	switch (pattern) {
+	case HW_DP_TRAINING_PATTERN_1:
+		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
+		break;
+	case HW_DP_TRAINING_PATTERN_2:
+		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
+		break;
+	case HW_DP_TRAINING_PATTERN_3:
+		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
+		break;
+	default:
+		ASSERT(0);
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_LINK_TRAINING,
+			"%s: Invalid HW Training pattern: %d\n",
+			__func__, pattern);
+		break;
+	}
+
+	return dpcd_tr_pattern;
+
+}
+
+static void dpcd_set_lt_pattern_and_lane_settings(
+	struct core_link* link,
+	const struct link_training_settings *lt_settings,
+	enum hw_dp_training_pattern pattern)
+{
+	union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
+	const uint32_t dpcd_base_lt_offset =
+	DPCD_ADDRESS_TRAINING_PATTERN_SET;
+	uint8_t dpcd_lt_buffer[5] = {0};
+	union dpcd_training_pattern dpcd_pattern = {{0}};
+	uint32_t lane;
+	uint32_t size_in_bytes;
+	bool edp_workaround = false; /* TODO link_prop.INTERNAL */
+
+	/*****************************************************************
+	* DpcdAddress_TrainingPatternSet
+	*****************************************************************/
+	dpcd_pattern.bits.TRAINING_PATTERN_SET =
+		hw_training_pattern_to_dpcd_training_pattern(link, pattern);
+
+	dpcd_lt_buffer[DPCD_ADDRESS_TRAINING_PATTERN_SET - dpcd_base_lt_offset]
+		= dpcd_pattern.raw;
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x pattern = %x\n",
+		__func__,
+		DPCD_ADDRESS_TRAINING_PATTERN_SET,
+		dpcd_pattern.bits.TRAINING_PATTERN_SET);
+
+
+	/*****************************************************************
+	* DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set
+	*****************************************************************/
+	for (lane = 0; lane <
+		(uint32_t)(lt_settings->link_settings.lane_count); lane++) {
+
+		dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
+		(uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING);
+		dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
+		(uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS);
+
+		dpcd_lane[lane].bits.MAX_SWING_REACHED =
+		(lt_settings->lane_settings[lane].VOLTAGE_SWING ==
+		VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
+		dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
+		(lt_settings->lane_settings[lane].PRE_EMPHASIS ==
+		PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
+	}
+
+	/* concatinate everything into one buffer*/
+
+	size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
+
+	 // 0x00103 - 0x00102
+	dm_memmove(
+		&dpcd_lt_buffer[DPCD_ADDRESS_LANE0_SET - dpcd_base_lt_offset],
+		dpcd_lane,
+		size_in_bytes);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n %x VS set = %x  PE set = %x \
+		max VS Reached = %x  max PE Reached = %x\n",
+		__func__,
+		DPCD_ADDRESS_LANE0_SET,
+		dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+		dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+		dpcd_lane[0].bits.MAX_SWING_REACHED,
+		dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+
+
+	if (edp_workaround) {
+		/* for eDP write in 2 parts because the 5-byte burst is
+		* causing issues on some eDP panels (EPR#366724)
+		*/
+		core_link_write_dpcd(
+			link,
+			DPCD_ADDRESS_TRAINING_PATTERN_SET,
+			&dpcd_pattern.raw,
+			sizeof(dpcd_pattern.raw) );
+
+		core_link_write_dpcd(
+			link,
+			DPCD_ADDRESS_LANE0_SET,
+			(uint8_t *)(dpcd_lane),
+			size_in_bytes);
+
+		} else
+		/* write it all in (1 + number-of-lanes)-byte burst*/
+			core_link_write_dpcd(
+				link,
+				dpcd_base_lt_offset,
+				dpcd_lt_buffer,
+				size_in_bytes + sizeof(dpcd_pattern.raw) );
+
+	link->ln_setting = lt_settings->lane_settings[0];
+}
+
+static bool is_cr_done(enum lane_count ln_count,
+	union lane_status *dpcd_lane_status)
+{
+	bool done = true;
+	uint32_t lane;
+	/*LANEx_CR_DONE bits All 1's?*/
+	for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
+		if (!dpcd_lane_status[lane].bits.CR_DONE_0)
+			done = false;
+	}
+	return done;
+
+}
+
+static bool is_ch_eq_done(enum lane_count ln_count,
+	union lane_status *dpcd_lane_status,
+	union lane_align_status_updated *lane_status_updated)
+{
+	bool done = true;
+	uint32_t lane;
+	if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE)
+		done = false;
+	else {
+		for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
+			if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 ||
+				!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
+				done = false;
+		}
+	}
+	return done;
+
+}
+
+static void update_drive_settings(
+		struct link_training_settings *dest,
+		struct link_training_settings src)
+{
+	uint32_t lane;
+	for (lane = 0; lane < src.link_settings.lane_count; lane++) {
+		dest->lane_settings[lane].VOLTAGE_SWING =
+			src.lane_settings[lane].VOLTAGE_SWING;
+		dest->lane_settings[lane].PRE_EMPHASIS =
+			src.lane_settings[lane].PRE_EMPHASIS;
+		dest->lane_settings[lane].POST_CURSOR2 =
+			src.lane_settings[lane].POST_CURSOR2;
+	}
+}
+
+static uint8_t get_nibble_at_index(const uint8_t *buf,
+	uint32_t index)
+{
+	uint8_t nibble;
+	nibble = buf[index / 2];
+
+	if (index % 2)
+		nibble >>= 4;
+	else
+		nibble &= 0x0F;
+
+	return nibble;
+}
+
+static enum pre_emphasis get_max_pre_emphasis_for_voltage_swing(
+	enum voltage_swing voltage)
+{
+	enum pre_emphasis pre_emphasis;
+	pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
+
+	if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
+		pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
+
+	return pre_emphasis;
+
+}
+
+static void find_max_drive_settings(
+	const struct link_training_settings *link_training_setting,
+	struct link_training_settings *max_lt_setting)
+{
+	uint32_t lane;
+	struct lane_settings max_requested;
+
+	max_requested.VOLTAGE_SWING =
+		link_training_setting->
+		lane_settings[0].VOLTAGE_SWING;
+	max_requested.PRE_EMPHASIS =
+		link_training_setting->
+		lane_settings[0].PRE_EMPHASIS;
+	/*max_requested.postCursor2 =
+	 * link_training_setting->laneSettings[0].postCursor2;*/
+
+	/* Determine what the maximum of the requested settings are*/
+	for (lane = 1; lane < link_training_setting->link_settings.lane_count;
+			lane++) {
+		if (link_training_setting->lane_settings[lane].VOLTAGE_SWING >
+			max_requested.VOLTAGE_SWING)
+
+			max_requested.VOLTAGE_SWING =
+			link_training_setting->
+			lane_settings[lane].VOLTAGE_SWING;
+
+
+		if (link_training_setting->lane_settings[lane].PRE_EMPHASIS >
+				max_requested.PRE_EMPHASIS)
+			max_requested.PRE_EMPHASIS =
+			link_training_setting->
+			lane_settings[lane].PRE_EMPHASIS;
+
+		/*
+		if (link_training_setting->laneSettings[lane].postCursor2 >
+		 max_requested.postCursor2)
+		{
+		max_requested.postCursor2 =
+		link_training_setting->laneSettings[lane].postCursor2;
+		}
+		*/
+	}
+
+	/* make sure the requested settings are
+	 * not higher than maximum settings*/
+	if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
+		max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
+
+	if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
+		max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
+	/*
+	if (max_requested.postCursor2 > PostCursor2_MaxLevel)
+	max_requested.postCursor2 = PostCursor2_MaxLevel;
+	*/
+
+	/* make sure the pre-emphasis matches the voltage swing*/
+	if (max_requested.PRE_EMPHASIS >
+		get_max_pre_emphasis_for_voltage_swing(
+			max_requested.VOLTAGE_SWING))
+		max_requested.PRE_EMPHASIS =
+		get_max_pre_emphasis_for_voltage_swing(
+			max_requested.VOLTAGE_SWING);
+
+	/*
+	 * Post Cursor2 levels are completely independent from
+	 * pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels
+	 * can only be applied to each allowable combination of voltage
+	 * swing and pre-emphasis levels */
+	 /* if ( max_requested.postCursor2 >
+	  *  getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing))
+	  *  max_requested.postCursor2 =
+	  *  getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing);
+	  */
+
+	max_lt_setting->link_settings.link_rate =
+		link_training_setting->link_settings.link_rate;
+	max_lt_setting->link_settings.lane_count =
+	link_training_setting->link_settings.lane_count;
+	max_lt_setting->link_settings.link_spread =
+		link_training_setting->link_settings.link_spread;
+
+	for (lane = 0; lane <
+		link_training_setting->link_settings.lane_count;
+		lane++) {
+		max_lt_setting->lane_settings[lane].VOLTAGE_SWING =
+			max_requested.VOLTAGE_SWING;
+		max_lt_setting->lane_settings[lane].PRE_EMPHASIS =
+			max_requested.PRE_EMPHASIS;
+		/*max_lt_setting->laneSettings[lane].postCursor2 =
+		 * max_requested.postCursor2;
+		 */
+	}
+
+}
+
+static void get_lane_status_and_drive_settings(
+	struct core_link* link,
+	const struct link_training_settings *link_training_setting,
+	union lane_status *ln_status,
+	union lane_align_status_updated *ln_status_updated,
+	struct link_training_settings *req_settings)
+{
+	uint8_t dpcd_buf[6] = {0};
+	union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {{{0}}};
+	struct link_training_settings request_settings = {{0}};
+	uint32_t lane;
+
+	dm_memset(req_settings, '\0', sizeof(struct link_training_settings));
+
+	core_link_read_dpcd(
+		link,
+		DPCD_ADDRESS_LANE_01_STATUS,
+		(uint8_t *)(dpcd_buf),
+		sizeof(dpcd_buf));
+
+
+	for (lane = 0; lane <
+		(uint32_t)(link_training_setting->link_settings.lane_count);
+		lane++) {
+
+		ln_status[lane].raw =
+			get_nibble_at_index(&dpcd_buf[0], lane);
+		dpcd_lane_adjust[lane].raw =
+			get_nibble_at_index(&dpcd_buf[4], lane);
+	}
+
+	ln_status_updated->raw = dpcd_buf[2];
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
+		__func__,
+		DPCD_ADDRESS_LANE_01_STATUS, dpcd_buf[0],
+		DPCD_ADDRESS_LANE_23_STATUS, dpcd_buf[1]);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
+		__func__,
+		DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1,
+		dpcd_buf[4],
+		DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3,
+		dpcd_buf[5]);
+
+	/*copy to req_settings*/
+	request_settings.link_settings.lane_count =
+		link_training_setting->link_settings.lane_count;
+	request_settings.link_settings.link_rate =
+		link_training_setting->link_settings.link_rate;
+	request_settings.link_settings.link_spread =
+		link_training_setting->link_settings.link_spread;
+
+	for (lane = 0; lane <
+		(uint32_t)(link_training_setting->link_settings.lane_count);
+		lane++) {
+
+		request_settings.lane_settings[lane].VOLTAGE_SWING =
+			(enum voltage_swing)(dpcd_lane_adjust[lane].bits.
+				VOLTAGE_SWING_LANE);
+		request_settings.lane_settings[lane].PRE_EMPHASIS =
+			(enum pre_emphasis)(dpcd_lane_adjust[lane].bits.
+				PRE_EMPHASIS_LANE);
+	}
+
+	/*Note: for postcursor2, read adjusted
+	 * postcursor2 settings from*/
+	/*DpcdAddress_AdjustRequestPostCursor2 =
+	 *0x020C (not implemented yet)*/
+
+	/* we find the maximum of the requested settings across all lanes*/
+	/* and set this maximum for all lanes*/
+	find_max_drive_settings(&request_settings, req_settings);
+
+	/* if post cursor 2 is needed in the future,
+	 * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C
+	 */
+
+}
+
+static void dpcd_set_lane_settings(
+	struct core_link* link,
+	const struct link_training_settings *link_training_setting)
+{
+	union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
+	uint32_t lane;
+
+	for (lane = 0; lane <
+		(uint32_t)(link_training_setting->
+		link_settings.lane_count);
+		lane++) {
+		dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
+			(uint8_t)(link_training_setting->
+			lane_settings[lane].VOLTAGE_SWING);
+		dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
+			(uint8_t)(link_training_setting->
+			lane_settings[lane].PRE_EMPHASIS);
+		dpcd_lane[lane].bits.MAX_SWING_REACHED =
+			(link_training_setting->
+			lane_settings[lane].VOLTAGE_SWING ==
+			VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
+		dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
+			(link_training_setting->
+			lane_settings[lane].PRE_EMPHASIS ==
+			PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
+	}
+
+	core_link_write_dpcd(link,
+		DPCD_ADDRESS_LANE0_SET,
+		(uint8_t *)(dpcd_lane),
+		link_training_setting->link_settings.lane_count);
+
+	/*
+	if (LTSettings.link.rate == LinkRate_High2)
+	{
+		DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0};
+		for ( uint32_t lane = 0;
+		lane < lane_count_DPMax; lane++)
+		{
+			dpcd_lane2[lane].bits.post_cursor2_set =
+			static_cast<unsigned char>(
+			LTSettings.laneSettings[lane].postCursor2);
+			dpcd_lane2[lane].bits.max_post_cursor2_reached = 0;
+		}
+		m_pDpcdAccessSrv->WriteDpcdData(
+		DpcdAddress_Lane0Set2,
+		reinterpret_cast<unsigned char*>(dpcd_lane2),
+		LTSettings.link.lanes);
+	}
+	*/
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x VS set = %x  PE set = %x \
+		max VS Reached = %x  max PE Reached = %x\n",
+		__func__,
+		DPCD_ADDRESS_LANE0_SET,
+		dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+		dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+		dpcd_lane[0].bits.MAX_SWING_REACHED,
+		dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+
+	link->ln_setting = link_training_setting->lane_settings[0];
+
+}
+
+static bool is_max_vs_reached(
+	const struct link_training_settings *lt_settings)
+{
+	uint32_t lane;
+	for (lane = 0; lane <
+		(uint32_t)(lt_settings->link_settings.lane_count);
+		lane++) {
+		if (lt_settings->lane_settings[lane].VOLTAGE_SWING
+			== VOLTAGE_SWING_MAX_LEVEL)
+			return true;
+	}
+	return false;
+
+}
+
+void set_drive_settings(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	/* program ASIC PHY settings*/
+	dp_set_hw_lane_settings(link, lt_settings);
+
+	/* Notify DP sink the PHY settings from source */
+	dpcd_set_lane_settings(link, lt_settings);
+}
+
+static bool perform_post_lt_adj_req_sequence(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	enum lane_count lane_count =
+	lt_settings->link_settings.lane_count;
+
+	uint32_t adj_req_count;
+	uint32_t adj_req_timer;
+	bool req_drv_setting_changed;
+	uint32_t lane;
+
+	req_drv_setting_changed = false;
+	for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
+	adj_req_count++) {
+
+		req_drv_setting_changed = false;
+
+		for (adj_req_timer = 0;
+			adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
+			adj_req_timer++) {
+
+			struct link_training_settings req_settings;
+			union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
+			union lane_align_status_updated
+				dpcd_lane_status_updated;
+
+			get_lane_status_and_drive_settings(
+			link,
+			lt_settings,
+			dpcd_lane_status,
+			&dpcd_lane_status_updated,
+			&req_settings);
+
+			if (dpcd_lane_status_updated.bits.
+					POST_LT_ADJ_REQ_IN_PROGRESS == 0)
+				return true;
+
+			if (!is_cr_done(lane_count, dpcd_lane_status))
+				return false;
+
+			if (!is_ch_eq_done(
+				lane_count,
+				dpcd_lane_status,
+				&dpcd_lane_status_updated))
+				return false;
+
+			for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
+
+				if (lt_settings->
+				lane_settings[lane].VOLTAGE_SWING !=
+				req_settings.lane_settings[lane].
+				VOLTAGE_SWING ||
+				lt_settings->lane_settings[lane].PRE_EMPHASIS !=
+				req_settings.lane_settings[lane].PRE_EMPHASIS) {
+
+					req_drv_setting_changed = true;
+					break;
+				}
+			}
+
+			if (req_drv_setting_changed) {
+				update_drive_settings(
+					lt_settings,req_settings);
+
+				set_drive_settings(link, lt_settings);
+				break;
+			}
+
+			dm_sleep_in_milliseconds(link->ctx, 1);
+		}
+
+		if (!req_drv_setting_changed) {
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_LINK_SERVICE,
+				"%s: Post Link Training Adjust Request Timed out\n",
+				__func__);
+
+			ASSERT(0);
+			return true;
+		}
+	}
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_WARNING,
+		LOG_MINOR_COMPONENT_LINK_SERVICE,
+		"%s: Post Link Training Adjust Request limit reached\n",
+		__func__);
+
+	ASSERT(0);
+	return true;
+
+}
+
+static bool perform_channel_equalization_sequence(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	struct link_training_settings req_settings;
+	enum hw_dp_training_pattern hw_tr_pattern;
+	uint32_t retries_ch_eq;
+	enum lane_count lane_count = lt_settings->link_settings.lane_count;
+	union lane_align_status_updated dpcd_lane_status_updated = {{0}};
+	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};;
+
+	/*TODO hw_tr_pattern = HW_DP_TRAINING_PATTERN_3;*/
+	hw_tr_pattern = HW_DP_TRAINING_PATTERN_2;
+
+	dp_set_hw_training_pattern(link, hw_tr_pattern);
+
+	for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
+		retries_ch_eq++) {
+
+		dp_set_hw_lane_settings(link, lt_settings);
+
+		/* 2. update DPCD*/
+		if (!retries_ch_eq)
+			/* EPR #361076 - write as a 5-byte burst,
+			 * but only for the 1-st iteration*/
+			dpcd_set_lt_pattern_and_lane_settings(
+				link,
+				lt_settings,
+				hw_tr_pattern);
+		else
+			dpcd_set_lane_settings(link, lt_settings);
+
+		/* 3. wait for receiver to lock-on*/
+		wait_for_training_aux_rd_interval(link, 400);
+
+		/* 4. Read lane status and requested
+		 * drive settings as set by the sink*/
+
+		get_lane_status_and_drive_settings(
+			link,
+			lt_settings,
+			dpcd_lane_status,
+			&dpcd_lane_status_updated,
+			&req_settings);
+
+		/* 5. check CR done*/
+		if (!is_cr_done(lane_count, dpcd_lane_status))
+			return false;
+
+		/* 6. check CHEQ done*/
+		if (is_ch_eq_done(lane_count,
+			dpcd_lane_status,
+			&dpcd_lane_status_updated))
+			return true;
+
+		/* 7. update VS/PE/PC2 in lt_settings*/
+		update_drive_settings(lt_settings, req_settings);
+	}
+
+	return false;
+
+}
+
+static bool perform_clock_recovery_sequence(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	uint32_t retries_cr;
+	uint32_t retry_count;
+	uint32_t lane;
+	struct link_training_settings req_settings;
+	enum lane_count lane_count =
+	lt_settings->link_settings.lane_count;
+	enum hw_dp_training_pattern hw_tr_pattern = HW_DP_TRAINING_PATTERN_1;
+	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
+	union lane_align_status_updated dpcd_lane_status_updated;
+
+	retries_cr = 0;
+	retry_count = 0;
+	/* initial drive setting (VS/PE/PC2)*/
+	for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
+		lt_settings->lane_settings[lane].VOLTAGE_SWING =
+		VOLTAGE_SWING_LEVEL0;
+		lt_settings->lane_settings[lane].PRE_EMPHASIS =
+		PRE_EMPHASIS_DISABLED;
+		lt_settings->lane_settings[lane].POST_CURSOR2 =
+		POST_CURSOR2_DISABLED;
+	}
+
+	dp_set_hw_training_pattern(link, hw_tr_pattern);
+
+	/* najeeb - The synaptics MST hub can put the LT in
+	* infinite loop by switching the VS
+	*/
+	/* between level 0 and level 1 continuously, here
+	* we try for CR lock for LinkTrainingMaxCRRetry count*/
+	while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
+	(retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
+
+		dm_memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
+		dm_memset(&dpcd_lane_status_updated, '\0',
+		sizeof(dpcd_lane_status_updated));
+
+		/* 1. call HWSS to set lane settings*/
+		dp_set_hw_lane_settings(
+				link,
+				lt_settings);
+
+		/* 2. update DPCD of the receiver*/
+		if (!retries_cr)
+			/* EPR #361076 - write as a 5-byte burst,
+			 * but only for the 1-st iteration.*/
+			dpcd_set_lt_pattern_and_lane_settings(
+					link,
+					lt_settings,
+					hw_tr_pattern);
+		else
+			dpcd_set_lane_settings(
+					link,
+					lt_settings);
+
+
+		/* 3. wait receiver to lock-on*/
+		wait_for_training_aux_rd_interval(
+				link,
+				100);
+
+		/* 4. Read lane status and requested drive
+		* settings as set by the sink
+		*/
+		get_lane_status_and_drive_settings(
+				link,
+				lt_settings,
+				dpcd_lane_status,
+				&dpcd_lane_status_updated,
+				&req_settings);
+
+
+		/* 5. check CR done*/
+		if (is_cr_done(lane_count, dpcd_lane_status))
+			return true;
+
+		/* 6. max VS reached*/
+		if (is_max_vs_reached(lt_settings))
+			return false;
+
+		/* 7. same voltage*/
+		/* Note: VS same for all lanes,
+		* so comparing first lane is sufficient*/
+		if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
+			req_settings.lane_settings[0].VOLTAGE_SWING)
+			retries_cr++;
+		else
+			retries_cr = 0;
+
+
+			/* 8. update VS/PE/PC2 in lt_settings*/
+			update_drive_settings(lt_settings, req_settings);
+
+			retry_count++;
+	}
+
+	if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
+		ASSERT(0);
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_LINK_SERVICE,
+			"%s: Link Training Error, could not \
+			 get CR after %d tries. \
+			Possibly voltage swing issue", __func__,
+			LINK_TRAINING_MAX_CR_RETRY);
+
+	}
+
+	return false;
+}
+
+ bool perform_link_training(
+	struct core_link *link,
+	const struct link_settings *link_setting,
+	bool skip_video_pattern)
+{
+	bool status;
+	union dpcd_training_pattern dpcd_pattern = {{0}};
+	union lane_count_set lane_count_set = {{0}};
+	const int8_t *link_rate = "Unknown";
+	struct link_training_settings lt_settings;
+
+	status = false;
+	dm_memset(&lt_settings, '\0', sizeof(lt_settings));
+
+	lt_settings.link_settings.link_rate = link_setting->link_rate;
+	lt_settings.link_settings.lane_count = link_setting->lane_count;
+
+	/*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/
+
+	/* TODO hard coded to SS for now
+	 * lt_settings.link_settings.link_spread =
+	 * dal_display_path_is_ss_supported(
+	 * path_mode->display_path) ?
+	 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
+	 * LINK_SPREAD_DISABLED;
+	 */
+	lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
+
+	/* 1. set link rate, lane count and spread*/
+	dpcd_set_link_settings(link, &lt_settings);
+
+	/* 2. perform link training (set link training done
+	 *  to false is done as well)*/
+	if (perform_clock_recovery_sequence(link, &lt_settings)) {
+
+		if (perform_channel_equalization_sequence(link, &lt_settings))
+			status = true;
+	}
+
+	if (status || !skip_video_pattern) {
+
+		/* 3. set training not in progress*/
+		dpcd_pattern.bits.TRAINING_PATTERN_SET =
+			DPCD_TRAINING_PATTERN_VIDEOIDLE;
+		dpcd_set_training_pattern(link, dpcd_pattern);
+
+		/* 4. mainlink output idle pattern*/
+		dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE);
+
+		/* 5. post training adjust if required*/
+		if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED
+			== 1) {
+			if (status == true) {
+				if (perform_post_lt_adj_req_sequence(
+					link, &lt_settings) == false)
+					status = false;
+			}
+
+			lane_count_set.bits.LANE_COUNT_SET =
+				lt_settings.link_settings.lane_count;
+			lane_count_set.bits.ENHANCED_FRAMING = 1;
+			lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
+
+			core_link_write_dpcd(
+				link,
+				DPCD_ADDRESS_LANE_COUNT_SET,
+				&lane_count_set.raw,
+				sizeof(lane_count_set));
+		}
+	}
+
+	/* 6. print status message*/
+	switch (lt_settings.link_settings.link_rate) {
+
+	case LINK_RATE_LOW:
+		link_rate = "Low";
+		break;
+	case LINK_RATE_HIGH:
+		link_rate = "High";
+		break;
+	case LINK_RATE_HIGH2:
+		link_rate = "High2";
+		break;
+	case LINK_RATE_RBR2:
+		link_rate = "RBR2";
+		break;
+	default:
+		break;
+	}
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_MST,
+		LOG_MINOR_MST_PROGRAMMING,
+		"Link training for %d lanes at %s rate %s with PE %d, VS %d\n",
+		lt_settings.link_settings.lane_count,
+		link_rate,
+		status ? "succeeded" : "failed",
+		lt_settings.lane_settings[0].PRE_EMPHASIS,
+		lt_settings.lane_settings[0].VOLTAGE_SWING);
+
+	return status;
+}
+
+/*TODO add more check to see if link support request link configuration */
+static bool is_link_setting_supported(
+	const struct link_settings *link_setting,
+	const struct link_settings *max_link_setting)
+{
+	if (link_setting->lane_count > max_link_setting->lane_count ||
+		link_setting->link_rate > max_link_setting->link_rate)
+		return false;
+	return true;
+}
+
+static const uint32_t get_link_training_fallback_table_len(
+	struct core_link *link)
+{
+	return ARRAY_SIZE(link_training_fallback_table);
+}
+
+static const struct link_settings *get_link_training_fallback_table(
+	struct core_link *link, uint32_t i)
+{
+	return &link_training_fallback_table[i];
+}
+
+static bool exceeded_limit_link_setting(const struct link_settings *link_setting,
+			const struct link_settings *limit_link_setting)
+{
+	return (link_setting->lane_count * link_setting->link_rate
+		 > limit_link_setting->lane_count * limit_link_setting->link_rate ?
+				 true : false);
+}
+
+
+bool dp_hbr_verify_link_cap(
+	struct core_link *link,
+	struct link_settings *known_limit_link_setting)
+{
+	struct link_settings max_link_cap = {0};
+	bool success;
+	bool skip_link_training;
+	const struct link_settings *cur;
+	bool skip_video_pattern;
+	uint32_t i;
+
+	success = false;
+	skip_link_training = false;
+
+	/* TODO confirm this is correct for cz */
+	max_link_cap.lane_count = LANE_COUNT_FOUR;
+	max_link_cap.link_rate = LINK_RATE_HIGH2;
+	max_link_cap.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
+
+	/* TODO implement override and monitor patch later */
+
+	/* try to train the link from high to low to
+	 * find the physical link capability
+	 */
+	/* disable PHY done possible by BIOS, will be done by driver itself */
+	dp_disable_link_phy(link, link->public.connector_signal);
+
+	for (i = 0; i < get_link_training_fallback_table_len(link) &&
+		!success; i++) {
+		cur = get_link_training_fallback_table(link, i);
+
+		if (known_limit_link_setting->lane_count != LANE_COUNT_UNKNOWN &&
+			exceeded_limit_link_setting(cur,
+					known_limit_link_setting))
+			continue;
+
+		if (!is_link_setting_supported(cur, &max_link_cap))
+			continue;
+
+		skip_video_pattern = true;
+		if (cur->link_rate == LINK_RATE_LOW)
+			skip_video_pattern = false;
+
+		dp_enable_link_phy(
+				link,
+				link->public.connector_signal,
+				cur);
+
+		if (skip_link_training)
+			success = true;
+		else {
+			uint8_t num_retries = 3;
+			uint8_t j;
+			uint8_t delay_between_retries = 10;
+
+			for (j = 0; j < num_retries; ++j) {
+				success = perform_link_training(
+					link,
+					cur,
+					skip_video_pattern);
+
+				if (success)
+					break;
+
+				dm_sleep_in_milliseconds(
+					link->ctx,
+					delay_between_retries);
+
+				delay_between_retries += 10;
+			}
+		}
+
+		if (success)
+			link->verified_link_cap = *cur;
+
+		/* always disable the link before trying another
+		 * setting or before returning we'll enable it later
+		 * based on the actual mode we're driving
+		 */
+		dp_disable_link_phy(link, link->public.connector_signal);
+	}
+
+	/* Link Training failed for all Link Settings
+	 *  (Lane Count is still unknown)
+	 */
+	if (!success) {
+		/* If all LT fails for all settings,
+		 * set verified = failed safe (1 lane low)
+		 */
+		link->verified_link_cap.lane_count = LANE_COUNT_ONE;
+		link->verified_link_cap.link_rate = LINK_RATE_LOW;
+
+		link->verified_link_cap.link_spread =
+		LINK_SPREAD_DISABLED;
+	}
+
+	link->max_link_setting = link->verified_link_cap;
+
+	return success;
+}
+
+static uint32_t bandwidth_in_kbps_from_timing(
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t bits_per_channel = 0;
+	uint32_t kbps;
+	switch (timing->display_color_depth) {
+
+	case COLOR_DEPTH_666:
+		bits_per_channel = 6;
+		break;
+	case COLOR_DEPTH_888:
+		bits_per_channel = 8;
+		break;
+	case COLOR_DEPTH_101010:
+		bits_per_channel = 10;
+		break;
+	case COLOR_DEPTH_121212:
+		bits_per_channel = 12;
+		break;
+	case COLOR_DEPTH_141414:
+		bits_per_channel = 14;
+		break;
+	case COLOR_DEPTH_161616:
+		bits_per_channel = 16;
+		break;
+	default:
+		break;
+	}
+	ASSERT(bits_per_channel != 0);
+
+	kbps = timing->pix_clk_khz;
+	kbps *= bits_per_channel;
+
+	if (timing->flags.Y_ONLY != 1)
+		/*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
+		kbps *= 3;
+
+	return kbps;
+
+}
+
+static uint32_t bandwidth_in_kbps_from_link_settings(
+	const struct link_settings *link_setting)
+{
+	uint32_t link_rate_in_kbps = link_setting->link_rate *
+		LINK_RATE_REF_FREQ_IN_KHZ;
+
+	uint32_t lane_count  = link_setting->lane_count;
+	uint32_t kbps = link_rate_in_kbps;
+	kbps *= lane_count;
+	kbps *= 8;   /* 8 bits per byte*/
+
+	return kbps;
+
+}
+
+bool dp_validate_mode_timing(
+	struct core_link *link,
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t req_bw;
+	uint32_t max_bw;
+
+	const struct link_settings *link_setting;
+
+	/*always DP fail safe mode*/
+	if (timing->pix_clk_khz == (uint32_t)25175 &&
+		timing->h_addressable == (uint32_t)640 &&
+		timing->v_addressable == (uint32_t)480)
+		return true;
+
+	/* For static validation we always use reported
+	 * link settings for other cases, when no modelist
+	 * changed we can use verified link setting*/
+	link_setting = &link->reported_link_cap;
+
+	/* TODO: DYNAMIC_VALIDATION needs to be implemented */
+	/*if (flags.DYNAMIC_VALIDATION == 1 &&
+		link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
+		link_setting = &link->verified_link_cap;
+	*/
+
+	req_bw = bandwidth_in_kbps_from_timing(timing);
+	max_bw = bandwidth_in_kbps_from_link_settings(link_setting);
+
+	if (req_bw < max_bw) {
+		/* remember the biggest mode here, during
+		 * initial link training (to get
+		 * verified_link_cap), LS sends event about
+		 * cannot train at reported cap to upper
+		 * layer and upper layer will re-enumerate modes.
+		 * this is not necessary if the lower
+		 * verified_link_cap is enough to drive
+		 * all the modes */
+
+		/* TODO: DYNAMIC_VALIDATION needs to be implemented */
+		/* if (flags.DYNAMIC_VALIDATION == 1)
+			dpsst->max_req_bw_for_verified_linkcap = dal_max(
+				dpsst->max_req_bw_for_verified_linkcap, req_bw); */
+		return true;
+	} else
+		return false;
+}
+
+void decide_link_settings(struct core_stream *stream,
+	struct link_settings *link_setting)
+{
+
+	const struct link_settings *cur_ls;
+	struct core_link* link;
+	uint32_t req_bw;
+	uint32_t link_bw;
+	uint32_t i;
+
+	req_bw = bandwidth_in_kbps_from_timing(
+			&stream->public.timing);
+
+	/* if preferred is specified through AMDDP, use it, if it's enough
+	 * to drive the mode
+	 */
+	link = stream->sink->link;
+
+	if ((link->reported_link_cap.lane_count != LANE_COUNT_UNKNOWN) &&
+		(link->reported_link_cap.link_rate <=
+				link->verified_link_cap.link_rate)) {
+
+		link_bw = bandwidth_in_kbps_from_link_settings(
+				&link->reported_link_cap);
+
+		if (req_bw < link_bw) {
+			*link_setting = link->reported_link_cap;
+			return;
+		}
+	}
+
+	/* search for first suitable setting for the requested
+	 * bandwidth
+	 */
+	for (i = 0; i < get_link_training_fallback_table_len(link); i++) {
+
+		cur_ls = get_link_training_fallback_table(link, i);
+
+		link_bw =
+				bandwidth_in_kbps_from_link_settings(
+				cur_ls);
+
+		if (req_bw < link_bw) {
+			if (is_link_setting_supported(
+				cur_ls,
+				&link->max_link_setting)) {
+				*link_setting = *cur_ls;
+				return;
+			}
+		}
+	}
+
+	BREAK_TO_DEBUGGER();
+	ASSERT(link->verified_link_cap.lane_count !=
+		LANE_COUNT_UNKNOWN);
+
+	*link_setting = link->verified_link_cap;
+}
+
+/*************************Short Pulse IRQ***************************/
+
+static bool hpd_rx_irq_check_link_loss_status(
+	struct core_link *link,
+	union hpd_irq_data *hpd_irq_dpcd_data)
+{
+	uint8_t irq_reg_rx_power_state;
+	enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
+	union lane_status lane_status;
+	uint32_t lane;
+	bool sink_status_changed;
+	bool return_code;
+
+	sink_status_changed = false;
+	return_code = false;
+
+	if (link->cur_link_settings.lane_count == 0)
+		return return_code;
+	/*1. Check that we can handle interrupt: Not in FS DOS,
+	 *  Not in "Display Timeout" state, Link is trained.
+	 */
+
+	dpcd_result = core_link_read_dpcd(link,
+		DPCD_ADDRESS_POWER_STATE,
+		&irq_reg_rx_power_state,
+		sizeof(irq_reg_rx_power_state));
+
+	if (dpcd_result != DC_OK) {
+		irq_reg_rx_power_state = DP_PWR_STATE_D0;
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_HPD_IRQ,
+			"%s: DPCD read failed to obtain power state.\n",
+			__func__);
+	}
+
+	if (irq_reg_rx_power_state == DP_PWR_STATE_D0) {
+
+		/*2. Check that Link Status changed, before re-training.*/
+
+		/*parse lane status*/
+		for (lane = 0;
+			lane < link->cur_link_settings.lane_count;
+			lane++) {
+
+			/* check status of lanes 0,1
+			 * changed DpcdAddress_Lane01Status (0x202)*/
+			lane_status.raw = get_nibble_at_index(
+				&hpd_irq_dpcd_data->bytes.lane01_status.raw,
+				lane);
+
+			if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
+				!lane_status.bits.CR_DONE_0 ||
+				!lane_status.bits.SYMBOL_LOCKED_0) {
+				/* if one of the channel equalization, clock
+				 * recovery or symbol lock is dropped
+				 * consider it as (link has been
+				 * dropped) dp sink status has changed*/
+				sink_status_changed = true;
+				break;
+			}
+
+		}
+
+		/* Check interlane align.*/
+		if (sink_status_changed ||
+			!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.
+			INTERLANE_ALIGN_DONE) {
+
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_HPD_IRQ,
+				"%s: Link Status changed.\n",
+				__func__);
+
+			return_code = true;
+		}
+	}
+
+	return return_code;
+}
+
+static enum dc_status read_hpd_rx_irq_data(
+	struct core_link *link,
+	union hpd_irq_data *irq_data)
+{
+	/* The HW reads 16 bytes from 200h on HPD,
+	 * but if we get an AUX_DEFER, the HW cannot retry
+	 * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
+	 * fail, so we now explicitly read 6 bytes which is
+	 * the req from the above mentioned test cases.
+	 */
+	return core_link_read_dpcd(
+	link,
+	DPCD_ADDRESS_SINK_COUNT,
+	irq_data->raw,
+	sizeof(union hpd_irq_data));
+}
+
+static bool allow_hpd_rx_irq(const struct core_link *link)
+{
+	/*
+	 * Don't handle RX IRQ unless one of following is met:
+	 * 1) The link is established (cur_link_settings != unknown)
+	 * 2) We kicked off MST detection
+	 * 3) We know we're dealing with an active dongle
+	 */
+
+	if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
+		(link->public.type == dc_connection_mst_branch) ||
+		is_dp_active_dongle(link))
+		return true;
+
+	return false;
+}
+
+bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link)
+{
+	struct core_link *link = DC_LINK_TO_LINK(dc_link);
+	union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}};
+	enum dc_status result = DDC_RESULT_UNKNOWN;
+	bool status = false;
+	/* For use cases related to down stream connection status change,
+	 * PSR and device auto test, refer to function handle_sst_hpd_irq
+	 * in DAL2.1*/
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_HPD_IRQ,
+		"%s: Got short pulse HPD on link %d\n",
+		__func__, link->public.link_index);
+
+	if (!allow_hpd_rx_irq(link)) {
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_HPD_IRQ,
+			"%s: skipping HPD handling on %d\n",
+			__func__, link->public.link_index);
+		return false;
+	}
+
+	 /* All the "handle_hpd_irq_xxx()" methods
+	 * should be called only after
+	 * dal_dpsst_ls_read_hpd_irq_data
+	 * Order of calls is important too
+	 */
+	result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
+
+	if (result != DC_OK) {
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_HPD_IRQ,
+			"%s: DPCD read failed to obtain irq data\n",
+			__func__);
+		return false;
+	}
+
+	/* check if we have MST msg and return since we poll for it */
+	if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY ||
+		hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY)
+		return false;
+
+
+	/* For now we only handle 'Downstream port status' case. */
+	/* If we got sink count changed it means Downstream port status changed,
+	 * then DM should call DC to do the detection. */
+	if (hpd_rx_irq_check_link_loss_status(
+		link,
+		&hpd_irq_dpcd_data)) {
+		perform_link_training(link, &link->cur_link_settings, true);
+		status = false;
+	}
+
+	if (hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
+				!= link->dpcd_sink_count)
+		status = true;
+
+	/* reasons for HPD RX:
+	 * 1. Link Loss - ie Re-train the Link
+	 * 2. MST sideband message
+	 * 3. Automated Test - ie. Internal Commit
+	 * 4. CP (copy protection) - (not interesting for DM???)
+	 * 5. DRR
+	 * 6. Downstream Port status changed -ie. Detect - this the only one
+	 * which is interesting for DM because it must call dc_link_detect.
+	 */
+	return status;
+}
+
+/*query dpcd for version and mst cap addresses*/
+bool is_mst_supported(struct core_link *link)
+{
+	bool mst          = false;
+	enum dc_status st = DC_OK;
+	union dpcd_rev rev;
+	union mstm_cap cap;
+
+	rev.raw  = 0;
+	cap.raw  = 0;
+
+	st = core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, &rev.raw,
+			sizeof(rev));
+
+	if (st == DC_OK && rev.raw >= DPCD_REV_12) {
+
+		st = core_link_read_dpcd(link, DPCD_ADDRESS_MSTM_CAP,
+				&cap.raw, sizeof(cap));
+		if (st == DC_OK && cap.bits.MST_CAP == 1)
+			mst = true;
+	}
+	return mst;
+
+}
+
+bool is_dp_active_dongle(const struct core_link *link)
+{
+	enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type;
+
+	return (dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) ||
+			(dongle_type == DISPLAY_DONGLE_DP_DVI_CONVERTER) ||
+			(dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER);
+}
+
+static void get_active_converter_info(
+	uint8_t data, struct core_link *link)
+{
+	union dp_downstream_port_present ds_port = { .byte = data };
+
+	/* decode converter info*/
+	if (!ds_port.fields.PORT_PRESENT) {
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
+		ddc_service_set_dongle_type(link->ddc,
+				link->dpcd_caps.dongle_type);
+		return;
+	}
+
+	switch (ds_port.fields.PORT_TYPE) {
+	case DOWNSTREAM_VGA:
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
+		break;
+	case DOWNSTREAM_DVI_HDMI:
+		/* At this point we don't know is it DVI or HDMI,
+		 * assume DVI.*/
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
+		break;
+	default:
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
+		break;
+	}
+
+	if (link->dpcd_caps.dpcd_rev.raw >= DCS_DPCD_REV_11) {
+		uint8_t det_caps[4];
+		union dwnstream_port_caps_byte0 *port_caps =
+			(union dwnstream_port_caps_byte0 *)det_caps;
+		core_link_read_dpcd(link, DPCD_ADDRESS_DWN_STRM_PORT0_CAPS,
+				det_caps, sizeof(det_caps));
+
+		switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
+		case DOWN_STREAM_DETAILED_VGA:
+			link->dpcd_caps.dongle_type =
+				DISPLAY_DONGLE_DP_VGA_CONVERTER;
+			break;
+		case DOWN_STREAM_DETAILED_DVI:
+			link->dpcd_caps.dongle_type =
+				DISPLAY_DONGLE_DP_DVI_CONVERTER;
+			break;
+		case DOWN_STREAM_DETAILED_HDMI:
+			link->dpcd_caps.dongle_type =
+				DISPLAY_DONGLE_DP_HDMI_CONVERTER;
+
+			if (ds_port.fields.DETAILED_CAPS) {
+
+				union dwnstream_port_caps_byte3_hdmi
+					hdmi_caps = {.raw = det_caps[3] };
+
+				link->dpcd_caps.is_dp_hdmi_s3d_converter =
+					hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
+			}
+			break;
+		}
+	}
+	ddc_service_set_dongle_type(link->ddc,
+			link->dpcd_caps.dongle_type);
+}
+
+static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data,
+		int length)
+{
+	int retry = 0;
+	struct dp_device_vendor_id dp_id;
+	union dp_downstream_port_present ds_port = { 0 };
+
+	if (!link->dpcd_caps.dpcd_rev.raw) {
+		do {
+			dp_receiver_power_ctrl(link, true);
+			core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV,
+							dpcd_data, length);
+			link->dpcd_caps.dpcd_rev.raw = dpcd_data[
+				DPCD_ADDRESS_DPCD_REV -
+				DPCD_ADDRESS_DPCD_REV];
+		} while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
+	}
+
+	ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT -
+				 DPCD_ADDRESS_DPCD_REV];
+
+	get_active_converter_info(ds_port.byte, link);
+
+	/* read IEEE branch device id */
+	core_link_read_dpcd(link, DPCD_ADDRESS_BRANCH_DEVICE_ID_START,
+			(uint8_t *)&dp_id, sizeof(dp_id));
+	link->dpcd_caps.branch_dev_id =
+			(dp_id.ieee_oui[0] << 16) +
+			(dp_id.ieee_oui[1] << 8) +
+			dp_id.ieee_oui[2];
+
+	if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
+		switch (link->dpcd_caps.branch_dev_id) {
+		/* Some active dongles (DP-VGA, DP-DLDVI converters) power down
+		 * all internal circuits including AUX communication preventing
+		 * reading DPCD table and EDID (spec violation).
+		 * Encoder will skip DP RX power down on disable_output to
+		 * keep receiver powered all the time.*/
+		case DP_BRANCH_DEVICE_ID_1:
+		case DP_BRANCH_DEVICE_ID_4:
+			link->wa_flags.dp_keep_receiver_powered = true;
+			break;
+
+		/* TODO: May need work around for other dongles. */
+		default:
+			link->wa_flags.dp_keep_receiver_powered = false;
+			break;
+		}
+	} else
+		link->wa_flags.dp_keep_receiver_powered = false;
+}
+
+static void retrieve_link_cap(struct core_link *link)
+{
+	uint8_t dpcd_data[
+			DPCD_ADDRESS_EDP_CONFIG_CAP -
+			DPCD_ADDRESS_DPCD_REV + 1];
+
+	union down_stream_port_count down_strm_port_count;
+	union edp_configuration_cap edp_config_cap;
+	union max_down_spread max_down_spread;
+	union dp_downstream_port_present ds_port = { 0 };
+
+	dm_memset(dpcd_data, '\0', sizeof(dpcd_data));
+	dm_memset(&down_strm_port_count,
+		'\0', sizeof(union down_stream_port_count));
+	dm_memset(&edp_config_cap, '\0',
+		sizeof(union edp_configuration_cap));
+	dm_memset(&max_down_spread, '\0',
+		sizeof(union max_down_spread));
+
+	core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV,
+			dpcd_data, sizeof(dpcd_data));
+	link->dpcd_caps.dpcd_rev.raw = dpcd_data[
+		DPCD_ADDRESS_DPCD_REV -
+		DPCD_ADDRESS_DPCD_REV];
+
+	ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT -
+				 DPCD_ADDRESS_DPCD_REV];
+
+	get_active_converter_info(ds_port.byte, link);
+
+	dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
+
+	link->dpcd_caps.allow_invalid_MSA_timing_param =
+		down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
+
+	link->dpcd_caps.max_ln_count.raw = dpcd_data[
+		DPCD_ADDRESS_MAX_LANE_COUNT - DPCD_ADDRESS_DPCD_REV];
+
+	max_down_spread.raw = dpcd_data[
+		DPCD_ADDRESS_MAX_DOWNSPREAD - DPCD_ADDRESS_DPCD_REV];
+
+	link->reported_link_cap.lane_count =
+		link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
+	link->reported_link_cap.link_rate = dpcd_data[
+		DPCD_ADDRESS_MAX_LINK_RATE - DPCD_ADDRESS_DPCD_REV];
+	link->reported_link_cap.link_spread =
+		max_down_spread.bits.MAX_DOWN_SPREAD ?
+		LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
+
+	edp_config_cap.raw = dpcd_data[
+		DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV];
+	link->dpcd_caps.panel_mode_edp =
+		edp_config_cap.bits.ALT_SCRAMBLER_RESET;
+
+	link->edp_revision = DPCD_EDP_REVISION_EDP_UNKNOWN;
+
+	/* read sink count */
+	core_link_read_dpcd(link,
+			DPCD_ADDRESS_SINK_COUNT,
+			&link->dpcd_caps.sink_count.raw,
+			sizeof(link->dpcd_caps.sink_count.raw));
+
+	/* Display control registers starting at DPCD 700h are only valid and
+	 * enabled if this eDP config cap bit is set. */
+	if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) {
+		/* Read the Panel's eDP revision at DPCD 700h. */
+		core_link_read_dpcd(link,
+			DPCD_ADDRESS_EDP_REV,
+			(uint8_t *)(&link->edp_revision),
+			sizeof(link->edp_revision));
+	}
+	/* TODO: Confirm if need retrieve_psr_link_cap */
+}
+
+void detect_dp_sink_caps(struct core_link *link)
+{
+	retrieve_link_cap(link);
+
+	/* dc init_hw has power encoder using default
+	 * signal for connector. For native DP, no
+	 * need to power up encoder again. If not native
+	 * DP, hw_init may need check signal or power up
+	 * encoder here.
+	 */
+
+	if (is_mst_supported(link)) {
+		link->verified_link_cap = link->reported_link_cap;
+	} else {
+		dp_hbr_verify_link_cap(link,
+			&link->reported_link_cap);
+	}
+	/* TODO save sink caps in link->sink */
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
new file mode 100644
index 000000000000..39aa734680c6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
@@ -0,0 +1,201 @@
+/* Copyright 2015 Advanced Micro Devices, Inc. */
+
+#include "dm_services.h"
+#include "dc.h"
+#include "inc/core_dc.h"
+#include "include/ddc_service_types.h"
+#include "include/i2caux_interface.h"
+#include "link_hwss.h"
+#include "hw_sequencer.h"
+#include "dc_link_ddc.h"
+#include "dm_helpers.h"
+#include "dce110/dce110_link_encoder.h"
+#include "dce110/dce110_stream_encoder.h"
+
+
+enum dc_status core_link_read_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t size)
+{
+	if (!dm_helper_dp_read_dpcd(link->ctx,
+			&link->public,
+			address, data, size))
+			return DC_ERROR_UNEXPECTED;
+
+	return DC_OK;
+}
+
+enum dc_status core_link_write_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t size)
+{
+	if (!dm_helper_dp_write_dpcd(link->ctx,
+			&link->public,
+			address, data, size))
+				return DC_ERROR_UNEXPECTED;
+
+	return DC_OK;
+}
+
+void dp_receiver_power_ctrl(struct core_link *link, bool on)
+{
+	uint8_t state;
+
+	state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
+
+	core_link_write_dpcd(link, DPCD_ADDRESS_POWER_STATE, &state,
+			sizeof(state));
+}
+
+void dp_enable_link_phy(
+	struct core_link *link,
+	enum signal_type signal,
+	const struct link_settings *link_settings)
+{
+	struct link_encoder *link_enc = link->link_enc;
+
+	if (dc_is_dp_sst_signal(signal)) {
+		if (signal == SIGNAL_TYPE_EDP) {
+			link_enc->funcs->power_control(link_enc, true);
+			link_enc->funcs->backlight_control(link_enc, true);
+		}
+
+		link_enc->funcs->enable_dp_output(
+						link_enc,
+						link_settings,
+						CLOCK_SOURCE_ID_EXTERNAL);
+	} else {
+		link_enc->funcs->enable_dp_mst_output(
+						link_enc,
+						link_settings,
+						CLOCK_SOURCE_ID_EXTERNAL);
+	}
+
+	dp_receiver_power_ctrl(link, true);
+}
+
+void dp_disable_link_phy(struct core_link *link, enum signal_type signal)
+{
+	if (!link->wa_flags.dp_keep_receiver_powered)
+		dp_receiver_power_ctrl(link, false);
+
+	if (signal == SIGNAL_TYPE_EDP)
+		link->link_enc->funcs->backlight_control(link->link_enc, false);
+
+	link->link_enc->funcs->disable_output(link->link_enc, signal);
+
+	/* Clear current link setting.*/
+	dm_memset(&link->cur_link_settings, 0,
+			sizeof(link->cur_link_settings));
+}
+
+void dp_disable_link_phy_mst(struct core_link *link, struct core_stream *stream)
+{
+	/* MST disable link only when no stream use the link */
+	if (link->mst_stream_alloc_table.stream_count > 0)
+		return;
+
+	dp_disable_link_phy(link, stream->signal);
+}
+
+bool dp_set_hw_training_pattern(
+	struct core_link *link,
+	enum hw_dp_training_pattern pattern)
+{
+	enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
+	struct encoder_set_dp_phy_pattern_param pattern_param = {0};
+	struct link_encoder *encoder = link->link_enc;
+
+	switch (pattern) {
+	case HW_DP_TRAINING_PATTERN_1:
+		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
+		break;
+	case HW_DP_TRAINING_PATTERN_2:
+		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
+		break;
+	case HW_DP_TRAINING_PATTERN_3:
+		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
+		break;
+	default:
+		break;
+	}
+
+	pattern_param.dp_phy_pattern = test_pattern;
+	pattern_param.custom_pattern = NULL;
+	pattern_param.custom_pattern_size = 0;
+	pattern_param.dp_panel_mode = dp_get_panel_mode(link);
+
+	encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
+
+	return true;
+}
+
+
+void dp_set_hw_lane_settings(
+	struct core_link *link,
+	const struct link_training_settings *link_settings)
+{
+	struct link_encoder *encoder = link->link_enc;
+
+	/* call Encoder to set lane settings */
+	encoder->funcs->dp_set_lane_settings(encoder, link_settings);
+}
+
+enum dp_panel_mode dp_get_panel_mode(struct core_link *link)
+{
+	/* We need to explicitly check that connector
+	 * is not DP. Some Travis_VGA get reported
+	 * by video bios as DP.
+	 */
+	if (link->public.connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
+
+		switch (link->dpcd_caps.branch_dev_id) {
+		case DP_BRANCH_DEVICE_ID_2:
+			if (strncmp(
+				link->dpcd_caps.branch_dev_name,
+				DP_VGA_LVDS_CONVERTER_ID_2,
+				sizeof(
+				link->dpcd_caps.
+				branch_dev_name)) == 0) {
+				return DP_PANEL_MODE_SPECIAL;
+			}
+			break;
+		case DP_BRANCH_DEVICE_ID_3:
+			if (strncmp(link->dpcd_caps.branch_dev_name,
+				DP_VGA_LVDS_CONVERTER_ID_3,
+				sizeof(
+				link->dpcd_caps.
+				branch_dev_name)) == 0) {
+				return DP_PANEL_MODE_SPECIAL;
+			}
+			break;
+		default:
+			break;
+		}
+
+		if (link->dpcd_caps.panel_mode_edp) {
+			return DP_PANEL_MODE_EDP;
+		}
+	}
+
+	return DP_PANEL_MODE_DEFAULT;
+}
+
+void dp_set_hw_test_pattern(
+	struct core_link *link,
+	enum dp_test_pattern test_pattern)
+{
+	struct encoder_set_dp_phy_pattern_param pattern_param = {0};
+	struct link_encoder *encoder = link->link_enc;
+
+	pattern_param.dp_phy_pattern = test_pattern;
+	pattern_param.custom_pattern = NULL;
+	pattern_param.custom_pattern_size = 0;
+	pattern_param.dp_panel_mode = dp_get_panel_mode(link);
+
+	encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
new file mode 100644
index 000000000000..8cb756e99bfd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
@@ -0,0 +1,1243 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+#include "link_encoder.h"
+#include "stream_encoder.h"
+#include "opp.h"
+#include "transform.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce100/dce100_resource.h"
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/dce110_resource.h"
+#endif
+
+bool dc_construct_resource_pool(struct adapter_service *adapter_serv,
+				struct dc *dc,
+				uint8_t num_virtual_links)
+{
+	enum dce_version dce_ver = dal_adapter_service_get_dce_version(adapter_serv);
+
+	switch (dce_ver) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dce100_construct_resource_pool(
+			adapter_serv, num_virtual_links, dc, &dc->res_pool);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dce110_construct_resource_pool(
+			adapter_serv, num_virtual_links, dc, &dc->res_pool);
+#endif
+	default:
+		break;
+	}
+
+	return false;
+}
+
+void unreference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.clk_src_count; i++) {
+		if (res_ctx->pool.clock_sources[i] == clock_source) {
+			res_ctx->clock_source_ref_count[i]--;
+
+		if (res_ctx->clock_source_ref_count[i] == 0)
+			clock_source->funcs->cs_power_down(clock_source);
+		}
+	}
+
+
+}
+
+void reference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.clk_src_count; i++) {
+		if (res_ctx->pool.clock_sources[i] == clock_source) {
+			res_ctx->clock_source_ref_count[i]++;
+		}
+	}
+}
+
+bool is_same_timing(
+	const struct dc_crtc_timing *timing1,
+	const struct dc_crtc_timing *timing2)
+{
+	return dm_memcmp(timing1, timing2, sizeof(struct dc_crtc_timing)) == 0;
+}
+
+static bool is_sharable_clk_src(
+	const struct core_stream *stream_with_clk_src,
+	const struct core_stream *stream)
+{
+	enum clock_source_id id = stream_with_clk_src->clock_source->id;
+
+	if (stream_with_clk_src->clock_source == NULL)
+		return false;
+
+	if (id == CLOCK_SOURCE_ID_EXTERNAL)
+		return false;
+
+	/* Sharing dual link is not working */
+	if (stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK ||
+			stream_with_clk_src->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
+			return false;
+
+	if(!is_same_timing(
+		&stream_with_clk_src->public.timing, &stream->public.timing))
+		return false;
+
+	return true;
+}
+
+struct clock_source *find_used_clk_src_for_sharing(
+					struct validate_context *context,
+					struct core_stream *stream)
+{
+	uint8_t i, j;
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *clock_source_stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			if (clock_source_stream->clock_source == NULL)
+				continue;
+
+			if (is_sharable_clk_src(clock_source_stream, stream))
+				return clock_source_stream->clock_source;
+		}
+	}
+
+	return NULL;
+}
+
+static enum pixel_format convert_pixel_format_to_dalsurface(
+		enum surface_pixel_format surface_pixel_format)
+{
+	enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+
+	switch (surface_pixel_format) {
+	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
+		dal_pixel_format = PIXEL_FORMAT_INDEX8;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+		dal_pixel_format = PIXEL_FORMAT_RGB565;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+		dal_pixel_format = PIXEL_FORMAT_RGB565;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
+		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+		dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+		dal_pixel_format = PIXEL_FORMAT_FP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+		dal_pixel_format = PIXEL_FORMAT_FP16;
+		break;
+
+
+	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+		dal_pixel_format = PIXEL_FORMAT_420BPP12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+		dal_pixel_format = PIXEL_FORMAT_420BPP12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCb:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCr:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb1555:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_CrYCb565:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb4444:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA5551:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb8888:
+		dal_pixel_format = PIXEL_FORMAT_444BPP32;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb2101010:
+		dal_pixel_format = PIXEL_FORMAT_444BPP32;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA1010102:
+		dal_pixel_format = PIXEL_FORMAT_444BPP32;
+		break;
+	default:
+		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+		break;
+	}
+	return dal_pixel_format;
+}
+
+static void calculate_viewport(
+		const struct dc_surface *surface,
+		struct core_stream *stream)
+{
+	const struct rect src = surface->src_rect;
+	const struct rect clip = surface->clip_rect;
+	const struct rect dst = surface->dst_rect;
+
+	/* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
+	 * num_pixels = clip.num_pix * scl_ratio
+	 */
+	stream->viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width;
+	stream->viewport.width = clip.width * src.width / dst.width;
+
+	stream->viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height;
+	stream->viewport.height = clip.height * src.height / dst.height;
+
+	/* Minimum viewport such that 420/422 chroma vp is non 0 */
+	if (stream->viewport.width < 2)
+	{
+		stream->viewport.width = 2;
+	}
+	if (stream->viewport.height < 2)
+	{
+		stream->viewport.height = 2;
+	}
+}
+
+static void calculate_overscan(
+		const struct dc_surface *surface,
+		struct core_stream *stream)
+{
+	stream->overscan.left = stream->public.dst.x;
+	if (stream->public.src.x < surface->clip_rect.x)
+		stream->overscan.left += (surface->clip_rect.x
+			- stream->public.src.x) * stream->public.dst.width
+			/ stream->public.src.width;
+
+	stream->overscan.right = stream->public.timing.h_addressable
+		- stream->public.dst.x - stream->public.dst.width;
+	if (stream->public.src.x + stream->public.src.width
+		> surface->clip_rect.x + surface->clip_rect.width)
+		stream->overscan.right = stream->public.timing.h_addressable -
+			dal_fixed31_32_floor(dal_fixed31_32_div(
+				dal_fixed31_32_from_int(
+						stream->viewport.width),
+						stream->ratios.horz)) -
+						stream->overscan.left;
+
+
+	stream->overscan.top = stream->public.dst.y;
+	if (stream->public.src.y < surface->clip_rect.y)
+		stream->overscan.top += (surface->clip_rect.y
+			- stream->public.src.y) * stream->public.dst.height
+			/ stream->public.src.height;
+
+	stream->overscan.bottom = stream->public.timing.v_addressable
+		- stream->public.dst.y - stream->public.dst.height;
+	if (stream->public.src.y + stream->public.src.height
+		> surface->clip_rect.y + surface->clip_rect.height)
+		stream->overscan.bottom = stream->public.timing.v_addressable -
+			dal_fixed31_32_floor(dal_fixed31_32_div(
+				dal_fixed31_32_from_int(
+						stream->viewport.height),
+						stream->ratios.vert)) -
+						stream->overscan.top;
+
+
+	/* TODO: Add timing overscan to finalize overscan calculation*/
+}
+
+static void calculate_scaling_ratios(
+		const struct dc_surface *surface,
+		struct core_stream *stream)
+{
+	const uint32_t in_w = stream->public.src.width;
+	const uint32_t in_h = stream->public.src.height;
+	const uint32_t out_w = stream->public.dst.width;
+	const uint32_t out_h = stream->public.dst.height;
+
+	stream->ratios.horz = dal_fixed31_32_from_fraction(
+					surface->src_rect.width,
+					surface->dst_rect.width);
+	stream->ratios.vert = dal_fixed31_32_from_fraction(
+					surface->src_rect.height,
+					surface->dst_rect.height);
+
+	if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE)
+		stream->ratios.horz.value *= 2;
+	else if (surface->stereo_format
+					== PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
+		stream->ratios.vert.value *= 2;
+
+	stream->ratios.vert.value = div64_s64(stream->ratios.vert.value * in_h,
+			out_h);
+	stream->ratios.horz.value = div64_s64(stream->ratios.horz.value * in_w ,
+			out_w);
+
+	stream->ratios.horz_c = stream->ratios.horz;
+	stream->ratios.vert_c = stream->ratios.vert;
+
+	if (stream->format == PIXEL_FORMAT_420BPP12) {
+		stream->ratios.horz_c.value /= 2;
+		stream->ratios.vert_c.value /= 2;
+	} else if (stream->format == PIXEL_FORMAT_422BPP16) {
+		stream->ratios.horz_c.value /= 2;
+	}
+}
+
+/*TODO: per pipe not per stream*/
+void build_scaling_params(
+	const struct dc_surface *surface,
+	struct core_stream *stream)
+{
+	/* Important: scaling ratio calculation requires pixel format,
+	 * overscan calculation requires scaling ratios and viewport
+	 * and lb depth/taps calculation requires overscan. Call sequence
+	 * is therefore important */
+	stream->format = convert_pixel_format_to_dalsurface(surface->format);
+
+	calculate_viewport(surface, stream);
+
+	calculate_scaling_ratios(surface, stream);
+
+	calculate_overscan(surface, stream);
+
+	/* Check if scaling is required update taps if not */
+	if (dal_fixed31_32_u2d19(stream->ratios.horz) == 1 << 19)
+		stream->taps.h_taps = 1;
+	else
+		stream->taps.h_taps = surface->scaling_quality.h_taps;
+
+	if (dal_fixed31_32_u2d19(stream->ratios.horz_c) == 1 << 19)
+		stream->taps.h_taps_c = 1;
+	else
+		stream->taps.h_taps_c = surface->scaling_quality.h_taps_c;
+
+	if (dal_fixed31_32_u2d19(stream->ratios.vert) == 1 << 19)
+		stream->taps.v_taps = 1;
+	else
+		stream->taps.v_taps = surface->scaling_quality.v_taps;
+
+	if (dal_fixed31_32_u2d19(stream->ratios.vert_c) == 1 << 19)
+		stream->taps.v_taps_c = 1;
+	else
+		stream->taps.v_taps_c = surface->scaling_quality.v_taps_c;
+
+	dal_logger_write(stream->ctx->logger,
+				LOG_MAJOR_DCP,
+				LOG_MINOR_DCP_SCALER,
+				"%s: Overscan:\n bot:%d left:%d right:%d "
+				"top:%d\nViewport:\nheight:%d width:%d x:%d "
+				"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
+				"y:%d\n",
+				__func__,
+				stream->overscan.bottom,
+				stream->overscan.left,
+				stream->overscan.right,
+				stream->overscan.top,
+				stream->viewport.height,
+				stream->viewport.width,
+				stream->viewport.x,
+				stream->viewport.y,
+				surface->dst_rect.height,
+				surface->dst_rect.width,
+				surface->dst_rect.x,
+				surface->dst_rect.y);
+}
+
+void build_scaling_params_for_context(
+	const struct dc *dc,
+	struct validate_context *context)
+{
+	uint8_t i, j, k;
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		if (context->target_flags[i].unchanged)
+			continue;
+		for (j = 0; j < target->status.surface_count; j++) {
+			const struct dc_surface *surface =
+				target->status.surfaces[j];
+			for (k = 0; k < target->public.stream_count; k++) {
+				struct core_stream *stream =
+					DC_STREAM_TO_CORE(
+						target->public.streams[k]);
+
+				build_scaling_params(surface, stream);
+			}
+		}
+	}
+}
+
+bool logical_attach_surfaces_to_target(
+		struct dc_surface *surfaces[],
+		uint8_t surface_count,
+		struct dc_target *dc_target)
+{
+	uint8_t i;
+	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+
+	if (surface_count > MAX_SURFACE_NUM) {
+		dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
+			surface_count, MAX_SURFACE_NUM);
+		return false;
+	}
+
+	for (i = 0; i < target->status.surface_count; i++)
+		dc_surface_release(target->status.surfaces[i]);
+
+	for (i = 0; i < surface_count; i++) {
+		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
+		surface->status.dc_target = &target->public;
+		target->status.surfaces[i] = surfaces[i];
+		dc_surface_retain(target->status.surfaces[i]);
+	}
+	target->status.surface_count = surface_count;
+
+	return true;
+}
+
+static uint32_t get_min_vblank_time_us(const struct validate_context *context)
+{
+	uint8_t i, j;
+	uint32_t min_vertical_blank_time = -1;
+
+	for (i = 0; i < context->target_count; i++) {
+		const struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			const struct dc_stream *stream =
+						target->public.streams[j];
+			uint32_t vertical_blank_in_pixels = 0;
+			uint32_t vertical_blank_time = 0;
+
+			vertical_blank_in_pixels = stream->timing.h_total *
+				(stream->timing.v_total
+					- stream->timing.v_addressable);
+			vertical_blank_time = vertical_blank_in_pixels
+				* 1000 / stream->timing.pix_clk_khz;
+			if (min_vertical_blank_time > vertical_blank_time)
+				min_vertical_blank_time = vertical_blank_time;
+		}
+	}
+	return min_vertical_blank_time;
+}
+
+static void fill_display_configs(
+	const struct validate_context *context,
+	struct dc_pp_display_configuration *pp_display_cfg)
+{
+	uint8_t i, j;
+	uint8_t num_cfgs = 0;
+
+	for (i = 0; i < context->target_count; i++) {
+		const struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			const struct core_stream *stream =
+			DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct dc_pp_single_disp_config *cfg =
+					&pp_display_cfg->disp_configs[num_cfgs];
+
+			num_cfgs++;
+			cfg->signal = stream->signal;
+			cfg->pipe_idx = stream->opp->inst;
+			cfg->src_height = stream->public.src.height;
+			cfg->src_width = stream->public.src.width;
+			cfg->ddi_channel_mapping =
+				stream->sink->link->ddi_channel_mapping.raw;
+			cfg->transmitter =
+				stream->sink->link->link_enc->transmitter;
+			cfg->link_settings =
+					stream->sink->link->cur_link_settings;
+			cfg->sym_clock = stream->public.timing.pix_clk_khz;
+			switch (stream->public.timing.display_color_depth) {
+			case COLOR_DEPTH_101010:
+				cfg->sym_clock = (cfg->sym_clock * 30) / 24;
+				break;
+			case COLOR_DEPTH_121212:
+				cfg->sym_clock = (cfg->sym_clock * 36) / 24;
+				break;
+			case COLOR_DEPTH_161616:
+				cfg->sym_clock = (cfg->sym_clock * 48) / 24;
+				break;
+			default:
+				break;
+			}
+			/* TODO: unhardcode*/
+			cfg->v_refresh = 60;
+		}
+	}
+	pp_display_cfg->display_count = num_cfgs;
+}
+
+void pplib_apply_safe_state(
+	const struct dc *dc)
+{
+	dm_pp_apply_safe_state(dc->ctx);
+}
+
+void pplib_apply_display_requirements(
+	const struct dc *dc,
+	const struct validate_context *context)
+{
+	struct dc_pp_display_configuration pp_display_cfg = { 0 };
+
+	pp_display_cfg.all_displays_in_sync =
+		context->bw_results.all_displays_in_sync;
+	pp_display_cfg.nb_pstate_switch_disable =
+			context->bw_results.nbp_state_change_enable == false;
+	pp_display_cfg.cpu_cc6_disable =
+			context->bw_results.cpuc_state_change_enable == false;
+	pp_display_cfg.cpu_pstate_disable =
+			context->bw_results.cpup_state_change_enable == false;
+	pp_display_cfg.cpu_pstate_separation_time =
+			context->bw_results.required_blackout_duration_us;
+
+	pp_display_cfg.min_memory_clock_khz = context->bw_results.required_yclk
+		/ MEMORY_TYPE_MULTIPLIER;
+	pp_display_cfg.min_engine_clock_khz = context->bw_results.required_sclk;
+	pp_display_cfg.min_engine_clock_deep_sleep_khz
+			= context->bw_results.required_sclk_deep_sleep;
+
+	pp_display_cfg.avail_mclk_switch_time_us =
+						get_min_vblank_time_us(context);
+	pp_display_cfg.avail_mclk_switch_time_in_disp_active_us = 0;
+
+	pp_display_cfg.disp_clk_khz = context->bw_results.dispclk_khz;
+
+	fill_display_configs(context, &pp_display_cfg);
+
+	/* TODO: is this still applicable?*/
+	if (pp_display_cfg.display_count == 1) {
+		const struct dc_crtc_timing *timing =
+			&context->targets[0]->public.streams[0]->timing;
+
+		pp_display_cfg.crtc_index =
+			pp_display_cfg.disp_configs[0].pipe_idx;
+		pp_display_cfg.line_time_in_us = timing->h_total * 1000
+							/ timing->pix_clk_khz;
+	}
+
+	dm_pp_apply_display_requirements(dc->ctx, &pp_display_cfg);
+}
+
+/* Maximum TMDS single link pixel clock 165MHz */
+#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
+
+static void attach_stream_to_controller(
+		struct resource_context *res_ctx,
+		struct core_stream *stream)
+{
+	res_ctx->controller_ctx[stream->controller_idx].stream = stream;
+}
+
+static void set_stream_engine_in_use(
+		struct resource_context *res_ctx,
+		struct stream_encoder *stream_enc)
+{
+	int i;
+
+	for (i = 0; i < res_ctx->pool.stream_enc_count; i++) {
+		if (res_ctx->pool.stream_enc[i] == stream_enc)
+			res_ctx->is_stream_enc_acquired[i] = true;
+	}
+}
+
+/* TODO: release audio object */
+static void set_audio_in_use(
+		struct resource_context *res_ctx,
+		struct audio *audio)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.audio_count; i++) {
+		if (res_ctx->pool.audios[i] == audio) {
+			res_ctx->is_audio_acquired[i] = true;
+		}
+	}
+}
+
+static bool assign_first_free_controller(
+		struct resource_context *res_ctx,
+		struct core_stream *stream)
+{
+	uint8_t i;
+	for (i = 0; i < res_ctx->pool.controller_count; i++) {
+		if (!res_ctx->controller_ctx[i].stream) {
+			stream->tg = res_ctx->pool.timing_generators[i];
+			stream->mi = res_ctx->pool.mis[i];
+			stream->ipp = res_ctx->pool.ipps[i];
+			stream->xfm = res_ctx->pool.transforms[i];
+			stream->opp = res_ctx->pool.opps[i];
+			stream->controller_idx = i;
+			stream->dis_clk = res_ctx->pool.display_clock;
+			return true;
+		}
+	}
+	return false;
+}
+
+static struct stream_encoder *find_first_free_match_stream_enc_for_link(
+		struct resource_context *res_ctx,
+		struct core_link *link)
+{
+	uint8_t i;
+	int8_t j = -1;
+	const struct dc_sink *sink = NULL;
+
+	for (i = 0; i < res_ctx->pool.stream_enc_count; i++) {
+		if (!res_ctx->is_stream_enc_acquired[i] &&
+					res_ctx->pool.stream_enc[i]) {
+			/* Store first available for MST second display
+			 * in daisy chain use case */
+			j = i;
+			if (res_ctx->pool.stream_enc[i]->id ==
+					link->link_enc->preferred_engine)
+				return res_ctx->pool.stream_enc[i];
+		}
+	}
+
+	/*
+	 * below can happen in cases when stream encoder is acquired:
+	 * 1) for second MST display in chain, so preferred engine already
+	 * acquired;
+	 * 2) for another link, which preferred engine already acquired by any
+	 * MST configuration.
+	 *
+	 * If signal is of DP type and preferred engine not found, return last available
+	 *
+	 * TODO - This is just a patch up and a generic solution is
+	 * required for non DP connectors.
+	 */
+
+	sink = link->public.local_sink ? link->public.local_sink : link->public.remote_sinks[0];
+
+	if (sink && j >= 0 &&  dc_is_dp_signal(sink->sink_signal))
+		return res_ctx->pool.stream_enc[j];
+
+	return NULL;
+}
+
+static struct audio *find_first_free_audio(struct resource_context *res_ctx)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.audio_count; i++) {
+		if (res_ctx->is_audio_acquired[i] == false) {
+			return res_ctx->pool.audios[i];
+		}
+	}
+
+	return 0;
+}
+
+static bool check_timing_change(struct core_stream *cur_stream,
+		struct core_stream *new_stream)
+{
+	if (cur_stream == NULL)
+		return true;
+
+	/* If sink pointer changed, it means this is a hotplug, we should do
+	 * full hw setting.
+	 */
+	if (cur_stream->sink != new_stream->sink)
+		return true;
+
+	return !is_same_timing(
+					&cur_stream->public.timing,
+					&new_stream->public.timing);
+}
+
+static void set_stream_signal(struct core_stream *stream)
+{
+	struct dc_sink *dc_sink = (struct dc_sink *)stream->public.sink;
+
+	/* For asic supports dual link DVI, we should adjust signal type
+	 * based on timing pixel clock. If pixel clock more than 165Mhz,
+	 * signal is dual link, otherwise, single link.
+	 */
+	if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
+			dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) {
+		if (stream->public.timing.pix_clk_khz >
+			TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
+			dc_sink->sink_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+		else
+			dc_sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+	}
+
+	stream->signal = dc_sink->sink_signal;
+}
+
+enum dc_status map_resources(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	uint8_t i, j;
+
+	/* mark resources used for targets that are already active */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (!context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			attach_stream_to_controller(
+				&context->res_ctx,
+				stream);
+
+			set_stream_engine_in_use(
+				&context->res_ctx,
+				stream->stream_enc);
+
+			reference_clock_source(
+				&context->res_ctx,
+				stream->clock_source);
+
+			if (stream->audio) {
+				set_audio_in_use(&context->res_ctx,
+					stream->audio);
+			}
+		}
+	}
+
+	/* acquire new resources */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct core_stream *curr_stream;
+
+			if (!assign_first_free_controller(
+					&context->res_ctx, stream))
+				return DC_NO_CONTROLLER_RESOURCE;
+
+			attach_stream_to_controller(&context->res_ctx, stream);
+
+			set_stream_signal(stream);
+
+			curr_stream =
+				dc->current_context.res_ctx.controller_ctx
+				[stream->controller_idx].stream;
+			context->res_ctx.controller_ctx[stream->controller_idx]
+			.flags.timing_changed =
+				check_timing_change(curr_stream, stream);
+
+			stream->stream_enc =
+				find_first_free_match_stream_enc_for_link(
+					&context->res_ctx,
+					stream->sink->link);
+
+			if (!stream->stream_enc)
+				return DC_NO_STREAM_ENG_RESOURCE;
+
+			set_stream_engine_in_use(
+					&context->res_ctx,
+					stream->stream_enc);
+
+			/* TODO: Add check if ASIC support and EDID audio */
+			if (!stream->sink->converter_disable_audio &&
+						dc_is_audio_capable_signal(
+						stream->signal)) {
+				stream->audio = find_first_free_audio(
+						&context->res_ctx);
+
+				if (!stream->audio)
+					return DC_NO_STREAM_AUDIO_RESOURCE;
+
+				set_audio_in_use(&context->res_ctx,
+						stream->audio);
+			}
+		}
+	}
+
+	return DC_OK;
+}
+
+static enum ds_color_space build_default_color_space(
+		struct core_stream *stream)
+{
+	enum ds_color_space color_space =
+			DS_COLOR_SPACE_SRGB_FULLRANGE;
+	struct dc_crtc_timing *timing = &stream->public.timing;
+
+	switch (stream->signal) {
+	/* TODO: implement other signal color space setting */
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	{
+		uint32_t pix_clk_khz;
+
+		if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 &&
+			timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) {
+			if (timing->timing_standard ==
+					TIMING_STANDARD_CEA770 &&
+				timing->timing_standard ==
+						TIMING_STANDARD_CEA861)
+				color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+
+			pix_clk_khz = timing->pix_clk_khz / 10;
+			if (timing->h_addressable == 640 &&
+				timing->v_addressable == 480 &&
+				(pix_clk_khz == 2520 || pix_clk_khz == 2517))
+				color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+		} else {
+			if (timing->timing_standard ==
+					TIMING_STANDARD_CEA770 ||
+					timing->timing_standard ==
+					TIMING_STANDARD_CEA861) {
+
+				color_space =
+					(timing->pix_clk_khz > PIXEL_CLOCK) ?
+						DS_COLOR_SPACE_YCBCR709 :
+						DS_COLOR_SPACE_YCBCR601;
+			}
+		}
+		break;
+	}
+	default:
+		switch (timing->pixel_encoding) {
+		case PIXEL_ENCODING_YCBCR422:
+		case PIXEL_ENCODING_YCBCR444:
+			if (timing->pix_clk_khz > PIXEL_CLOCK)
+				color_space = DS_COLOR_SPACE_YCBCR709;
+			else
+				color_space = DS_COLOR_SPACE_YCBCR601;
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+	return color_space;
+}
+
+static void translate_info_frame(const struct hw_info_frame *hw_info_frame,
+	struct encoder_info_frame *encoder_info_frame)
+{
+	dm_memset(
+		encoder_info_frame, 0, sizeof(struct encoder_info_frame));
+
+	/* For gamut we recalc checksum */
+	if (hw_info_frame->gamut_packet.valid) {
+		uint8_t chk_sum = 0;
+		uint8_t *ptr;
+		uint8_t i;
+
+		dm_memmove(
+						&encoder_info_frame->gamut,
+						&hw_info_frame->gamut_packet,
+						sizeof(struct hw_info_packet));
+
+		/*start of the Gamut data. */
+		ptr = &encoder_info_frame->gamut.sb[3];
+
+		for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++)
+			chk_sum += ptr[i];
+
+		encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum);
+	}
+
+	if (hw_info_frame->avi_info_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->avi,
+						&hw_info_frame->avi_info_packet,
+						sizeof(struct hw_info_packet));
+	}
+
+	if (hw_info_frame->vendor_info_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->vendor,
+						&hw_info_frame->vendor_info_packet,
+						sizeof(struct hw_info_packet));
+	}
+
+	if (hw_info_frame->spd_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->spd,
+						&hw_info_frame->spd_packet,
+						sizeof(struct hw_info_packet));
+	}
+
+	if (hw_info_frame->vsc_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->vsc,
+						&hw_info_frame->vsc_packet,
+						sizeof(struct hw_info_packet));
+	}
+}
+
+static void set_avi_info_frame(struct hw_info_packet *info_packet,
+		struct core_stream *stream)
+{
+	enum ds_color_space color_space = DS_COLOR_SPACE_UNKNOWN;
+	struct info_frame info_frame = { {0} };
+	uint32_t pixel_encoding = 0;
+	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
+	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
+	bool itc = false;
+	uint8_t cn0_cn1 = 0;
+	uint8_t *check_sum = NULL;
+	uint8_t byte_index = 0;
+
+	if (info_packet == NULL)
+		return;
+
+	color_space = build_default_color_space(stream);
+
+	/* Initialize header */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.header.
+			info_frame_type = INFO_FRAME_AVI;
+	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
+	* not be used in HDMI 2.0 (Section 10.1) */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.header.version =
+			INFO_FRAME_VERSION_2;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.header.length =
+			INFO_FRAME_SIZE_AVI;
+
+	/* IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
+	* according to HDMI 2.0 spec (Section 10.1)
+	* Add "case PixelEncoding_YCbCr420:    pixelEncoding = 3; break;"
+	* when YCbCr 4:2:0 is supported by DAL hardware. */
+
+	switch (stream->public.timing.pixel_encoding) {
+	case PIXEL_ENCODING_YCBCR422:
+		pixel_encoding = 1;
+		break;
+
+	case PIXEL_ENCODING_YCBCR444:
+		pixel_encoding = 2;
+		break;
+
+	case PIXEL_ENCODING_RGB:
+	default:
+		pixel_encoding = 0;
+	}
+
+	/* Y0_Y1_Y2 : The pixel encoding */
+	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 =
+		pixel_encoding;
+
+
+	/* A0 = 1 Active Format Information valid */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.A0 =
+		ACTIVE_FORMAT_VALID;
+
+	/* B0, B1 = 3; Bar info data is valid */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 =
+		BAR_INFO_BOTH_VALID;
+
+	info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 =
+			PICTURE_SCALING_UNIFORM;
+
+	/* S0, S1 : Underscan / Overscan */
+	/* TODO: un-hardcode scan type */
+	scan_type = SCANNING_TYPE_UNDERSCAN;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type;
+
+	/* C0, C1 : Colorimetry */
+	if (color_space == DS_COLOR_SPACE_YCBCR709)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_ITU709;
+	else if (color_space == DS_COLOR_SPACE_YCBCR601)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_ITU601;
+	else
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_NO_DATA;
+
+
+	/* TODO: un-hardcode aspect ratio */
+	aspect = stream->public.timing.aspect_ratio;
+
+	switch (aspect) {
+	case ASPECT_RATIO_4_3:
+	case ASPECT_RATIO_16_9:
+		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect;
+		break;
+
+	case ASPECT_RATIO_NO_DATA:
+	case ASPECT_RATIO_64_27:
+	case ASPECT_RATIO_256_135:
+	default:
+		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0;
+	}
+
+	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 =
+			ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
+
+	/* TODO: un-hardcode cn0_cn1 and itc */
+	cn0_cn1 = 0;
+	itc = false;
+
+	if (itc) {
+		info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1;
+		info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 =
+			cn0_cn1;
+	}
+
+	/* TODO: un-hardcode q0_q1 */
+	if (color_space == DS_COLOR_SPACE_SRGB_FULLRANGE)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
+						RGB_QUANTIZATION_FULL_RANGE;
+	else if (color_space == DS_COLOR_SPACE_SRGB_LIMITEDRANGE)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
+						RGB_QUANTIZATION_LIMITED_RANGE;
+	else
+		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
+						RGB_QUANTIZATION_DEFAULT_RANGE;
+
+	/* TODO : We should handle YCC quantization,
+	 * but we do not have matrix calculation */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
+					YYC_QUANTIZATION_LIMITED_RANGE;
+
+	info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 =
+					stream->public.timing.vic;
+
+	/* pixel repetition
+	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
+	 * repetition start from 1 */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0;
+
+	/* Bar Info
+	 * barTop:    Line Number of End of Top Bar.
+	 * barBottom: Line Number of Start of Bottom Bar.
+	 * barLeft:   Pixel Number of End of Left Bar.
+	 * barRight:  Pixel Number of Start of Right Bar. */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top =
+			stream->public.timing.v_border_top;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom =
+		(stream->public.timing.v_border_top
+			- stream->public.timing.v_border_bottom + 1);
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left =
+			stream->public.timing.h_border_left;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right =
+		(stream->public.timing.h_total
+			- stream->public.timing.h_border_right + 1);
+
+	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
+	check_sum =
+		&info_frame.
+		avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
+	*check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI
+			+ INFO_FRAME_VERSION_2;
+
+	for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++)
+		*check_sum += info_frame.avi_info_packet.info_packet_hdmi.
+				packet_raw_data.sb[byte_index];
+
+	/* one byte complement */
+	*check_sum = (uint8_t) (0x100 - *check_sum);
+
+	/* Store in hw_path_mode */
+	info_packet->hb0 =
+		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0;
+	info_packet->hb1 =
+		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1;
+	info_packet->hb2 =
+		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2;
+
+	for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++)
+		info_packet->sb[byte_index] = info_frame.avi_info_packet.
+		info_packet_hdmi.packet_raw_data.sb[byte_index];
+
+	info_packet->valid = true;
+}
+
+static void set_vendor_info_packet(struct core_stream *stream,
+		struct hw_info_packet *info_packet)
+{
+	uint32_t length = 0;
+	bool hdmi_vic_mode = false;
+	uint8_t checksum = 0;
+	uint32_t i = 0;
+	enum dc_timing_3d_format format;
+
+	ASSERT_CRITICAL(stream != NULL);
+	ASSERT_CRITICAL(info_packet != NULL);
+
+	format = stream->public.timing.timing_3d_format;
+
+	/* Can be different depending on packet content */
+	length = 5;
+
+	if (stream->public.timing.hdmi_vic != 0
+			&& stream->public.timing.h_total >= 3840
+			&& stream->public.timing.v_total >= 2160)
+		hdmi_vic_mode = true;
+
+	/* According to HDMI 1.4a CTS, VSIF should be sent
+	 * for both 3D stereo and HDMI VIC modes.
+	 * For all other modes, there is no VSIF sent.  */
+
+	if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
+		return;
+
+	/* 24bit IEEE Registration identifier (0x000c03). LSB first. */
+	info_packet->sb[1] = 0x03;
+	info_packet->sb[2] = 0x0C;
+	info_packet->sb[3] = 0x00;
+
+	/*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
+	 * The value for HDMI_Video_Format are:
+	 * 0x0 (0b000) - No additional HDMI video format is presented in this
+	 * packet
+	 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
+	 * parameter follows
+	 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
+	 * potentially 3D_Ext_Data follows
+	 * 0x3..0x7 (0b011..0b111) - reserved for future use */
+	if (format != TIMING_3D_FORMAT_NONE)
+		info_packet->sb[4] = (2 << 5);
+	else if (hdmi_vic_mode)
+		info_packet->sb[4] = (1 << 5);
+
+	/* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
+	 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
+	 * The value for 3D_Structure are:
+	 * 0x0 - Frame Packing
+	 * 0x1 - Field Alternative
+	 * 0x2 - Line Alternative
+	 * 0x3 - Side-by-Side (full)
+	 * 0x4 - L + depth
+	 * 0x5 - L + depth + graphics + graphics-depth
+	 * 0x6 - Top-and-Bottom
+	 * 0x7 - Reserved for future use
+	 * 0x8 - Side-by-Side (Half)
+	 * 0x9..0xE - Reserved for future use
+	 * 0xF - Not used */
+	switch (format) {
+	case TIMING_3D_FORMAT_HW_FRAME_PACKING:
+	case TIMING_3D_FORMAT_SW_FRAME_PACKING:
+		info_packet->sb[5] = (0x0 << 4);
+		break;
+
+	case TIMING_3D_FORMAT_SIDE_BY_SIDE:
+	case TIMING_3D_FORMAT_SBS_SW_PACKED:
+		info_packet->sb[5] = (0x8 << 4);
+		length = 6;
+		break;
+
+	case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
+	case TIMING_3D_FORMAT_TB_SW_PACKED:
+		info_packet->sb[5] = (0x6 << 4);
+		break;
+
+	default:
+		break;
+	}
+
+	/*PB5: If PB4 is set to 0x1 (extended resolution format)
+	 * fill PB5 with the correct HDMI VIC code */
+	if (hdmi_vic_mode)
+		info_packet->sb[5] = stream->public.timing.hdmi_vic;
+
+	/* Header */
+	info_packet->hb0 = 0x81; /* VSIF packet type. */
+	info_packet->hb1 = 0x01; /* Version */
+
+	/* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
+	info_packet->hb2 = (uint8_t) (length);
+
+	/* Calculate checksum */
+	checksum = 0;
+	checksum += info_packet->hb0;
+	checksum += info_packet->hb1;
+	checksum += info_packet->hb2;
+
+	for (i = 1; i <= length; i++)
+		checksum += info_packet->sb[i];
+
+	info_packet->sb[0] = (uint8_t) (0x100 - checksum);
+
+	info_packet->valid = true;
+}
+
+void build_info_frame(struct core_stream *stream)
+{
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+	struct hw_info_frame info_frame = { { 0 } };
+
+	/* default all packets to invalid */
+	info_frame.avi_info_packet.valid = false;
+	info_frame.gamut_packet.valid = false;
+	info_frame.vendor_info_packet.valid = false;
+	info_frame.spd_packet.valid = false;
+	info_frame.vsc_packet.valid = false;
+
+	signal = stream->sink->public.sink_signal;
+
+	/* HDMi and DP have different info packets*/
+	if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+		set_avi_info_frame(&info_frame.avi_info_packet,
+				stream);
+		set_vendor_info_packet(stream, &info_frame.vendor_info_packet);
+	}
+
+	translate_info_frame(&info_frame,
+			&stream->encoder_info_frame);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c b/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
new file mode 100644
index 000000000000..c5a770e61812
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "core_types.h"
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+
+struct sink {
+	struct core_sink protected;
+	int ref_count;
+};
+
+#define DC_SINK_TO_SINK(dc_sink) \
+			container_of(dc_sink, struct sink, protected.public)
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+
+static void destruct(struct sink *sink)
+{
+
+}
+
+static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params)
+{
+
+	struct core_link *core_link = DC_LINK_TO_LINK(init_params->link);
+
+	sink->protected.public.sink_signal = init_params->sink_signal;
+	sink->protected.link = core_link;
+	sink->protected.ctx = core_link->ctx;
+	sink->protected.dongle_max_pix_clk = init_params->dongle_max_pix_clk;
+	sink->protected.converter_disable_audio =
+			init_params->converter_disable_audio;
+
+	return true;
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+void dc_sink_retain(const struct dc_sink *dc_sink)
+{
+	struct sink *sink = DC_SINK_TO_SINK(dc_sink);
+
+	++sink->ref_count;
+}
+
+void dc_sink_release(const struct dc_sink *dc_sink)
+{
+	struct core_sink *core_sink = DC_SINK_TO_CORE(dc_sink);
+	struct sink *sink = DC_SINK_TO_SINK(dc_sink);
+
+	--sink->ref_count;
+
+	if (sink->ref_count == 0) {
+		destruct(sink);
+		dm_free(core_sink->ctx, sink);
+	}
+}
+
+struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params)
+{
+	struct core_link *core_link = DC_LINK_TO_LINK(init_params->link);
+
+	struct sink *sink = dm_alloc(core_link->ctx, sizeof(*sink));
+
+	if (NULL == sink)
+		goto alloc_fail;
+
+	if (false == construct(sink, init_params))
+		goto construct_fail;
+
+	/* TODO should we move this outside to where the assignment actually happens? */
+	dc_sink_retain(&sink->protected.public);
+
+	return &sink->protected.public;
+
+construct_fail:
+	dm_free(core_link->ctx, sink);
+
+alloc_fail:
+	return NULL;
+}
+
+/*******************************************************************************
+ * Protected functions - visible only inside of DC (not visible in DM)
+ ******************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c b/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
new file mode 100644
index 000000000000..d7012bcda10a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dc.h"
+#include "core_types.h"
+#include "resource.h"
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+
+struct stream {
+	struct core_stream protected;
+	int ref_count;
+};
+
+#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected.public)
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static void build_bit_depth_reduction_params(
+		const struct core_stream *stream,
+		struct bit_depth_reduction_params *fmt_bit_depth)
+{
+	dm_memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
+
+	/*TODO: Need to un-hardcode, refer to function with same name
+	 * in dal2 hw_sequencer*/
+
+	fmt_bit_depth->flags.TRUNCATE_ENABLED = 0;
+	fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 0;
+	fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 0;
+
+	/* Diagnostics need consistent CRC of the image, that means
+	 * dithering should not be enabled for Diagnostics. */
+	if (IS_DIAG_DC(stream->ctx->dce_environment) == false) {
+
+		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
+		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
+
+		/* frame random is on by default */
+		fmt_bit_depth->flags.FRAME_RANDOM = 1;
+		/* apply RGB dithering */
+		fmt_bit_depth->flags.RGB_RANDOM = true;
+	}
+
+	return;
+}
+
+static void setup_pixel_encoding(
+	struct clamping_and_pixel_encoding_params *clamping)
+{
+	/*TODO: Need to un-hardcode, refer to function with same name
+		 * in dal2 hw_sequencer*/
+
+	clamping->pixel_encoding = PIXEL_ENCODING_RGB;
+
+	return;
+}
+
+static bool construct(struct core_stream *stream,
+	const struct dc_sink *dc_sink_data)
+{
+	uint32_t i = 0;
+
+	stream->sink = DC_SINK_TO_CORE(dc_sink_data);
+	stream->ctx = stream->sink->ctx;
+	stream->public.sink = dc_sink_data;
+
+	dc_sink_retain(dc_sink_data);
+
+	build_bit_depth_reduction_params(stream, &stream->bit_depth_params);
+	setup_pixel_encoding(&stream->clamping);
+
+	/* Copy audio modes */
+	/* TODO - Remove this translation */
+	for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++)
+	{
+		stream->public.audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count;
+		stream->public.audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code;
+		stream->public.audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate;
+		stream->public.audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size;
+	}
+	stream->public.audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count;
+	stream->public.audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency;
+	stream->public.audio_info.video_latency = dc_sink_data->edid_caps.video_latency;
+	dm_memmove(
+		stream->public.audio_info.display_name,
+		dc_sink_data->edid_caps.display_name,
+		AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
+	stream->public.audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id;
+	stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id;
+	stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags;
+
+	/* TODO - Unhardcode port_id */
+	stream->public.audio_info.port_id[0] = 0x5558859e;
+	stream->public.audio_info.port_id[1] = 0xd989449;
+
+	/* EDID CAP translation for HDMI 2.0 */
+	stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
+	return true;
+}
+
+static void destruct(struct core_stream *stream)
+{
+	dc_sink_release(&stream->sink->public);
+}
+
+void dc_stream_retain(struct dc_stream *dc_stream)
+{
+	struct stream *stream = DC_STREAM_TO_STREAM(dc_stream);
+	stream->ref_count++;
+}
+
+void dc_stream_release(struct dc_stream *public)
+{
+	struct stream *stream = DC_STREAM_TO_STREAM(public);
+	struct core_stream *protected = DC_STREAM_TO_CORE(public);
+	struct dc_context *ctx = protected->ctx;
+	stream->ref_count--;
+
+	if (stream->ref_count == 0) {
+		destruct(protected);
+		dm_free(ctx, stream);
+	}
+}
+
+struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink)
+{
+	struct core_sink *sink = DC_SINK_TO_CORE(dc_sink);
+	struct stream *stream;
+
+	if (sink == NULL)
+		goto alloc_fail;
+
+	stream = dm_alloc(sink->ctx, sizeof(struct stream));
+
+	if (NULL == stream)
+		goto alloc_fail;
+
+	if (false == construct(&stream->protected, dc_sink))
+			goto construct_fail;
+
+	dc_stream_retain(&stream->protected.public);
+
+	return &stream->protected.public;
+
+construct_fail:
+	dm_free(sink->ctx, stream);
+
+alloc_fail:
+	return NULL;
+}
+
+void dc_update_stream(const struct dc_stream *dc_stream,
+		struct rect *src,
+		struct rect *dst)
+{
+	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
+
+	stream->public.src = *src;
+	stream->public.dst = *dst;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
new file mode 100644
index 000000000000..1a9ee8f97757
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/* DC interface (public) */
+#include "dm_services.h"
+#include "dc.h"
+
+/* DC core (private) */
+#include "core_dc.h"
+#include "inc/transform.h"
+
+/*******************************************************************************
+ * Private structures
+ ******************************************************************************/
+struct surface {
+	struct core_surface protected;
+	enum dc_irq_source irq_source;
+	int ref_count;
+};
+
+#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public)
+#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected)
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static bool construct(struct dc_context *ctx, struct surface *surface)
+{
+	uint32_t i;
+	struct gamma_ramp *gamma =
+			&surface->protected.public.gamma_correction;
+
+	/* construct gamma default value. */
+	for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) {
+		gamma->gamma_ramp_rgb256x3x16.red[i] =
+				(unsigned short) (i << 8);
+		gamma->gamma_ramp_rgb256x3x16.green[i] =
+				(unsigned short) (i << 8);
+		gamma->gamma_ramp_rgb256x3x16.blue[i] =
+				(unsigned short) (i << 8);
+	}
+	gamma->type = GAMMA_RAMP_TYPE_RGB256;
+	gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
+
+	surface->protected.ctx = ctx;
+	return true;
+}
+
+static void destruct(struct surface *surface)
+{
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+void enable_surface_flip_reporting(struct dc_surface *dc_surface,
+		uint32_t controller_id)
+{
+	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
+	surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1;
+	/*register_flip_interrupt(surface);*/
+}
+
+struct dc_surface *dc_create_surface(const struct dc *dc)
+{
+	struct surface *surface = dm_alloc(dc->ctx, sizeof(*surface));
+
+	if (NULL == surface)
+		goto alloc_fail;
+
+	if (false == construct(dc->ctx, surface))
+		goto construct_fail;
+
+	dc_surface_retain(&surface->protected.public);
+
+	return &surface->protected.public;
+
+construct_fail:
+	dm_free(dc->ctx, surface);
+
+alloc_fail:
+	return NULL;
+}
+
+void dc_surface_retain(const struct dc_surface *dc_surface)
+{
+	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
+
+	++surface->ref_count;
+}
+
+void dc_surface_release(const struct dc_surface *dc_surface)
+{
+	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
+	--surface->ref_count;
+
+	if (surface->ref_count == 0) {
+		destruct(surface);
+		dm_free(surface->protected.ctx, surface);
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
new file mode 100644
index 000000000000..e93e73d13448
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
@@ -0,0 +1,548 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "core_types.h"
+#include "hw_sequencer.h"
+#include "resource.h"
+#include "ipp.h"
+#include "timing_generator.h"
+
+#define COEFF_RANGE	3
+#define REGAMMA_COEFF_A0	31308
+#define REGAMMA_COEFF_A1	12920
+#define REGAMMA_COEFF_A2	55
+#define REGAMMA_COEFF_A3	55
+#define REGAMMA_COEFF_GAMMA	2400
+
+struct target {
+	struct core_target protected;
+	int ref_count;
+};
+
+#define DC_TARGET_TO_TARGET(dc_target) \
+	container_of(dc_target, struct target, protected.public)
+#define CORE_TARGET_TO_TARGET(core_target) \
+	container_of(core_target, struct target, protected)
+
+static void construct(
+	struct core_target *target,
+	struct dc_context *ctx,
+	struct dc_stream *dc_streams[],
+	uint8_t stream_count)
+{
+	uint8_t i;
+	for (i = 0; i < stream_count; i++) {
+		target->public.streams[i] = dc_streams[i];
+		dc_stream_retain(dc_streams[i]);
+	}
+
+	target->ctx = ctx;
+	target->public.stream_count = stream_count;
+}
+
+static void destruct(struct core_target *core_target)
+{
+	int i;
+
+	for (i = 0; i < core_target->status.surface_count; i++) {
+		dc_surface_release(core_target->status.surfaces[i]);
+		core_target->status.surfaces[i] = NULL;
+	}
+	for (i = 0; i < core_target->public.stream_count; i++) {
+		dc_stream_release(
+			(struct dc_stream *)core_target->public.streams[i]);
+		core_target->public.streams[i] = NULL;
+	}
+}
+
+void dc_target_retain(struct dc_target *dc_target)
+{
+	struct target *target = DC_TARGET_TO_TARGET(dc_target);
+
+	target->ref_count++;
+}
+
+void dc_target_release(struct dc_target *dc_target)
+{
+	struct target *target = DC_TARGET_TO_TARGET(dc_target);
+	struct core_target *protected = DC_TARGET_TO_CORE(dc_target);
+
+	ASSERT(target->ref_count > 0);
+	target->ref_count--;
+	if (target->ref_count == 0) {
+		destruct(protected);
+		dm_free(protected->ctx, target);
+	}
+}
+
+const struct dc_target_status *dc_target_get_status(
+					const struct dc_target* dc_target)
+{
+	struct core_target* target = DC_TARGET_TO_CORE(dc_target);
+	return &target->status;
+}
+
+struct dc_target *dc_create_target_for_streams(
+		struct dc_stream *dc_streams[],
+		uint8_t stream_count)
+{
+	struct core_stream *stream;
+	struct target *target;
+
+	if (0 == stream_count)
+		goto target_alloc_fail;
+
+	stream = DC_STREAM_TO_CORE(dc_streams[0]);
+
+	target = dm_alloc(stream->ctx, sizeof(struct target));
+
+	if (NULL == target)
+		goto target_alloc_fail;
+
+	construct(&target->protected, stream->ctx, dc_streams, stream_count);
+
+	dc_target_retain(&target->protected.public);
+
+	return &target->protected.public;
+
+
+target_alloc_fail:
+	return NULL;
+}
+
+static void build_gamma_params(
+		enum pixel_format pixel_format,
+		struct gamma_parameters *gamma_param)
+{
+	uint32_t i;
+
+	/* translate parameters */
+	gamma_param->surface_pixel_format = pixel_format;
+
+	gamma_param->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW;
+	gamma_param->degamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW;
+
+	gamma_param->selected_gamma_lut = GRAPHICS_GAMMA_LUT_REGAMMA;
+
+	/* TODO support non-legacy gamma */
+	gamma_param->disable_adjustments = false;
+	gamma_param->flag.bits.config_is_changed = 0;
+	gamma_param->flag.bits.regamma_update = 1;
+	gamma_param->flag.bits.gamma_update = 1;
+
+	/* Set regamma */
+	gamma_param->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 1;
+	gamma_param->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 1;
+	gamma_param->regamma.features.bits.GAMMA_RAMP_ARRAY = 0;
+	gamma_param->regamma.features.bits.APPLY_DEGAMMA = 0;
+
+	for (i = 0; i < COEFF_RANGE; i++) {
+		gamma_param->regamma.gamma_coeff.a0[i] = REGAMMA_COEFF_A0;
+		gamma_param->regamma.gamma_coeff.a1[i] = REGAMMA_COEFF_A1;
+		gamma_param->regamma.gamma_coeff.a2[i] = REGAMMA_COEFF_A2;
+		gamma_param->regamma.gamma_coeff.a3[i] = REGAMMA_COEFF_A3;
+		gamma_param->regamma.gamma_coeff.gamma[i] = REGAMMA_COEFF_GAMMA;
+	}
+}
+
+
+static bool program_gamma(
+		struct dc_context *ctx,
+		struct dc_surface *surface,
+		struct input_pixel_processor *ipp,
+		struct output_pixel_processor *opp)
+{
+	struct gamma_parameters *gamma_param;
+	bool result= false;
+
+	gamma_param = dm_alloc(ctx, sizeof(struct gamma_parameters));
+
+	if (!gamma_param)
+		goto gamma_param_fail;
+
+	build_gamma_params(surface->format, gamma_param);
+
+	result = ctx->dc->hwss.set_gamma_ramp(ipp, opp,
+			&surface->gamma_correction,
+			gamma_param);
+
+	dm_free(ctx, gamma_param);
+
+gamma_param_fail:
+	return result;
+}
+
+static bool validate_surface_address(
+		struct dc_plane_address address)
+{
+	bool is_valid_address = false;
+
+	switch (address.type) {
+	case PLN_ADDR_TYPE_GRAPHICS:
+		if (address.grph.addr.quad_part != 0)
+			is_valid_address = true;
+		break;
+	case PLN_ADDR_TYPE_GRPH_STEREO:
+		if ((address.grph_stereo.left_addr.quad_part != 0) &&
+			(address.grph_stereo.right_addr.quad_part != 0)) {
+			is_valid_address = true;
+		}
+		break;
+	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
+	default:
+		/* not supported */
+		BREAK_TO_DEBUGGER();
+		break;
+	}
+
+	return is_valid_address;
+}
+
+bool dc_commit_surfaces_to_target(
+		struct dc *dc,
+		struct dc_surface *new_surfaces[],
+		uint8_t new_surface_count,
+		struct dc_target *dc_target)
+
+{
+	int i, j;
+	uint32_t prev_disp_clk = dc->current_context.bw_results.dispclk_khz;
+	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+
+	int current_enabled_surface_count = 0;
+	int new_enabled_surface_count = 0;
+
+	if (!dal_adapter_service_is_in_accelerated_mode(
+						dc->res_pool.adapter_srv) ||
+			dc->current_context.target_count == 0) {
+		return false;
+	}
+
+	for (i = 0; i < dc->current_context.target_count; i++)
+		if (target == dc->current_context.targets[i])
+			break;
+
+	/* Cannot commit surface to a target that is not commited */
+	if (i == dc->current_context.target_count)
+		return false;
+
+	for (i = 0; i < target->status.surface_count; i++)
+		if (target->status.surfaces[i]->visible)
+			current_enabled_surface_count++;
+
+	for (i = 0; i < new_surface_count; i++)
+		if (new_surfaces[i]->visible)
+			new_enabled_surface_count++;
+
+	dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_INTERFACE_TRACE,
+				LOG_MINOR_COMPONENT_DC,
+				"%s: commit %d surfaces to target 0x%x\n",
+				__func__,
+				new_surface_count,
+				dc_target);
+
+
+	if (!logical_attach_surfaces_to_target(
+						new_surfaces,
+						new_surface_count,
+						dc_target)) {
+		BREAK_TO_DEBUGGER();
+		goto unexpected_fail;
+	}
+
+	for (i = 0; i < new_surface_count; i++)
+		for (j = 0; j < target->public.stream_count; j++)
+			build_scaling_params(
+				new_surfaces[i],
+				DC_STREAM_TO_CORE(target->public.streams[j]));
+
+	if (dc->res_pool.funcs->validate_bandwidth(dc, &dc->current_context)
+								!= DC_OK) {
+		BREAK_TO_DEBUGGER();
+		goto unexpected_fail;
+	}
+
+	if (prev_disp_clk < dc->current_context.bw_results.dispclk_khz) {
+		dc->hwss.program_bw(dc, &dc->current_context);
+		pplib_apply_display_requirements(dc, &dc->current_context);
+	}
+
+	if (current_enabled_surface_count > 0 && new_enabled_surface_count == 0)
+		dc_target_disable_memory_requests(dc_target);
+
+	for (i = 0; i < new_surface_count; i++) {
+		struct dc_surface *surface = new_surfaces[i];
+		struct core_surface *core_surface = DC_SURFACE_TO_CORE(surface);
+		bool is_valid_address =
+				validate_surface_address(surface->address);
+
+		dal_logger_write(dc->ctx->logger,
+					LOG_MAJOR_INTERFACE_TRACE,
+					LOG_MINOR_COMPONENT_DC,
+					"0x%x:",
+					surface);
+
+		program_gamma(dc->ctx, surface,
+			DC_STREAM_TO_CORE(target->public.streams[0])->ipp,
+			DC_STREAM_TO_CORE(target->public.streams[0])->opp);
+
+		dc->hwss.set_plane_config(dc, core_surface, target);
+
+		if (is_valid_address)
+			dc->hwss.update_plane_address(dc, core_surface, target);
+	}
+
+	if (current_enabled_surface_count == 0 && new_enabled_surface_count > 0)
+		dc_target_enable_memory_requests(dc_target);
+
+	/* Lower display clock if necessary */
+	if (prev_disp_clk > dc->current_context.bw_results.dispclk_khz) {
+		dc->hwss.program_bw(dc, &dc->current_context);
+		pplib_apply_display_requirements(dc, &dc->current_context);
+	}
+
+	return true;
+
+unexpected_fail:
+	for (i = 0; i < new_surface_count; i++) {
+		target->status.surfaces[i] = NULL;
+	}
+	target->status.surface_count = 0;
+
+	return false;
+}
+
+bool dc_target_is_connected_to_sink(
+		const struct dc_target * dc_target,
+		const struct dc_sink *dc_sink)
+{
+	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+	uint8_t i;
+	for (i = 0; i < target->public.stream_count; i++) {
+		if (target->public.streams[i]->sink == dc_sink)
+			return true;
+	}
+	return false;
+}
+
+void dc_target_enable_memory_requests(struct dc_target *target)
+{
+	uint8_t i;
+	struct core_target *core_target = DC_TARGET_TO_CORE(target);
+	for (i = 0; i < core_target->public.stream_count; i++) {
+		struct timing_generator *tg =
+			DC_STREAM_TO_CORE(core_target->public.streams[i])->tg;
+
+		if (!tg->funcs->set_blank(tg, false)) {
+			dm_error("DC: failed to unblank crtc!\n");
+			BREAK_TO_DEBUGGER();
+		}
+	}
+}
+
+void dc_target_disable_memory_requests(struct dc_target *target)
+{
+	uint8_t i;
+	struct core_target *core_target = DC_TARGET_TO_CORE(target);
+	for (i = 0; i < core_target->public.stream_count; i++) {
+	struct timing_generator *tg =
+		DC_STREAM_TO_CORE(core_target->public.streams[i])->tg;
+
+		if (NULL == tg) {
+			dm_error("DC: timing generator is NULL!\n");
+			BREAK_TO_DEBUGGER();
+			continue;
+		}
+
+		if (false == tg->funcs->set_blank(tg, true)) {
+			dm_error("DC: failed to blank crtc!\n");
+			BREAK_TO_DEBUGGER();
+		}
+	}
+}
+
+/**
+ * Update the cursor attributes and set cursor surface address
+ */
+bool dc_target_set_cursor_attributes(
+	struct dc_target *dc_target,
+	const struct dc_cursor_attributes *attributes)
+{
+	struct core_target *core_target;
+	struct input_pixel_processor *ipp;
+
+	if (NULL == dc_target) {
+		dm_error("DC: dc_target is NULL!\n");
+			return false;
+
+	}
+
+	core_target = DC_TARGET_TO_CORE(dc_target);
+	ipp = DC_STREAM_TO_CORE(core_target->public.streams[0])->ipp;
+
+	if (NULL == ipp) {
+		dm_error("DC: input pixel processor is NULL!\n");
+		return false;
+	}
+
+	if (true == ipp->funcs->ipp_cursor_set_attributes(ipp, attributes))
+		return true;
+
+	return false;
+}
+
+bool dc_target_set_cursor_position(
+	struct dc_target *dc_target,
+	const struct dc_cursor_position *position)
+{
+	struct core_target *core_target;
+	struct input_pixel_processor *ipp;
+
+	if (NULL == dc_target) {
+		dm_error("DC: dc_target is NULL!\n");
+		return false;
+	}
+
+	if (NULL == position) {
+		dm_error("DC: cursor position is NULL!\n");
+		return false;
+	}
+
+	core_target = DC_TARGET_TO_CORE(dc_target);
+	ipp = DC_STREAM_TO_CORE(core_target->public.streams[0])->ipp;
+
+	if (NULL == ipp) {
+		dm_error("DC: input pixel processor is NULL!\n");
+		return false;
+	}
+
+
+	if (true == ipp->funcs->ipp_cursor_set_position(ipp, position))
+		return true;
+
+	return false;
+}
+
+/* TODO: #flip temporary to make flip work */
+uint8_t dc_target_get_link_index(const struct dc_target *dc_target)
+{
+	const struct core_target *target = CONST_DC_TARGET_TO_CORE(dc_target);
+	const struct core_sink *sink =
+		DC_SINK_TO_CORE(target->public.streams[0]->sink);
+
+	return sink->link->public.link_index;
+}
+
+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target)
+{
+	struct core_target *core_target = DC_TARGET_TO_CORE(dc_target);
+	struct timing_generator *tg =
+		DC_STREAM_TO_CORE(core_target->public.streams[0])->tg;
+
+	return tg->funcs->get_frame_count(tg);
+}
+
+enum dc_irq_source dc_target_get_irq_src(
+	const struct dc_target *dc_target, const enum irq_type irq_type)
+{
+	struct core_target *core_target = DC_TARGET_TO_CORE(dc_target);
+
+	/* #TODO - Remove the assumption that the controller is always in the
+	 * first stream of a core target */
+	struct core_stream *stream =
+		DC_STREAM_TO_CORE(core_target->public.streams[0]);
+	uint8_t controller_idx = stream->controller_idx;
+
+	/* Get controller id */
+	enum controller_id crtc_id = controller_idx + 1;
+
+	/* Calculate controller offset */
+	unsigned int offset = crtc_id - CONTROLLER_ID_D0;
+	unsigned int base = irq_type;
+
+	/* Calculate irq source */
+	enum dc_irq_source src = base + offset;
+
+	return src;
+}
+
+void dc_target_log(
+	const struct dc_target *dc_target,
+	struct dal_logger *dal_logger,
+	enum log_major log_major,
+	enum log_minor log_minor)
+{
+	int i;
+
+	const struct core_target *core_target =
+			CONST_DC_TARGET_TO_CORE(dc_target);
+
+	dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"core_target 0x%x: surface_count=%d, stream_count=%d\n",
+			core_target,
+			core_target->status.surface_count,
+			core_target->public.stream_count);
+
+	for (i = 0; i < core_target->public.stream_count; i++) {
+		const struct core_stream *core_stream =
+			DC_STREAM_TO_CORE(core_target->public.streams[i]);
+
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n",
+			core_stream,
+			core_stream->public.src.x,
+			core_stream->public.src.y,
+			core_stream->public.src.width,
+			core_stream->public.src.height,
+			core_stream->public.dst.x,
+			core_stream->public.dst.y,
+			core_stream->public.dst.width,
+			core_stream->public.dst.height);
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"\tpix_clk_khz: %d, h_total: %d, v_total: %d\n",
+			core_stream->public.timing.pix_clk_khz,
+			core_stream->public.timing.h_total,
+			core_stream->public.timing.v_total);
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"\tsink name: %s, serial: %d\n",
+			core_stream->sink->public.edid_caps.display_name,
+			core_stream->sink->public.edid_caps.serial_number);
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"\tlink: %d\n",
+			core_stream->sink->link->public.link_index);
+	}
+}
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 25/29] drm/amd/dal: Adding amdgpu_dm for dal
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (23 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 24/29] drm/amd/dal: Add display core Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 17:20 ` [PATCH 26/29] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel

Implements DRM's atomic KMS interfaces using DC.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile         |   17 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c      | 1470 +++++++++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h      |  168 ++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c  |  474 ++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c  |  820 +++++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h  |  122 +
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c    |  480 ++++
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h    |   36 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c |  457 ++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c    | 2572 ++++++++++++++++++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h    |  100 +
 drivers/gpu/drm/amd/dal/dc/dm_services.h           |   17 -
 12 files changed, 6716 insertions(+), 17 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h

diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
new file mode 100644
index 000000000000..0f365c65342e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the 'dm' sub-component of DAL.
+# It provides the control and status of dm blocks.
+
+
+
+AMDGPUDM = amdgpu_dm_types.o amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o
+
+ifneq ($(CONFIG_DRM_AMD_DAL),)
+AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o
+endif
+
+subdir-ccflags-y += -I$(FULL_AMD_DAL_PATH)/dc
+
+AMDGPU_DM = $(addprefix $(AMDDALPATH)/amdgpu_dm/,$(AMDGPUDM))
+
+AMD_DAL_FILES += $(AMDGPU_DM)
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
new file mode 100644
index 000000000000..aeb7887356cd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
@@ -0,0 +1,1470 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services_types.h"
+#include "dc.h"
+
+#include "vid.h"
+#include "amdgpu.h"
+#include "atom.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_types.h"
+
+#include "amd_shared.h"
+#include "amdgpu_dm_irq.h"
+#include "dm_helpers.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dce/dce_11_0_enum.h"
+#include "ivsrcid/ivsrcid_vislands30.h"
+
+#include "oss/oss_3_0_d.h"
+#include "oss/oss_3_0_sh_mask.h"
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_dp_mst_helper.h>
+
+/* TODO: Remove when mc access work around is removed */
+static const u32 crtc_offsets[] =
+{
+	CRTC0_REGISTER_OFFSET,
+	CRTC1_REGISTER_OFFSET,
+	CRTC2_REGISTER_OFFSET,
+	CRTC3_REGISTER_OFFSET,
+	CRTC4_REGISTER_OFFSET,
+	CRTC5_REGISTER_OFFSET,
+	CRTC6_REGISTER_OFFSET
+};
+/* TODO: End of when Remove mc access work around is removed */
+
+/* Define variables here
+ * These values will be passed to DAL for feature enable purpose
+ * Disable ALL for HDMI light up
+ * TODO: follow up if need this mechanism*/
+struct dal_override_parameters display_param = {
+	.bool_param_enable_mask = 0,
+	.bool_param_values = 0,
+	.int_param_values[DAL_PARAM_MAX_COFUNC_NON_DP_DISPLAYS] = DAL_PARAM_INVALID_INT,
+	.int_param_values[DAL_PARAM_DRR_SUPPORT] = DAL_PARAM_INVALID_INT,
+};
+
+/* Debug facilities */
+#define AMDGPU_DM_NOT_IMPL(fmt, ...) \
+	DRM_INFO("DM_NOT_IMPL: " fmt, ##__VA_ARGS__)
+
+/*
+ * dm_vblank_get_counter
+ *
+ * @brief
+ * Get counter for number of vertical blanks
+ *
+ * @param
+ * struct amdgpu_device *adev - [in] desired amdgpu device
+ * int disp_idx - [in] which CRTC to get the counter from
+ *
+ * @return
+ * Counter for vertical blanks
+ */
+static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
+{
+	if (crtc >= adev->mode_info.num_crtc)
+		return 0;
+	else {
+		struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
+
+		if (NULL == acrtc->target) {
+			DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc);
+			return 0;
+		}
+
+		return dc_target_get_vblank_counter(acrtc->target);
+	}
+}
+
+static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
+					u32 *vbl, u32 *position)
+{
+	if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
+		return -EINVAL;
+
+/* TODO: #DAL3 Implement scanoutpos
+	dal_get_crtc_scanoutpos(adev->dm.dal, crtc, vbl, position);
+*/
+	return 0;
+}
+
+static u32 dm_hpd_get_gpio_reg(struct amdgpu_device *adev)
+{
+	return mmDC_GPIO_HPD_A;
+}
+
+
+static bool dm_is_display_hung(struct amdgpu_device *adev)
+{
+	/* TODO: #DAL3 need to replace
+	u32 crtc_hung = 0;
+	u32 i, j, tmp;
+
+	crtc_hung = dal_get_connected_targets_vector(adev->dm.dal);
+
+	for (j = 0; j < 10; j++) {
+		for (i = 0; i < adev->mode_info.num_crtc; i++) {
+			if (crtc_hung & (1 << i)) {
+				int32_t vpos1, hpos1;
+				int32_t vpos2, hpos2;
+
+				tmp = dal_get_crtc_scanoutpos(
+					adev->dm.dal,
+					i,
+					&vpos1,
+					&hpos1);
+				udelay(10);
+				tmp = dal_get_crtc_scanoutpos(
+					adev->dm.dal,
+					i,
+					&vpos2,
+					&hpos2);
+
+				if (hpos1 != hpos2 && vpos1 != vpos2)
+					crtc_hung &= ~(1 << i);
+			}
+		}
+
+		if (crtc_hung == 0)
+			return false;
+	}
+*/
+	return true;
+}
+
+/* TODO: Remove mc access work around*/
+static void dm_stop_mc_access(struct amdgpu_device *adev,
+				     struct amdgpu_mode_mc_save *save)
+{
+
+	u32 crtc_enabled, tmp;
+	int i;
+
+	save->vga_render_control = RREG32(mmVGA_RENDER_CONTROL);
+	save->vga_hdp_control = RREG32(mmVGA_HDP_CONTROL);
+
+	/* disable VGA render */
+	tmp = RREG32(mmVGA_RENDER_CONTROL);
+	tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0);
+	WREG32(mmVGA_RENDER_CONTROL, tmp);
+
+	/* blank the display controllers */
+	for (i = 0; i < adev->mode_info.num_crtc; i++) {
+		crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
+					     CRTC_CONTROL, CRTC_MASTER_EN);
+		if (crtc_enabled) {
+#if 0
+			u32 frame_count;
+			int j;
+
+			save->crtc_enabled[i] = true;
+			tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN) == 0) {
+				amdgpu_display_vblank_wait(adev, i);
+				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+				tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
+				WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			}
+			/* wait for the next frame */
+			frame_count = amdgpu_display_vblank_get_counter(adev, i);
+			for (j = 0; j < adev->usec_timeout; j++) {
+				if (amdgpu_display_vblank_get_counter(adev, i) != frame_count)
+					break;
+				udelay(1);
+			}
+			tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK) == 0) {
+				tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
+				WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK) == 0) {
+				tmp = REG_SET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK, 1);
+				WREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+			}
+#else
+			/* XXX this is a hack to avoid strange behavior with EFI on certain systems */
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+			tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
+			tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0);
+			WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			save->crtc_enabled[i] = false;
+			/* ***** */
+#endif
+		} else {
+			save->crtc_enabled[i] = false;
+		}
+	}
+}
+
+
+static void dm_resume_mc_access(struct amdgpu_device *adev,
+				       struct amdgpu_mode_mc_save *save)
+{
+
+	u32 tmp, frame_count;
+	int i, j;
+
+	/* update crtc base addresses */
+	for (i = 0; i < adev->mode_info.num_crtc; i++) {
+		WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
+		       upper_32_bits(adev->mc.vram_start));
+		WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
+		       upper_32_bits(adev->mc.vram_start));
+		WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i],
+		       (u32)adev->mc.vram_start);
+		WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
+		       (u32)adev->mc.vram_start);
+
+		if (save->crtc_enabled[i]) {
+			tmp = RREG32(mmCRTC_MASTER_UPDATE_MODE + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, CRTC_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 3) {
+				tmp = REG_SET_FIELD(tmp, CRTC_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 3);
+				WREG32(mmCRTC_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK)) {
+				tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
+				WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK)) {
+				tmp = REG_SET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK, 0);
+				WREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+			}
+			for (j = 0; j < adev->usec_timeout; j++) {
+				tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+				if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING) == 0)
+					break;
+				udelay(1);
+			}
+			tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]);
+			tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 0);
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+			WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			/* wait for the next frame */
+			frame_count = amdgpu_display_vblank_get_counter(adev, i);
+			for (j = 0; j < adev->usec_timeout; j++) {
+				if (amdgpu_display_vblank_get_counter(adev, i) != frame_count)
+					break;
+				udelay(1);
+			}
+		}
+	}
+
+	WREG32(mmVGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start));
+	WREG32(mmVGA_MEMORY_BASE_ADDRESS, lower_32_bits(adev->mc.vram_start));
+
+	/* Unlock vga access */
+	WREG32(mmVGA_HDP_CONTROL, save->vga_hdp_control);
+	mdelay(1);
+	WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control);
+}
+
+/* End of TODO: Remove mc access work around*/
+
+static bool dm_is_idle(void *handle)
+{
+	/* XXX todo */
+	return true;
+}
+
+static int dm_wait_for_idle(void *handle)
+{
+	/* XXX todo */
+	return 0;
+}
+
+static void dm_print_status(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	dev_info(adev->dev, "DCE 10.x registers\n");
+	/* XXX todo */
+}
+
+static int dm_soft_reset(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	u32 srbm_soft_reset = 0, tmp;
+
+	if (dm_is_display_hung(adev))
+		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK;
+
+	if (srbm_soft_reset) {
+		dm_print_status(adev);
+
+		tmp = RREG32(mmSRBM_SOFT_RESET);
+		tmp |= srbm_soft_reset;
+		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
+		WREG32(mmSRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmSRBM_SOFT_RESET);
+
+		udelay(50);
+
+		tmp &= ~srbm_soft_reset;
+		WREG32(mmSRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmSRBM_SOFT_RESET);
+
+		/* Wait a little for things to settle down */
+		udelay(50);
+		dm_print_status(adev);
+	}
+	return 0;
+}
+
+static struct amdgpu_crtc *get_crtc_by_target(
+	struct amdgpu_device *adev,
+	const struct dc_target *dc_target)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_crtc *crtc;
+	struct amdgpu_crtc *amdgpu_crtc;
+
+	/*
+	 * following if is check inherited from both functions where this one is
+	 * used now. Need to be checked why it could happen.
+	 */
+	if (dc_target == NULL)
+		return adev->mode_info.crtcs[0];
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+		if (amdgpu_crtc->target == dc_target)
+			return amdgpu_crtc;
+	}
+
+	return NULL;
+}
+
+static void dm_pflip_high_irq(void *interrupt_params)
+{
+	struct amdgpu_flip_work *works;
+	struct amdgpu_crtc *amdgpu_crtc;
+	struct common_irq_params *irq_params = interrupt_params;
+	struct amdgpu_device *adev = irq_params->adev;
+	unsigned long flags;
+	const struct dc *dc = irq_params->adev->dm.dc;
+	const struct dc_target *dc_target =
+			dc_get_target_on_irq_source(dc, irq_params->irq_src);
+
+	amdgpu_crtc = get_crtc_by_target(adev, dc_target);
+
+	/* IRQ could occur when in initial stage */
+	if(amdgpu_crtc == NULL)
+		return;
+
+	spin_lock_irqsave(&adev->ddev->event_lock, flags);
+	works = amdgpu_crtc->pflip_works;
+	if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
+		DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
+						 "AMDGPU_FLIP_SUBMITTED(%d)\n",
+						 amdgpu_crtc->pflip_status,
+						 AMDGPU_FLIP_SUBMITTED);
+		spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+		return;
+	}
+
+	/* page flip completed. clean up */
+	amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
+	amdgpu_crtc->pflip_works = NULL;
+
+	/* wakeup usersapce */
+	if(works->event)
+		drm_send_vblank_event(
+			adev->ddev,
+			amdgpu_crtc->crtc_id,
+			works->event);
+
+	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+
+	drm_crtc_vblank_put(&amdgpu_crtc->base);
+	queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
+}
+
+static void dm_crtc_high_irq(void *interrupt_params)
+{
+	struct common_irq_params *irq_params = interrupt_params;
+	struct amdgpu_device *adev = irq_params->adev;
+	const struct dc *dc = irq_params->adev->dm.dc;
+	const struct dc_target *dc_target =
+			dc_get_target_on_irq_source(dc, irq_params->irq_src);
+	uint8_t crtc_index = 0;
+	struct amdgpu_crtc *acrtc = get_crtc_by_target(adev, dc_target);
+
+	if (acrtc)
+		crtc_index = acrtc->crtc_id;
+
+	drm_handle_vblank(adev->ddev, crtc_index);
+
+}
+
+static int dm_set_clockgating_state(void *handle,
+		  enum amd_clockgating_state state)
+{
+	return 0;
+}
+
+static int dm_set_powergating_state(void *handle,
+		  enum amd_powergating_state state)
+{
+	return 0;
+}
+
+/* Prototypes of private functions */
+static int dm_early_init(void* handle);
+
+static void hotplug_notify_work_func(struct work_struct *work)
+{
+	struct amdgpu_display_manager *dm = container_of(work, struct amdgpu_display_manager, mst_hotplug_work);
+	struct drm_device *dev = dm->ddev;
+
+	drm_kms_helper_hotplug_event(dev);
+}
+
+/* Init display KMS
+ *
+ * Returns 0 on success
+ */
+int amdgpu_dm_init(struct amdgpu_device *adev)
+{
+	struct dal_init_data init_data;
+	struct drm_device *ddev = adev->ddev;
+	adev->dm.ddev = adev->ddev;
+	adev->dm.adev = adev;
+
+	/* Zero all the fields */
+	memset(&init_data, 0, sizeof(init_data));
+
+	/* initialize DAL's lock (for SYNC context use) */
+	spin_lock_init(&adev->dm.dal_lock);
+
+	/* initialize DAL's mutex */
+	mutex_init(&adev->dm.dal_mutex);
+
+	if(amdgpu_dm_irq_init(adev)) {
+		DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
+		goto error;
+	}
+
+	if (ddev->pdev) {
+		init_data.bdf_info.DEVICE_NUMBER = PCI_SLOT(ddev->pdev->devfn);
+		init_data.bdf_info.FUNCTION_NUMBER =
+			PCI_FUNC(ddev->pdev->devfn);
+		if (ddev->pdev->bus)
+			init_data.bdf_info.BUS_NUMBER = ddev->pdev->bus->number;
+	}
+
+	init_data.display_param = display_param;
+
+	init_data.asic_id.chip_family = adev->family;
+
+	init_data.asic_id.pci_revision_id = adev->rev_id;
+	init_data.asic_id.hw_internal_rev = adev->external_rev_id;
+
+	init_data.asic_id.vram_width = adev->mc.vram_width;
+	/* TODO: initialize init_data.asic_id.vram_type here!!!! */
+	init_data.asic_id.atombios_base_address =
+		adev->mode_info.atom_context->bios;
+	init_data.asic_id.runtime_flags.flags.bits.SKIP_POWER_DOWN_ON_RESUME = 1;
+
+	if (adev->asic_type == CHIP_CARRIZO)
+		init_data.asic_id.runtime_flags.flags.bits.GNB_WAKEUP_SUPPORTED = 1;
+
+	init_data.driver = adev;
+
+	adev->dm.cgs_device = amdgpu_cgs_create_device(adev);
+
+	if (!adev->dm.cgs_device) {
+		DRM_ERROR("amdgpu: failed to create cgs device.\n");
+		goto error;
+	}
+
+	init_data.cgs_device = adev->dm.cgs_device;
+
+	adev->dm.dal = NULL;
+
+	/* enable gpu scaling in DAL */
+	init_data.display_param.bool_param_enable_mask |=
+		1 << DAL_PARAM_ENABLE_GPU_SCALING;
+	init_data.display_param.bool_param_values |=
+		1 << DAL_PARAM_ENABLE_GPU_SCALING;
+
+	init_data.dce_environment = DCE_ENV_PRODUCTION_DRV;
+
+	/* Display Core create. */
+	adev->dm.dc = dc_create(&init_data);
+
+	INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func);
+
+	if (amdgpu_dm_initialize_drm_device(adev)) {
+		DRM_ERROR(
+		"amdgpu: failed to initialize sw for display support.\n");
+		goto error;
+	}
+
+	/* Update the actual used number of crtc */
+	adev->mode_info.num_crtc = adev->dm.display_indexes_num;
+
+	/* TODO: Add_display_info? */
+
+	/* TODO use dynamic cursor width */
+	adev->ddev->mode_config.cursor_width = 128;
+	adev->ddev->mode_config.cursor_height = 128;
+
+	if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) {
+		DRM_ERROR(
+		"amdgpu: failed to initialize sw for display support.\n");
+		goto error;
+	}
+
+	DRM_INFO("KMS initialized.\n");
+
+	return 0;
+error:
+	amdgpu_dm_fini(adev);
+
+	return -1;
+}
+
+void amdgpu_dm_fini(struct amdgpu_device *adev)
+{
+	amdgpu_dm_destroy_drm_device(&adev->dm);
+	/*
+	 * TODO: pageflip, vlank interrupt
+	 *
+	 * amdgpu_dm_irq_fini(adev);
+	 */
+
+	if (adev->dm.cgs_device) {
+		amdgpu_cgs_destroy_device(adev->dm.cgs_device);
+		adev->dm.cgs_device = NULL;
+	}
+
+	/* DC Destroy TODO: Replace destroy DAL */
+	{
+		dc_destroy(&adev->dm.dc);
+	}
+	return;
+}
+
+/* moved from amdgpu_dm_kms.c */
+void amdgpu_dm_destroy()
+{
+}
+
+static int dm_sw_init(void *handle)
+{
+	return 0;
+}
+
+static int dm_sw_fini(void *handle)
+{
+	return 0;
+}
+
+
+static void detect_link_for_all_connectors(struct drm_device *dev)
+{
+	struct amdgpu_connector *aconnector;
+	struct drm_connector *connector;
+
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		   aconnector = to_amdgpu_connector(connector);
+		   if (aconnector->dc_link->type == dc_connection_mst_branch) {
+			   DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n",
+						aconnector, aconnector->base.base.id);
+
+				if (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) < 0) {
+					DRM_ERROR("DM_MST: Failed to start MST\n");
+					((struct dc_link *)aconnector->dc_link)->type = dc_connection_single;
+				}
+		   }
+	}
+
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+}
+
+
+static int dm_hw_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	/* Create DAL display manager */
+	amdgpu_dm_init(adev);
+
+	amdgpu_dm_hpd_init(adev);
+
+	detect_link_for_all_connectors(adev->ddev);
+
+
+
+	return 0;
+}
+
+static int dm_hw_fini(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	amdgpu_dm_hpd_fini(adev);
+
+	amdgpu_dm_irq_fini(adev);
+
+	return 0;
+}
+
+static int dm_display_suspend(struct drm_device *ddev)
+{
+	struct drm_mode_config *config = &ddev->mode_config;
+	struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
+	struct drm_atomic_state *state;
+	struct drm_crtc *crtc;
+	unsigned crtc_mask = 0;
+	int ret = 0;
+
+	if (WARN_ON(!ctx))
+		return 0;
+
+	lockdep_assert_held(&ctx->ww_ctx);
+
+	state = drm_atomic_state_alloc(ddev);
+	if (WARN_ON(!state))
+		return -ENOMEM;
+
+	state->acquire_ctx = ctx;
+	state->allow_modeset = true;
+
+	/* Set all active crtcs to inactive, to turn off displays*/
+	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
+		struct drm_crtc_state *crtc_state =
+			drm_atomic_get_crtc_state(state, crtc);
+
+		ret = PTR_ERR_OR_ZERO(crtc_state);
+		if (ret)
+			goto free;
+
+		if (!crtc_state->active)
+			continue;
+
+		crtc_state->active = false;
+		crtc_mask |= (1 << drm_crtc_index(crtc));
+	}
+
+	if (crtc_mask) {
+		ret = drm_atomic_commit(state);
+
+		/* In case of failure, revert everything we did*/
+		if (!ret) {
+			list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head)
+				if (crtc_mask & (1 << drm_crtc_index(crtc)))
+					crtc->state->active = true;
+
+			return ret;
+		}
+	}
+
+free:
+	if (ret) {
+		DRM_ERROR("Suspending crtc's failed with %i\n", ret);
+		drm_atomic_state_free(state);
+		return ret;
+	}
+
+	return 0;
+}
+static int dm_suspend(void *handle)
+{
+	struct amdgpu_device *adev = handle;
+	struct amdgpu_display_manager *dm = &adev->dm;
+	struct drm_device *ddev = adev->ddev;
+	int ret = 0;
+
+	drm_modeset_lock_all(ddev);
+	ret = dm_display_suspend(ddev);
+	drm_modeset_unlock_all(ddev);
+
+	if (ret)
+		goto fail;
+
+	dc_set_power_state(
+		dm->dc,
+		DC_ACPI_CM_POWER_STATE_D3,
+		DC_VIDEO_POWER_SUSPEND);
+
+	amdgpu_dm_irq_suspend(adev);
+fail:
+	return ret;
+}
+
+static int dm_display_resume(struct drm_device *ddev)
+{
+	int ret = 0;
+	struct drm_connector *connector;
+
+	struct drm_atomic_state *state = drm_atomic_state_alloc(ddev);
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+
+	if (!state)
+		return ENOMEM;
+
+	state->acquire_ctx = ddev->mode_config.acquire_ctx;
+
+	/* Construct an atomic state to restore previous display setting*/
+	/* Attach crtcs to drm_atomic_state*/
+	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
+		struct drm_crtc_state *crtc_state =
+			drm_atomic_get_crtc_state(state, crtc);
+
+		ret = PTR_ERR_OR_ZERO(crtc_state);
+		if (ret)
+			goto err;
+
+		/* force a restore */
+		crtc_state->mode_changed = true;
+	}
+
+	/* Attach planes to drm_atomic_state*/
+	list_for_each_entry(plane, &ddev->mode_config.plane_list, head) {
+		ret = PTR_ERR_OR_ZERO(drm_atomic_get_plane_state(state, plane));
+		if (ret)
+			goto err;
+	}
+
+	/* Attach connectors to drm_atomic_state*/
+	list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
+		ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(state, connector));
+		if (ret)
+			goto err;
+	}
+
+	/* Call commit internally with the state we just constructed */
+	ret = drm_atomic_commit(state);
+	if (!ret)
+		return 0;
+
+err:
+	DRM_ERROR("Restoring old state failed with %i\n", ret);
+	drm_atomic_state_free(state);
+
+	return ret;
+}
+
+static int dm_resume(void *handle)
+{
+	struct amdgpu_device *adev = handle;
+	struct drm_device *ddev = adev->ddev;
+	struct amdgpu_display_manager *dm = &adev->dm;
+	struct amdgpu_connector *aconnector;
+	struct drm_connector *connector;
+	int ret = 0;
+
+	/* power on hardware */
+	dc_set_power_state(
+		dm->dc,
+		DC_ACPI_CM_POWER_STATE_D0,
+		DC_VIDEO_POWER_ON);
+
+	/* Do detection*/
+	list_for_each_entry(connector,
+			&ddev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		dc_link_detect(aconnector->dc_link, false);
+		aconnector->dc_sink = NULL;
+		amdgpu_dm_update_connector_after_detect(aconnector);
+	}
+
+
+	drm_modeset_lock_all(ddev);
+	ret = dm_display_resume(ddev);
+	drm_modeset_unlock_all(ddev);
+
+	drm_kms_helper_hotplug_event(ddev);
+
+	/* program HPD filter*/
+	dc_resume(dm->dc);
+	/* resume IRQ */
+	amdgpu_dm_irq_resume(adev);
+
+	return ret;
+}
+const struct amd_ip_funcs amdgpu_dm_funcs = {
+	.early_init = dm_early_init,
+	.late_init = NULL,
+	.sw_init = dm_sw_init,
+	.sw_fini = dm_sw_fini,
+	.hw_init = dm_hw_init,
+	.hw_fini = dm_hw_fini,
+	.suspend = dm_suspend,
+	.resume = dm_resume,
+	.is_idle = dm_is_idle,
+	.wait_for_idle = dm_wait_for_idle,
+	.soft_reset = dm_soft_reset,
+	.print_status = dm_print_status,
+	.set_clockgating_state = dm_set_clockgating_state,
+	.set_powergating_state = dm_set_powergating_state,
+};
+
+/* TODO: it is temporary non-const, should fixed later */
+static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
+	.atomic_check = amdgpu_dm_atomic_check,
+	.atomic_commit = amdgpu_dm_atomic_commit
+};
+
+
+void amdgpu_dm_update_connector_after_detect(
+	struct amdgpu_connector *aconnector)
+{
+	struct drm_connector *connector = &aconnector->base;
+	struct drm_device *dev = connector->dev;
+	const struct dc_sink *sink;
+
+	/* MST handled by drm_mst framework */
+	if (aconnector->mst_mgr.mst_state == true)
+		return;
+
+	sink = aconnector->dc_link->local_sink;
+
+	/*
+	 * TODO: temporary guard to look for proper fix
+	 * if this sink is MST sink, we should not do anything
+	 */
+	if (sink && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+		return;
+
+	if (aconnector->dc_sink == sink) {
+		/* We got a DP short pulse (Link Loss, DP CTS, etc...).
+		 * Do nothing!! */
+		DRM_INFO("DCHPD: connector_id=%d: dc_sink didn't change.\n",
+				aconnector->connector_id);
+		return;
+	}
+
+	DRM_INFO("DCHPD: connector_id=%d: Old sink=%p New sink=%p\n",
+		aconnector->connector_id, aconnector->dc_sink, sink);
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/* 1. Update status of the drm connector
+	 * 2. Send an event and let userspace tell us what to do */
+	if (sink) {
+		/* TODO: check if we still need the S3 mode update workaround.
+		 * If yes, put it here. */
+
+		aconnector->dc_sink = sink;
+		if (sink->dc_edid.length == 0)
+			aconnector->edid = NULL;
+		else {
+			aconnector->edid =
+				(struct edid *) sink->dc_edid.raw_edid;
+			drm_mode_connector_update_edid_property(connector,
+					aconnector->edid);
+		}
+	} else {
+		drm_mode_connector_update_edid_property(connector, NULL);
+		aconnector->num_modes = 0;
+		aconnector->dc_sink = NULL;
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void handle_hpd_irq(void *param)
+{
+	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
+	struct drm_connector *connector = &aconnector->base;
+	struct drm_device *dev = connector->dev;
+
+	/* In case of failure or MST no need to update connector status or notify the OS
+	 * since (for MST case) MST does this in it's own context.
+	 */
+	if (dc_link_detect(aconnector->dc_link, false)) {
+		amdgpu_dm_update_connector_after_detect(aconnector);
+		drm_kms_helper_hotplug_event(dev);
+	}
+}
+
+static void handle_hpd_rx_irq(void *param)
+{
+	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
+	struct drm_connector *connector = &aconnector->base;
+	struct drm_device *dev = connector->dev;
+	bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
+
+	if (dc_link_handle_hpd_rx_irq(aconnector->dc_link) &&
+			!is_mst_root_connector) {
+		/* Downstream Port status changed. */
+		if (dc_link_detect(aconnector->dc_link, false)) {
+			amdgpu_dm_update_connector_after_detect(aconnector);
+			drm_kms_helper_hotplug_event(dev);
+		}
+	}
+
+	if (is_mst_root_connector)
+		dm_helpers_dp_mst_handle_mst_hpd_rx_irq(param);
+}
+
+static void register_hpd_handlers(struct amdgpu_device *adev)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_connector *connector;
+	struct amdgpu_connector *aconnector;
+	const struct dc_link *dc_link;
+	struct dc_interrupt_params int_params = {0};
+
+	int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
+	int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
+
+	list_for_each_entry(connector,
+			&dev->mode_config.connector_list, head)	{
+
+		aconnector = to_amdgpu_connector(connector);
+		dc_link = aconnector->dc_link;
+
+		int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
+		int_params.irq_source = dc_link->irq_source_hpd;
+
+		amdgpu_dm_irq_register_interrupt(adev, &int_params,
+				handle_hpd_irq,
+				(void *) aconnector);
+
+		if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+
+			/* Also register for DP short pulse (hpd_rx). */
+			int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
+			int_params.irq_source =	dc_link->irq_source_hpd_rx;
+
+			amdgpu_dm_irq_register_interrupt(adev, &int_params,
+					handle_hpd_rx_irq,
+					(void *) aconnector);
+		}
+	}
+}
+
+/* Register IRQ sources and initialize IRQ callbacks */
+static int dce110_register_irq_handlers(struct amdgpu_device *adev)
+{
+	struct dc *dc = adev->dm.dc;
+	struct common_irq_params *c_irq_params;
+	struct dc_interrupt_params int_params = {0};
+	int r;
+	int i;
+	struct dc_caps caps = { 0 };
+
+	dc_get_caps(dc, &caps);
+
+	int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
+	int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
+
+	/* Actions of amdgpu_irq_add_id():
+	 * 1. Register a set() function with base driver.
+	 *    Base driver will call set() function to enable/disable an
+	 *    interrupt in DC hardware.
+	 * 2. Register amdgpu_dm_irq_handler().
+	 *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
+	 *    coming from DC hardware.
+	 *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
+	 *    for acknowledging and handling. */
+
+	for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT;
+			i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) {
+		r = amdgpu_irq_add_id(adev, i, &adev->crtc_irq);
+		if (r) {
+			DRM_ERROR("Failed to add crtc irq id!\n");
+			return r;
+		}
+
+		int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+		int_params.irq_source =
+			dc_interrupt_to_irq_source(dc, i, 0);
+
+		c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
+
+		c_irq_params->adev = adev;
+		c_irq_params->irq_src = int_params.irq_source;
+
+		amdgpu_dm_irq_register_interrupt(adev, &int_params,
+				dm_crtc_high_irq, c_irq_params);
+	}
+
+	for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP;
+			i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) {
+		r = amdgpu_irq_add_id(adev, i, &adev->pageflip_irq);
+		if (r) {
+			DRM_ERROR("Failed to add page flip irq id!\n");
+			return r;
+		}
+
+		int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+		int_params.irq_source =
+			dc_interrupt_to_irq_source(dc, i, 0);
+
+		c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST];
+
+		c_irq_params->adev = adev;
+		c_irq_params->irq_src = int_params.irq_source;
+
+		amdgpu_dm_irq_register_interrupt(adev, &int_params,
+				dm_pflip_high_irq, c_irq_params);
+
+	}
+
+	/* HPD */
+	r = amdgpu_irq_add_id(adev, VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A,
+			&adev->hpd_irq);
+	if (r) {
+		DRM_ERROR("Failed to add hpd irq id!\n");
+		return r;
+	}
+
+	register_hpd_handlers(adev);
+
+	return 0;
+}
+
+static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
+{
+	int r;
+
+	adev->mode_info.mode_config_initialized = true;
+
+	amdgpu_dm_mode_funcs.fb_create =
+		amdgpu_mode_funcs.fb_create;
+	amdgpu_dm_mode_funcs.output_poll_changed =
+		amdgpu_mode_funcs.output_poll_changed;
+
+	adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs;
+
+	adev->ddev->mode_config.max_width = 16384;
+	adev->ddev->mode_config.max_height = 16384;
+
+	adev->ddev->mode_config.preferred_depth = 24;
+	adev->ddev->mode_config.prefer_shadow = 1;
+
+	adev->ddev->mode_config.fb_base = adev->mc.aper_base;
+
+	r = amdgpu_modeset_create_props(adev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
+	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
+{
+	struct amdgpu_display_manager *dm = bl_get_data(bd);
+
+	if (dc_link_set_backlight_level(dm->backlight_link,
+			bd->props.brightness))
+		return 0;
+	else
+		return 1;
+}
+
+static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static const struct backlight_ops amdgpu_dm_backlight_ops = {
+	.get_brightness = amdgpu_dm_backlight_get_brightness,
+	.update_status	= amdgpu_dm_backlight_update_status,
+};
+
+void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
+{
+	char bl_name[16];
+	struct backlight_properties props = { 0 };
+
+	props.max_brightness = AMDGPU_MAX_BL_LEVEL;
+	props.type = BACKLIGHT_RAW;
+
+	snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
+			dm->adev->ddev->primary->index);
+
+	dm->backlight_dev = backlight_device_register(bl_name,
+			dm->adev->ddev->dev,
+			dm,
+			&amdgpu_dm_backlight_ops,
+			&props);
+
+	if (NULL == dm->backlight_dev)
+		DRM_ERROR("DM: Backlight registration failed!\n");
+	else
+		DRM_INFO("DM: Registered Backlight device: %s\n", bl_name);
+}
+
+#endif
+
+/* In this architecture, the association
+ * connector -> encoder -> crtc
+ * id not really requried. The crtc and connector will hold the
+ * display_index as an abstraction to use with DAL component
+ *
+ * Returns 0 on success
+ */
+int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+{
+	struct amdgpu_display_manager *dm = &adev->dm;
+	uint32_t i;
+	struct amdgpu_connector *aconnector;
+	struct amdgpu_encoder *aencoder;
+	struct amdgpu_crtc *acrtc;
+	struct dc_caps caps = { 0 };
+	uint32_t link_cnt;
+
+	dc_get_caps(dm->dc, &caps);
+	link_cnt = caps.max_links;
+
+	if (amdgpu_dm_mode_config_init(dm->adev)) {
+		DRM_ERROR("DM: Failed to initialize mode config\n");
+		return -1;
+	}
+
+	for (i = 0; i < caps.max_targets; i++) {
+		acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL);
+		if (!acrtc)
+			goto fail;
+
+		if (amdgpu_dm_crtc_init(
+			dm,
+			acrtc,
+			i)) {
+			DRM_ERROR("KMS: Failed to initialize crtc\n");
+			kfree(acrtc);
+			goto fail;
+		}
+	}
+
+	dm->display_indexes_num = caps.max_targets;
+
+	/* loops over all connectors on the board */
+	for (i = 0; i < link_cnt; i++) {
+
+		if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) {
+			DRM_ERROR(
+				"KMS: Cannot support more than %d display indexes\n",
+					AMDGPU_DM_MAX_DISPLAY_INDEX);
+			continue;
+		}
+
+		aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
+		if (!aconnector)
+			goto fail;
+
+		aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL);
+		if (!aencoder) {
+			goto fail_free_connector;
+		}
+
+		if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) {
+			DRM_ERROR("KMS: Failed to initialize encoder\n");
+			goto fail_free_encoder;
+		}
+
+		if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) {
+			DRM_ERROR("KMS: Failed to initialize connector\n");
+			goto fail_free_connector;
+		}
+
+		if (dc_link_detect(dc_get_link_at_index(dm->dc, i), true))
+			amdgpu_dm_update_connector_after_detect(
+				aconnector);
+	}
+
+	/* Software is initialized. Now we can register interrupt handlers. */
+	switch (adev->asic_type) {
+	case CHIP_TONGA:
+	case CHIP_FIJI:
+	case CHIP_CARRIZO:
+		if (dce110_register_irq_handlers(dm->adev)) {
+			DRM_ERROR("DM: Failed to initialize IRQ\n");
+			return -1;
+		}
+		break;
+	default:
+		DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type);
+		return -1;
+	}
+
+	drm_mode_config_reset(dm->ddev);
+
+	return 0;
+fail_free_encoder:
+	kfree(aencoder);
+fail_free_connector:
+	kfree(aconnector);
+fail:
+	return -1;
+}
+
+void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
+{
+	drm_mode_config_cleanup(dm->ddev);
+	return;
+}
+
+/******************************************************************************
+ * amdgpu_display_funcs functions
+ *****************************************************************************/
+
+
+static void dm_set_vga_render_state(struct amdgpu_device *adev,
+					   bool render)
+{
+	u32 tmp;
+
+	/* Lockout access through VGA aperture*/
+	tmp = RREG32(mmVGA_HDP_CONTROL);
+	if (render)
+		tmp = REG_SET_FIELD(tmp, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE, 0);
+	else
+		tmp = REG_SET_FIELD(tmp, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE, 1);
+	WREG32(mmVGA_HDP_CONTROL, tmp);
+
+	/* disable VGA render */
+	tmp = RREG32(mmVGA_RENDER_CONTROL);
+	if (render)
+		tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 1);
+	else
+		tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0);
+	WREG32(mmVGA_RENDER_CONTROL, tmp);
+}
+
+/**
+ * dm_bandwidth_update - program display watermarks
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Calculate and program the display watermarks and line buffer allocation.
+ */
+static void dm_bandwidth_update(struct amdgpu_device *adev)
+{
+	AMDGPU_DM_NOT_IMPL("%s\n", __func__);
+}
+
+static void dm_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder,
+				     u8 level)
+{
+	/* TODO: translate amdgpu_encoder to display_index and call DAL */
+	AMDGPU_DM_NOT_IMPL("%s\n", __func__);
+}
+
+static u8 dm_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder)
+{
+	/* TODO: translate amdgpu_encoder to display_index and call DAL */
+	AMDGPU_DM_NOT_IMPL("%s\n", __func__);
+	return 0;
+}
+
+/******************************************************************************
+ * Page Flip functions
+ ******************************************************************************/
+
+void amdgpu_dm_flip_cleanup(
+	struct amdgpu_device *adev,
+	struct amdgpu_crtc *acrtc)
+{
+	int r;
+	struct amdgpu_flip_work *works = acrtc->pflip_works;
+
+	acrtc->pflip_works = NULL;
+	acrtc->pflip_status = AMDGPU_FLIP_NONE;
+
+	if (works) {
+		if(works->event)
+			drm_send_vblank_event(
+				adev->ddev,
+				acrtc->crtc_id,
+				works->event);
+
+		r = amdgpu_bo_reserve(works->old_rbo, false);
+		if (likely(r == 0)) {
+			r = amdgpu_bo_unpin(works->old_rbo);
+			if (unlikely(r != 0)) {
+				DRM_ERROR("failed to unpin buffer after flip\n");
+			}
+			amdgpu_bo_unreserve(works->old_rbo);
+		} else
+			DRM_ERROR("failed to reserve buffer after flip\n");
+
+		drm_gem_object_unreference_unlocked(&works->old_rbo->gem_base);
+		kfree(works->shared);
+		kfree(works);
+	}
+}
+
+/**
+ * dm_page_flip - called by amdgpu_flip_work_func(), which is triggered
+ * 			via DRM IOCTL, by user mode.
+ *
+ * @adev: amdgpu_device pointer
+ * @crtc_id: crtc to cleanup pageflip on
+ * @crtc_base: new address of the crtc (GPU MC address)
+ *
+ * Does the actual pageflip (surface address update).
+ */
+static void dm_page_flip(struct amdgpu_device *adev,
+			int crtc_id, u64 crtc_base)
+{
+	struct amdgpu_crtc *acrtc;
+	struct dc_target *target;
+	struct dc_flip_addrs addr = { {0} };
+
+	/*
+	 * TODO risk of concurrency issues
+	 *
+	 * This should guarded by the dal_mutex but we can't do this since the
+	 * caller uses a spin_lock on event_lock.
+	 *
+	 * If we wait on the dal_mutex a second page flip interrupt might come,
+	 * spin on the event_lock, disabling interrupts while it does so. At
+	 * this point the core can no longer be pre-empted and return to the
+	 * thread that waited on the dal_mutex and we're deadlocked.
+	 *
+	 * With multiple cores the same essentially happens but might just take
+	 * a little longer to lock up all cores.
+	 *
+	 * The reason we should lock on dal_mutex is so that we can be sure
+	 * nobody messes with acrtc->target after we read and check its value.
+	 *
+	 * We might be able to fix our concurrency issues with a work queue
+	 * where we schedule all work items (mode_set, page_flip, etc.) and
+	 * execute them one by one. Care needs to be taken to still deal with
+	 * any potential concurrency issues arising from interrupt calls.
+	 */
+
+	acrtc = adev->mode_info.crtcs[crtc_id];
+	target = acrtc->target;
+
+	/*
+	 * Received a page flip call after the display has been reset. Make sure
+	 * we return the buffers.
+	 */
+	if (!target) {
+		amdgpu_dm_flip_cleanup(adev, acrtc);
+		return;
+	}
+
+	addr.address.grph.addr.low_part = lower_32_bits(crtc_base);
+	addr.address.grph.addr.high_part = upper_32_bits(crtc_base);
+
+	dc_flip_surface_addrs(
+			adev->dm.dc,
+			dc_target_get_status(target)->surfaces,
+			&addr, 1);
+}
+
+static const struct amdgpu_display_funcs display_funcs = {
+	.set_vga_render_state = dm_set_vga_render_state,
+	.bandwidth_update = dm_bandwidth_update, /* called unconditionally */
+	.vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */
+	.vblank_wait = NULL, /* not called anywhere */
+	.is_display_hung = dm_is_display_hung,/* called unconditionally */
+	.backlight_set_level =
+		dm_set_backlight_level,/* called unconditionally */
+	.backlight_get_level =
+		dm_get_backlight_level,/* called unconditionally */
+	.hpd_sense = NULL,/* called unconditionally */
+	.hpd_set_polarity = NULL, /* called unconditionally */
+	.hpd_get_gpio_reg = dm_hpd_get_gpio_reg,/* called unconditionally */
+	.page_flip = dm_page_flip, /* called unconditionally */
+	.page_flip_get_scanoutpos =
+		dm_crtc_get_scanoutpos,/* called unconditionally */
+	.add_encoder = NULL, /* VBIOS parsing. DAL does it. */
+	.add_connector = NULL, /* VBIOS parsing. DAL does it. */
+	.stop_mc_access = dm_stop_mc_access, /* called unconditionally */
+	.resume_mc_access = dm_resume_mc_access, /* called unconditionally */
+};
+
+static void set_display_funcs(struct amdgpu_device *adev)
+{
+	if (adev->mode_info.funcs == NULL)
+		adev->mode_info.funcs = &display_funcs;
+}
+
+static int dm_early_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	set_display_funcs(adev);
+	amdgpu_dm_set_irq_funcs(adev);
+
+	switch (adev->asic_type) {
+	case CHIP_FIJI:
+	case CHIP_TONGA:
+		adev->mode_info.num_crtc = 6;
+		adev->mode_info.num_hpd = 6;
+		adev->mode_info.num_dig = 7;
+		break;
+	case CHIP_CARRIZO:
+		adev->mode_info.num_crtc = 3;
+		adev->mode_info.num_hpd = 6;
+		adev->mode_info.num_dig = 9;
+		break;
+	default:
+		DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type);
+		return -EINVAL;
+	}
+
+	/* Note: Do NOT change adev->audio_endpt_rreg and
+	 * adev->audio_endpt_wreg because they are initialised in
+	 * amdgpu_device_init() */
+
+
+
+	return 0;
+}
+
+
+bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm)
+{
+	/* TODO */
+	return true;
+}
+
+bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm)
+{
+	/* TODO */
+	return true;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
new file mode 100644
index 000000000000..c4ae90b31523
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AMDGPU_DM_H__
+#define __AMDGPU_DM_H__
+
+/*
+#include "linux/switch.h"
+*/
+
+/*
+ * This file contains the definition for amdgpu_display_manager
+ * and its API for amdgpu driver's use.
+ * This component provides all the display related functionality
+ * and this is the only component that calls DAL API.
+ * The API contained here intended for amdgpu driver use.
+ * The API that is called directly from KMS framework is located
+ * in amdgpu_dm_kms.h file
+ */
+
+#define AMDGPU_DM_MAX_DISPLAY_INDEX 31
+/*
+#include "include/amdgpu_dal_power_if.h"
+#include "amdgpu_dm_irq.h"
+*/
+
+#include "irq_types.h"
+
+/* Forward declarations */
+struct amdgpu_device;
+struct drm_device;
+struct amdgpu_dm_irq_handler_data;
+
+struct amdgpu_dm_prev_state {
+	struct drm_framebuffer *fb;
+	int32_t x;
+	int32_t y;
+	struct drm_display_mode mode;
+};
+
+struct common_irq_params {
+	struct amdgpu_device *adev;
+	enum dc_irq_source irq_src;
+};
+
+struct irq_list_head {
+	struct list_head head;
+	/* In case this interrupt needs post-processing, 'work' will be queued*/
+	struct work_struct work;
+};
+
+struct amdgpu_display_manager {
+	struct dal *dal;
+	struct dc *dc;
+	void *cgs_device;
+	/* lock to be used when DAL is called from SYNC IRQ context */
+	spinlock_t dal_lock;
+
+	struct amdgpu_device *adev;	/*AMD base driver*/
+	struct drm_device *ddev;	/*DRM base driver*/
+	u16 display_indexes_num;
+
+	struct amdgpu_dm_prev_state prev_state;
+
+	/*
+	 * 'irq_source_handler_table' holds a list of handlers
+	 * per (DAL) IRQ source.
+	 *
+	 * Each IRQ source may need to be handled at different contexts.
+	 * By 'context' we mean, for example:
+	 * - The ISR context, which is the direct interrupt handler.
+	 * - The 'deferred' context - this is the post-processing of the
+	 *	interrupt, but at a lower priority.
+	 *
+	 * Note that handlers are called in the same order as they were
+	 * registered (FIFO).
+	 */
+	struct irq_list_head irq_handler_list_low_tab[DAL_IRQ_SOURCES_NUMBER];
+	struct list_head irq_handler_list_high_tab[DAL_IRQ_SOURCES_NUMBER];
+
+	struct common_irq_params
+	pflip_params[DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1];
+
+	struct common_irq_params
+	vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1];
+
+	/* this spin lock synchronizes access to 'irq_handler_list_table' */
+	spinlock_t irq_handler_list_table_lock;
+
+	/* Timer-related data. */
+	struct list_head timer_handler_list;
+	struct workqueue_struct *timer_workqueue;
+
+	/* Use dal_mutex for any activity which is NOT syncronized by
+	 * DRM mode setting locks.
+	 * For example: amdgpu_dm_hpd_low_irq() calls into DAL *without*
+	 * DRM mode setting locks being acquired. This is where dal_mutex
+	 * is acquired before calling into DAL. */
+	struct mutex dal_mutex;
+
+	struct backlight_device *backlight_dev;
+
+	const struct dc_link *backlight_link;
+
+	struct work_struct mst_hotplug_work;
+};
+
+
+/* basic init/fini API */
+int amdgpu_dm_init(struct amdgpu_device *adev);
+
+void amdgpu_dm_fini(struct amdgpu_device *adev);
+
+void amdgpu_dm_destroy(void);
+
+/* initializes drm_device display related structures, based on the information
+ * provided by DAL. The drm strcutures are: drm_crtc, drm_connector,
+ * drm_encoder, drm_mode_config
+ *
+ * Returns 0 on success
+ */
+int amdgpu_dm_initialize_drm_device(
+	struct amdgpu_device *adev);
+
+/* removes and deallocates the drm structures, created by the above function */
+void amdgpu_dm_destroy_drm_device(
+	struct amdgpu_display_manager *dm);
+
+/* Locking/Mutex */
+bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm);
+
+bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm);
+
+/* Register "Backlight device" accessible by user-mode. */
+void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm);
+
+void amdgpu_dm_flip_cleanup(
+	struct amdgpu_device *adev,
+	struct amdgpu_crtc *acrtc);
+
+extern const struct amd_ip_funcs amdgpu_dm_funcs;
+
+void amdgpu_dm_update_connector_after_detect(
+	struct amdgpu_connector *aconnector);
+
+#endif /* __AMDGPU_DM_H__ */
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
new file mode 100644
index 000000000000..39c5c98fe918
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/acpi.h>
+#include <linux/version.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/amdgpu_drm.h>
+#include <drm/drm_edid.h>
+
+#include "dm_services.h"
+#include "amdgpu.h"
+#include "dc.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_irq.h"
+#include "amdgpu_dm_types.h"
+
+/* dm_helpers_parse_edid_caps
+ *
+ * Parse edid caps
+ *
+ * @edid:	[in] pointer to edid
+ *  edid_caps:	[in] pointer to edid caps
+ * @return
+ *	void
+ * */
+enum dc_edid_status dm_helpers_parse_edid_caps(
+		struct dc_context *ctx,
+		const struct dc_edid *edid,
+		struct dc_edid_caps *edid_caps)
+{
+	struct edid *edid_buf = (struct edid *) edid->raw_edid;
+	struct cea_sad *sads;
+	int sad_count = -1;
+	int sadb_count = -1;
+	int i = 0;
+	int j = 0;
+	uint8_t *sadb = NULL;
+
+	enum dc_edid_status result = EDID_OK;
+
+	if (!edid_caps || !edid)
+		return EDID_BAD_INPUT;
+
+	if (!drm_edid_is_valid(edid_buf))
+		result = EDID_BAD_CHECKSUM;
+
+	edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] |
+					((uint16_t) edid_buf->mfg_id[1])<<8;
+	edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] |
+					((uint16_t) edid_buf->prod_code[1])<<8;
+	edid_caps->serial_number = edid_buf->serial;
+	edid_caps->manufacture_week = edid_buf->mfg_week;
+	edid_caps->manufacture_year = edid_buf->mfg_year;
+
+	/* One of the four detailed_timings stores the monitor name. It's
+	 * stored in an array of length 13. */
+	for (i = 0; i < 4; i++) {
+		if (edid_buf->detailed_timings[i].data.other_data.type == 0xfc) {
+			while (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] && j < 13) {
+				if (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] == '\n')
+					break;
+
+				edid_caps->display_name[j] =
+					edid_buf->detailed_timings[i].data.other_data.data.str.str[j];
+				j++;
+			}
+		}
+	}
+
+	sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
+	if (sad_count <= 0) {
+		DRM_INFO("SADs count is: %d, don't need to read it\n",
+				sad_count);
+		return result;
+	}
+
+	edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT;
+	for (i = 0; i < edid_caps->audio_mode_count; ++i) {
+		struct cea_sad *sad = &sads[i];
+
+		edid_caps->audio_modes[i].format_code = sad->format;
+		edid_caps->audio_modes[i].channel_count = sad->channels;
+		edid_caps->audio_modes[i].sample_rate = sad->freq;
+		edid_caps->audio_modes[i].sample_size = sad->byte2;
+	}
+
+	sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb);
+
+	if (sadb_count < 0) {
+		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count);
+		sadb_count = 0;
+	}
+
+	if (sadb_count)
+		edid_caps->speaker_flags = sadb[0];
+	else
+		edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION;
+
+	kfree(sads);
+	kfree(sadb);
+
+	return result;
+}
+
+static struct amdgpu_connector *get_connector_for_sink(
+	struct drm_device *dev,
+	const struct dc_sink *sink)
+{
+	struct drm_connector *connector;
+	struct amdgpu_connector *aconnector = NULL;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		if (aconnector->dc_sink == sink)
+			break;
+	}
+
+	return aconnector;
+}
+
+static struct amdgpu_connector *get_connector_for_link(
+	struct drm_device *dev,
+	const struct dc_link *link)
+{
+	struct drm_connector *connector;
+	struct amdgpu_connector *aconnector = NULL;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		if (aconnector->dc_link == link)
+			break;
+	}
+
+	return aconnector;
+}
+
+
+static void get_payload_table(
+		struct amdgpu_connector *aconnector,
+		struct dp_mst_stream_allocation_table *proposed_table)
+{
+	int i;
+	struct drm_dp_mst_topology_mgr *mst_mgr =
+			&aconnector->mst_port->mst_mgr;
+
+	mutex_lock(&mst_mgr->payload_lock);
+
+	proposed_table->stream_count = 0;
+
+	/* number of active streams */
+	for (i = 0; i < mst_mgr->max_payloads; i++) {
+		if (mst_mgr->payloads[i].num_slots == 0)
+			break; /* end of vcp_id table */
+
+		ASSERT(mst_mgr->payloads[i].payload_state !=
+				DP_PAYLOAD_DELETE_LOCAL);
+
+		if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL ||
+			mst_mgr->payloads[i].payload_state ==
+					DP_PAYLOAD_REMOTE) {
+
+			struct dp_mst_stream_allocation *sa =
+					&proposed_table->stream_allocations[
+						proposed_table->stream_count];
+
+			sa->slot_count = mst_mgr->payloads[i].num_slots;
+			sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi;
+			proposed_table->stream_count++;
+		}
+	}
+
+	mutex_unlock(&mst_mgr->payload_lock);
+}
+
+/*
+ * Writes payload allocation table in immediate downstream device.
+ */
+bool dm_helpers_dp_mst_write_payload_allocation_table(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		struct dp_mst_stream_allocation_table *proposed_table,
+		bool enable)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
+	struct drm_dp_mst_port *mst_port;
+	int slots = 0;
+	bool ret;
+	int clock;
+	int bpp = 0;
+	int pbn = 0;
+
+	aconnector = get_connector_for_sink(dev, stream->sink);
+
+	if (!aconnector->mst_port)
+		return false;
+
+	mst_mgr = &aconnector->mst_port->mst_mgr;
+
+	if (!mst_mgr->mst_state)
+		return false;
+
+	mst_port = aconnector->port;
+
+	if (enable) {
+		clock = stream->timing.pix_clk_khz;
+
+		switch (stream->timing.display_color_depth) {
+
+		case COLOR_DEPTH_666:
+			bpp = 6;
+			break;
+		case COLOR_DEPTH_888:
+			bpp = 8;
+			break;
+		case COLOR_DEPTH_101010:
+			bpp = 10;
+			break;
+		case COLOR_DEPTH_121212:
+			bpp = 12;
+			break;
+		case COLOR_DEPTH_141414:
+			bpp = 14;
+			break;
+		case COLOR_DEPTH_161616:
+			bpp = 16;
+			break;
+		default:
+			ASSERT(bpp != 0);
+			break;
+		}
+
+		bpp = bpp * 3;
+
+		/* TODO need to know link rate */
+
+		pbn = drm_dp_calc_pbn_mode(clock, bpp);
+
+		ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, &slots);
+
+		if (!ret)
+			return false;
+
+	} else {
+		drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port);
+	}
+
+	ret = drm_dp_update_payload_part1(mst_mgr);
+
+	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
+	 * AUX message. The sequence is slot 1-63 allocated sequence for each
+	 * stream. AMD ASIC stream slot allocation should follow the same
+	 * sequence. copy DRM MST allocation to dc */
+
+	get_payload_table(aconnector, proposed_table);
+
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/*
+ * Polls for ACT (allocation change trigger) handled and sends
+ * ALLOCATE_PAYLOAD message.
+ */
+bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+		struct dc_context *ctx,
+		const struct dc_stream *stream)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
+	int ret;
+
+	aconnector = get_connector_for_sink(dev, stream->sink);
+
+	if (!aconnector->mst_port)
+		return false;
+
+	mst_mgr = &aconnector->mst_port->mst_mgr;
+
+	if (!mst_mgr->mst_state)
+		return false;
+
+	ret = drm_dp_check_act_status(mst_mgr);
+
+	if (ret)
+		return false;
+
+	return true;
+}
+
+bool dm_helpers_dp_mst_send_payload_allocation(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		bool enable)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
+	struct drm_dp_mst_port *mst_port;
+	int ret;
+
+	aconnector = get_connector_for_sink(dev, stream->sink);
+
+	mst_port = aconnector->port;
+
+	if (!aconnector->mst_port)
+		return false;
+
+	mst_mgr = &aconnector->mst_port->mst_mgr;
+
+	if (!mst_mgr->mst_state)
+		return false;
+
+	ret = drm_dp_update_payload_part2(mst_mgr);
+
+	if (ret)
+		return false;
+
+	if (!enable)
+		drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port);
+
+	return true;
+}
+
+void dm_helpers_dp_mst_handle_mst_hpd_rx_irq(void *param)
+{
+	uint8_t esi[8] = { 0 };
+	uint8_t dret;
+	bool new_irq_handled = true;
+	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
+
+	/* DPCD 0x2002 - 0x2008 for down stream IRQ from MST, eDP etc. */
+	dret = drm_dp_dpcd_read(
+		&aconnector->dm_dp_aux.aux,
+		DP_SINK_COUNT_ESI, esi, 8);
+
+	while ((dret == 8) && new_irq_handled) {
+		uint8_t retry;
+
+		DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+
+		/* handle HPD short pulse irq */
+		drm_dp_mst_hpd_irq(&aconnector->mst_mgr, esi, &new_irq_handled);
+
+		if (new_irq_handled) {
+			/* ACK at DPCD to notify down stream */
+			for (retry = 0; retry < 3; retry++) {
+				uint8_t wret;
+
+				wret = drm_dp_dpcd_write(
+					&aconnector->dm_dp_aux.aux,
+					DP_SINK_COUNT_ESI + 1,
+					&esi[1],
+					3);
+				if (wret == 3)
+					break;
+			}
+
+			/* check if there is new irq to be handle */
+			dret = drm_dp_dpcd_read(
+				&aconnector->dm_dp_aux.aux,
+				DP_SINK_COUNT_ESI, esi, 8);
+		}
+	}
+}
+
+bool dm_helpers_dp_mst_start_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		bool boot)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	if (boot) {
+		DRM_INFO("DM_MST: Differing MST start on aconnector: %p [id: %d]\n",
+					aconnector, aconnector->base.base.id);
+		return true;
+	}
+
+	DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n",
+			aconnector, aconnector->base.base.id);
+
+	return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0);
+}
+
+void dm_helpers_dp_mst_stop_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n",
+			aconnector, aconnector->base.base.id);
+
+	if (aconnector->mst_mgr.mst_state == true)
+		drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false);
+}
+
+bool dm_helper_dp_read_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size) {
+
+
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	if (!aconnector) {
+		DRM_ERROR("Failed to found connector for link!");
+		return false;
+	}
+
+	return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address,
+			data, size) > 0;
+}
+
+bool dm_helper_dp_write_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t size) {
+
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	if (!aconnector) {
+		DRM_ERROR("Failed to found connector for link!");
+		return false;
+	}
+
+	return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux,
+			address, (uint8_t *)data, size) > 0;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
new file mode 100644
index 000000000000..9b5fd7063a0b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <drm/drmP.h>
+
+#include "dm_services_types.h"
+#include "dc.h"
+
+#include "amdgpu.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_irq.h"
+
+
+/******************************************************************************
+ * Private declarations.
+ *****************************************************************************/
+
+struct handler_common_data {
+	struct list_head list;
+	interrupt_handler handler;
+	void *handler_arg;
+
+	/* DM which this handler belongs to */
+	struct amdgpu_display_manager *dm;
+};
+
+struct amdgpu_dm_irq_handler_data {
+	struct handler_common_data hcd;
+	/* DAL irq source which registered for this interrupt. */
+	enum dc_irq_source irq_source;
+};
+
+struct amdgpu_dm_timer_handler_data {
+	struct handler_common_data hcd;
+	struct delayed_work d_work;
+};
+
+
+#define DM_IRQ_TABLE_LOCK(adev, flags) \
+	spin_lock_irqsave(&adev->dm.irq_handler_list_table_lock, flags)
+
+#define DM_IRQ_TABLE_UNLOCK(adev, flags) \
+	spin_unlock_irqrestore(&adev->dm.irq_handler_list_table_lock, flags)
+
+/******************************************************************************
+ * Private functions.
+ *****************************************************************************/
+
+static void init_handler_common_data(
+	struct handler_common_data *hcd,
+	void (*ih)(void *),
+	void *args,
+	struct amdgpu_display_manager *dm)
+{
+	hcd->handler = ih;
+	hcd->handler_arg = args;
+	hcd->dm = dm;
+}
+
+/**
+ * dm_irq_work_func - Handle an IRQ outside of the interrupt handler proper.
+ *
+ * @work: work struct
+ */
+static void dm_irq_work_func(struct work_struct *work)
+{
+	struct list_head *entry;
+	struct irq_list_head *irq_list_head =
+		container_of(work, struct irq_list_head, work);
+	struct list_head *handler_list = &irq_list_head->head;
+	struct amdgpu_dm_irq_handler_data *handler_data;
+
+	list_for_each(entry, handler_list) {
+		handler_data =
+			list_entry(
+				entry,
+				struct amdgpu_dm_irq_handler_data,
+				hcd.list);
+
+		DRM_DEBUG_KMS("DM_IRQ: work_func: for dal_src=%d\n",
+				handler_data->irq_source);
+
+		DRM_DEBUG_KMS("DM_IRQ: schedule_work: for dal_src=%d\n",
+			handler_data->irq_source);
+
+		handler_data->hcd.handler(handler_data->hcd.handler_arg);
+	}
+
+	/* Call a DAL subcomponent which registered for interrupt notification
+	 * at INTERRUPT_LOW_IRQ_CONTEXT.
+	 * (The most common use is HPD interrupt) */
+}
+
+/**
+ * Remove a handler and return a pointer to hander list from which the
+ * handler was removed.
+ */
+static struct list_head *remove_irq_handler(
+	struct amdgpu_device *adev,
+	void *ih,
+	const struct dc_interrupt_params *int_params)
+{
+	struct list_head *hnd_list;
+	struct list_head *entry, *tmp;
+	struct amdgpu_dm_irq_handler_data *handler;
+	unsigned long irq_table_flags;
+	bool handler_removed = false;
+	enum dc_irq_source irq_source;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	irq_source = int_params->irq_source;
+
+	switch (int_params->int_context) {
+	case INTERRUPT_HIGH_IRQ_CONTEXT:
+		hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source];
+		break;
+	case INTERRUPT_LOW_IRQ_CONTEXT:
+	default:
+		hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head;
+		break;
+	}
+
+	list_for_each_safe(entry, tmp, hnd_list) {
+
+		handler = list_entry(entry, struct amdgpu_dm_irq_handler_data,
+				hcd.list);
+
+		if (ih == handler) {
+			/* Found our handler. Remove it from the list. */
+			list_del(&handler->hcd.list);
+			handler_removed = true;
+			break;
+		}
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	if (handler_removed == false) {
+		/* Not necessarily an error - caller may not
+		 * know the context. */
+		return NULL;
+	}
+
+	kfree(handler);
+
+	DRM_DEBUG_KMS(
+	"DM_IRQ: removed irq handler: %p for: dal_src=%d, irq context=%d\n",
+		ih, int_params->irq_source, int_params->int_context);
+
+	return hnd_list;
+}
+
+/* If 'handler_in == NULL' then remove ALL handlers. */
+static void remove_timer_handler(
+	struct amdgpu_device *adev,
+	struct amdgpu_dm_timer_handler_data *handler_in)
+{
+	struct amdgpu_dm_timer_handler_data *handler_temp;
+	struct list_head *handler_list;
+	struct list_head *entry, *tmp;
+	unsigned long irq_table_flags;
+	bool handler_removed = false;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	handler_list = &adev->dm.timer_handler_list;
+
+	list_for_each_safe(entry, tmp, handler_list) {
+		/* Note that list_for_each_safe() guarantees that
+		 * handler_temp is NOT null. */
+		handler_temp = list_entry(entry,
+				struct amdgpu_dm_timer_handler_data, hcd.list);
+
+		if (handler_in == NULL || handler_in == handler_temp) {
+			list_del(&handler_temp->hcd.list);
+			DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+			DRM_DEBUG_KMS("DM_IRQ: removing timer handler: %p\n",
+					handler_temp);
+
+			if (handler_in == NULL) {
+				/* Since it is still in the queue, it must
+				 * be cancelled. */
+				cancel_delayed_work_sync(&handler_temp->d_work);
+			}
+
+			kfree(handler_temp);
+			handler_removed = true;
+
+			DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+		}
+
+		if (handler_in == NULL) {
+			/* Remove ALL handlers. */
+			continue;
+		}
+
+		if (handler_in == handler_temp) {
+			/* Remove a SPECIFIC handler.
+			 * Found our handler - we can stop here. */
+			break;
+		}
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	if (handler_in != NULL && handler_removed == false) {
+		DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n",
+				handler_in);
+	}
+}
+
+/**
+ * dm_timer_work_func - Handle a timer.
+ *
+ * @work: work struct
+ */
+static void dm_timer_work_func(
+	struct work_struct *work)
+{
+	struct amdgpu_dm_timer_handler_data *handler_data =
+		container_of(work, struct amdgpu_dm_timer_handler_data,
+				d_work.work);
+
+	DRM_DEBUG_KMS("DM_IRQ: work_func: handler_data=%p\n", handler_data);
+
+	/* Call a DAL subcomponent which registered for timer notification. */
+	handler_data->hcd.handler(handler_data->hcd.handler_arg);
+
+	/* We support only "single shot" timers. That means we must delete
+	 * the handler after it was called. */
+	remove_timer_handler(handler_data->hcd.dm->adev, handler_data);
+}
+
+static bool validate_irq_registration_params(
+	struct dc_interrupt_params *int_params,
+	void (*ih)(void *))
+{
+	if (NULL == int_params || NULL == ih) {
+		DRM_ERROR("DM_IRQ: invalid input!\n");
+		return false;
+	}
+
+	if (int_params->int_context >= INTERRUPT_CONTEXT_NUMBER) {
+		DRM_ERROR("DM_IRQ: invalid context: %d!\n",
+				int_params->int_context);
+		return false;
+	}
+
+	if (!DAL_VALID_IRQ_SRC_NUM(int_params->irq_source)) {
+		DRM_ERROR("DM_IRQ: invalid irq_source: %d!\n",
+				int_params->irq_source);
+		return false;
+	}
+
+	return true;
+}
+
+static bool validate_irq_unregistration_params(
+	enum dc_irq_source irq_source,
+	irq_handler_idx handler_idx)
+{
+	if (DAL_INVALID_IRQ_HANDLER_IDX == handler_idx) {
+		DRM_ERROR("DM_IRQ: invalid handler_idx==NULL!\n");
+		return false;
+	}
+
+	if (!DAL_VALID_IRQ_SRC_NUM(irq_source)) {
+		DRM_ERROR("DM_IRQ: invalid irq_source:%d!\n", irq_source);
+		return false;
+	}
+
+	return true;
+}
+/******************************************************************************
+ * Public functions.
+ *
+ * Note: caller is responsible for input validation.
+ *****************************************************************************/
+
+void *amdgpu_dm_irq_register_interrupt(
+	struct amdgpu_device *adev,
+	struct dc_interrupt_params *int_params,
+	void (*ih)(void *),
+	void *handler_args)
+{
+	struct list_head *hnd_list;
+	struct amdgpu_dm_irq_handler_data *handler_data;
+	unsigned long irq_table_flags;
+	enum dc_irq_source irq_source;
+
+	if (false == validate_irq_registration_params(int_params, ih))
+		return DAL_INVALID_IRQ_HANDLER_IDX;
+
+	handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL);
+	if (!handler_data) {
+		DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n");
+		return DAL_INVALID_IRQ_HANDLER_IDX;
+	}
+
+	memset(handler_data, 0, sizeof(*handler_data));
+
+	init_handler_common_data(&handler_data->hcd, ih, handler_args,
+			&adev->dm);
+
+	irq_source = int_params->irq_source;
+
+	handler_data->irq_source = irq_source;
+
+	/* Lock the list, add the handler. */
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	switch (int_params->int_context) {
+	case INTERRUPT_HIGH_IRQ_CONTEXT:
+		hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source];
+		break;
+	case INTERRUPT_LOW_IRQ_CONTEXT:
+	default:
+		hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head;
+		break;
+	}
+
+	list_add_tail(&handler_data->hcd.list, hnd_list);
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	/* This pointer will be stored by code which requested interrupt
+	 * registration.
+	 * The same pointer will be needed in order to unregister the
+	 * interrupt. */
+
+	DRM_DEBUG_KMS(
+		"DM_IRQ: added irq handler: %p for: dal_src=%d, irq context=%d\n",
+		handler_data,
+		irq_source,
+		int_params->int_context);
+
+	return handler_data;
+}
+
+void amdgpu_dm_irq_unregister_interrupt(
+	struct amdgpu_device *adev,
+	enum dc_irq_source irq_source,
+	void *ih)
+{
+	struct list_head *handler_list;
+	struct dc_interrupt_params int_params;
+	int i;
+
+	if (false == validate_irq_unregistration_params(irq_source, ih))
+		return;
+
+	memset(&int_params, 0, sizeof(int_params));
+
+	int_params.irq_source = irq_source;
+
+	for (i = 0; i < INTERRUPT_CONTEXT_NUMBER; i++) {
+
+		int_params.int_context = i;
+
+		handler_list = remove_irq_handler(adev, ih, &int_params);
+
+		if (handler_list != NULL)
+			break;
+	}
+
+	if (handler_list == NULL) {
+		/* If we got here, it means we searched all irq contexts
+		 * for this irq source, but the handler was not found. */
+		DRM_ERROR(
+		"DM_IRQ: failed to find irq handler:%p for irq_source:%d!\n",
+			ih, irq_source);
+	}
+}
+
+int amdgpu_dm_irq_init(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct irq_list_head *lh;
+
+	DRM_DEBUG_KMS("DM_IRQ\n");
+
+	spin_lock_init(&adev->dm.irq_handler_list_table_lock);
+
+	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+		/* low context handler list init */
+		lh = &adev->dm.irq_handler_list_low_tab[src];
+		INIT_LIST_HEAD(&lh->head);
+		INIT_WORK(&lh->work, dm_irq_work_func);
+
+		/* high context handler init */
+		INIT_LIST_HEAD(&adev->dm.irq_handler_list_high_tab[src]);
+	}
+
+	INIT_LIST_HEAD(&adev->dm.timer_handler_list);
+
+	/* allocate and initialize the workqueue for DM timer */
+	adev->dm.timer_workqueue = create_singlethread_workqueue(
+			"dm_timer_queue");
+	if (adev->dm.timer_workqueue == NULL) {
+		DRM_ERROR("DM_IRQ: unable to create timer queue!\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void amdgpu_dm_irq_register_timer(
+	struct amdgpu_device *adev,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *args)
+{
+	unsigned long jf_delay;
+	struct list_head *handler_list;
+	struct amdgpu_dm_timer_handler_data *handler_data;
+	unsigned long irq_table_flags;
+
+	handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL);
+	if (!handler_data) {
+		DRM_ERROR("DM_IRQ: failed to allocate timer handler!\n");
+		return;
+	}
+
+	memset(handler_data, 0, sizeof(*handler_data));
+
+	init_handler_common_data(&handler_data->hcd, ih, args, &adev->dm);
+
+	INIT_DELAYED_WORK(&handler_data->d_work, dm_timer_work_func);
+
+	/* Lock the list, add the handler. */
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	handler_list = &adev->dm.timer_handler_list;
+
+	list_add_tail(&handler_data->hcd.list, handler_list);
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	jf_delay = usecs_to_jiffies(int_params->micro_sec_interval);
+
+	queue_delayed_work(adev->dm.timer_workqueue, &handler_data->d_work,
+			jf_delay);
+
+	DRM_DEBUG_KMS("DM_IRQ: added handler:%p with micro_sec_interval=%u\n",
+			handler_data, int_params->micro_sec_interval);
+	return;
+}
+
+/* DM IRQ and timer resource release */
+void amdgpu_dm_irq_fini(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct irq_list_head *lh;
+	DRM_DEBUG_KMS("DM_IRQ: releasing resources.\n");
+
+	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+
+		/* The handler was removed from the table,
+		 * it means it is safe to flush all the 'work'
+		 * (because no code can schedule a new one). */
+		lh = &adev->dm.irq_handler_list_low_tab[src];
+		flush_work(&lh->work);
+	}
+
+	/* Cancel ALL timers and release handlers (if any). */
+	remove_timer_handler(adev, NULL);
+	/* Release the queue itself. */
+	destroy_workqueue(adev->dm.timer_workqueue);
+}
+
+int amdgpu_dm_irq_suspend(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct list_head *hnd_list_h;
+	struct list_head *hnd_list_l;
+	unsigned long irq_table_flags;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	DRM_DEBUG_KMS("DM_IRQ: suspend\n");
+
+	/* disable HW interrupt */
+	for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+		hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
+		hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
+		if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
+			dc_interrupt_set(adev->dm.dc, src, false);
+
+		DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+		flush_work(&adev->dm.irq_handler_list_low_tab[src].work);
+
+		DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	return 0;
+}
+
+int amdgpu_dm_irq_resume(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct list_head *hnd_list_h, *hnd_list_l;
+	unsigned long irq_table_flags;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	DRM_DEBUG_KMS("DM_IRQ: resume\n");
+
+	/* re-enable HW interrupt */
+	for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+		hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
+		hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
+		if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
+			dc_interrupt_set(adev->dm.dc, src, true);
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	return 0;
+}
+
+
+/**
+ * amdgpu_dm_irq_schedule_work - schedule all work items registered for the
+ * "irq_source".
+ */
+static void amdgpu_dm_irq_schedule_work(
+	struct amdgpu_device *adev,
+	enum dc_irq_source irq_source)
+{
+	unsigned long irq_table_flags;
+	struct work_struct *work = NULL;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	if (!list_empty(&adev->dm.irq_handler_list_low_tab[irq_source].head))
+		work = &adev->dm.irq_handler_list_low_tab[irq_source].work;
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	if (work) {
+		if (!schedule_work(work))
+			DRM_INFO("amdgpu_dm_irq_schedule_work FAILED src %d\n",
+						irq_source);
+	}
+
+}
+
+/** amdgpu_dm_irq_immediate_work
+ *  Callback high irq work immediately, don't send to work queue
+ */
+static void amdgpu_dm_irq_immediate_work(
+	struct amdgpu_device *adev,
+	enum dc_irq_source irq_source)
+{
+	struct amdgpu_dm_irq_handler_data *handler_data;
+	struct list_head *entry;
+	unsigned long irq_table_flags;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	list_for_each(
+		entry,
+		&adev->dm.irq_handler_list_high_tab[irq_source]) {
+
+		handler_data =
+			list_entry(
+				entry,
+				struct amdgpu_dm_irq_handler_data,
+				hcd.list);
+
+		/* Call a subcomponent which registered for immediate
+		 * interrupt notification */
+		handler_data->hcd.handler(handler_data->hcd.handler_arg);
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+}
+
+/*
+ * amdgpu_dm_irq_handler
+ *
+ * Generic IRQ handler, calls all registered high irq work immediately, and
+ * schedules work for low irq
+ */
+int amdgpu_dm_irq_handler(
+		struct amdgpu_device *adev,
+		struct amdgpu_irq_src *source,
+		struct amdgpu_iv_entry *entry)
+{
+
+	enum dc_irq_source src =
+		dc_interrupt_to_irq_source(
+			adev->dm.dc,
+			entry->src_id,
+			entry->src_data);
+
+	dc_interrupt_ack(adev->dm.dc, src);
+
+	/* Call high irq work immediately */
+	amdgpu_dm_irq_immediate_work(adev, src);
+	/*Schedule low_irq work */
+	amdgpu_dm_irq_schedule_work(adev, src);
+
+	return 0;
+}
+
+static enum dc_irq_source amdgpu_dm_hpd_to_dal_irq_source(unsigned type)
+{
+	switch (type) {
+	case AMDGPU_HPD_1:
+		return DC_IRQ_SOURCE_HPD1;
+	case AMDGPU_HPD_2:
+		return DC_IRQ_SOURCE_HPD2;
+	case AMDGPU_HPD_3:
+		return DC_IRQ_SOURCE_HPD3;
+	case AMDGPU_HPD_4:
+		return DC_IRQ_SOURCE_HPD4;
+	case AMDGPU_HPD_5:
+		return DC_IRQ_SOURCE_HPD5;
+	case AMDGPU_HPD_6:
+		return DC_IRQ_SOURCE_HPD6;
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev,
+					struct amdgpu_irq_src *source,
+					unsigned type,
+					enum amdgpu_interrupt_state state)
+{
+	enum dc_irq_source src = amdgpu_dm_hpd_to_dal_irq_source(type);
+	bool st = (state == AMDGPU_IRQ_STATE_ENABLE);
+
+	dc_interrupt_set(adev->dm.dc, src, st);
+	return 0;
+}
+
+static inline int dm_irq_state(
+	struct amdgpu_device *adev,
+	struct amdgpu_irq_src *source,
+	unsigned crtc_id,
+	enum amdgpu_interrupt_state state,
+	const enum irq_type dal_irq_type,
+	const char *func)
+{
+	bool st;
+	enum dc_irq_source irq_source;
+
+	struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc_id];
+
+	if (!acrtc->target) {
+		DRM_INFO(
+			"%s: target is null for crtc %d, talk to David R\n",
+			func,
+			crtc_id);
+		WARN_ON(true);
+		return 0;
+	}
+
+	irq_source = dc_target_get_irq_src(acrtc->target, dal_irq_type);
+
+	st = (state == AMDGPU_IRQ_STATE_ENABLE);
+
+	dc_interrupt_set(adev->dm.dc, irq_source, st);
+	return 0;
+}
+
+static int amdgpu_dm_set_pflip_irq_state(struct amdgpu_device *adev,
+					struct amdgpu_irq_src *source,
+					unsigned crtc_id,
+					enum amdgpu_interrupt_state state)
+{
+	return dm_irq_state(
+		adev,
+		source,
+		crtc_id,
+		state,
+		IRQ_TYPE_PFLIP,
+		__func__);
+}
+
+static int amdgpu_dm_set_crtc_irq_state(struct amdgpu_device *adev,
+					struct amdgpu_irq_src *source,
+					unsigned crtc_id,
+					enum amdgpu_interrupt_state state)
+{
+	return dm_irq_state(
+		adev,
+		source,
+		crtc_id,
+		state,
+		IRQ_TYPE_VUPDATE,
+		__func__);
+}
+
+static const struct amdgpu_irq_src_funcs dm_crtc_irq_funcs = {
+	.set = amdgpu_dm_set_crtc_irq_state,
+	.process = amdgpu_dm_irq_handler,
+};
+
+static const struct amdgpu_irq_src_funcs dm_pageflip_irq_funcs = {
+	.set = amdgpu_dm_set_pflip_irq_state,
+	.process = amdgpu_dm_irq_handler,
+};
+
+static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = {
+	.set = amdgpu_dm_set_hpd_irq_state,
+	.process = amdgpu_dm_irq_handler,
+};
+
+void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev)
+{
+	adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST;
+	adev->crtc_irq.funcs = &dm_crtc_irq_funcs;
+
+	adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST;
+	adev->pageflip_irq.funcs = &dm_pageflip_irq_funcs;
+
+	adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
+	adev->hpd_irq.funcs = &dm_hpd_irq_funcs;
+}
+
+/*
+ * amdgpu_dm_hpd_init - hpd setup callback.
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Setup the hpd pins used by the card (evergreen+).
+ * Enable the pin, set the polarity, and enable the hpd interrupts.
+ */
+void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct amdgpu_connector *amdgpu_connector =
+				to_amdgpu_connector(connector);
+
+		const struct dc_link *dc_link = amdgpu_connector->dc_link;
+
+		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+			connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+			/* don't try to enable hpd on eDP or LVDS avoid breaking
+			 * the aux dp channel on imac and help (but not
+			 * completely fix)
+			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+			 * also avoid interrupt storms during dpms.
+			 */
+			continue;
+		}
+
+		dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, true);
+
+		if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+			dc_interrupt_set(adev->dm.dc,
+					dc_link->irq_source_hpd_rx,
+					true);
+		}
+	}
+}
+
+/**
+ * amdgpu_dm_hpd_fini - hpd tear down callback.
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Tear down the hpd pins used by the card (evergreen+).
+ * Disable the hpd interrupts.
+ */
+void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct amdgpu_connector *amdgpu_connector =
+				to_amdgpu_connector(connector);
+		const struct dc_link *dc_link = amdgpu_connector->dc_link;
+
+		dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, false);
+
+		if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+			dc_interrupt_set(adev->dm.dc,
+					dc_link->irq_source_hpd_rx,
+					false);
+		}
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
new file mode 100644
index 000000000000..afedb50897bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION 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 __AMDGPU_DM_IRQ_H__
+#define __AMDGPU_DM_IRQ_H__
+
+#include "irq_types.h" /* DAL irq definitions */
+
+/*
+ * Display Manager IRQ-related interfaces (for use by DAL).
+ */
+
+/**
+ * amdgpu_dm_irq_init - Initialize internal structures of 'amdgpu_dm_irq'.
+ *
+ * This function should be called exactly once - during DM initialization.
+ *
+ * Returns:
+ *	0 - success
+ *	non-zero - error
+ */
+int amdgpu_dm_irq_init(
+	struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_fini - deallocate internal structures of 'amdgpu_dm_irq'.
+ *
+ * This function should be called exactly once - during DM destruction.
+ *
+ */
+void amdgpu_dm_irq_fini(
+	struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_register_interrupt - register irq handler for Display block.
+ *
+ * @adev: AMD DRM device
+ * @int_params: parameters for the irq
+ * @ih: pointer to the irq hander function
+ * @handler_args: arguments which will be passed to ih
+ *
+ * Returns:
+ * 	IRQ Handler Index on success.
+ * 	NULL on failure.
+ *
+ * Cannot be called from an interrupt handler.
+ */
+void *amdgpu_dm_irq_register_interrupt(
+		struct amdgpu_device *adev,
+		struct dc_interrupt_params *int_params,
+		void (*ih)(void *),
+		void *handler_args);
+
+/**
+ * amdgpu_dm_irq_unregister_interrupt - unregister handler which was registered
+ *	by amdgpu_dm_irq_register_interrupt().
+ *
+ * @adev: AMD DRM device.
+ * @ih_index: irq handler index which was returned by
+ *	amdgpu_dm_irq_register_interrupt
+ */
+void amdgpu_dm_irq_unregister_interrupt(
+		struct amdgpu_device *adev,
+		enum dc_irq_source irq_source,
+		void *ih_index);
+
+void amdgpu_dm_irq_register_timer(
+	struct amdgpu_device *adev,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *args);
+
+/**
+ * amdgpu_dm_irq_handler
+ * Generic IRQ handler, calls all registered high irq work immediately, and
+ * schedules work for low irq
+ */
+int amdgpu_dm_irq_handler(
+		struct amdgpu_device *adev,
+		struct amdgpu_irq_src *source,
+		struct amdgpu_iv_entry *entry);
+
+void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev);
+
+void amdgpu_dm_hpd_init(struct amdgpu_device *adev);
+void amdgpu_dm_hpd_fini(struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_suspend - disable ASIC interrupt during suspend.
+ *
+ */
+int amdgpu_dm_irq_suspend(
+	struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_resume - enable ASIC interrupt during resume.
+ *
+ */
+int amdgpu_dm_irq_resume(
+	struct amdgpu_device *adev);
+
+#endif /* __AMDGPU_DM_IRQ_H__ */
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
new file mode 100644
index 000000000000..22ba13080cf1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/version.h>
+#include <drm/drm_atomic_helper.h>
+#include "dm_services.h"
+#include "amdgpu.h"
+#include "amdgpu_dm_types.h"
+#include "amdgpu_dm_mst_types.h"
+
+#include "dc.h"
+#include "dm_helpers.h"
+
+
+/* #define TRACE_DPCD */
+
+#ifdef TRACE_DPCD
+#define SIDE_BAND_MSG(address) (address >= DP_SIDEBAND_MSG_DOWN_REQ_BASE && address < DP_SINK_COUNT_ESI)
+
+static inline char *side_band_msg_type_to_str(uint32_t address)
+{
+	static char str[10] = {0};
+
+	if (address < DP_SIDEBAND_MSG_UP_REP_BASE)
+		strcpy(str, "DOWN_REQ");
+	else if (address < DP_SIDEBAND_MSG_DOWN_REP_BASE)
+		strcpy(str, "UP_REP");
+	else if (address < DP_SIDEBAND_MSG_UP_REQ_BASE)
+		strcpy(str, "DOWN_REP");
+	else
+		strcpy(str, "UP_REQ");
+
+	return str;
+}
+
+void log_dpcd(uint8_t type,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size,
+		bool res)
+{
+	DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n",
+			(type == DP_AUX_NATIVE_READ) ||
+			(type == DP_AUX_I2C_READ) ?
+					"Read" : "Write",
+			address,
+			SIDE_BAND_MSG(address) ?
+					side_band_msg_type_to_str(address) : "Nop",
+			res ? "OK" : "Fail");
+
+	if (res) {
+		print_hex_dump(KERN_INFO, "Body: ", DUMP_PREFIX_NONE, 16, 1, data, size, false);
+	}
+}
+#endif
+
+static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
+{
+	struct pci_dev *pdev = to_pci_dev(aux->dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct amdgpu_device *adev = drm_dev->dev_private;
+	struct dc *dc = adev->dm.dc;
+	bool res;
+
+	switch (msg->request) {
+	case DP_AUX_NATIVE_READ:
+		res = dc_read_dpcd(
+			dc,
+			TO_DM_AUX(aux)->link_index,
+			msg->address,
+			msg->buffer,
+			msg->size);
+		break;
+	case DP_AUX_NATIVE_WRITE:
+		res = dc_write_dpcd(
+			dc,
+			TO_DM_AUX(aux)->link_index,
+			msg->address,
+			msg->buffer,
+			msg->size);
+		break;
+	default:
+		return 0;
+	}
+
+#ifdef TRACE_DPCD
+	log_dpcd(msg->request,
+			msg->address,
+			msg->buffer,
+			msg->size,
+			res);
+#endif
+
+	return msg->size;
+}
+
+static enum drm_connector_status
+dm_dp_mst_detect(struct drm_connector *connector, bool force)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+	struct amdgpu_connector *master = aconnector->mst_port;
+
+	enum drm_connector_status status =
+		drm_dp_mst_detect_port(
+			connector,
+			&master->mst_mgr,
+			aconnector->port);
+
+	if (status == connector_status_disconnected && aconnector->edid) {
+		kfree(aconnector->edid);
+		aconnector->edid = NULL;
+	}
+
+	/*
+	 * we do not want to make this connector connected until we have edid on
+	 * it
+	 */
+	if (status == connector_status_connected &&
+		!aconnector->port->cached_edid)
+		status = connector_status_disconnected;
+
+	return status;
+}
+
+static void
+dm_dp_mst_connector_destroy(struct drm_connector *connector)
+{
+	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+	struct amdgpu_encoder *amdgpu_encoder = amdgpu_connector->mst_encoder;
+
+	drm_encoder_cleanup(&amdgpu_encoder->base);
+	kfree(amdgpu_encoder);
+	drm_connector_cleanup(connector);
+	kfree(amdgpu_connector);
+}
+
+static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = dm_dp_mst_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = dm_dp_mst_connector_destroy,
+	.reset = amdgpu_dm_connector_funcs_reset,
+	.atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
+	.atomic_destroy_state = amdgpu_dm_connector_atomic_destroy_state,
+	.atomic_set_property = amdgpu_dm_connector_atomic_set_property
+};
+
+static struct dc_sink *dm_dp_mst_add_mst_sink(
+		const struct dc_link *dc_link,
+		uint8_t *edid,
+		uint16_t len)
+{
+	struct dc_sink *dc_sink;
+	struct dc_sink_init_data init_params = {
+			.link = dc_link,
+			.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST};
+	enum dc_edid_status edid_status;
+
+	if (len > MAX_EDID_BUFFER_SIZE) {
+		DRM_ERROR("Max EDID buffer size breached!\n");
+		return NULL;
+	}
+
+	if (!dc_link) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	/*
+	 * TODO make dynamic-ish?
+	 * dc_link->connector_signal;
+	 */
+
+	dc_sink = dc_sink_create(&init_params);
+
+	if (!dc_sink)
+		return NULL;
+
+	dm_memmove(dc_sink->dc_edid.raw_edid, edid, len);
+	dc_sink->dc_edid.length = len;
+
+	if (!dc_link_add_remote_sink(
+			dc_link,
+			dc_sink))
+		goto fail_add_sink;
+
+	edid_status = dm_helpers_parse_edid_caps(
+			NULL,
+			&dc_sink->dc_edid,
+			&dc_sink->edid_caps);
+	if (edid_status != EDID_OK)
+		goto fail;
+
+	/* dc_sink_retain(&core_sink->public); */
+
+	return dc_sink;
+fail:
+	dc_link_remove_remote_sink(dc_link, dc_sink);
+fail_add_sink:
+	return NULL;
+}
+
+static int dm_dp_mst_get_modes(struct drm_connector *connector)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+	struct amdgpu_connector *master = aconnector->mst_port;
+	struct edid *edid;
+	const struct dc_sink *sink;
+	int ret = 0;
+
+	if (!aconnector->edid) {
+		edid = drm_dp_mst_get_edid(connector, &master->mst_mgr, aconnector->port);
+
+		if (!edid) {
+			drm_mode_connector_update_edid_property(
+				&aconnector->base,
+				NULL);
+
+			return ret;
+		}
+
+		aconnector->edid = edid;
+
+		if (aconnector->dc_sink)
+			dc_link_remove_remote_sink(
+				aconnector->dc_link,
+				aconnector->dc_sink);
+
+		sink = dm_dp_mst_add_mst_sink(
+			aconnector->dc_link,
+			(uint8_t *)edid,
+			(edid->extensions + 1) * EDID_LENGTH);
+		aconnector->dc_sink = sink;
+	} else
+		edid = aconnector->edid;
+
+	DRM_DEBUG_KMS("edid retrieved %p\n", edid);
+
+	drm_mode_connector_update_edid_property(
+		&aconnector->base,
+		aconnector->edid);
+
+	ret = drm_add_edid_modes(&aconnector->base, aconnector->edid);
+
+	drm_edid_to_eld(&aconnector->base, aconnector->edid);
+
+	return ret;
+}
+
+static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
+{
+	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+
+	return &amdgpu_connector->mst_encoder->base;
+}
+
+static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = {
+	.get_modes = dm_dp_mst_get_modes,
+	.mode_valid = amdgpu_dm_connector_mode_valid,
+	.best_encoder = dm_mst_best_encoder,
+};
+
+static struct amdgpu_encoder *
+dm_dp_create_fake_mst_encoder(struct amdgpu_connector *connector)
+{
+	struct drm_device *dev = connector->base.dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct amdgpu_encoder *amdgpu_encoder;
+	struct drm_encoder *encoder;
+	const struct drm_connector_helper_funcs *connector_funcs =
+		connector->base.helper_private;
+	struct drm_encoder *enc_master =
+		connector_funcs->best_encoder(&connector->base);
+
+	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
+	amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
+	if (!amdgpu_encoder)
+		return NULL;
+
+	encoder = &amdgpu_encoder->base;
+	encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
+
+	drm_encoder_init(
+		dev,
+		&amdgpu_encoder->base,
+		NULL,
+		DRM_MODE_ENCODER_DPMST,
+		NULL);
+
+	drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
+
+	return amdgpu_encoder;
+}
+
+static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
+							 struct drm_dp_mst_port *port,
+							 const char *pathprop)
+{
+	struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr);
+	struct drm_device *dev = master->base.dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct amdgpu_connector *aconnector;
+	struct drm_connector *connector;
+
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		if (aconnector->mst_port == master
+				&& !aconnector->port) {
+			DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n",
+						aconnector, connector->base.id, aconnector->mst_port);
+
+			aconnector->port = port;
+			drm_mode_connector_set_path_property(connector, pathprop);
+
+			drm_modeset_unlock(&dev->mode_config.connection_mutex);
+			return &aconnector->base;
+		}
+	}
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+
+	aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
+	if (!aconnector)
+		return NULL;
+
+	connector = &aconnector->base;
+	aconnector->port = port;
+	aconnector->mst_port = master;
+
+	if (drm_connector_init(
+		dev,
+		connector,
+		&dm_dp_mst_connector_funcs,
+		DRM_MODE_CONNECTOR_DisplayPort)) {
+		kfree(aconnector);
+		return NULL;
+	}
+	drm_connector_helper_add(connector, &dm_dp_mst_connector_helper_funcs);
+
+	amdgpu_dm_connector_init_helper(
+		&adev->dm,
+		aconnector,
+		DRM_MODE_CONNECTOR_DisplayPort,
+		master->dc_link,
+		master->connector_id);
+
+	aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
+
+	/*
+	 * TODO: understand why this one is needed
+	 */
+	drm_object_attach_property(
+		&connector->base,
+		dev->mode_config.path_property,
+		0);
+	drm_object_attach_property(
+		&connector->base,
+		dev->mode_config.tile_property,
+		0);
+
+	drm_mode_connector_set_path_property(connector, pathprop);
+
+	/*
+	 * Initialize connector state before adding the connectror to drm and
+	 * framebuffer lists
+	 */
+	amdgpu_dm_connector_funcs_reset(connector);
+
+	DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n",
+			aconnector, connector->base.id, aconnector->mst_port);
+
+	DRM_DEBUG_KMS(":%d\n", connector->base.id);
+
+	return connector;
+}
+
+static void dm_dp_destroy_mst_connector(
+	struct drm_dp_mst_topology_mgr *mgr,
+	struct drm_connector *connector)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+
+	DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n",
+				aconnector, connector->base.id, aconnector->mst_port);
+
+	aconnector->port = NULL;
+	if (aconnector->dc_sink) {
+		dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink);
+		aconnector->dc_sink = NULL;
+	}
+}
+
+static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr);
+	struct drm_device *dev = master->base.dev;
+	struct amdgpu_device *adev = dev->dev_private;
+
+	schedule_work(&adev->dm.mst_hotplug_work);
+}
+
+static void dm_dp_mst_register_connector(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	int i;
+
+	drm_modeset_lock_all(dev);
+	if (adev->mode_info.rfbdev) {
+		/*Do not add if already registered in past*/
+		for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) {
+			if (adev->mode_info.rfbdev->helper.connector_info[i]->connector
+					== connector) {
+				drm_modeset_unlock_all(dev);
+				return;
+			}
+		}
+
+		drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector);
+	}
+	else
+		DRM_ERROR("adev->mode_info.rfbdev is NULL\n");
+
+	drm_modeset_unlock_all(dev);
+
+	drm_connector_register(connector);
+
+}
+
+struct drm_dp_mst_topology_cbs dm_mst_cbs = {
+	.add_connector = dm_dp_add_mst_connector,
+	.destroy_connector = dm_dp_destroy_mst_connector,
+	.hotplug = dm_dp_mst_hotplug,
+	.register_connector = dm_dp_mst_register_connector
+};
+
+
+void amdgpu_dm_initialize_mst_connector(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector)
+{
+	aconnector->dm_dp_aux.aux.name = "dmdc";
+	aconnector->dm_dp_aux.aux.dev = dm->adev->dev;
+	aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
+	aconnector->dm_dp_aux.link_index = aconnector->connector_id;
+
+	drm_dp_aux_register(&aconnector->dm_dp_aux.aux);
+	aconnector->mst_mgr.cbs = &dm_mst_cbs;
+	drm_dp_mst_topology_mgr_init(
+		&aconnector->mst_mgr,
+		dm->adev->dev,
+		&aconnector->dm_dp_aux.aux,
+		16,
+		4,
+		aconnector->connector_id);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
new file mode 100644
index 000000000000..6130d62ac65c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AMDGPU_DM_MST_TYPES_H__
+#define __DAL_AMDGPU_DM_MST_TYPES_H__
+
+struct amdgpu_display_manager;
+struct amdgpu_connector;
+
+void amdgpu_dm_initialize_mst_connector(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
new file mode 100644
index 000000000000..b1552700d9e0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/acpi.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/amdgpu_drm.h>
+#include "dm_services.h"
+#include "amdgpu.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_irq.h"
+#include "amdgpu_dm_types.h"
+#include "amdgpu_pm.h"
+
+/*
+#include "logger_interface.h"
+#include "acpimethod_atif.h"
+#include "amdgpu_powerplay.h"
+#include "amdgpu_notifications.h"
+*/
+
+/* if the pointer is not NULL, the allocated memory is zeroed */
+void *dm_alloc(struct dc_context *ctx, uint32_t size)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+
+/* Reallocate memory. The contents will remain unchanged.*/
+void *dm_realloc(struct dc_context *ctx, const void *ptr, uint32_t size)
+{
+	return krealloc(ptr, size, GFP_KERNEL);
+}
+
+void dm_memmove(void *dst, const void *src, uint32_t size)
+{
+	memmove(dst, src, size);
+}
+
+void dm_free(struct dc_context *ctx, void *p)
+{
+	kfree(p);
+}
+
+void dm_memset(void *p, int32_t c, uint32_t count)
+{
+	memset(p, c, count);
+}
+
+int32_t dm_memcmp(const void *p1, const void *p2, uint32_t count)
+{
+	return memcmp(p1, p2, count);
+}
+
+int32_t dm_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count)
+{
+	return strncmp(p1, p2, count);
+}
+
+void dm_sleep_in_milliseconds(struct dc_context *ctx, uint32_t milliseconds)
+{
+	if (milliseconds >= 20)
+		msleep(milliseconds);
+	else
+		usleep_range(milliseconds*1000, milliseconds*1000+1);
+}
+
+void dal_delay_in_nanoseconds(uint32_t nanoseconds)
+{
+	ndelay(nanoseconds);
+}
+
+void dm_delay_in_microseconds(struct dc_context *ctx, uint32_t microseconds)
+{
+	udelay(microseconds);
+}
+
+/******************************************************************************
+ * IRQ Interfaces.
+ *****************************************************************************/
+
+void dal_register_timer_interrupt(
+	struct dc_context *ctx,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *args)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+
+	if (!adev || !int_params) {
+		DRM_ERROR("DM_IRQ: invalid input!\n");
+		return;
+	}
+
+	if (int_params->int_context != INTERRUPT_LOW_IRQ_CONTEXT) {
+		/* only low irq ctx is supported. */
+		DRM_ERROR("DM_IRQ: invalid context: %d!\n",
+				int_params->int_context);
+		return;
+	}
+
+	amdgpu_dm_irq_register_timer(adev, int_params, ih, args);
+}
+
+void dal_isr_acquire_lock(struct dc_context *ctx)
+{
+	/*TODO*/
+}
+
+void dal_isr_release_lock(struct dc_context *ctx)
+{
+	/*TODO*/
+}
+
+/******************************************************************************
+ * End-of-IRQ Interfaces.
+ *****************************************************************************/
+
+bool dm_get_platform_info(struct dc_context *ctx,
+			struct platform_info_params *params)
+{
+	/*TODO*/
+	return false;
+}
+
+/**** power component interfaces ****/
+
+bool dm_pp_pre_dce_clock_change(
+		struct dc_context *ctx,
+		struct dal_to_power_info *input,
+		struct power_to_dal_info *output)
+{
+	/*TODO*/
+	return false;
+}
+
+bool dm_pp_apply_safe_state(
+		const struct dc_context *ctx)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+
+	if (adev->pm.dpm_enabled) {
+		/* TODO: Does this require PreModeChange event to PPLIB? */
+	}
+
+	return true;
+#else
+	return false;
+#endif
+}
+
+bool dm_pp_apply_display_requirements(
+		const struct dc_context *ctx,
+		const struct dc_pp_display_configuration *pp_display_cfg)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+
+	if (adev->pm.dpm_enabled) {
+
+		memset(&adev->pm.pm_display_cfg, 0,
+				sizeof(adev->pm.pm_display_cfg));
+
+		adev->pm.pm_display_cfg.cpu_cc6_disable =
+			pp_display_cfg->cpu_cc6_disable;
+
+		adev->pm.pm_display_cfg.cpu_pstate_disable =
+			pp_display_cfg->cpu_pstate_disable;
+
+		adev->pm.pm_display_cfg.cpu_pstate_separation_time =
+			pp_display_cfg->cpu_pstate_separation_time;
+
+		adev->pm.pm_display_cfg.nb_pstate_switch_disable =
+			pp_display_cfg->nb_pstate_switch_disable;
+
+		adev->pm.pm_display_cfg.num_display =
+				pp_display_cfg->display_count;
+		adev->pm.pm_display_cfg.num_path_including_non_display =
+				pp_display_cfg->display_count;
+
+		adev->pm.pm_display_cfg.min_core_set_clock =
+				pp_display_cfg->min_engine_clock_khz/10;
+		adev->pm.pm_display_cfg.min_core_set_clock_in_sr =
+				pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
+		adev->pm.pm_display_cfg.min_mem_set_clock =
+				pp_display_cfg->min_memory_clock_khz/10;
+
+		adev->pm.pm_display_cfg.multi_monitor_in_sync =
+				pp_display_cfg->all_displays_in_sync;
+		adev->pm.pm_display_cfg.min_vblank_time =
+				pp_display_cfg->avail_mclk_switch_time_us;
+
+		adev->pm.pm_display_cfg.display_clk =
+				pp_display_cfg->disp_clk_khz/10;
+
+		adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency =
+				pp_display_cfg->avail_mclk_switch_time_in_disp_active_us;
+
+		adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index;
+		adev->pm.pm_display_cfg.line_time_in_us =
+				pp_display_cfg->line_time_in_us;
+
+		adev->pm.pm_display_cfg.crossfire_display_index = -1;
+		adev->pm.pm_display_cfg.min_bus_bandwidth = 0;
+
+		/* TODO: complete implementation of
+		 * amd_powerplay_display_configuration_change().
+		 * Follow example of:
+		 * PHM_StoreDALConfigurationData - powerplay\hwmgr\hardwaremanager.c
+		 * PP_IRI_DisplayConfigurationChange - powerplay\eventmgr\iri.c */
+		amd_powerplay_display_configuration_change(
+				adev->powerplay.pp_handle,
+				&adev->pm.pm_display_cfg);
+
+		/* TODO: replace by a separate call to 'apply display cfg'? */
+		amdgpu_pm_compute_clocks(adev);
+	}
+
+	return true;
+#else
+	return false;
+#endif
+}
+
+bool dc_service_get_system_clocks_range(
+		const struct dc_context *ctx,
+		struct dal_system_clock_range *sys_clks)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+#endif
+
+	/* Default values, in case PPLib is not compiled-in. */
+	sys_clks->max_mclk = 80000;
+	sys_clks->min_mclk = 80000;
+
+	sys_clks->max_sclk = 60000;
+	sys_clks->min_sclk = 30000;
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	if (adev->pm.dpm_enabled) {
+		sys_clks->max_mclk = amdgpu_dpm_get_mclk(adev, false);
+		sys_clks->min_mclk = amdgpu_dpm_get_mclk(adev, true);
+
+		sys_clks->max_sclk = amdgpu_dpm_get_sclk(adev, false);
+		sys_clks->min_sclk = amdgpu_dpm_get_sclk(adev, true);
+	}
+#endif
+
+	return true;
+}
+
+static void get_default_clock_levels(
+		enum dc_pp_clock_type clk_type,
+		struct dc_pp_clock_levels *clks)
+{
+	uint32_t disp_clks_in_khz[6] = {
+			300000, 400000, 496560, 626090, 685720, 757900 };
+	uint32_t sclks_in_khz[6] = {
+			300000, 360000, 423530, 514290, 626090, 720000 };
+	uint32_t mclks_in_khz[2] = { 333000, 800000 };
+
+	switch (clk_type) {
+	case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
+		clks->num_levels = 6;
+		dm_memmove(clks->clocks_in_khz, disp_clks_in_khz,
+				sizeof(disp_clks_in_khz));
+		break;
+	case DC_PP_CLOCK_TYPE_ENGINE_CLK:
+		clks->num_levels = 6;
+		dm_memmove(clks->clocks_in_khz, sclks_in_khz,
+				sizeof(sclks_in_khz));
+		break;
+	case DC_PP_CLOCK_TYPE_MEMORY_CLK:
+		clks->num_levels = 2;
+		dm_memmove(clks->clocks_in_khz, mclks_in_khz,
+				sizeof(mclks_in_khz));
+		break;
+	default:
+		clks->num_levels = 0;
+		break;
+	}
+}
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+static enum amd_pp_clock_type dc_to_pp_clock_type(
+		enum dc_pp_clock_type dc_pp_clk_type)
+{
+	enum amd_pp_clock_type amd_pp_clk_type = 0;
+
+	switch (dc_pp_clk_type) {
+	case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
+		amd_pp_clk_type = amd_pp_disp_clock;
+		break;
+	case DC_PP_CLOCK_TYPE_ENGINE_CLK:
+		amd_pp_clk_type = amd_pp_sys_clock;
+		break;
+	case DC_PP_CLOCK_TYPE_MEMORY_CLK:
+		amd_pp_clk_type = amd_pp_mem_clock;
+		break;
+	default:
+		DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
+				dc_pp_clk_type);
+		break;
+	}
+
+	return amd_pp_clk_type;
+}
+
+static void pp_to_dc_clock_levels(
+		const struct amd_pp_clocks *pp_clks,
+		struct dc_pp_clock_levels *dc_clks,
+		enum dc_pp_clock_type dc_clk_type)
+{
+	uint32_t i;
+
+	if (pp_clks->count > DC_PP_MAX_CLOCK_LEVELS) {
+		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
+				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
+				pp_clks->count,
+				DC_PP_MAX_CLOCK_LEVELS);
+
+		dc_clks->num_levels = DC_PP_MAX_CLOCK_LEVELS;
+	} else
+		dc_clks->num_levels = pp_clks->count;
+
+	DRM_INFO("DM_PPLIB: values for %s clock\n",
+			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
+
+	for (i = 0; i < dc_clks->num_levels; i++) {
+		DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
+		/* translate 10kHz to kHz */
+		dc_clks->clocks_in_khz[i] = pp_clks->clock[i] * 10;
+	}
+}
+#endif
+
+bool dm_pp_get_clock_levels_by_type(
+		const struct dc_context *ctx,
+		enum dc_pp_clock_type clk_type,
+		struct dc_pp_clock_levels *dc_clks)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+	void *pp_handle = adev->powerplay.pp_handle;
+	struct amd_pp_clocks pp_clks = { 0 };
+	struct amd_pp_simple_clock_info validation_clks = { 0 };
+	uint32_t i;
+
+	if (amd_powerplay_get_clock_by_type(pp_handle,
+			dc_to_pp_clock_type(clk_type), &pp_clks)) {
+		/* Error in pplib. Provide default values. */
+		get_default_clock_levels(clk_type, dc_clks);
+		return true;
+	}
+
+	pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
+
+	if (amd_powerplay_get_display_mode_validation_clocks(pp_handle,
+			&validation_clks)) {
+		/* Error in pplib. Provide default values. */
+		DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
+		validation_clks.engine_max_clock = 72000;
+		validation_clks.memory_max_clock = 80000;
+		validation_clks.level = 0;
+	}
+
+	DRM_INFO("DM_PPLIB: Validation clocks:\n");
+	DRM_INFO("DM_PPLIB:    engine_max_clock: %d\n",
+			validation_clks.engine_max_clock);
+	DRM_INFO("DM_PPLIB:    memory_max_clock: %d\n",
+			validation_clks.memory_max_clock);
+	DRM_INFO("DM_PPLIB:    level           : %d\n",
+			validation_clks.level);
+
+	/* Translate 10 kHz to kHz. */
+	validation_clks.engine_max_clock *= 10;
+	validation_clks.memory_max_clock *= 10;
+
+	/* Determine the highest non-boosted level from the Validation Clocks */
+	if (clk_type == DC_PP_CLOCK_TYPE_ENGINE_CLK) {
+		for (i = 0; i < dc_clks->num_levels; i++) {
+			if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
+				/* This clock is higher the validation clock.
+				 * Than means the previous one is the highest
+				 * non-boosted one. */
+				DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
+						dc_clks->num_levels, i + 1);
+				dc_clks->num_levels = i;
+				break;
+			}
+		}
+	} else if (clk_type == DC_PP_CLOCK_TYPE_MEMORY_CLK) {
+		for (i = 0; i < dc_clks->num_levels; i++) {
+			if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
+				DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
+						dc_clks->num_levels, i + 1);
+				dc_clks->num_levels = i;
+				break;
+			}
+		}
+	}
+#else
+	get_default_clock_levels(clk_type, dc_clks);
+#endif
+	return true;
+}
+
+/**** end of power component interfaces ****/
+
+
+/* Calls to notification */
+
+void dal_notify_setmode_complete(struct dc_context *ctx,
+	uint32_t h_total,
+	uint32_t v_total,
+	uint32_t h_active,
+	uint32_t v_active,
+	uint32_t pix_clk_in_khz)
+{
+	/*TODO*/
+}
+/* End of calls to notification */
+
+long dm_get_pid(void)
+{
+	return current->pid;
+}
+
+long dm_get_tgid(void)
+{
+	return current->tgid;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
new file mode 100644
index 000000000000..1cc9fd1054ab
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
@@ -0,0 +1,2572 @@
+/*
+ * Copyright 2012-13 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic.h>
+
+#include "amdgpu.h"
+#include "amdgpu_pm.h"
+#include "dm_services_types.h"
+
+// We need to #undef FRAME_SIZE and DEPRECATED because they conflict
+// with ptrace-abi.h's #define's of them.
+#undef FRAME_SIZE
+#undef DEPRECATED
+
+#include "dc.h"
+
+#include "amdgpu_dm_types.h"
+#include "amdgpu_dm_mst_types.h"
+
+struct dm_connector_state {
+	struct drm_connector_state base;
+
+	enum amdgpu_rmx_type scaling;
+	uint8_t underscan_vborder;
+	uint8_t underscan_hborder;
+	bool underscan_enable;
+};
+
+#define to_dm_connector_state(x)\
+	container_of((x), struct dm_connector_state, base)
+
+#define AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET 1
+#define MAX_TARGET_NUM 6
+
+void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+	kfree(encoder);
+}
+
+static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
+	.destroy = amdgpu_dm_encoder_destroy,
+};
+
+static void dm_set_cursor(
+	struct amdgpu_crtc *amdgpu_crtc,
+	uint64_t gpu_addr,
+	uint32_t width,
+	uint32_t height)
+{
+	struct dc_cursor_attributes attributes;
+	amdgpu_crtc->cursor_width = width;
+	amdgpu_crtc->cursor_height = height;
+
+	attributes.address.high_part = upper_32_bits(gpu_addr);
+	attributes.address.low_part  = lower_32_bits(gpu_addr);
+	attributes.width             = width-1;
+	attributes.height            = height-1;
+	attributes.x_hot             = 0;
+	attributes.y_hot             = 0;
+	attributes.color_format      = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA;
+	attributes.rotation_angle    = 0;
+	attributes.attribute_flags.value = 0;
+
+	if (!dc_target_set_cursor_attributes(
+				amdgpu_crtc->target,
+				&attributes)) {
+		DRM_ERROR("DC failed to set cursor attributes\n");
+	}
+}
+
+static int dm_crtc_unpin_cursor_bo_old(
+	struct amdgpu_crtc *amdgpu_crtc)
+{
+	struct amdgpu_bo *robj;
+	int ret = 0;
+
+	if (NULL != amdgpu_crtc && NULL != amdgpu_crtc->cursor_bo) {
+		robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
+
+		ret = amdgpu_bo_reserve(robj, false);
+
+		if (likely(ret == 0)) {
+			ret = amdgpu_bo_unpin(robj);
+
+			if (unlikely(ret != 0)) {
+				DRM_ERROR(
+					"%s: unpin failed (ret=%d), bo %p\n",
+					__func__,
+					ret,
+					amdgpu_crtc->cursor_bo);
+			}
+
+			amdgpu_bo_unreserve(robj);
+		} else {
+			DRM_ERROR(
+				"%s: reserve failed (ret=%d), bo %p\n",
+				__func__,
+				ret,
+				amdgpu_crtc->cursor_bo);
+		}
+
+		drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo);
+		amdgpu_crtc->cursor_bo = NULL;
+	}
+
+	return ret;
+}
+
+static int dm_crtc_pin_cursor_bo_new(
+	struct drm_crtc *crtc,
+	struct drm_file *file_priv,
+	uint32_t handle,
+	struct amdgpu_bo **ret_obj)
+{
+	struct amdgpu_crtc *amdgpu_crtc;
+	struct amdgpu_bo *robj;
+	struct drm_gem_object *obj;
+	int ret = -EINVAL;
+
+	if (NULL != crtc) {
+		struct drm_device *dev = crtc->dev;
+		struct amdgpu_device *adev = dev->dev_private;
+		uint64_t gpu_addr;
+
+		amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+		obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+
+		if (!obj) {
+			DRM_ERROR(
+				"Cannot find cursor object %x for crtc %d\n",
+				handle,
+				amdgpu_crtc->crtc_id);
+			goto release;
+		}
+		robj = gem_to_amdgpu_bo(obj);
+
+		ret  = amdgpu_bo_reserve(robj, false);
+
+		if (unlikely(ret != 0)) {
+			drm_gem_object_unreference_unlocked(obj);
+		DRM_ERROR("dm_crtc_pin_cursor_bo_new ret %x, handle %x\n",
+				 ret, handle);
+			goto release;
+		}
+
+		ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, 0,
+						adev->mc.visible_vram_size,
+						&gpu_addr);
+
+		if (ret == 0) {
+			amdgpu_crtc->cursor_addr = gpu_addr;
+			*ret_obj  = robj;
+		}
+		amdgpu_bo_unreserve(robj);
+		if (ret)
+			drm_gem_object_unreference_unlocked(obj);
+
+	}
+release:
+
+	return ret;
+}
+
+static int dm_crtc_cursor_set(
+	struct drm_crtc *crtc,
+	struct drm_file *file_priv,
+	uint32_t handle,
+	uint32_t width,
+	uint32_t height)
+{
+	struct amdgpu_bo *new_cursor_bo;
+	struct dc_cursor_position position;
+
+	int ret;
+
+	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+	ret		= EINVAL;
+	new_cursor_bo	= NULL;
+
+	DRM_DEBUG_KMS(
+	"%s: crtc_id=%d with handle %d and size %d to %d, bo_object %p\n",
+		__func__,
+		amdgpu_crtc->crtc_id,
+		handle,
+		width,
+		height,
+		amdgpu_crtc->cursor_bo);
+
+	if (!handle) {
+		/* turn off cursor */
+		position.enable = false;
+		position.x = 0;
+		position.y = 0;
+		position.hot_spot_enable = false;
+
+		if (amdgpu_crtc->target) {
+			/*set cursor visible false*/
+			dc_target_set_cursor_position(
+				amdgpu_crtc->target,
+				&position);
+		}
+		/*unpin old cursor buffer and update cache*/
+		ret = dm_crtc_unpin_cursor_bo_old(amdgpu_crtc);
+		goto release;
+
+	}
+
+	if ((width > amdgpu_crtc->max_cursor_width) ||
+		(height > amdgpu_crtc->max_cursor_height)) {
+		DRM_ERROR(
+			"%s: bad cursor width or height %d x %d\n",
+			__func__,
+			width,
+			height);
+		goto release;
+	}
+	/*try to pin new cursor bo*/
+	ret = dm_crtc_pin_cursor_bo_new(crtc, file_priv, handle, &new_cursor_bo);
+	/*if map not successful then return an error*/
+	if (ret)
+		goto release;
+
+	/*program new cursor bo to hardware*/
+	dm_set_cursor(amdgpu_crtc, amdgpu_crtc->cursor_addr, width, height);
+
+	/*un map old, not used anymore cursor bo ,
+	 * return memory and mapping back */
+	dm_crtc_unpin_cursor_bo_old(amdgpu_crtc);
+
+	/*assign new cursor bo to our internal cache*/
+	amdgpu_crtc->cursor_bo = &new_cursor_bo->gem_base;
+
+release:
+	return ret;
+
+}
+
+static int dm_crtc_cursor_move(struct drm_crtc *crtc,
+				     int x, int y)
+{
+	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+	int xorigin = 0, yorigin = 0;
+	struct dc_cursor_position position;
+
+	/* avivo cursor are offset into the total surface */
+	x += crtc->primary->state->src_x >> 16;
+	y += crtc->primary->state->src_y >> 16;
+
+	/*
+	 * TODO: for cursor debugging unguard the following
+	 */
+#if 0
+	DRM_DEBUG_KMS(
+		"%s: x %d y %d c->x %d c->y %d\n",
+		__func__,
+		x,
+		y,
+		crtc->x,
+		crtc->y);
+#endif
+
+	if (x < 0) {
+		xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1);
+		x = 0;
+	}
+	if (y < 0) {
+		yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1);
+		y = 0;
+	}
+
+	position.enable = true;
+	position.x = x;
+	position.y = y;
+
+	position.hot_spot_enable = true;
+	position.x_origin = xorigin;
+	position.y_origin = yorigin;
+
+	if (!dc_target_set_cursor_position(
+				amdgpu_crtc->target,
+				&position)) {
+		DRM_ERROR("DC failed to set cursor position\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void dm_crtc_cursor_reset(struct drm_crtc *crtc)
+{
+	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+	DRM_DEBUG_KMS(
+		"%s: with cursor_bo %p\n",
+		__func__,
+		amdgpu_crtc->cursor_bo);
+
+	if (amdgpu_crtc->cursor_bo && amdgpu_crtc->target) {
+		dm_set_cursor(
+		amdgpu_crtc,
+		amdgpu_crtc->cursor_addr,
+		amdgpu_crtc->cursor_width,
+		amdgpu_crtc->cursor_height);
+	}
+}
+static bool fill_rects_from_plane_state(
+	const struct drm_plane_state *state,
+	struct dc_surface *surface)
+{
+	surface->src_rect.x = state->src_x >> 16;
+	surface->src_rect.y = state->src_y >> 16;
+	/*we ignore for now mantissa and do not to deal with floating pixels :(*/
+	surface->src_rect.width = state->src_w >> 16;
+
+	if (surface->src_rect.width == 0)
+		return false;
+
+	surface->src_rect.height = state->src_h >> 16;
+	if (surface->src_rect.height == 0)
+		return false;
+
+	surface->dst_rect.x = state->crtc_x;
+	surface->dst_rect.y = state->crtc_y;
+
+	if (state->crtc_w == 0)
+		return false;
+
+	surface->dst_rect.width = state->crtc_w;
+
+	if (state->crtc_h == 0)
+		return false;
+
+	surface->dst_rect.height = state->crtc_h;
+
+	surface->clip_rect = surface->dst_rect;
+
+	switch (state->rotation) {
+	case DRM_ROTATE_0:
+		surface->rotation = ROTATION_ANGLE_0;
+		break;
+	case DRM_ROTATE_90:
+		surface->rotation = ROTATION_ANGLE_90;
+		break;
+	case DRM_ROTATE_180:
+		surface->rotation = ROTATION_ANGLE_180;
+		break;
+	case DRM_ROTATE_270:
+		surface->rotation = ROTATION_ANGLE_270;
+		break;
+	default:
+		surface->rotation = ROTATION_ANGLE_0;
+		break;
+	}
+
+	return true;
+}
+static bool get_fb_info(
+	const struct amdgpu_framebuffer *amdgpu_fb,
+	uint64_t *tiling_flags,
+	uint64_t *fb_location)
+{
+	struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj);
+	int r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r != 0)){
+		DRM_ERROR("Unable to reserve buffer\n");
+		return false;
+	}
+
+
+	if (fb_location)
+		*fb_location = amdgpu_bo_gpu_offset(rbo);
+
+	if (tiling_flags)
+		amdgpu_bo_get_tiling_flags(rbo, tiling_flags);
+
+	amdgpu_bo_unreserve(rbo);
+
+	return true;
+}
+static void fill_plane_attributes_from_fb(
+	struct dc_surface *surface,
+	const struct amdgpu_framebuffer *amdgpu_fb)
+{
+	uint64_t tiling_flags;
+	uint64_t fb_location;
+	const struct drm_framebuffer *fb = &amdgpu_fb->base;
+
+	get_fb_info(
+		amdgpu_fb,
+		&tiling_flags,
+		&fb_location);
+
+	surface->address.type                = PLN_ADDR_TYPE_GRAPHICS;
+	surface->address.grph.addr.low_part  = lower_32_bits(fb_location);
+	surface->address.grph.addr.high_part = upper_32_bits(fb_location);
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_C8:
+		surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS;
+		break;
+	case DRM_FORMAT_RGB565:
+		surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565;
+		break;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+		surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888;
+		break;
+	default:
+		DRM_ERROR("Unsupported screen depth %d\n", fb->bits_per_pixel);
+		return;
+	}
+
+	memset(&surface->tiling_info, 0, sizeof(surface->tiling_info));
+
+	if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1)
+	{
+		unsigned bankw, bankh, mtaspect, tile_split, num_banks;
+
+		bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
+		bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
+		mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
+		tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
+		num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
+
+
+		/* XXX fix me for VI */
+		surface->tiling_info.num_banks = num_banks;
+		surface->tiling_info.array_mode =
+				DC_ARRAY_2D_TILED_THIN1;
+		surface->tiling_info.tile_split = tile_split;
+		surface->tiling_info.bank_width = bankw;
+		surface->tiling_info.bank_height = bankh;
+		surface->tiling_info.tile_aspect = mtaspect;
+		surface->tiling_info.tile_mode =
+				DC_ADDR_SURF_MICRO_TILING_DISPLAY;
+	} else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE)
+			== DC_ARRAY_1D_TILED_THIN1) {
+		surface->tiling_info.array_mode = DC_ARRAY_1D_TILED_THIN1;
+	}
+
+	surface->tiling_info.pipe_config =
+			AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
+
+	surface->plane_size.grph.surface_size.x = 0;
+	surface->plane_size.grph.surface_size.y = 0;
+	surface->plane_size.grph.surface_size.width = fb->width;
+	surface->plane_size.grph.surface_size.height = fb->height;
+	surface->plane_size.grph.surface_pitch =
+		fb->pitches[0] / (fb->bits_per_pixel / 8);
+
+	surface->visible = true;
+	surface->scaling_quality.h_taps_c = 2;
+	surface->scaling_quality.v_taps_c = 2;
+
+	/* TODO: unhardcode */
+	surface->colorimetry.limited_range = false;
+	surface->colorimetry.color_space = SURFACE_COLOR_SPACE_SRGB;
+	surface->scaling_quality.h_taps = 2;
+	surface->scaling_quality.v_taps = 2;
+	surface->stereo_format = PLANE_STEREO_FORMAT_NONE;
+
+}
+
+#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256
+
+static void fill_gamma_from_crtc(
+	const struct drm_crtc *crtc,
+	struct dc_surface *dc_surface)
+{
+	int i;
+	struct gamma_ramp *gamma;
+	uint16_t *red, *green, *blue;
+	int end = (crtc->gamma_size > NUM_OF_RAW_GAMMA_RAMP_RGB_256) ?
+			NUM_OF_RAW_GAMMA_RAMP_RGB_256 : crtc->gamma_size;
+
+	red = crtc->gamma_store;
+	green = red + crtc->gamma_size;
+	blue = green + crtc->gamma_size;
+
+	gamma = &dc_surface->gamma_correction;
+
+	for (i = 0; i < end; i++) {
+		gamma->gamma_ramp_rgb256x3x16.red[i] =
+				(unsigned short) red[i];
+		gamma->gamma_ramp_rgb256x3x16.green[i] =
+				(unsigned short) green[i];
+		gamma->gamma_ramp_rgb256x3x16.blue[i] =
+				(unsigned short) blue[i];
+	}
+
+	gamma->type = GAMMA_RAMP_RBG256X3X16;
+	gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
+}
+
+static void fill_plane_attributes(
+			struct dc_surface *surface,
+			struct drm_plane_state *state)
+{
+	const struct amdgpu_framebuffer *amdgpu_fb =
+		to_amdgpu_framebuffer(state->fb);
+	const struct drm_crtc *crtc = state->crtc;
+
+	fill_rects_from_plane_state(state, surface);
+	fill_plane_attributes_from_fb(
+		surface,
+		amdgpu_fb);
+
+	/* In case of gamma set, update gamma value */
+	if (crtc->mode.private_flags &
+		AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET) {
+		fill_gamma_from_crtc(crtc, surface);
+	}
+}
+
+/*****************************************************************************/
+
+struct amdgpu_connector *aconnector_from_drm_crtc_id(
+		const struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+	struct amdgpu_connector *aconnector;
+
+	list_for_each_entry(connector,
+			&dev->mode_config.connector_list, head)	{
+
+		aconnector = to_amdgpu_connector(connector);
+
+		if (aconnector->base.state->crtc != &acrtc->base)
+			continue;
+
+		/* Found the connector */
+		return aconnector;
+	}
+
+	/* If we get here, not found. */
+	return NULL;
+}
+
+static void calculate_stream_scaling_settings(
+		const struct drm_display_mode *mode,
+		const struct dc_stream *stream,
+		struct dm_connector_state *dm_state)
+{
+	enum amdgpu_rmx_type rmx_type;
+
+	struct rect src = { 0 }; /* viewport in target space*/
+	struct rect dst = { 0 }; /* stream addressable area */
+
+	/* Full screen scaling by default */
+	src.width = mode->hdisplay;
+	src.height = mode->vdisplay;
+	dst.width = stream->timing.h_addressable;
+	dst.height = stream->timing.v_addressable;
+
+	rmx_type = dm_state->scaling;
+	if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) {
+		if (src.width * dst.height <
+				src.height * dst.width) {
+			/* height needs less upscaling/more downscaling */
+			dst.width = src.width *
+					dst.height / src.height;
+		} else {
+			/* width needs less upscaling/more downscaling */
+			dst.height = src.height *
+					dst.width / src.width;
+		}
+	} else if (rmx_type == RMX_CENTER) {
+		dst = src;
+	}
+
+	dst.x = (stream->timing.h_addressable - dst.width) / 2;
+	dst.y = (stream->timing.v_addressable - dst.height) / 2;
+
+	if (dm_state->underscan_enable) {
+		dst.x += dm_state->underscan_hborder / 2;
+		dst.y += dm_state->underscan_vborder / 2;
+		dst.width -= dm_state->underscan_hborder;
+		dst.height -= dm_state->underscan_vborder;
+	}
+
+	dc_update_stream(stream, &src, &dst);
+
+	DRM_DEBUG_KMS("Destination Rectangle x:%d  y:%d  width:%d  height:%d\n",
+			dst.x, dst.y, dst.width, dst.height);
+
+}
+
+static void dm_dc_surface_commit(
+		struct dc *dc,
+		struct drm_crtc *crtc,
+		struct dm_connector_state *dm_state)
+{
+	struct dc_surface *dc_surface;
+	const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+	struct dc_target *dc_target = acrtc->target;
+
+	if (!dc_target) {
+		dm_error(
+			"%s: Failed to obtain target on crtc (%d)!\n",
+			__func__,
+			acrtc->crtc_id);
+		goto fail;
+	}
+
+	dc_surface = dc_create_surface(dc);
+
+	if (!dc_surface) {
+		dm_error(
+			"%s: Failed to create a surface!\n",
+			__func__);
+		goto fail;
+	}
+
+	calculate_stream_scaling_settings(&crtc->state->mode,
+			dc_target->streams[0],
+			dm_state);
+
+	/* Surface programming */
+	fill_plane_attributes(dc_surface, crtc->primary->state);
+	if (crtc->mode.private_flags &
+		AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET) {
+		/* reset trigger of gamma */
+		crtc->mode.private_flags &=
+			~AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET;
+	}
+
+	if (false == dc_commit_surfaces_to_target(
+			dc,
+			&dc_surface,
+			1,
+			dc_target)) {
+		dm_error(
+			"%s: Failed to attach surface!\n",
+			__func__);
+	}
+
+	dc_surface_release(dc_surface);
+fail:
+	return;
+}
+
+static enum dc_color_depth convert_color_depth_from_display_info(
+		const struct drm_connector *connector)
+{
+	uint32_t bpc = connector->display_info.bpc;
+
+	/* Limited color depth to 8bit
+	 * TODO: Still need to handle deep color*/
+	if (bpc > 8)
+		bpc = 8;
+
+	switch (bpc) {
+	case 0:
+		/* Temporary Work around, DRM don't parse color depth for
+		 * EDID revision before 1.4
+		 * TODO: Fix edid parsing
+		 */
+		return COLOR_DEPTH_888;
+	case 6:
+		return COLOR_DEPTH_666;
+	case 8:
+		return COLOR_DEPTH_888;
+	case 10:
+		return COLOR_DEPTH_101010;
+	case 12:
+		return COLOR_DEPTH_121212;
+	case 14:
+		return COLOR_DEPTH_141414;
+	case 16:
+		return COLOR_DEPTH_161616;
+	default:
+		return COLOR_DEPTH_UNDEFINED;
+	}
+}
+
+static enum dc_aspect_ratio get_aspect_ratio(
+		const struct drm_display_mode *mode_in)
+{
+	int32_t width = mode_in->crtc_hdisplay * 9;
+	int32_t height = mode_in->crtc_vdisplay * 16;
+	if ((width - height) < 10 && (width - height) > -10)
+		return ASPECT_RATIO_16_9;
+	else
+		return ASPECT_RATIO_4_3;
+}
+
+/*****************************************************************************/
+
+static void dc_timing_from_drm_display_mode(
+	struct dc_crtc_timing *timing_out,
+	const struct drm_display_mode *mode_in,
+	const struct drm_connector *connector)
+{
+	memset(timing_out, 0, sizeof(struct dc_crtc_timing));
+
+	timing_out->h_border_left = 0;
+	timing_out->h_border_right = 0;
+	timing_out->v_border_top = 0;
+	timing_out->v_border_bottom = 0;
+	/* TODO: un-hardcode */
+	timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
+	timing_out->timing_standard = TIMING_STANDARD_HDMI;
+	timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
+	timing_out->display_color_depth = convert_color_depth_from_display_info(
+			connector);
+	timing_out->scan_type = SCANNING_TYPE_NODATA;
+	timing_out->hdmi_vic = 0;
+	timing_out->vic = drm_match_cea_mode(mode_in);
+
+	timing_out->h_addressable = mode_in->crtc_hdisplay;
+	timing_out->h_total = mode_in->crtc_htotal;
+	timing_out->h_sync_width =
+		mode_in->crtc_hsync_end - mode_in->crtc_hsync_start;
+	timing_out->h_front_porch =
+		mode_in->crtc_hsync_start - mode_in->crtc_hdisplay;
+	timing_out->v_total = mode_in->crtc_vtotal;
+	timing_out->v_addressable = mode_in->crtc_vdisplay;
+	timing_out->v_front_porch =
+		mode_in->crtc_vsync_start - mode_in->crtc_vdisplay;
+	timing_out->v_sync_width =
+		mode_in->crtc_vsync_end - mode_in->crtc_vsync_start;
+	timing_out->pix_clk_khz = mode_in->crtc_clock;
+	timing_out->aspect_ratio = get_aspect_ratio(mode_in);
+}
+
+static void fill_audio_info(
+	struct audio_info *audio_info,
+	const struct drm_connector *drm_connector,
+	const struct dc_sink *dc_sink)
+{
+	int i = 0;
+	int cea_revision = 0;
+	const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps;
+
+	audio_info->manufacture_id = edid_caps->manufacturer_id;
+	audio_info->product_id = edid_caps->product_id;
+
+	cea_revision = drm_connector->display_info.cea_rev;
+
+	while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS &&
+		edid_caps->display_name[i]) {
+		audio_info->display_name[i] = edid_caps->display_name[i];
+		i++;
+	}
+
+	if(cea_revision >= 3) {
+		audio_info->mode_count = edid_caps->audio_mode_count;
+
+		for (i = 0; i < audio_info->mode_count; ++i) {
+			audio_info->modes[i].format_code =
+					(enum audio_format_code)
+					(edid_caps->audio_modes[i].format_code);
+			audio_info->modes[i].channel_count =
+					edid_caps->audio_modes[i].channel_count;
+			audio_info->modes[i].sample_rates.all =
+					edid_caps->audio_modes[i].sample_rate;
+			audio_info->modes[i].sample_size =
+					edid_caps->audio_modes[i].sample_size;
+		}
+	}
+
+	audio_info->flags.all = edid_caps->speaker_flags;
+
+	/* TODO: We only check for the progressive mode, check for interlace mode too */
+	if(drm_connector->latency_present[0]) {
+		audio_info->video_latency = drm_connector->video_latency[0];
+		audio_info->audio_latency = drm_connector->audio_latency[0];
+	}
+
+	/* TODO: For DP, video and audio latency should be calculated from DPCD caps */
+
+}
+
+/*TODO: move these defines elsewhere*/
+#define DAL_MAX_CONTROLLERS 4
+
+static void copy_crtc_timing_for_drm_display_mode(
+		const struct drm_display_mode *src_mode,
+		struct drm_display_mode *dst_mode)
+{
+	dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay;
+	dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay;
+	dst_mode->crtc_clock = src_mode->crtc_clock;
+	dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start;
+	dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end;
+	dst_mode->crtc_hsync_start=  src_mode->crtc_hsync_start;
+	dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end;
+	dst_mode->crtc_htotal = src_mode->crtc_htotal;
+	dst_mode->crtc_hskew = src_mode->crtc_hskew;
+	dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start;;
+	dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end;;
+	dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start;;
+	dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end;;
+	dst_mode->crtc_vtotal = src_mode->crtc_vtotal;;
+}
+
+static void decide_crtc_timing_for_drm_display_mode(
+		struct drm_display_mode *drm_mode,
+		const struct drm_display_mode *native_mode,
+		bool scale_enabled)
+{
+	if (scale_enabled) {
+		copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode);
+	} else if (native_mode->clock == drm_mode->clock &&
+			native_mode->htotal == drm_mode->htotal &&
+			native_mode->vtotal == drm_mode->vtotal) {
+		copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode);
+	} else {
+		/* no scaling nor amdgpu inserted, no need to patch */
+	}
+}
+
+
+static struct dc_target *create_target_for_sink(
+		const struct amdgpu_connector *aconnector,
+		struct drm_display_mode *drm_mode)
+{
+	struct drm_display_mode *preferred_mode = NULL;
+	const struct drm_connector *drm_connector;
+	struct dm_connector_state *dm_state;
+	struct dc_target *target = NULL;
+	struct dc_stream *stream;
+	struct drm_display_mode mode = *drm_mode;
+	bool native_mode_found = false;
+
+	if (NULL == aconnector) {
+		DRM_ERROR("aconnector is NULL!\n");
+		goto drm_connector_null;
+	}
+
+	drm_connector = &aconnector->base;
+	dm_state = to_dm_connector_state(drm_connector->state);
+	stream = dc_create_stream_for_sink(aconnector->dc_sink);
+
+	if (NULL == stream) {
+		DRM_ERROR("Failed to create stream for sink!\n");
+		goto stream_create_fail;
+	}
+
+	list_for_each_entry(preferred_mode, &aconnector->base.modes, head) {
+		/* Search for preferred mode */
+		if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) {
+			native_mode_found = true;
+			break;
+		}
+	}
+	if (!native_mode_found)
+		preferred_mode = list_first_entry_or_null(
+				&aconnector->base.modes,
+				struct drm_display_mode,
+				head);
+	if (NULL == preferred_mode) {
+		DRM_ERROR("No preferred mode found\n");
+		goto stream_create_fail;
+	}
+
+	decide_crtc_timing_for_drm_display_mode(
+			&mode, preferred_mode,
+			dm_state->scaling != RMX_OFF);
+
+	dc_timing_from_drm_display_mode(&stream->timing,
+			&mode, &aconnector->base);
+
+	fill_audio_info(
+		&stream->audio_info,
+		drm_connector,
+		aconnector->dc_sink);
+
+	target = dc_create_target_for_streams(&stream, 1);
+	dc_stream_release(stream);
+
+	if (NULL == target) {
+		DRM_ERROR("Failed to create target with streams!\n");
+		goto target_create_fail;
+	}
+
+drm_connector_null:
+target_create_fail:
+stream_create_fail:
+	return target;
+}
+
+void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct amdgpu_crtc *dm_crtc = to_amdgpu_crtc(crtc);
+
+	drm_crtc_cleanup(crtc);
+	destroy_workqueue(dm_crtc->pflip_queue);
+	kfree(crtc);
+}
+
+static void amdgpu_dm_atomic_crtc_gamma_set(
+		struct drm_crtc *crtc,
+		u16 *red,
+		u16 *green,
+		u16 *blue,
+		uint32_t start,
+		uint32_t size)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_property *prop = dev->mode_config.prop_crtc_id;
+
+	crtc->state->mode.private_flags |= AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET;
+
+	drm_atomic_helper_crtc_set_property(crtc, prop, 0);
+}
+
+static int dm_crtc_funcs_atomic_set_property(
+	struct drm_crtc *crtc,
+	struct drm_crtc_state *crtc_state,
+	struct drm_property *property,
+	uint64_t val)
+{
+	struct drm_plane_state *plane_state;
+
+	crtc_state->planes_changed = true;
+
+	/*
+	 * Bit of magic done here. We need to ensure
+	 * that planes get update after mode is set.
+	 * So, we need to add primary plane to state,
+	 * and this way atomic_update would be called
+	 * for it
+	 */
+	plane_state =
+		drm_atomic_get_plane_state(
+			crtc_state->state,
+			crtc->primary);
+
+	if (!plane_state)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Implemented only the options currently availible for the driver */
+static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
+	.reset = drm_atomic_helper_crtc_reset,
+	.cursor_set = dm_crtc_cursor_set,
+	.cursor_move = dm_crtc_cursor_move,
+	.destroy = amdgpu_dm_crtc_destroy,
+	.gamma_set = amdgpu_dm_atomic_crtc_gamma_set,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.atomic_set_property = dm_crtc_funcs_atomic_set_property
+};
+
+static enum drm_connector_status
+amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
+{
+	bool connected;
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+
+	/* Notes:
+	 * 1. This interface is NOT called in context of HPD irq.
+	 * 2. This interface *is called* in context of user-mode ioctl. Which
+	 * makes it a bad place for *any* MST-related activit. */
+
+	connected = (NULL != aconnector->dc_sink);
+
+	return (connected ? connector_status_connected :
+			connector_status_disconnected);
+}
+
+int amdgpu_dm_connector_atomic_set_property(
+	struct drm_connector *connector,
+	struct drm_connector_state *connector_state,
+	struct drm_property *property,
+	uint64_t val)
+{
+	struct drm_device *dev = connector->dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct dm_connector_state *dm_old_state =
+		to_dm_connector_state(connector->state);
+	struct dm_connector_state *dm_new_state =
+		to_dm_connector_state(connector_state);
+
+	if (property == dev->mode_config.scaling_mode_property) {
+		struct drm_crtc_state *new_crtc_state;
+		struct drm_crtc *crtc;
+		int i;
+		enum amdgpu_rmx_type rmx_type;
+
+		switch (val) {
+		case DRM_MODE_SCALE_CENTER:
+			rmx_type = RMX_CENTER;
+			break;
+		case DRM_MODE_SCALE_ASPECT:
+			rmx_type = RMX_ASPECT;
+			break;
+		case DRM_MODE_SCALE_FULLSCREEN:
+			rmx_type = RMX_FULL;
+			break;
+		case DRM_MODE_SCALE_NONE:
+		default:
+			rmx_type = RMX_OFF;
+			break;
+		}
+
+		if (dm_old_state->scaling == rmx_type)
+			return 0;
+
+		dm_new_state->scaling = rmx_type;
+
+		for_each_crtc_in_state(
+			connector_state->state,
+			crtc,
+			new_crtc_state,
+			i) {
+
+			if (crtc == connector_state->crtc) {
+				struct drm_plane_state *plane_state;
+
+				new_crtc_state->mode_changed = true;
+
+				/*
+				 * Bit of magic done here. We need to ensure
+				 * that planes get update after mode is set.
+				 * So, we need to add primary plane to state,
+				 * and this way atomic_update would be called
+				 * for it
+				 */
+				plane_state =
+					drm_atomic_get_plane_state(
+						connector_state->state,
+						crtc->primary);
+
+				if (!plane_state)
+					return -EINVAL;
+			}
+		}
+
+		return 0;
+	} else if (property == adev->mode_info.underscan_hborder_property) {
+		dm_new_state->underscan_hborder = val;
+		return 0;
+	} else if (property == adev->mode_info.underscan_vborder_property) {
+		dm_new_state->underscan_vborder = val;
+		return 0;
+	} else if (property == adev->mode_info.underscan_property) {
+		struct drm_crtc_state *new_crtc_state;
+		struct drm_crtc *crtc;
+		int i;
+
+		dm_new_state->underscan_enable = val;
+
+		for_each_crtc_in_state(
+			connector_state->state,
+			crtc,
+			new_crtc_state,
+			i) {
+
+			if (crtc == connector_state->crtc) {
+				struct drm_plane_state *plane_state;
+
+				/*
+				 * Bit of magic done here. We need to ensure
+				 * that planes get update after mode is set.
+				 * So, we need to add primary plane to state,
+				 * and this way atomic_update would be called
+				 * for it
+				 */
+				plane_state =
+					drm_atomic_get_plane_state(
+						connector_state->state,
+						crtc->primary);
+
+				if (!plane_state)
+					return -EINVAL;
+			}
+		}
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+void amdgpu_dm_connector_destroy(struct drm_connector *connector)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+	const struct dc_link *link = aconnector->dc_link;
+	struct amdgpu_device *adev = connector->dev->dev_private;
+	struct amdgpu_display_manager *dm = &adev->dm;
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
+	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+	if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) {
+		amdgpu_dm_register_backlight_device(dm);
+
+		if (dm->backlight_dev) {
+			backlight_device_unregister(dm->backlight_dev);
+			dm->backlight_dev = NULL;
+		}
+
+	}
+#endif
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
+{
+	struct dm_connector_state *state =
+		to_dm_connector_state(connector->state);
+
+	kfree(state);
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+
+	if (state) {
+		state->scaling = RMX_OFF;
+		state->underscan_enable = false;
+		state->underscan_hborder = 0;
+		state->underscan_vborder = 0;
+
+		connector->state = &state->base;
+		connector->state->connector = connector;
+	}
+}
+
+struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state(
+	struct drm_connector *connector)
+{
+	struct dm_connector_state *state =
+		to_dm_connector_state(connector->state);
+
+	struct dm_connector_state *new_state =
+		kzalloc(sizeof(*new_state), GFP_KERNEL);
+
+	if (new_state) {
+		*new_state = *state;
+
+		return &new_state->base;
+	}
+
+	return NULL;
+}
+
+void amdgpu_dm_connector_atomic_destroy_state(
+	struct drm_connector *connector,
+	struct drm_connector_state *state)
+{
+	struct dm_connector_state *dm_state =
+		to_dm_connector_state(state);
+
+	__drm_atomic_helper_connector_destroy_state(connector, state);
+
+	kfree(dm_state);
+}
+
+static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = amdgpu_dm_connector_funcs_reset,
+	.detect = amdgpu_dm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = drm_atomic_helper_connector_set_property,
+	.destroy = amdgpu_dm_connector_destroy,
+	.atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
+	.atomic_destroy_state = amdgpu_dm_connector_atomic_destroy_state,
+	.atomic_set_property = amdgpu_dm_connector_atomic_set_property
+};
+
+static struct drm_encoder *best_encoder(struct drm_connector *connector)
+{
+	int enc_id = connector->encoder_ids[0];
+	struct drm_mode_object *obj;
+	struct drm_encoder *encoder;
+
+	DRM_DEBUG_KMS("Finding the best encoder\n");
+
+	/* pick the encoder ids */
+	if (enc_id) {
+		obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
+		if (!obj) {
+			DRM_ERROR("Couldn't find a matching encoder for our connector\n");
+			return NULL;
+		}
+		encoder = obj_to_encoder(obj);
+		return encoder;
+	}
+	DRM_ERROR("No encoder id\n");
+	return NULL;
+}
+
+static int get_modes(struct drm_connector *connector)
+{
+	return amdgpu_dm_connector_get_modes(connector);
+}
+
+int amdgpu_dm_connector_mode_valid(
+		struct drm_connector *connector,
+		struct drm_display_mode *mode)
+{
+	int result = MODE_ERROR;
+	const struct dc_sink *dc_sink =
+			to_amdgpu_connector(connector)->dc_sink;
+	struct amdgpu_device *adev = connector->dev->dev_private;
+	struct dc_validation_set val_set = { 0 };
+	/* TODO: Unhardcode stream count */
+	struct dc_stream *streams[1];
+	struct dc_target *target;
+
+	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+			(mode->flags & DRM_MODE_FLAG_DBLSCAN))
+		return result;
+
+	if (NULL == dc_sink) {
+		DRM_ERROR("dc_sink is NULL!\n");
+		goto stream_create_fail;
+	}
+
+	streams[0] = dc_create_stream_for_sink(dc_sink);
+
+	if (NULL == streams[0]) {
+		DRM_ERROR("Failed to create stream for sink!\n");
+		goto stream_create_fail;
+	}
+
+	drm_mode_set_crtcinfo(mode, 0);
+	dc_timing_from_drm_display_mode(&streams[0]->timing, mode, connector);
+
+	target = dc_create_target_for_streams(streams, 1);
+	val_set.target = target;
+
+	if (NULL == val_set.target) {
+		DRM_ERROR("Failed to create target with stream!\n");
+		goto target_create_fail;
+	}
+
+	val_set.surface_count = 0;
+	streams[0]->src.width = mode->hdisplay;
+	streams[0]->src.height = mode->vdisplay;
+	streams[0]->dst = streams[0]->src;
+
+	if (dc_validate_resources(adev->dm.dc, &val_set, 1))
+		result = MODE_OK;
+
+	dc_target_release(target);
+target_create_fail:
+	dc_stream_release(streams[0]);
+stream_create_fail:
+	/* TODO: error handling*/
+	return result;
+}
+
+
+static const struct drm_connector_helper_funcs
+amdgpu_dm_connector_helper_funcs = {
+	/*
+	* If hotplug a second bigger display in FB Con mode, bigger resolution
+	* modes will be filtered by drm_mode_validate_size(), and those modes
+	* is missing after user start lightdm. So we need to renew modes list.
+	* in get_modes call back, not just return the modes count
+	*/
+	.get_modes = get_modes,
+	.mode_valid = amdgpu_dm_connector_mode_valid,
+	.best_encoder = best_encoder
+};
+
+static void dm_crtc_helper_disable(struct drm_crtc *crtc)
+{
+}
+
+static int dm_crtc_helper_atomic_check(
+	struct drm_crtc *crtc,
+	struct drm_crtc_state *state)
+{
+	return 0;
+}
+
+static bool dm_crtc_helper_mode_fixup(
+	struct drm_crtc *crtc,
+	const struct drm_display_mode *mode,
+	struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = {
+	.disable = dm_crtc_helper_disable,
+	.atomic_check = dm_crtc_helper_atomic_check,
+	.mode_fixup = dm_crtc_helper_mode_fixup
+};
+
+static void dm_encoder_helper_disable(struct drm_encoder *encoder)
+{
+
+}
+
+static int dm_encoder_helper_atomic_check(
+	struct drm_encoder *encoder,
+	struct drm_crtc_state *crtc_state,
+	struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = {
+	.disable = dm_encoder_helper_disable,
+	.atomic_check = dm_encoder_helper_atomic_check
+};
+
+static const struct drm_plane_funcs dm_plane_funcs = {
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state
+};
+
+static void clear_unrelated_fields(struct drm_plane_state *state)
+{
+	state->crtc = NULL;
+	state->fb = NULL;
+	state->state = NULL;
+	state->fence = NULL;
+}
+
+static bool page_flip_needed(
+	const struct drm_plane_state *new_state,
+	const struct drm_plane_state *old_state)
+{
+	struct drm_plane_state old_state_tmp;
+	struct drm_plane_state new_state_tmp;
+
+	struct amdgpu_framebuffer *amdgpu_fb_old;
+	struct amdgpu_framebuffer *amdgpu_fb_new;
+
+	uint64_t old_tiling_flags;
+	uint64_t new_tiling_flags;
+
+	if (!old_state)
+		return false;
+
+	if (!old_state->fb)
+		return false;
+
+	if (!new_state)
+		return false;
+
+	if (!new_state->fb)
+		return false;
+
+	old_state_tmp = *old_state;
+	new_state_tmp = *new_state;
+
+	if (!new_state->crtc->state->event)
+		return false;
+
+	amdgpu_fb_old = to_amdgpu_framebuffer(old_state->fb);
+	amdgpu_fb_new = to_amdgpu_framebuffer(new_state->fb);
+
+	if (!get_fb_info(amdgpu_fb_old, &old_tiling_flags, NULL))
+		return false;
+
+	if (!get_fb_info(amdgpu_fb_new, &new_tiling_flags, NULL))
+		return false;
+
+	if (old_tiling_flags != new_tiling_flags)
+		return false;
+
+	clear_unrelated_fields(&old_state_tmp);
+	clear_unrelated_fields(&new_state_tmp);
+
+	return memcmp(&old_state_tmp, &new_state_tmp, sizeof(old_state_tmp)) == 0;
+}
+
+static int dm_plane_helper_prepare_fb(
+	struct drm_plane *plane,
+	const struct drm_plane_state *new_state)
+{
+	struct drm_framebuffer *fb = new_state->fb;
+	struct amdgpu_framebuffer *afb;
+	struct drm_gem_object *obj;
+	struct amdgpu_bo *rbo;
+	int r;
+
+	if (!fb) {
+		DRM_DEBUG_KMS("No FB bound\n");
+		return 0;
+	}
+
+	afb = to_amdgpu_framebuffer(fb);
+
+	obj = afb->obj;
+	rbo = gem_to_amdgpu_bo(obj);
+	r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r != 0))
+		return r;
+
+	r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL);
+
+	amdgpu_bo_unreserve(rbo);
+
+	if (unlikely(r != 0)) {
+		DRM_ERROR("Failed to pin framebuffer\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static void dm_plane_helper_cleanup_fb(
+	struct drm_plane *plane,
+	const struct drm_plane_state *old_state)
+{
+	struct drm_framebuffer *fb = old_state->fb;
+	struct amdgpu_bo *rbo;
+	struct amdgpu_framebuffer *afb;
+	int r;
+
+	if (!fb)
+		return;
+
+	afb = to_amdgpu_framebuffer(fb);
+	rbo = gem_to_amdgpu_bo(afb->obj);
+	r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r)) {
+		DRM_ERROR("failed to reserve rbo before unpin\n");
+		return;
+	} else {
+		amdgpu_bo_unpin(rbo);
+		amdgpu_bo_unreserve(rbo);
+	}
+}
+
+int dm_create_validation_set_for_target(struct drm_connector *connector,
+		struct drm_display_mode *mode, struct dc_validation_set *val_set)
+{
+	int result = MODE_ERROR;
+	const struct dc_sink *dc_sink =
+			to_amdgpu_connector(connector)->dc_sink;
+	/* TODO: Unhardcode stream count */
+	struct dc_stream *streams[1];
+	struct dc_target *target;
+
+	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+			(mode->flags & DRM_MODE_FLAG_DBLSCAN))
+		return result;
+
+	if (NULL == dc_sink) {
+		DRM_ERROR("dc_sink is NULL!\n");
+		return result;
+	}
+
+	streams[0] = dc_create_stream_for_sink(dc_sink);
+
+	if (NULL == streams[0]) {
+		DRM_ERROR("Failed to create stream for sink!\n");
+		return result;
+	}
+
+	drm_mode_set_crtcinfo(mode, 0);
+	dc_timing_from_drm_display_mode(&streams[0]->timing, mode, connector);
+
+	target = dc_create_target_for_streams(streams, 1);
+	val_set->target = target;
+
+	if (NULL == val_set->target) {
+		DRM_ERROR("Failed to create target with stream!\n");
+		goto fail;
+	}
+
+	streams[0]->src.width = mode->hdisplay;
+	streams[0]->src.height = mode->vdisplay;
+	streams[0]->dst = streams[0]->src;
+
+	return MODE_OK;
+
+fail:
+	dc_stream_release(streams[0]);
+	return result;
+
+}
+
+static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
+	.prepare_fb = dm_plane_helper_prepare_fb,
+	.cleanup_fb = dm_plane_helper_cleanup_fb,
+};
+
+/*
+ * TODO: these are currently initialized to rgb formats only.
+ * For future use cases we should either initialize them dynamically based on
+ * plane capabilities, or initialize this array to all formats, so internal drm
+ * check will succeed, and let DC to implement proper check
+ */
+static uint32_t rgb_formats[] = {
+	DRM_FORMAT_XRGB4444,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_RGBA4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_RGBA8888,
+};
+
+int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
+			struct amdgpu_crtc *acrtc,
+			uint32_t crtc_index)
+{
+	int res = -ENOMEM;
+
+	struct drm_plane *primary_plane =
+		kzalloc(sizeof(*primary_plane), GFP_KERNEL);
+
+	if (!primary_plane)
+		goto fail_plane;
+
+	primary_plane->format_default = true;
+
+	res = drm_universal_plane_init(
+		dm->adev->ddev,
+		primary_plane,
+		0,
+		&dm_plane_funcs,
+		rgb_formats,
+		ARRAY_SIZE(rgb_formats),
+		DRM_PLANE_TYPE_PRIMARY,
+		NULL);
+
+	primary_plane->crtc = &acrtc->base;
+
+	drm_plane_helper_add(primary_plane, &dm_plane_helper_funcs);
+
+	res = drm_crtc_init_with_planes(
+			dm->ddev,
+			&acrtc->base,
+			primary_plane,
+			NULL,
+			&amdgpu_dm_crtc_funcs,
+			NULL);
+
+	if (res)
+		goto fail;
+
+	drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs);
+
+	acrtc->max_cursor_width = 128;
+	acrtc->max_cursor_height = 128;
+
+	acrtc->crtc_id = crtc_index;
+	acrtc->base.enabled = false;
+
+	dm->adev->mode_info.crtcs[crtc_index] = acrtc;
+	drm_mode_crtc_set_gamma_size(&acrtc->base, 256);
+
+	acrtc->pflip_queue =
+		create_singlethread_workqueue("amdgpu-pageflip-queue");
+
+	return 0;
+fail:
+	kfree(primary_plane);
+fail_plane:
+	acrtc->crtc_id = -1;
+	return res;
+}
+
+static int to_drm_connector_type(enum signal_type st)
+{
+	switch (st) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		return DRM_MODE_CONNECTOR_HDMIA;
+	case SIGNAL_TYPE_EDP:
+		return DRM_MODE_CONNECTOR_eDP;
+	case SIGNAL_TYPE_RGB:
+		return DRM_MODE_CONNECTOR_VGA;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		return DRM_MODE_CONNECTOR_DisplayPort;
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+		return DRM_MODE_CONNECTOR_DVID;
+	case SIGNAL_TYPE_VIRTUAL:
+		return DRM_MODE_CONNECTOR_VIRTUAL;
+
+	default:
+		return DRM_MODE_CONNECTOR_Unknown;
+	}
+}
+
+static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
+{
+	const struct drm_connector_helper_funcs *helper =
+		connector->helper_private;
+	struct drm_encoder *encoder;
+	struct amdgpu_encoder *amdgpu_encoder;
+
+	encoder = helper->best_encoder(connector);
+
+	if (encoder == NULL)
+		return;
+
+	amdgpu_encoder = to_amdgpu_encoder(encoder);
+
+	amdgpu_encoder->native_mode.clock = 0;
+
+	if (!list_empty(&connector->probed_modes)) {
+		struct drm_display_mode *preferred_mode = NULL;
+		list_for_each_entry(preferred_mode,
+				&connector->probed_modes,
+				head) {
+		if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) {
+			amdgpu_encoder->native_mode = *preferred_mode;
+		}
+			break;
+		}
+
+	}
+}
+
+static struct drm_display_mode *amdgpu_dm_create_common_mode(
+		struct drm_encoder *encoder, char *name,
+		int hdisplay, int vdisplay)
+{
+	struct drm_device *dev = encoder->dev;
+	struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
+	struct drm_display_mode *mode = NULL;
+	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
+
+	mode = drm_mode_duplicate(dev, native_mode);
+
+	if(mode == NULL)
+		return NULL;
+
+	mode->hdisplay = hdisplay;
+	mode->vdisplay = vdisplay;
+	mode->type &= ~DRM_MODE_TYPE_PREFERRED;
+	strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN);
+
+	return mode;
+
+}
+
+static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
+					struct drm_connector *connector)
+{
+	struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
+	struct drm_display_mode *mode = NULL;
+	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
+	struct amdgpu_connector *amdgpu_connector =
+				to_amdgpu_connector(connector);
+	int i;
+	int n;
+	struct mode_size {
+		char name[DRM_DISPLAY_MODE_LEN];
+		int w;
+		int h;
+	}common_modes[] = {
+		{  "640x480",  640,  480},
+		{  "800x600",  800,  600},
+		{ "1024x768", 1024,  768},
+		{ "1280x720", 1280,  720},
+		{ "1280x800", 1280,  800},
+		{"1280x1024", 1280, 1024},
+		{ "1440x900", 1440,  900},
+		{"1680x1050", 1680, 1050},
+		{"1600x1200", 1600, 1200},
+		{"1920x1080", 1920, 1080},
+		{"1920x1200", 1920, 1200}
+	};
+
+	n = sizeof(common_modes) / sizeof(common_modes[0]);
+
+	for (i = 0; i < n; i++) {
+		struct drm_display_mode *curmode = NULL;
+		bool mode_existed = false;
+
+		if (common_modes[i].w > native_mode->hdisplay ||
+			common_modes[i].h > native_mode->vdisplay ||
+			(common_modes[i].w == native_mode->hdisplay &&
+			common_modes[i].h == native_mode->vdisplay))
+				continue;
+
+		list_for_each_entry(curmode, &connector->probed_modes, head) {
+			if (common_modes[i].w == curmode->hdisplay &&
+				common_modes[i].h == curmode->vdisplay) {
+				mode_existed = true;
+				break;
+			}
+		}
+
+		if (mode_existed)
+			continue;
+
+		mode = amdgpu_dm_create_common_mode(encoder,
+				common_modes[i].name, common_modes[i].w,
+				common_modes[i].h);
+		drm_mode_probed_add(connector, mode);
+		amdgpu_connector->num_modes++;
+	}
+}
+
+static void amdgpu_dm_connector_ddc_get_modes(
+	struct drm_connector *connector,
+	struct edid *edid)
+{
+	struct amdgpu_connector *amdgpu_connector =
+			to_amdgpu_connector(connector);
+
+	if (edid) {
+		/* empty probed_modes */
+		INIT_LIST_HEAD(&connector->probed_modes);
+		amdgpu_connector->num_modes =
+				drm_add_edid_modes(connector, edid);
+
+		drm_edid_to_eld(connector, edid);
+
+		amdgpu_dm_get_native_mode(connector);
+	} else
+		amdgpu_connector->num_modes = 0;
+}
+
+int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
+{
+	const struct drm_connector_helper_funcs *helper =
+			connector->helper_private;
+	struct amdgpu_connector *amdgpu_connector =
+			to_amdgpu_connector(connector);
+	struct drm_encoder *encoder;
+	struct edid *edid = amdgpu_connector->edid;
+
+	encoder = helper->best_encoder(connector);
+
+	amdgpu_dm_connector_ddc_get_modes(connector, edid);
+	amdgpu_dm_connector_add_common_modes(encoder, connector);
+	return amdgpu_connector->num_modes;
+}
+
+void amdgpu_dm_connector_init_helper(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector,
+	int connector_type,
+	const struct dc_link *link,
+	int link_index)
+{
+	struct amdgpu_device *adev = dm->ddev->dev_private;
+
+	aconnector->connector_id = link_index;
+	aconnector->dc_link = link;
+	aconnector->base.interlace_allowed = true;
+	aconnector->base.doublescan_allowed = true;
+	aconnector->base.dpms = DRM_MODE_DPMS_OFF;
+	aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */
+
+	/*configure suport HPD hot plug connector_>polled default value is 0
+	 * which means HPD hot plug not supported*/
+	switch (connector_type) {
+	case DRM_MODE_CONNECTOR_HDMIA:
+		aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	case DRM_MODE_CONNECTOR_DVID:
+		aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	default:
+		break;
+	}
+
+	drm_object_attach_property(&aconnector->base.base,
+				dm->ddev->mode_config.scaling_mode_property,
+				DRM_MODE_SCALE_NONE);
+
+	drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.underscan_property,
+				UNDERSCAN_OFF);
+	drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.underscan_hborder_property,
+				0);
+	drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.underscan_vborder_property,
+				0);
+}
+
+/* Note: this function assumes that dc_link_detect() was called for the
+ * dc_link which will be represented by this aconnector. */
+int amdgpu_dm_connector_init(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector,
+	uint32_t link_index,
+	struct amdgpu_encoder *aencoder)
+{
+	int res, connector_type;
+	struct dc *dc = dm->dc;
+	const struct dc_link *link = dc_get_link_at_index(dc, link_index);
+
+	DRM_DEBUG_KMS("%s()\n", __func__);
+
+	connector_type = to_drm_connector_type(link->connector_signal);
+
+	res = drm_connector_init(
+			dm->ddev,
+			&aconnector->base,
+			&amdgpu_dm_connector_funcs,
+			connector_type);
+
+	if (res) {
+		DRM_ERROR("connector_init failed\n");
+		aconnector->connector_id = -1;
+		return res;
+	}
+
+	drm_connector_helper_add(
+			&aconnector->base,
+			&amdgpu_dm_connector_helper_funcs);
+
+	amdgpu_dm_connector_init_helper(
+		dm,
+		aconnector,
+		connector_type,
+		link,
+		link_index);
+
+	drm_mode_connector_attach_encoder(
+		&aconnector->base, &aencoder->base);
+
+	drm_connector_register(&aconnector->base);
+
+	if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
+		|| connector_type == DRM_MODE_CONNECTOR_eDP)
+		amdgpu_dm_initialize_mst_connector(dm, aconnector);
+
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
+	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+	/* NOTE: this currently will create backlight device even if a panel
+	 * is not connected to the eDP/LVDS connector.
+	 *
+	 * This is less than ideal but we don't have sink information at this
+	 * stage since detection happens after. We can't do detection earlier
+	 * since MST detection needs connectors to be created first.
+	 */
+	if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) {
+		/* Event if registration failed, we should continue with
+		 * DM initialization because not having a backlight control
+		 * is better then a black screen. */
+		amdgpu_dm_register_backlight_device(dm);
+
+		if (dm->backlight_dev)
+			dm->backlight_link = link;
+	}
+#endif
+
+	return 0;
+}
+
+int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev)
+{
+	switch (adev->mode_info.num_crtc) {
+	case 1:
+		return 0x1;
+	case 2:
+		return 0x3;
+	case 3:
+		return 0x7;
+	case 4:
+		return 0xf;
+	case 5:
+		return 0x1f;
+	case 6:
+	default:
+		return 0x3f;
+	}
+}
+
+int amdgpu_dm_encoder_init(
+	struct drm_device *dev,
+	struct amdgpu_encoder *aencoder,
+	uint32_t link_index)
+{
+	struct amdgpu_device *adev = dev->dev_private;
+
+	int res = drm_encoder_init(dev,
+				   &aencoder->base,
+				   &amdgpu_dm_encoder_funcs,
+				   DRM_MODE_ENCODER_TMDS,
+				   NULL);
+
+	aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
+
+	if (!res)
+		aencoder->encoder_id = link_index;
+	else
+		aencoder->encoder_id = -1;
+
+	drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs);
+
+	return res;
+}
+
+enum dm_commit_action {
+	DM_COMMIT_ACTION_NOTHING,
+	DM_COMMIT_ACTION_RESET,
+	DM_COMMIT_ACTION_DPMS_ON,
+	DM_COMMIT_ACTION_DPMS_OFF,
+	DM_COMMIT_ACTION_SET
+};
+
+static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state)
+{
+	/* mode changed means either actually mode changed or enabled changed */
+	/* active changed means dpms changed */
+	if (state->mode_changed) {
+		/* if it is got disabled - call reset mode */
+		if (!state->enable)
+			return DM_COMMIT_ACTION_RESET;
+
+		if (state->active)
+			return DM_COMMIT_ACTION_SET;
+		else
+			return DM_COMMIT_ACTION_RESET;
+	} else {
+		/* ! mode_changed */
+
+		/* if it is remain disable - skip it */
+		if (!state->enable)
+			return DM_COMMIT_ACTION_NOTHING;
+
+		if (state->active_changed) {
+			if (state->active) {
+				return DM_COMMIT_ACTION_DPMS_ON;
+			} else {
+				return DM_COMMIT_ACTION_DPMS_OFF;
+			}
+		} else {
+			/* ! active_changed */
+			return DM_COMMIT_ACTION_NOTHING;
+		}
+	}
+}
+
+static void manage_dm_interrupts(
+	struct amdgpu_device *adev,
+	struct amdgpu_crtc *acrtc,
+	bool enable)
+{
+	if (enable) {
+		drm_crtc_vblank_on(&acrtc->base);
+		amdgpu_irq_get(
+			adev,
+			&adev->pageflip_irq,
+			amdgpu_crtc_idx_to_irq_type(
+				adev,
+				acrtc->crtc_id));
+	} else {
+		unsigned long flags;
+		amdgpu_irq_put(
+			adev,
+			&adev->pageflip_irq,
+			amdgpu_crtc_idx_to_irq_type(
+				adev,
+				acrtc->crtc_id));
+		drm_crtc_vblank_off(&acrtc->base);
+
+		/*
+		 * should be called here, to guarantee no works left in queue.
+		 * As this function sleeps it was bug to call it inside the
+		 * amdgpu_dm_flip_cleanup function under locked event_lock
+		 */
+		flush_workqueue(acrtc->pflip_queue);
+
+		/*
+		 * TODO: once Vitaly's change to adjust locking in
+		 * page_flip_work_func is submitted to base driver move
+		 * lock and check to amdgpu_dm_flip_cleanup function
+		 */
+
+		spin_lock_irqsave(&adev->ddev->event_lock, flags);
+		if (acrtc->pflip_status != AMDGPU_FLIP_NONE) {
+			/*
+			 * this is the case when on reset, last pending pflip
+			 * interrupt did not not occur. Clean-up
+			 */
+			amdgpu_dm_flip_cleanup(adev, acrtc);
+		}
+		spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+	}
+}
+
+/*
+ * Handle headless hotplug workaround
+ *
+ * In case of headless hotplug, if plugging the same monitor to the same
+ * DDI, DRM consider it as mode unchanged. We should check whether the
+ * sink pointer changed, and set mode_changed properly to
+ * make sure commit is doing everything.
+ */
+static void handle_headless_hotplug(
+		const struct amdgpu_crtc *acrtc,
+		struct drm_crtc_state *state,
+		struct amdgpu_connector **aconnector)
+{
+	struct amdgpu_connector *old_connector =
+			aconnector_from_drm_crtc_id(&acrtc->base);
+
+	/*
+	 * TODO Revisit this. This code is kinda hacky and might break things.
+	 */
+
+	if (!old_connector)
+		return;
+
+	if (!*aconnector)
+		*aconnector = old_connector;
+
+	if (acrtc->target && (*aconnector)->dc_sink) {
+		if ((*aconnector)->dc_sink !=
+				acrtc->target->streams[0]->sink) {
+			state->mode_changed = true;
+		}
+	}
+
+	if (!acrtc->target) {
+		/* In case of headless with DPMS on, when system waked up,
+		 * if no monitor connected, target is null and will not create
+		 * new target, on that condition, we should check
+		 * if any connector is connected, if connected,
+		 * it means a hot plug happened after wake up,
+		 * mode_changed should be set to true to make sure
+		 * commit targets will do everything.
+		 */
+		state->mode_changed =
+			(*aconnector)->base.status ==
+					connector_status_connected;
+	} else {
+		/* In case of headless hotplug, if plug same monitor to same
+		 * DDI, DRM consider it as mode unchanged, we should check
+		 * sink pointer changed, and set mode changed properly to
+		 * make sure commit doing everything.
+		 */
+		/* check if sink has changed from last commit */
+		if ((*aconnector)->dc_sink && (*aconnector)->dc_sink !=
+					acrtc->target->streams[0]->sink)
+			state->mode_changed = true;
+	}
+}
+
+int amdgpu_dm_atomic_commit(
+	struct drm_device *dev,
+	struct drm_atomic_state *state,
+	bool async)
+{
+	struct amdgpu_device *adev = dev->dev_private;
+	struct amdgpu_display_manager *dm = &adev->dm;
+	struct drm_plane *plane;
+	struct drm_plane_state *old_plane_state;
+	uint32_t i, j;
+	int32_t ret;
+	uint32_t commit_targets_count = 0;
+	uint32_t new_crtcs_count = 0;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *old_crtc_state;
+
+	struct dc_target *commit_targets[DAL_MAX_CONTROLLERS];
+	struct amdgpu_crtc *new_crtcs[DAL_MAX_CONTROLLERS];
+
+	/* In this step all new fb would be pinned */
+
+	ret = drm_atomic_helper_prepare_planes(dev, state);
+	if (ret)
+		return ret;
+
+	/*
+	 * This is the point of no return - everything below never fails except
+	 * when the hw goes bonghits. Which means we can commit the new state on
+	 * the software side now.
+	 */
+
+	drm_atomic_helper_swap_state(dev, state);
+
+	/*
+	 * From this point state become old state really. New state is
+	 * initialized to appropriate objects and could be accessed from there
+	 */
+
+	/*
+	 * there is no fences usage yet in state. We can skip the following line
+	 * wait_for_fences(dev, state);
+	 */
+
+	drm_atomic_helper_update_legacy_modeset_state(dev, state);
+
+	/* update changed items */
+	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+		struct amdgpu_crtc *acrtc;
+		struct amdgpu_connector *aconnector = NULL;
+		enum dm_commit_action action;
+		struct drm_crtc_state *new_state = crtc->state;
+		struct drm_connector *connector;
+		struct drm_connector_state *old_con_state;
+
+		acrtc = to_amdgpu_crtc(crtc);
+
+		for_each_connector_in_state(
+			state,
+			connector,
+			old_con_state,
+			j) {
+			if (connector->state->crtc == crtc) {
+				aconnector = to_amdgpu_connector(connector);
+				break;
+			}
+		}
+
+		/* handles headless hotplug case, updating new_state and
+		 * aconnector as needed
+		 */
+		handle_headless_hotplug(acrtc, new_state, &aconnector);
+
+		action = get_dm_commit_action(new_state);
+
+		switch (action) {
+		case DM_COMMIT_ACTION_DPMS_ON:
+		case DM_COMMIT_ACTION_SET: {
+			struct dc_target *new_target =
+				create_target_for_sink(
+					aconnector,
+					&crtc->state->mode);
+
+			DRM_DEBUG_KMS("Atomic commit: SET.\n");
+
+			if (!new_target) {
+				/*
+				 * this could happen because of issues with
+				 * userspace notifications delivery.
+				 * In this case userspace tries to set mode on
+				 * display which is disconnect in fact.
+				 * dc_sink in NULL in this case on aconnector.
+				 * We expect reset mode will come soon.
+				 *
+				 * This can also happen when unplug is done
+				 * during resume sequence ended
+				 */
+				new_state->planes_changed = false;
+				DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n",
+						__func__, acrtc->base.base.id);
+				break;
+			}
+
+			if (acrtc->target) {
+				/*
+				 * we evade vblanks and pflips on crtc that
+				 * should be changed
+				 */
+				manage_dm_interrupts(adev, acrtc, false);
+				/* this is the update mode case */
+				dc_target_release(acrtc->target);
+				acrtc->target = NULL;
+			}
+
+			/*
+			 * this loop saves set mode crtcs
+			 * we needed to enable vblanks once all
+			 * resources acquired in dc after dc_commit_targets
+			 */
+			new_crtcs[new_crtcs_count] = acrtc;
+			new_crtcs_count++;
+
+			acrtc->target = new_target;
+			acrtc->enabled = true;
+
+			break;
+		}
+
+		case DM_COMMIT_ACTION_NOTHING:
+			break;
+
+		case DM_COMMIT_ACTION_DPMS_OFF:
+		case DM_COMMIT_ACTION_RESET:
+			DRM_DEBUG_KMS("Atomic commit: RESET.\n");
+			/* i.e. reset mode */
+			if (acrtc->target) {
+				manage_dm_interrupts(adev, acrtc, false);
+
+				dc_target_release(acrtc->target);
+				acrtc->target = NULL;
+				acrtc->enabled = false;
+			}
+			break;
+		} /* switch() */
+	} /* for_each_crtc_in_state() */
+
+	commit_targets_count = 0;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+		if (acrtc->target) {
+			commit_targets[commit_targets_count] = acrtc->target;
+			++commit_targets_count;
+		}
+	}
+
+	/* DC is optimized not to do anything if 'targets' didn't change. */
+	dc_commit_targets(dm->dc, commit_targets, commit_targets_count);
+
+	/* update planes when needed */
+	for_each_plane_in_state(state, plane, old_plane_state, i) {
+		struct drm_plane_state *plane_state = plane->state;
+		struct drm_crtc *crtc = plane_state->crtc;
+		struct drm_framebuffer *fb = plane_state->fb;
+		struct drm_connector *connector;
+		struct dm_connector_state *dm_state = NULL;
+		enum dm_commit_action action;
+
+		if (!fb || !crtc || !crtc->state->planes_changed ||
+			!crtc->state->active)
+			continue;
+
+		action = get_dm_commit_action(crtc->state);
+
+		/* Surfaces are created under two scenarios:
+		 * 1. This commit is not a page flip.
+		 * 2. This commit is a page flip, and targets are created.
+		 */
+		if (!page_flip_needed(plane_state, old_plane_state) ||
+				action == DM_COMMIT_ACTION_DPMS_ON ||
+				action == DM_COMMIT_ACTION_SET) {
+			list_for_each_entry(connector,
+				&dev->mode_config.connector_list, head)	{
+				if (connector->state->crtc == crtc) {
+					dm_state = to_dm_connector_state(
+						connector->state);
+					break;
+				}
+			}
+
+			/*
+			 * This situation happens in the following case:
+			 * we are about to get set mode for connector who's only
+			 * possible crtc (in encoder crtc mask) is used by
+			 * another connector, that is why it will try to
+			 * re-assing crtcs in order to make configuration
+			 * supported. For our implementation we need to make all
+			 * encoders support all crtcs, then this issue will
+			 * never arise again. But to guard code from this issue
+			 * check is left.
+			 *
+			 * Also it should be needed when used with actual
+			 * drm_atomic_commit ioctl in future
+			 */
+			if (!dm_state)
+				continue;
+
+			dm_dc_surface_commit(
+				dm->dc,
+				crtc,
+				dm_state);
+		}
+	}
+
+	for (i = 0; i < new_crtcs_count; i++) {
+		/*
+		 * loop to enable interrupts on newly arrived crtc
+		 */
+		struct amdgpu_crtc *acrtc = new_crtcs[i];
+
+		manage_dm_interrupts(adev, acrtc, true);
+		dm_crtc_cursor_reset(&acrtc->base);
+
+	}
+
+	/* Page flip if needed */
+	for_each_plane_in_state(state, plane, old_plane_state, i) {
+		struct drm_plane_state *plane_state = plane->state;
+		struct drm_crtc *crtc = plane_state->crtc;
+		struct drm_framebuffer *fb = plane_state->fb;
+
+		if (!fb || !crtc || !crtc->state->planes_changed ||
+			!crtc->state->active)
+			continue;
+
+		if (page_flip_needed(plane_state, old_plane_state))
+			amdgpu_crtc_page_flip(
+				crtc,
+				fb,
+				crtc->state->event,
+				0);
+	}
+
+	drm_atomic_helper_wait_for_vblanks(dev, state);
+
+	/* In this state all old framebuffers would be unpinned */
+
+	drm_atomic_helper_cleanup_planes(dev, state);
+
+	drm_atomic_state_free(state);
+
+	return 0;
+}
+
+static uint32_t add_val_sets_surface(
+	struct dc_validation_set *val_sets,
+	uint32_t set_count,
+	const struct dc_target *target,
+	const struct dc_surface *surface)
+{
+	uint32_t i = 0;
+
+	while (i < set_count) {
+		if (val_sets[i].target == target)
+			break;
+		++i;
+	}
+
+	val_sets[i].surfaces[val_sets[i].surface_count] = surface;
+	val_sets[i].surface_count++;
+
+	return val_sets[i].surface_count;
+}
+
+static uint32_t update_in_val_sets_target(
+	struct dc_validation_set *val_sets,
+	uint32_t set_count,
+	const struct dc_target *old_target,
+	const struct dc_target *new_target)
+{
+	uint32_t i = 0;
+
+	while (i < set_count) {
+		if (val_sets[i].target == old_target)
+			break;
+		++i;
+	}
+
+	val_sets[i].target = new_target;
+
+	if (i == set_count) {
+		/* nothing found. add new one to the end */
+		return set_count + 1;
+	}
+
+	return set_count;
+}
+
+static uint32_t remove_from_val_sets(
+	struct dc_validation_set *val_sets,
+	uint32_t set_count,
+	const struct dc_target *target)
+{
+	uint32_t i = 0;
+
+	while (i < set_count) {
+		if (val_sets[i].target == target)
+			break;
+		++i;
+	}
+
+	if (i == set_count) {
+		/* nothing found */
+		return set_count;
+	}
+
+	memmove(
+		&val_sets[i],
+		&val_sets[i + 1],
+		sizeof(struct dc_validation_set *) * (set_count - i - 1));
+
+	return set_count - 1;
+}
+
+int amdgpu_dm_atomic_check(struct drm_device *dev,
+			struct drm_atomic_state *state)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_plane *plane;
+	struct drm_plane_state *plane_state;
+	int i;
+	int j;
+	int ret;
+	int set_count;
+	int new_target_count;
+	struct dc_validation_set set[MAX_TARGET_NUM] = {{ 0 }};
+	struct dc_target *new_targets[MAX_TARGET_NUM] = { 0 };
+	struct amdgpu_device *adev = dev->dev_private;
+	struct dc *dc = adev->dm.dc;
+	bool need_to_validate = false;
+
+	ret = drm_atomic_helper_check(dev, state);
+
+	if (ret) {
+		DRM_ERROR("Atomic state validation failed with error :%d !\n",
+				ret);
+		return ret;
+	}
+
+	ret = -EINVAL;
+
+	/* copy existing configuration */
+	new_target_count = 0;
+	set_count = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+		if (acrtc->target) {
+			set[set_count].target = acrtc->target;
+			++set_count;
+		}
+	}
+
+	/* update changed items */
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		struct amdgpu_crtc *acrtc = NULL;
+		struct amdgpu_connector *aconnector = NULL;
+		enum dm_commit_action action;
+		struct drm_connector *connector;
+		struct drm_connector_state *con_state;
+
+		acrtc = to_amdgpu_crtc(crtc);
+
+		for_each_connector_in_state(state, connector, con_state, j) {
+			if (con_state->crtc == crtc) {
+				aconnector = to_amdgpu_connector(connector);
+				break;
+			}
+		}
+
+		/*TODO:
+		handle_headless_hotplug(acrtc, crtc_state, &aconnector);*/
+
+		action = get_dm_commit_action(crtc_state);
+
+		switch (action) {
+		case DM_COMMIT_ACTION_DPMS_ON:
+		case DM_COMMIT_ACTION_SET: {
+			struct drm_display_mode mode = crtc_state->mode;
+			struct dc_target *new_target = NULL;
+
+			if (!aconnector) {
+				DRM_ERROR(
+					"%s: Can't find connector for crtc %d\n",
+					__func__,
+					acrtc->crtc_id);
+				goto connector_not_found;
+			}
+
+			new_target =
+				create_target_for_sink(
+					aconnector,
+					&mode);
+
+			/*
+			 * we can have no target on ACTION_SET if a display
+			 * was disconnected during S3, in this case it not and
+			 * error, the OS will be updated after detection, and
+			 * do the right thing on next atomic commit
+			 */
+			if (!new_target) {
+				DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n",
+						__func__, acrtc->base.base.id);
+				break;
+			}
+
+			new_targets[new_target_count] = new_target;
+
+			set_count = update_in_val_sets_target(
+					set,
+					set_count,
+					acrtc->target,
+					new_target);
+			new_target_count++;
+			need_to_validate = true;
+			break;
+		}
+
+		case DM_COMMIT_ACTION_NOTHING:
+			break;
+		case DM_COMMIT_ACTION_DPMS_OFF:
+		case DM_COMMIT_ACTION_RESET:
+			/* i.e. reset mode */
+			if (acrtc->target) {
+				set_count = remove_from_val_sets(
+						set,
+						set_count,
+						acrtc->target);
+			}
+			break;
+		}
+	}
+
+
+	for (i = 0; i < set_count; i++) {
+		for_each_plane_in_state(state, plane, plane_state, j) {
+			struct drm_plane_state *old_plane_state = plane->state;
+			struct drm_framebuffer *fb = plane_state->fb;
+			struct drm_crtc *crtc = plane_state->crtc;
+			struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+			if (!fb || acrtc->target != set[i].target)
+				continue;
+
+			if (!crtc->state->planes_changed)
+				continue;
+
+			if (!page_flip_needed(plane_state, old_plane_state)) {
+				struct dc_surface *surface =
+					dc_create_surface(dc);
+
+				fill_plane_attributes(
+					surface,
+					plane_state);
+
+				add_val_sets_surface(
+					set,
+					set_count,
+					acrtc->target,
+					surface);
+				need_to_validate = true;
+			}
+		}
+
+	}
+
+	if (need_to_validate == false || set_count == 0
+				|| dc_validate_resources(dc, set, set_count))
+		ret = 0;
+
+connector_not_found:
+	for (i = 0; i < set_count; i++) {
+		for (j = 0; j < set[i].surface_count; j++) {
+			dc_surface_release(set[i].surfaces[j]);
+		}
+	}
+	for (i = 0; i < new_target_count; i++)
+		dc_target_release(new_targets[i]);
+
+	if (ret != 0)
+		DRM_ERROR("Atomic check failed.\n");
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
new file mode 100644
index 000000000000..0481075de6e9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012-13 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#ifndef __AMDGPU_DM_TYPES_H__
+#define __AMDGPU_DM_TYPES_H__
+
+#include <drm/drmP.h>
+
+struct amdgpu_framebuffer;
+struct amdgpu_display_manager;
+struct dc_validation_set;
+struct dc_surface;
+
+/*TODO Jodan Hersen use the one in amdgpu_dm*/
+int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
+			struct amdgpu_crtc *amdgpu_crtc,
+			uint32_t link_index);
+int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
+			struct amdgpu_connector *amdgpu_connector,
+			uint32_t link_index,
+			struct amdgpu_encoder *amdgpu_encoder);
+int amdgpu_dm_encoder_init(
+	struct drm_device *dev,
+	struct amdgpu_encoder *aencoder,
+	uint32_t link_index);
+
+void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc);
+void amdgpu_dm_connector_destroy(struct drm_connector *connector);
+void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder);
+
+void dm_add_display_info(
+	struct drm_display_info *disp_info,
+	struct amdgpu_display_manager *dm,
+	uint32_t display_index);
+
+int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
+
+int amdgpu_dm_atomic_commit(
+	struct drm_device *dev,
+	struct drm_atomic_state *state,
+	bool async);
+int amdgpu_dm_atomic_check(struct drm_device *dev,
+				struct drm_atomic_state *state);
+
+int dm_create_validation_set_for_target(
+	struct drm_connector *connector,
+	struct drm_display_mode *mode,
+	struct dc_validation_set *val_set);
+
+void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector);
+struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state(
+	struct drm_connector *connector);
+void amdgpu_dm_connector_atomic_destroy_state(
+	struct drm_connector *connector,
+	struct drm_connector_state *state);
+int amdgpu_dm_connector_atomic_set_property(
+	struct drm_connector *connector,
+	struct drm_connector_state *state,
+	struct drm_property *property,
+	uint64_t val);
+
+int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev);
+
+void amdgpu_dm_connector_init_helper(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector,
+	int connector_type,
+	const struct dc_link *link,
+	int link_index);
+
+int amdgpu_dm_connector_mode_valid(
+	struct drm_connector *connector,
+	struct drm_display_mode *mode);
+
+extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs;
+
+#endif		/* __AMDGPU_DM_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services.h b/drivers/gpu/drm/amd/dal/dc/dm_services.h
index 206c0b7df7c6..47bbb9e6e060 100644
--- a/drivers/gpu/drm/amd/dal/dc/dm_services.h
+++ b/drivers/gpu/drm/amd/dal/dc/dm_services.h
@@ -166,19 +166,7 @@ bool dm_exec_bios_cmd_table(
 	uint32_t index,
 	void *params);
 
-#ifdef BUILD_DAL_TEST
-uint32_t dm_bios_cmd_table_para_revision(
-struct dc_context *ctx,
-	uint32_t index);
 
-bool dm_bios_cmd_table_revision(
-	struct dc_context *ctx,
-	uint32_t index,
-	uint8_t *frev,
-	uint8_t *crev);
-#endif
-
-#ifndef BUILD_DAL_TEST
 static inline uint32_t dm_bios_cmd_table_para_revision(
 	struct dc_context *ctx,
 	uint32_t index)
@@ -195,11 +183,6 @@ static inline uint32_t dm_bios_cmd_table_para_revision(
 
 	return crev;
 }
-#else
-uint32_t dm_bios_cmd_table_para_revision(
-		struct dc_context *ctx,
-		uint32_t index);
-#endif
 
 /**************************************
  * Power Play (PP) interfaces
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 26/29] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (24 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 25/29] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 17:20 ` [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set Harry Wentland
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel

Start to use dal by default on Carrizo, Tonga, and Fiji ASICs.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/Kconfig         |   3 +
 drivers/gpu/drm/amd/amdgpu/Makefile        |  17 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h        |  10 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |  69 ++++++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c    |   4 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c     |   5 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c    |  20 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h   |  54 ++++++-
 drivers/gpu/drm/amd/amdgpu/vi.c            | 250 +++++++++++++++++++++++++++++
 9 files changed, 402 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
index b30fcfa4b1f2..3a37e37bef28 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -15,3 +15,6 @@ config DRM_AMDGPU_USERPTR
 	help
 	  This option selects CONFIG_MMU_NOTIFIER if it isn't already
 	  selected to enabled full userptr support.
+
+source "drivers/gpu/drm/amd/dal/Kconfig"
+
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index c7fcdcedaadb..c434ee5c589f 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -3,13 +3,19 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 FULL_AMD_PATH=$(src)/..
+DAL_FOLDER_NAME=dal
+FULL_AMD_DAL_PATH = $(FULL_AMD_PATH)/$(DAL_FOLDER_NAME)
 
 ccflags-y := -Iinclude/drm -I$(FULL_AMD_PATH)/include/asic_reg \
 	-I$(FULL_AMD_PATH)/include \
 	-I$(FULL_AMD_PATH)/amdgpu \
 	-I$(FULL_AMD_PATH)/scheduler \
 	-I$(FULL_AMD_PATH)/powerplay/inc \
-	-I$(FULL_AMD_PATH)/acp/include
+	-I$(FULL_AMD_PATH)/acp/include \
+	-I$(FULL_AMD_DAL_PATH) \
+	-I$(FULL_AMD_DAL_PATH)/include \
+	-I$(FULL_AMD_DAL_PATH)/dc \
+	-I$(FULL_AMD_DAL_PATH)/amdgpu_dm
 
 amdgpu-y := amdgpu_drv.o
 
@@ -118,6 +124,15 @@ amdgpu-y += $(AMD_POWERPLAY_FILES)
 
 endif
 
+ifneq ($(CONFIG_DRM_AMD_DAL),)
+
+RELATIVE_AMD_DAL_PATH = ../$(DAL_FOLDER_NAME)
+include $(FULL_AMD_DAL_PATH)/Makefile
+
+amdgpu-y += $(AMD_DAL_FILES)
+
+endif
+
 obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o
 
 CFLAGS_amdgpu_trace_points.o := -I$(src)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 99e660fec190..d154b3473ae8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -54,6 +54,7 @@
 #include "amdgpu_gds.h"
 #include "amd_powerplay.h"
 #include "amdgpu_acp.h"
+#include "amdgpu_dm.h"
 
 #include "gpu_scheduler.h"
 
@@ -85,6 +86,7 @@ extern int amdgpu_vm_debug;
 extern int amdgpu_sched_jobs;
 extern int amdgpu_sched_hw_submission;
 extern int amdgpu_powerplay;
+extern int amdgpu_dal;
 
 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS	        3000
 #define AMDGPU_MAX_USEC_TIMEOUT			100000	/* 100 ms */
@@ -2017,6 +2019,7 @@ struct amdgpu_device {
 
 	/* display */
 	struct amdgpu_mode_info		mode_info;
+	/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
 	struct work_struct		hotplug_work;
 	struct amdgpu_irq_src		crtc_irq;
 	struct amdgpu_irq_src		pageflip_irq;
@@ -2064,6 +2067,9 @@ struct amdgpu_device {
 	/* GDS */
 	struct amdgpu_gds		gds;
 
+	/* display related functionality */
+	struct amdgpu_display_manager dm;
+
 	const struct amdgpu_ip_block_version *ip_blocks;
 	int				num_ip_blocks;
 	struct amdgpu_ip_block_status	*ip_block_status;
@@ -2100,7 +2106,7 @@ void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v);
 
 u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index);
 void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v);
-
+bool amdgpu_device_has_dal_support(struct amdgpu_device *adev);
 /*
  * Cast helper
  */
@@ -2345,6 +2351,8 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
 
 #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a))
 
+#define amdgpu_has_dal_support(adev) (amdgpu_dal && amdgpu_device_has_dal_support(adev))
+
 /* Common functions */
 int amdgpu_gpu_reset(struct amdgpu_device *adev);
 void amdgpu_pci_config_reset(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index f0fb938457d9..3df6fe35ec63 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1369,6 +1369,32 @@ static int amdgpu_resume(struct amdgpu_device *adev)
 	return 0;
 }
 
+
+/**
+ * amdgpu_device_has_dal_support - check if dal is supported
+ *
+ * @adev: amdgpu_device_pointer
+ *
+ * Returns true for supported, false for not supported
+ */
+bool amdgpu_device_has_dal_support(struct amdgpu_device *adev)
+{
+	switch(adev->asic_type) {
+#if defined(CONFIG_DRM_AMD_DAL) && defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case CHIP_CARRIZO:
+		return true;
+#endif
+#if defined(CONFIG_DRM_AMD_DAL) && defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case CHIP_TONGA:
+	case CHIP_FIJI:
+		return true;
+#endif
+	default:
+		return false;
+	}
+}
+
+
 /**
  * amdgpu_device_init - initialize the driver
  *
@@ -1522,7 +1548,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
 		return r;
 	}
 	/* init i2c buses */
-	amdgpu_atombios_i2c_init(adev);
+	if (!amdgpu_has_dal_support(adev))
+		amdgpu_atombios_i2c_init(adev);
 
 	/* Fence driver */
 	r = amdgpu_fence_driver_init(adev);
@@ -1628,7 +1655,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
 	adev->ip_block_status = NULL;
 	adev->accel_working = false;
 	/* free i2c buses */
-	amdgpu_i2c_fini(adev);
+	if (!amdgpu_has_dal_support(adev))
+		amdgpu_i2c_fini(adev);
 	amdgpu_atombios_fini(adev);
 	kfree(adev->bios);
 	adev->bios = NULL;
@@ -1676,12 +1704,14 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 
 	drm_kms_helper_poll_disable(dev);
 
-	/* turn off display hw */
-	drm_modeset_lock_all(dev);
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+	if (!amdgpu_has_dal_support(adev)) {
+		/* turn off display hw */
+		drm_modeset_lock_all(dev);
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+		}
+		drm_modeset_unlock_all(dev);
 	}
-	drm_modeset_unlock_all(dev);
 
 	/* unpin the front buffers and cursors */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -1773,6 +1803,9 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
 
 	r = amdgpu_resume(adev);
 
+	if (r)
+		DRM_ERROR("amdgpu_resume failed (%d).\n", r);
+
 	amdgpu_fence_driver_resume(adev);
 
 	r = amdgpu_ib_ring_tests(adev);
@@ -1803,17 +1836,25 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
 
 	/* blat the mode back in */
 	if (fbcon) {
-		drm_helper_resume_force_mode(dev);
-		/* turn on display hw */
-		drm_modeset_lock_all(dev);
-		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+		if (!amdgpu_has_dal_support(adev)) {
+			/* pre DCE11 */
+			drm_helper_resume_force_mode(dev);
+
+			/* turn on display hw */
+			drm_modeset_lock_all(dev);
+			list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+				drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+			}
+			drm_modeset_unlock_all(dev);
 		}
-		drm_modeset_unlock_all(dev);
 	}
 
 	drm_kms_helper_poll_enable(dev);
-	drm_helper_hpd_irq_event(dev);
+
+	if (!amdgpu_has_dal_support(adev))
+		 drm_helper_hpd_irq_event(dev);
+	else
+		drm_kms_helper_hotplug_event(dev);
 
 	if (fbcon) {
 		amdgpu_fbdev_set_suspend(adev, 0);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index ce79a8b605a0..6f1dec5d76c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -80,6 +80,7 @@ int amdgpu_exp_hw_support = 0;
 int amdgpu_sched_jobs = 32;
 int amdgpu_sched_hw_submission = 2;
 int amdgpu_powerplay = -1;
+int amdgpu_dal = 1;
 
 MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
 module_param_named(vramlimit, amdgpu_vram_limit, int, 0600);
@@ -158,6 +159,9 @@ MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 =
 module_param_named(powerplay, amdgpu_powerplay, int, 0444);
 #endif
 
+MODULE_PARM_DESC(dal, "DAL display driver (1 = enable (default), 0 = disable)");
+module_param_named(dal, amdgpu_dal, int, 0444);
+
 static struct pci_device_id pciidlist[] = {
 #ifdef CONFIG_DRM_AMDGPU_CIK
 	/* Kaveri */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 919146780a15..e694c9983bbd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -42,11 +42,6 @@
    this contains a helper + a amdgpu fb
    the helper contains a pointer to amdgpu framebuffer baseclass.
 */
-struct amdgpu_fbdev {
-	struct drm_fb_helper helper;
-	struct amdgpu_framebuffer rfb;
-	struct amdgpu_device *adev;
-};
 
 static struct fb_ops amdgpufb_ops = {
 	.owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index f594cfaa97e5..4775930b678d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -36,6 +36,10 @@
 
 #include <linux/pm_runtime.h>
 
+#ifdef CONFIG_DRM_AMD_DAL
+#include "amdgpu_dm_irq.h"
+#endif
+
 #define AMDGPU_WAIT_IDLE_TIMEOUT 200
 
 /*
@@ -215,10 +219,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
 	int r = 0;
 
 	spin_lock_init(&adev->irq.lock);
-	r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
-	if (r) {
-		return r;
-	}
+
 	/* enable msi */
 	adev->irq.msi_enabled = false;
 
@@ -230,7 +231,16 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
 		}
 	}
 
-	INIT_WORK(&adev->hotplug_work, amdgpu_hotplug_work_func);
+	if (!amdgpu_has_dal_support(adev)) {
+		r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
+		if (r)
+			return r;
+
+		/* pre DCE11 */
+		INIT_WORK(&adev->hotplug_work,
+				amdgpu_hotplug_work_func);
+	}
+
 	INIT_WORK(&adev->reset_work, amdgpu_irq_reset_work_func);
 
 	adev->irq.installed = true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index fdc1be8550da..e2fb0c5bab82 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -35,11 +35,13 @@
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_fixed.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_fb_helper.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 
+#include <drm/drm_dp_mst_helper.h>
+
 struct amdgpu_bo;
 struct amdgpu_device;
 struct amdgpu_encoder;
@@ -305,6 +307,18 @@ struct amdgpu_display_funcs {
 				 struct amdgpu_mode_mc_save *save);
 };
 
+struct amdgpu_framebuffer {
+	struct drm_framebuffer base;
+	struct drm_gem_object *obj;
+};
+
+struct amdgpu_fbdev {
+	struct drm_fb_helper helper;
+	struct amdgpu_framebuffer rfb;
+	struct list_head fbdev_list;
+	struct amdgpu_device *adev;
+};
+
 struct amdgpu_mode_info {
 	struct atom_context *atom_context;
 	struct card_info *atom_card_info;
@@ -410,6 +424,9 @@ struct amdgpu_crtc {
 	u32 wm_high;
 	u32 lb_vblank_lead_lines;
 	struct drm_display_mode hw_mode;
+
+	/* After Set Mode target will be non-NULL */
+	struct dc_target *target;
 };
 
 struct amdgpu_encoder_atom_dig {
@@ -499,6 +516,13 @@ enum amdgpu_connector_dither {
 	AMDGPU_FMT_DITHER_ENABLE = 1,
 };
 
+struct amdgpu_dm_dp_aux {
+	struct drm_dp_aux aux;
+	uint32_t link_index;
+};
+
+#define TO_DM_AUX(x) container_of((x), struct amdgpu_dm_dp_aux, aux)
+
 struct amdgpu_connector {
 	struct drm_connector base;
 	uint32_t connector_id;
@@ -510,6 +534,13 @@ struct amdgpu_connector {
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
 	struct edid *edid;
+	/* number of modes generated from EDID at 'dc_sink' */
+	int num_modes;
+	/* The 'old' sink - before an HPD.
+	 * The 'current' sink is in dc_link->sink. */
+	const struct dc_sink *dc_sink;
+	const struct dc_link *dc_link;
+	const struct dc_target *target;
 	void *con_priv;
 	bool dac_load_detect;
 	bool detected_by_load; /* if the connection status was determined by load */
@@ -520,11 +551,26 @@ struct amdgpu_connector {
 	enum amdgpu_connector_audio audio;
 	enum amdgpu_connector_dither dither;
 	unsigned pixelclock_for_modeset;
+
+	struct drm_dp_mst_topology_mgr mst_mgr;
+	struct amdgpu_dm_dp_aux dm_dp_aux;
+	struct drm_dp_mst_port *port;
+	struct amdgpu_connector *mst_port;
+	bool is_mst_connector;
+	struct amdgpu_encoder *mst_encoder;
+	struct semaphore mst_sem;
 };
 
-struct amdgpu_framebuffer {
-	struct drm_framebuffer base;
-	struct drm_gem_object *obj;
+/* TODO: start to use this struct and remove same field from base one */
+struct amdgpu_mst_connector {
+	struct amdgpu_connector base;
+
+	struct drm_dp_mst_topology_mgr mst_mgr;
+	struct amdgpu_dm_dp_aux dm_dp_aux;
+	struct drm_dp_mst_port *port;
+	struct amdgpu_connector *mst_port;
+	bool is_mst_connector;
+	struct amdgpu_encoder *mst_encoder;
 };
 
 #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 125003517544..4b27092d14c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -77,6 +77,7 @@
 #if defined(CONFIG_DRM_AMD_ACP)
 #include "amdgpu_acp.h"
 #endif
+#include "amdgpu_dm.h"
 
 /*
  * Indirect registers accessor
@@ -984,6 +985,225 @@ static const struct amdgpu_ip_block_version cz_ip_blocks[] =
 #endif
 };
 
+/*
+ * This is temporary. After we've gone through full testing with
+ * DAL we want to remove dce_v11
+ */
+#if defined(CONFIG_DRM_AMD_DAL)
+static const struct amdgpu_ip_block_version cz_ip_blocks_dal[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &cz_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 11,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &amdgpu_dm_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+#if defined(CONFIG_DRM_AMD_ACP)
+	{
+		.type = AMD_IP_BLOCK_TYPE_ACP,
+		.major = 2,
+		.minor = 2,
+		.rev = 0,
+		.funcs = &acp_ip_funcs,
+	},
+#endif
+};
+
+static const struct amdgpu_ip_block_version tonga_ip_blocks_dal[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &tonga_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 7,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 10,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &amdgpu_dm_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 5,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v5_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+};
+
+static const struct amdgpu_ip_block_version fiji_ip_blocks_dal[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 5,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &tonga_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 7,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 10,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &amdgpu_dm_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+};
+#endif
+
 int vi_set_ip_blocks(struct amdgpu_device *adev)
 {
 	switch (adev->asic_type) {
@@ -992,17 +1212,47 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		adev->num_ip_blocks = ARRAY_SIZE(topaz_ip_blocks);
 		break;
 	case CHIP_FIJI:
+#if defined(CONFIG_DRM_AMD_DAL)
+		if (amdgpu_dal && amdgpu_device_has_dal_support(adev)) {
+			adev->ip_blocks = fiji_ip_blocks_dal;
+			adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks_dal);
+		} else {
+			adev->ip_blocks = fiji_ip_blocks;
+			adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks);
+		}
+#else
 		adev->ip_blocks = fiji_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks);
+#endif
 		break;
 	case CHIP_TONGA:
+#if defined(CONFIG_DRM_AMD_DAL)
+		if (amdgpu_dal && amdgpu_device_has_dal_support(adev)) {
+			adev->ip_blocks = tonga_ip_blocks_dal;
+			adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks_dal);
+		} else {
+			adev->ip_blocks = tonga_ip_blocks;
+			adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
+		}
+#else
 		adev->ip_blocks = tonga_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
+#endif
 		break;
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
+#if defined(CONFIG_DRM_AMD_DAL)
+		if (amdgpu_dal && amdgpu_device_has_dal_support(adev)) {
+			adev->ip_blocks = cz_ip_blocks_dal;
+			adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks_dal);
+		} else {
+			adev->ip_blocks = cz_ip_blocks;
+			adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks);
+		}
+#else
 		adev->ip_blocks = cz_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks);
+#endif
 		break;
 	default:
 		/* FIXME: not supported yet */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (25 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 26/29] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 21:00   ` Oded Gabbay
  2016-02-11 17:20 ` [PATCH 28/29] drm/amd/dal: fix flip clean-up state Harry Wentland
                   ` (5 subsequent siblings)
  32 siblings, 1 reply; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Mykola Lysenko <mykola.lysenko@amd.com>
---
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
index 1cc9fd1054ab..da6c0116aa1a 100644
--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
@@ -366,16 +366,16 @@ static bool fill_rects_from_plane_state(
 	surface->clip_rect = surface->dst_rect;
 
 	switch (state->rotation) {
-	case DRM_ROTATE_0:
+	case BIT(DRM_ROTATE_0):
 		surface->rotation = ROTATION_ANGLE_0;
 		break;
-	case DRM_ROTATE_90:
+	case BIT(DRM_ROTATE_90):
 		surface->rotation = ROTATION_ANGLE_90;
 		break;
-	case DRM_ROTATE_180:
+	case BIT(DRM_ROTATE_180):
 		surface->rotation = ROTATION_ANGLE_180;
 		break;
-	case DRM_ROTATE_270:
+	case BIT(DRM_ROTATE_270):
 		surface->rotation = ROTATION_ANGLE_270;
 		break;
 	default:
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 28/29] drm/amd/dal: fix flip clean-up state
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (26 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 17:20 ` [PATCH 29/29] drm/amd/dal: Force bw programming for DCE 10 until we start calculate BW Harry Wentland
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel; +Cc: Mykola Lysenko

From: Mykola Lysenko <Mykola.Lysenko@amd.com>

Get on par with buffer management changes made in base driver

Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c       | 10 ++++------
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c | 17 +++++++++++------
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
index aeb7887356cd..0ceb505355e8 100644
--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
@@ -1329,7 +1329,7 @@ void amdgpu_dm_flip_cleanup(
 		} else
 			DRM_ERROR("failed to reserve buffer after flip\n");
 
-		drm_gem_object_unreference_unlocked(&works->old_rbo->gem_base);
+		amdgpu_bo_unref(&works->old_rbo);
 		kfree(works->shared);
 		kfree(works);
 	}
@@ -1379,13 +1379,11 @@ static void dm_page_flip(struct amdgpu_device *adev,
 	target = acrtc->target;
 
 	/*
-	 * Received a page flip call after the display has been reset. Make sure
-	 * we return the buffers.
+	 * Received a page flip call after the display has been reset.
+	 * Just return in this case. Everything should be clean-up on reset.
 	 */
-	if (!target) {
-		amdgpu_dm_flip_cleanup(adev, acrtc);
+	if (!target)
 		return;
-	}
 
 	addr.address.grph.addr.low_part = lower_32_bits(crtc_base);
 	addr.address.grph.addr.high_part = upper_32_bits(crtc_base);
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
index da6c0116aa1a..7643f751fcc6 100644
--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
@@ -1972,22 +1972,27 @@ static void manage_dm_interrupts(
 	struct amdgpu_crtc *acrtc,
 	bool enable)
 {
+	/*
+	 * this is not correct translation but will work as soon as VBLANK
+	 * constant is the same as PFLIP
+	 */
+	int irq_type =
+		amdgpu_crtc_idx_to_irq_type(
+			adev,
+			acrtc->crtc_id);
+
 	if (enable) {
 		drm_crtc_vblank_on(&acrtc->base);
 		amdgpu_irq_get(
 			adev,
 			&adev->pageflip_irq,
-			amdgpu_crtc_idx_to_irq_type(
-				adev,
-				acrtc->crtc_id));
+			irq_type);
 	} else {
 		unsigned long flags;
 		amdgpu_irq_put(
 			adev,
 			&adev->pageflip_irq,
-			amdgpu_crtc_idx_to_irq_type(
-				adev,
-				acrtc->crtc_id));
+			irq_type);
 		drm_crtc_vblank_off(&acrtc->base);
 
 		/*
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH 29/29] drm/amd/dal: Force bw programming for DCE 10 until we start calculate BW.
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (27 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 28/29] drm/amd/dal: fix flip clean-up state Harry Wentland
@ 2016-02-11 17:20 ` Harry Wentland
  2016-02-11 20:02 ` [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Mike Lothian
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-11 17:20 UTC (permalink / raw)
  To: dri-devel; +Cc: Andrey Grodzovsky

From: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>

Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Acked-by: Jordan Lazare <Jordan.Lazare@amd.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
---
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.c    | 28 ----------------------
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c    |  3 ++-
 2 files changed, 2 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
index 82c5e155d91a..a1dbac487366 100644
--- a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
@@ -335,33 +335,6 @@ static void dal_dc_clock_gating_dce100_power_up(struct dc_context *ctx, bool ena
 	}
 }
 
-/**
- * Call display_engine_clock_dce80 to perform the Dclk programming.
- */
-static void set_display_clock(struct validate_context *context)
-{
-	/* Program the display engine clock.
-	 * Check DFS bypass mode support or not. DFSbypass feature is only when
-	 * BIOS GPU info table reports support. */
-
-	if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) {
-		/*TODO: set_display_clock_dfs_bypass(
-				hws,
-				path_set,
-				context->res_ctx.pool.display_clock,
-				context->res_ctx.min_clocks.min_dclk_khz);*/
-	} else
-		dal_display_clock_set_clock(context->res_ctx.pool.display_clock,
-				681000);
-
-	/* TODO: When changing display engine clock, DMCU WaitLoop must be
-	 * reconfigured in order to maintain the same delays within DMCU
-	 * programming sequences. */
-
-	/* TODO: Start GTC counter */
-}
-
-
 static void set_displaymarks(
 		const struct dc *dc, struct validate_context *context)
 {
@@ -381,7 +354,6 @@ bool dce100_hw_sequencer_construct(struct dc *dc)
 	dc->hwss.enable_fe_clock = dce100_enable_fe_clock;
 	dc->hwss.pipe_control_lock = dce100_pipe_control_lock;
 	dc->hwss.set_blender_mode = dce100_set_blender_mode;
-	dc->hwss.set_display_clock = set_display_clock;
 	dc->hwss.set_displaymarks = set_displaymarks;
 	return true;
 }
diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
index e67ba81f1c85..783d47eba325 100644
--- a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
@@ -773,7 +773,8 @@ enum dc_status dce100_validate_bandwidth(
 	const struct dc *dc,
 	struct validate_context *context)
 {
-	/* TODO implement when needed */
+	/* TODO implement when needed but for now hardcode max value*/
+	context->bw_results.dispclk_khz = 681000;
 
 	return DC_OK;
 }
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (28 preceding siblings ...)
  2016-02-11 17:20 ` [PATCH 29/29] drm/amd/dal: Force bw programming for DCE 10 until we start calculate BW Harry Wentland
@ 2016-02-11 20:02 ` Mike Lothian
  2016-02-11 20:05   ` Wentland, Harry
  2016-02-11 20:52 ` Dave Airlie
                   ` (2 subsequent siblings)
  32 siblings, 1 reply; 87+ messages in thread
From: Mike Lothian @ 2016-02-11 20:02 UTC (permalink / raw)
  To: Harry Wentland, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 41225 bytes --]

Hi

Does that mean Tonga is capable of HDMI 2.0 or is it only Carrizo

Cheers

Mike

On Thu, 11 Feb 2016 at 17:20 Harry Wentland <harry.wentland@amd.com> wrote:

> This set of patches enables the new DAL display driver for amdgpu on
> Carrizo
> Tonga, and Fiji ASICs. This driver will allow us going forward to bring
> display features on the open amdgpu driver (mostly) on par with the
> Catalyst
> driver.
>
> This driver adds support for
> - Atomic KMS API
> - MST
> - HDMI 2.0
> - Better powerplay integration
> - Support of HW bandwidth formula on Carrizo
> - Better multi-display support and handling of co-functionality
> - Broader support of display dongles
> - Timing synchronization between DP and HDMI
>
> This patch series is based on Alex Deucher's drm-next-4.6-wip tree.
>
>
>
> Andrey Grodzovsky (1):
>   drm/amd/dal: Force bw programming for DCE 10 until we start calculate
>     BW.
>
> Harry Wentland (27):
>   drm/amd/dal: Add dal headers
>   drm/amd/dal: Add DAL Basic Types and Logger
>   drm/amd/dal: Fixed point arithmetic
>   drm/amd/dal: Asic Capabilities
>   drm/amd/dal: GPIO (General Purpose IO)
>   drm/amd/dal: Adapter Service
>   drm/amd/dal: BIOS Parser
>   drm/amd/dal: I2C Aux Manager
>   drm/amd/dal: IRQ Service
>   drm/amd/dal: GPU
>   drm/amd/dal: Audio
>   drm/amd/dal: Bandwidth calculations
>   drm/amd/dal: Add encoder HW programming
>   drm/amd/dal: Add clock source HW programming
>   drm/amd/dal: Add timing generator HW programming
>   drm/amd/dal: Add surface HW programming
>   drm/amd/dal: Add framebuffer compression HW programming
>   drm/amd/dal: Add input pixel processing HW programming
>   drm/amd/dal: Add output pixel processing HW programming
>   drm/amd/dal: Add transform & scaler HW programming
>   drm/amd/dal: Add Carrizo HW sequencer and resource
>   drm/amd/dal: Add Tonga/Fiji HW sequencer and resource
>   drm/amd/dal: Add empty encoder programming for virtual HW
>   drm/amd/dal: Add display core
>   drm/amd/dal: Adding amdgpu_dm for dal
>   drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji
>   drm/amd/dal: Correctly interpret rotation as bit set
>
> Mykola Lysenko (1):
>   drm/amd/dal: fix flip clean-up state
>
>  drivers/gpu/drm/amd/amdgpu/Kconfig                 |    3 +
>  drivers/gpu/drm/amd/amdgpu/Makefile                |   17 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h                |   10 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         |   69 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c            |    4 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c             |    5 -
>  drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c            |   20 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h           |   54 +-
>  drivers/gpu/drm/amd/amdgpu/vi.c                    |  250 +
>  drivers/gpu/drm/amd/dal/Kconfig                    |   48 +
>  drivers/gpu/drm/amd/dal/Makefile                   |   21 +
>  drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile         |   17 +
>  drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c      | 1468 ++++++
>  drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h      |  168 +
>  .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c  |  474 ++
>  drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c  |  820 ++++
>  drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h  |  122 +
>  .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c    |  480 ++
>  .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h    |   36 +
>  .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c |  457 ++
>  .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c    | 2577 ++++++++++
>  .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h    |  100 +
>  drivers/gpu/drm/amd/dal/dal_services.h             |  266 ++
>  drivers/gpu/drm/amd/dal/dal_services_types.h       |   62 +
>  drivers/gpu/drm/amd/dal/dc/Makefile                |   28 +
>  drivers/gpu/drm/amd/dal/dc/adapter/Makefile        |   24 +
>  .../gpu/drm/amd/dal/dc/adapter/adapter_service.c   | 2089 ++++++++
>  .../gpu/drm/amd/dal/dc/adapter/adapter_service.h   |   71 +
>  .../adapter/dce110/hw_ctx_adapter_service_dce110.c |  304 ++
>  .../adapter/dce110/hw_ctx_adapter_service_dce110.h |   40 +
>  .../diagnostics/hw_ctx_adapter_service_diag.c      |  133 +
>  .../diagnostics/hw_ctx_adapter_service_diag.h      |   33 +
>  .../amd/dal/dc/adapter/hw_ctx_adapter_service.c    |  164 +
>  .../amd/dal/dc/adapter/hw_ctx_adapter_service.h    |   86 +
>  .../drm/amd/dal/dc/adapter/wireless_data_source.c  |  208 +
>  .../drm/amd/dal/dc/adapter/wireless_data_source.h  |   80 +
>  .../gpu/drm/amd/dal/dc/asic_capability/Makefile    |   35 +
>  .../amd/dal/dc/asic_capability/asic_capability.c   |  190 +
>  .../dc/asic_capability/carrizo_asic_capability.c   |  147 +
>  .../dc/asic_capability/carrizo_asic_capability.h   |   36 +
>  .../dal/dc/asic_capability/tonga_asic_capability.c |  146 +
>  .../dal/dc/asic_capability/tonga_asic_capability.h |   36 +
>  drivers/gpu/drm/amd/dal/dc/audio/Makefile          |   22 +
>  drivers/gpu/drm/amd/dal/dc/audio/audio.h           |  195 +
>  drivers/gpu/drm/amd/dal/dc/audio/audio_base.c      |  470 ++
>  .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c |  453 ++
>  .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h |   42 +
>  .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c  | 1930 ++++++++
>  .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h  |   47 +
>  drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c    |  771 +++
>  drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h    |  285 ++
>  drivers/gpu/drm/amd/dal/dc/basics/Makefile         |   10 +
>  drivers/gpu/drm/amd/dal/dc/basics/conversion.c     |  224 +
>  drivers/gpu/drm/amd/dal/dc/basics/conversion.h     |   49 +
>  drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c     |  692 +++
>  drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c     |  223 +
>  drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c |  134 +
>  drivers/gpu/drm/amd/dal/dc/basics/logger.c         |  954 ++++
>  drivers/gpu/drm/amd/dal/dc/basics/logger.h         |   64 +
>  .../gpu/drm/amd/dal/dc/basics/register_logger.c    |  197 +
>  drivers/gpu/drm/amd/dal/dc/basics/signal_types.c   |  116 +
>  drivers/gpu/drm/amd/dal/dc/basics/vector.c         |  309 ++
>  drivers/gpu/drm/amd/dal/dc/bios/Makefile           |   26 +
>  drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c      | 5029
> ++++++++++++++++++++
>  drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h      |   84 +
>  .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c   |  198 +
>  .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h   |  108 +
>  drivers/gpu/drm/amd/dal/dc/bios/command_table.c    | 2730 +++++++++++
>  drivers/gpu/drm/amd/dal/dc/bios/command_table.h    |  117 +
>  .../gpu/drm/amd/dal/dc/bios/command_table_helper.c |  285 ++
>  .../gpu/drm/amd/dal/dc/bios/command_table_helper.h |   90 +
>  .../dal/dc/bios/dce110/bios_parser_helper_dce110.c |  484 ++
>  .../dal/dc/bios/dce110/bios_parser_helper_dce110.h |   34 +
>  .../dc/bios/dce110/command_table_helper_dce110.c   |  366 ++
>  .../dc/bios/dce110/command_table_helper_dce110.h   |   34 +
>  drivers/gpu/drm/amd/dal/dc/calcs/Makefile          |   10 +
>  drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 3941 +++++++++++++++
>  drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c        |  300 ++
>  drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c   | 1992 ++++++++
>  drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h   |   74 +
>  drivers/gpu/drm/amd/dal/dc/core/dc.c               |  932 ++++
>  drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c  |   56 +
>  drivers/gpu/drm/amd/dal/dc/core/dc_link.c          | 1644 +++++++
>  drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c      | 1151 +++++
>  drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c       | 1728 +++++++
>  drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c     |  201 +
>  drivers/gpu/drm/amd/dal/dc/core/dc_resource.c      | 1243 +++++
>  drivers/gpu/drm/amd/dal/dc/core/dc_sink.c          |  116 +
>  drivers/gpu/drm/amd/dal/dc/core/dc_stream.c        |  188 +
>  drivers/gpu/drm/amd/dal/dc/core/dc_surface.c       |  123 +
>  drivers/gpu/drm/amd/dal/dc/core/dc_target.c        |  548 +++
>  drivers/gpu/drm/amd/dal/dc/dc.h                    |  462 ++
>  drivers/gpu/drm/amd/dal/dc/dc_bios_types.h         |  277 ++
>  drivers/gpu/drm/amd/dal/dc/dc_types.h              |  936 ++++
>  drivers/gpu/drm/amd/dal/dc/dce100/Makefile         |   23 +
>  .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.c    |  360 ++
>  .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.h    |   36 +
>  .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c    | 1135 +++++
>  .../gpu/drm/amd/dal/dc/dce100/dce100_resource.h    |   43 +
>  drivers/gpu/drm/amd/dal/dc/dce110/Makefile         |   15 +
>  .../drm/amd/dal/dc/dce110/dce110_clock_source.c    | 1162 +++++
>  .../drm/amd/dal/dc/dce110/dce110_clock_source.h    |   64 +
>  .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.c  |  886 ++++
>  .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.h  |   84 +
>  .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 1658 +++++++
>  .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h    |   36 +
>  drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c     |   65 +
>  drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h     |  100 +
>  .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c  |  256 +
>  .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c   |  872 ++++
>  .../drm/amd/dal/dc/dce110/dce110_link_encoder.c    | 1927 ++++++++
>  .../drm/amd/dal/dc/dce110/dce110_link_encoder.h    |  156 +
>  .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c   |  965 ++++
>  .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h   |  117 +
>  drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c     |  272 ++
>  drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h     |  143 +
>  drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c |  904 ++++
>  .../drm/amd/dal/dc/dce110/dce110_opp_formatter.c   |  610 +++
>  .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2474 ++++++++++
>  .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c    | 1238 +++++
>  .../gpu/drm/amd/dal/dc/dce110/dce110_resource.h    |   46 +
>  .../drm/amd/dal/dc/dce110/dce110_stream_encoder.c  | 1123 +++++
>  .../drm/amd/dal/dc/dce110/dce110_stream_encoder.h  |  122 +
>  .../amd/dal/dc/dce110/dce110_timing_generator.c    | 1864 ++++++++
>  .../amd/dal/dc/dce110/dce110_timing_generator.h    |  234 +
>  .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c   |   91 +
>  .../gpu/drm/amd/dal/dc/dce110/dce110_transform.h   |   87 +
>  .../amd/dal/dc/dce110/dce110_transform_bit_depth.c |  851 ++++
>  .../amd/dal/dc/dce110/dce110_transform_bit_depth.h |   51 +
>  .../drm/amd/dal/dc/dce110/dce110_transform_gamut.c |  296 ++
>  .../drm/amd/dal/dc/dce110/dce110_transform_scl.c   |  818 ++++
>  .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c  |  531 +++
>  drivers/gpu/drm/amd/dal/dc/dm_helpers.h            |   98 +
>  drivers/gpu/drm/amd/dal/dc/dm_services.h           |  468 ++
>  drivers/gpu/drm/amd/dal/dc/dm_services_types.h     |  167 +
>  drivers/gpu/drm/amd/dal/dc/gpio/Makefile           |   32 +
>  .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c |  882 ++++
>  .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h |   46 +
>  .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c |   81 +
>  .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h |   32 +
>  .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c |  366 ++
>  .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h |   47 +
>  .../amd/dal/dc/gpio/dce110/hw_translate_dce110.c   |  400 ++
>  .../amd/dal/dc/gpio/dce110/hw_translate_dce110.h   |   34 +
>  drivers/gpu/drm/amd/dal/dc/gpio/ddc.c              |  290 ++
>  drivers/gpu/drm/amd/dal/dc/gpio/ddc.h              |   45 +
>  .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c  |   97 +
>  .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h  |   34 +
>  .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.c  |   65 +
>  .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.h  |   32 +
>  .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c  |  101 +
>  .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h  |   35 +
>  .../dal/dc/gpio/diagnostics/hw_translate_diag.c    |   41 +
>  .../dal/dc/gpio/diagnostics/hw_translate_diag.h    |   34 +
>  drivers/gpu/drm/amd/dal/dc/gpio/gpio.h             |   48 +
>  drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c        |  279 ++
>  drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c     |  386 ++
>  drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h     |   57 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c           |  104 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h           |   60 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c       |   93 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h       |   71 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c          |  407 ++
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h          |  129 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c      |   92 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h      |   47 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c      |   85 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h      |   79 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c           |   87 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h           |   45 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c     |   77 +
>  drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h     |   50 +
>  drivers/gpu/drm/amd/dal/dc/gpio/irq.c              |  180 +
>  drivers/gpu/drm/amd/dal/dc/gpio/irq.h              |   42 +
>  drivers/gpu/drm/amd/dal/dc/gpu/Makefile            |   22 +
>  .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c    |   92 +
>  .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h    |   63 +
>  .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c |   90 +
>  .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h |   33 +
>  .../amd/dal/dc/gpu/dce110/display_clock_dce110.c   |  968 ++++
>  .../amd/dal/dc/gpu/dce110/display_clock_dce110.h   |   53 +
>  drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c     |  205 +
>  drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h     |   82 +
>  drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c     |  127 +
>  drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h     |   63 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |   33 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     |  567 +++
>  drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     |  119 +
>  .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   |  788 +++
>  .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |   56 +
>  .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |   25 +
>  .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    |  954 ++++
>  .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |   58 +
>  .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    |  172 +
>  .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |   43 +
>  .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   |  266 ++
>  .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |   39 +
>  .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    |  112 +
>  .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |   33 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         |  129 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |   67 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     |  121 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     |  113 +
>  .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  |  286 ++
>  .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |   77 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  |  246 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |   80 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  |  614 +++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |   81 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         |  529 ++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         |  123 +
>  drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h   |  510 ++
>  drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h          |   64 +
>  drivers/gpu/drm/amd/dal/dc/inc/clock_source.h      |  176 +
>  drivers/gpu/drm/amd/dal/dc/inc/compressor.h        |  140 +
>  drivers/gpu/drm/amd/dal/dc/inc/core_dc.h           |   54 +
>  drivers/gpu/drm/amd/dal/dc/inc/core_status.h       |   46 +
>  drivers/gpu/drm/amd/dal/dc/inc/core_types.h        |  357 ++
>  drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h       |  151 +
>  drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h        |   56 +
>  drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h       |  118 +
>  drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h      |  126 +
>  drivers/gpu/drm/amd/dal/dc/inc/ipp.h               |  106 +
>  drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h      |  138 +
>  drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h         |   68 +
>  drivers/gpu/drm/amd/dal/dc/inc/mem_input.h         |   83 +
>  drivers/gpu/drm/amd/dal/dc/inc/opp.h               |  308 ++
>  drivers/gpu/drm/amd/dal/dc/inc/resource.h          |   80 +
>  drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h    |   88 +
>  drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h  |  155 +
>  drivers/gpu/drm/amd/dal/dc/inc/transform.h         |  217 +
>  drivers/gpu/drm/amd/dal/dc/irq/Makefile            |   21 +
>  .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.c |  389 ++
>  .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.h |   34 +
>  drivers/gpu/drm/amd/dal/dc/irq/irq_service.c       |  177 +
>  drivers/gpu/drm/amd/dal/dc/irq/irq_service.h       |   85 +
>  drivers/gpu/drm/amd/dal/dc/irq_types.h             |  199 +
>  drivers/gpu/drm/amd/dal/dc/virtual/Makefile        |    9 +
>  .../drm/amd/dal/dc/virtual/virtual_link_encoder.c  |  133 +
>  .../drm/amd/dal/dc/virtual/virtual_link_encoder.h  |   35 +
>  .../amd/dal/dc/virtual/virtual_stream_encoder.c    |  124 +
>  .../amd/dal/dc/virtual/virtual_stream_encoder.h    |   39 +
>  .../amd/dal/include/adapter_service_interface.h    |  632 +++
>  .../drm/amd/dal/include/adapter_service_types.h    |   71 +
>  .../amd/dal/include/asic_capability_interface.h    |   58 +
>  .../drm/amd/dal/include/asic_capability_types.h    |  134 +
>  drivers/gpu/drm/amd/dal/include/audio_interface.h  |  184 +
>  drivers/gpu/drm/amd/dal/include/audio_types.h      |  277 ++
>  .../drm/amd/dal/include/bios_parser_interface.h    |   98 +
>  .../gpu/drm/amd/dal/include/bios_parser_types.h    |  327 ++
>  drivers/gpu/drm/amd/dal/include/dal_asic_id.h      |  117 +
>  .../gpu/drm/amd/dal/include/dal_register_logger.h  |   43 +
>  drivers/gpu/drm/amd/dal/include/dal_types.h        |  305 ++
>  .../amd/dal/include/dc_clock_generator_interface.h |   77 +
>  drivers/gpu/drm/amd/dal/include/dcs_types.h        |  742 +++
>  drivers/gpu/drm/amd/dal/include/ddc_interface.h    |   74 +
>  .../gpu/drm/amd/dal/include/ddc_service_types.h    |  221 +
>  .../drm/amd/dal/include/display_clock_interface.h  |  186 +
>  .../drm/amd/dal/include/display_path_interface.h   |  436 ++
>  drivers/gpu/drm/amd/dal/include/dmcu_interface.h   |   87 +
>  drivers/gpu/drm/amd/dal/include/dmcu_types.h       |  199 +
>  drivers/gpu/drm/amd/dal/include/dpcd_defs.h        |  873 ++++
>  .../gpu/drm/amd/dal/include/encoder_interface.h    |  278 ++
>  drivers/gpu/drm/amd/dal/include/fixed31_32.h       |  389 ++
>  drivers/gpu/drm/amd/dal/include/fixed32_32.h       |   82 +
>  drivers/gpu/drm/amd/dal/include/gpio_interface.h   |   93 +
>  .../drm/amd/dal/include/gpio_service_interface.h   |   81 +
>  drivers/gpu/drm/amd/dal/include/gpio_types.h       |  341 ++
>  drivers/gpu/drm/amd/dal/include/grph_csc_types.h   |   98 +
>  .../drm/amd/dal/include/grph_object_ctrl_defs.h    |  593 +++
>  drivers/gpu/drm/amd/dal/include/grph_object_defs.h |  328 ++
>  drivers/gpu/drm/amd/dal/include/grph_object_id.h   |  277 ++
>  .../drm/amd/dal/include/hw_sequencer_interface.h   |  388 ++
>  .../gpu/drm/amd/dal/include/hw_sequencer_types.h   |  304 ++
>  drivers/gpu/drm/amd/dal/include/i2caux_interface.h |  127 +
>  drivers/gpu/drm/amd/dal/include/irq_interface.h    |   53 +
>  .../drm/amd/dal/include/irq_service_interface.h    |   55 +
>  .../drm/amd/dal/include/link_service_interface.h   |  202 +
>  .../gpu/drm/amd/dal/include/link_service_types.h   |  427 ++
>  drivers/gpu/drm/amd/dal/include/logger_interface.h |  153 +
>  drivers/gpu/drm/amd/dal/include/logger_types.h     |  356 ++
>  drivers/gpu/drm/amd/dal/include/scaler_types.h     |  196 +
>  drivers/gpu/drm/amd/dal/include/set_mode_types.h   |  142 +
>  drivers/gpu/drm/amd/dal/include/signal_types.h     |   59 +
>  drivers/gpu/drm/amd/dal/include/vector.h           |  150 +
>  drivers/gpu/drm/amd/dal/include/video_csc_types.h  |  135 +
>  .../gpu/drm/amd/dal/include/video_gamma_types.h    |   57 +
>  287 files changed, 93942 insertions(+), 30 deletions(-)
>  create mode 100644 drivers/gpu/drm/amd/dal/Kconfig
>  create mode 100644 drivers/gpu/drm/amd/dal/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
>  create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dal_services.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dal_services_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_target.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dc.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_helpers.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/compressor.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_status.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/ipp.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/opp.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/resource.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/transform.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/Makefile
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/irq_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/Makefile
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
>  create mode 100644
> drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_types.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/audio_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/audio_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/dal_asic_id.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/dal_register_logger.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/dal_types.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_types.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/include/display_clock_interface.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/include/display_path_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_defs.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/fixed31_32.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/fixed32_32.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_interface.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/grph_csc_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_defs.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_id.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/i2caux_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/irq_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/irq_service_interface.h
>  create mode 100644
> drivers/gpu/drm/amd/dal/include/link_service_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/logger_interface.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/logger_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/scaler_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/signal_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/vector.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/video_csc_types.h
>  create mode 100644 drivers/gpu/drm/amd/dal/include/video_gamma_types.h
>
> --
> 2.1.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>

[-- Attachment #1.2: Type: text/html, Size: 45285 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* RE: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-11 20:02 ` [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Mike Lothian
@ 2016-02-11 20:05   ` Wentland, Harry
  0 siblings, 0 replies; 87+ messages in thread
From: Wentland, Harry @ 2016-02-11 20:05 UTC (permalink / raw)
  To: Mike Lothian, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 40845 bytes --]

That applies only to Carrizo, unfortunately.

Harry

From: Mike Lothian [mailto:mike@fireburn.co.uk]
Sent: February 11, 2016 3:03 PM
To: Wentland, Harry <Harry.Wentland@amd.com>; dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga

Hi

Does that mean Tonga is capable of HDMI 2.0 or is it only Carrizo

Cheers

Mike

On Thu, 11 Feb 2016 at 17:20 Harry Wentland <harry.wentland@amd.com<mailto:harry.wentland@amd.com>> wrote:
This set of patches enables the new DAL display driver for amdgpu on Carrizo
Tonga, and Fiji ASICs. This driver will allow us going forward to bring
display features on the open amdgpu driver (mostly) on par with the Catalyst
driver.

This driver adds support for
- Atomic KMS API
- MST
- HDMI 2.0
- Better powerplay integration
- Support of HW bandwidth formula on Carrizo
- Better multi-display support and handling of co-functionality
- Broader support of display dongles
- Timing synchronization between DP and HDMI

This patch series is based on Alex Deucher's drm-next-4.6-wip tree.



Andrey Grodzovsky (1):
  drm/amd/dal: Force bw programming for DCE 10 until we start calculate
    BW.

Harry Wentland (27):
  drm/amd/dal: Add dal headers
  drm/amd/dal: Add DAL Basic Types and Logger
  drm/amd/dal: Fixed point arithmetic
  drm/amd/dal: Asic Capabilities
  drm/amd/dal: GPIO (General Purpose IO)
  drm/amd/dal: Adapter Service
  drm/amd/dal: BIOS Parser
  drm/amd/dal: I2C Aux Manager
  drm/amd/dal: IRQ Service
  drm/amd/dal: GPU
  drm/amd/dal: Audio
  drm/amd/dal: Bandwidth calculations
  drm/amd/dal: Add encoder HW programming
  drm/amd/dal: Add clock source HW programming
  drm/amd/dal: Add timing generator HW programming
  drm/amd/dal: Add surface HW programming
  drm/amd/dal: Add framebuffer compression HW programming
  drm/amd/dal: Add input pixel processing HW programming
  drm/amd/dal: Add output pixel processing HW programming
  drm/amd/dal: Add transform & scaler HW programming
  drm/amd/dal: Add Carrizo HW sequencer and resource
  drm/amd/dal: Add Tonga/Fiji HW sequencer and resource
  drm/amd/dal: Add empty encoder programming for virtual HW
  drm/amd/dal: Add display core
  drm/amd/dal: Adding amdgpu_dm for dal
  drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji
  drm/amd/dal: Correctly interpret rotation as bit set

Mykola Lysenko (1):
  drm/amd/dal: fix flip clean-up state

 drivers/gpu/drm/amd/amdgpu/Kconfig                 |    3 +
 drivers/gpu/drm/amd/amdgpu/Makefile                |   17 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h                |   10 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         |   69 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c            |    4 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c             |    5 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c            |   20 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h           |   54 +-
 drivers/gpu/drm/amd/amdgpu/vi.c                    |  250 +
 drivers/gpu/drm/amd/dal/Kconfig                    |   48 +
 drivers/gpu/drm/amd/dal/Makefile                   |   21 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile         |   17 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c      | 1468 ++++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h      |  168 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c  |  474 ++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c  |  820 ++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h  |  122 +
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c    |  480 ++
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h    |   36 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c |  457 ++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c    | 2577 ++++++++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h    |  100 +
 drivers/gpu/drm/amd/dal/dal_services.h             |  266 ++
 drivers/gpu/drm/amd/dal/dal_services_types.h       |   62 +
 drivers/gpu/drm/amd/dal/dc/Makefile                |   28 +
 drivers/gpu/drm/amd/dal/dc/adapter/Makefile        |   24 +
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.c   | 2089 ++++++++
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.h   |   71 +
 .../adapter/dce110/hw_ctx_adapter_service_dce110.c |  304 ++
 .../adapter/dce110/hw_ctx_adapter_service_dce110.h |   40 +
 .../diagnostics/hw_ctx_adapter_service_diag.c      |  133 +
 .../diagnostics/hw_ctx_adapter_service_diag.h      |   33 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.c    |  164 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.h    |   86 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.c  |  208 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.h  |   80 +
 .../gpu/drm/amd/dal/dc/asic_capability/Makefile    |   35 +
 .../amd/dal/dc/asic_capability/asic_capability.c   |  190 +
 .../dc/asic_capability/carrizo_asic_capability.c   |  147 +
 .../dc/asic_capability/carrizo_asic_capability.h   |   36 +
 .../dal/dc/asic_capability/tonga_asic_capability.c |  146 +
 .../dal/dc/asic_capability/tonga_asic_capability.h |   36 +
 drivers/gpu/drm/amd/dal/dc/audio/Makefile          |   22 +
 drivers/gpu/drm/amd/dal/dc/audio/audio.h           |  195 +
 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c      |  470 ++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c |  453 ++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h |   42 +
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c  | 1930 ++++++++
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h  |   47 +
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c    |  771 +++
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h    |  285 ++
 drivers/gpu/drm/amd/dal/dc/basics/Makefile         |   10 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.c     |  224 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.h     |   49 +
 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c     |  692 +++
 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c     |  223 +
 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c |  134 +
 drivers/gpu/drm/amd/dal/dc/basics/logger.c         |  954 ++++
 drivers/gpu/drm/amd/dal/dc/basics/logger.h         |   64 +
 .../gpu/drm/amd/dal/dc/basics/register_logger.c    |  197 +
 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c   |  116 +
 drivers/gpu/drm/amd/dal/dc/basics/vector.c         |  309 ++
 drivers/gpu/drm/amd/dal/dc/bios/Makefile           |   26 +
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c      | 5029 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h      |   84 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c   |  198 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h   |  108 +
 drivers/gpu/drm/amd/dal/dc/bios/command_table.c    | 2730 +++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/command_table.h    |  117 +
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.c |  285 ++
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.h |   90 +
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.c |  484 ++
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.h |   34 +
 .../dc/bios/dce110/command_table_helper_dce110.c   |  366 ++
 .../dc/bios/dce110/command_table_helper_dce110.h   |   34 +
 drivers/gpu/drm/amd/dal/dc/calcs/Makefile          |   10 +
 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 3941 +++++++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c        |  300 ++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c   | 1992 ++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h   |   74 +
 drivers/gpu/drm/amd/dal/dc/core/dc.c               |  932 ++++
 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c  |   56 +
 drivers/gpu/drm/amd/dal/dc/core/dc_link.c          | 1644 +++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c      | 1151 +++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c       | 1728 +++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c     |  201 +
 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c      | 1243 +++++
 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c          |  116 +
 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c        |  188 +
 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c       |  123 +
 drivers/gpu/drm/amd/dal/dc/core/dc_target.c        |  548 +++
 drivers/gpu/drm/amd/dal/dc/dc.h                    |  462 ++
 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h         |  277 ++
 drivers/gpu/drm/amd/dal/dc/dc_types.h              |  936 ++++
 drivers/gpu/drm/amd/dal/dc/dce100/Makefile         |   23 +
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.c    |  360 ++
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.h    |   36 +
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c    | 1135 +++++
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.h    |   43 +
 drivers/gpu/drm/amd/dal/dc/dce110/Makefile         |   15 +
 .../drm/amd/dal/dc/dce110/dce110_clock_source.c    | 1162 +++++
 .../drm/amd/dal/dc/dce110/dce110_clock_source.h    |   64 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.c  |  886 ++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.h  |   84 +
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 1658 +++++++
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h    |   36 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c     |   65 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h     |  100 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c  |  256 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c   |  872 ++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.c    | 1927 ++++++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.h    |  156 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c   |  965 ++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h   |  117 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c     |  272 ++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h     |  143 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c |  904 ++++
 .../drm/amd/dal/dc/dce110/dce110_opp_formatter.c   |  610 +++
 .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2474 ++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c    | 1238 +++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.h    |   46 +
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.c  | 1123 +++++
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.h  |  122 +
 .../amd/dal/dc/dce110/dce110_timing_generator.c    | 1864 ++++++++
 .../amd/dal/dc/dce110/dce110_timing_generator.h    |  234 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c   |   91 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.h   |   87 +
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.c |  851 ++++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.h |   51 +
 .../drm/amd/dal/dc/dce110/dce110_transform_gamut.c |  296 ++
 .../drm/amd/dal/dc/dce110/dce110_transform_scl.c   |  818 ++++
 .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c  |  531 +++
 drivers/gpu/drm/amd/dal/dc/dm_helpers.h            |   98 +
 drivers/gpu/drm/amd/dal/dc/dm_services.h           |  468 ++
 drivers/gpu/drm/amd/dal/dc/dm_services_types.h     |  167 +
 drivers/gpu/drm/amd/dal/dc/gpio/Makefile           |   32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c |  882 ++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h |   46 +
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c |   81 +
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h |   32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c |  366 ++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h |   47 +
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.c   |  400 ++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.h   |   34 +
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c              |  290 ++
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h              |   45 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c  |   97 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h  |   34 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.c  |   65 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.h  |   32 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c  |  101 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h  |   35 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.c    |   41 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.h    |   34 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h             |   48 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c        |  279 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c     |  386 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h     |   57 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c           |  104 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h           |   60 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c       |   93 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h       |   71 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c          |  407 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h          |  129 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c      |   92 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h      |   47 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c      |   85 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h      |   79 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c           |   87 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h           |   45 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c     |   77 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h     |   50 +
 drivers/gpu/drm/amd/dal/dc/gpio/irq.c              |  180 +
 drivers/gpu/drm/amd/dal/dc/gpio/irq.h              |   42 +
 drivers/gpu/drm/amd/dal/dc/gpu/Makefile            |   22 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c    |   92 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h    |   63 +
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c |   90 +
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h |   33 +
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.c   |  968 ++++
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.h   |   53 +
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c     |  205 +
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h     |   82 +
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c     |  127 +
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h     |   63 +
 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |   33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     |  567 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     |  119 +
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   |  788 +++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |   56 +
 .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |   25 +
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    |  954 ++++
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |   58 +
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    |  172 +
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |   43 +
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   |  266 ++
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |   39 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    |  112 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |   33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         |  129 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |   67 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     |  121 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     |  113 +
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  |  286 ++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |   77 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  |  246 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |   80 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  |  614 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |   81 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         |  529 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         |  123 +
 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h   |  510 ++
 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h          |   64 +
 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h      |  176 +
 drivers/gpu/drm/amd/dal/dc/inc/compressor.h        |  140 +
 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h           |   54 +
 drivers/gpu/drm/amd/dal/dc/inc/core_status.h       |   46 +
 drivers/gpu/drm/amd/dal/dc/inc/core_types.h        |  357 ++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h       |  151 +
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h        |   56 +
 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h       |  118 +
 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h      |  126 +
 drivers/gpu/drm/amd/dal/dc/inc/ipp.h               |  106 +
 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h      |  138 +
 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h         |   68 +
 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h         |   83 +
 drivers/gpu/drm/amd/dal/dc/inc/opp.h               |  308 ++
 drivers/gpu/drm/amd/dal/dc/inc/resource.h          |   80 +
 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h    |   88 +
 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h  |  155 +
 drivers/gpu/drm/amd/dal/dc/inc/transform.h         |  217 +
 drivers/gpu/drm/amd/dal/dc/irq/Makefile            |   21 +
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.c |  389 ++
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.h |   34 +
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c       |  177 +
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h       |   85 +
 drivers/gpu/drm/amd/dal/dc/irq_types.h             |  199 +
 drivers/gpu/drm/amd/dal/dc/virtual/Makefile        |    9 +
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.c  |  133 +
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.h  |   35 +
 .../amd/dal/dc/virtual/virtual_stream_encoder.c    |  124 +
 .../amd/dal/dc/virtual/virtual_stream_encoder.h    |   39 +
 .../amd/dal/include/adapter_service_interface.h    |  632 +++
 .../drm/amd/dal/include/adapter_service_types.h    |   71 +
 .../amd/dal/include/asic_capability_interface.h    |   58 +
 .../drm/amd/dal/include/asic_capability_types.h    |  134 +
 drivers/gpu/drm/amd/dal/include/audio_interface.h  |  184 +
 drivers/gpu/drm/amd/dal/include/audio_types.h      |  277 ++
 .../drm/amd/dal/include/bios_parser_interface.h    |   98 +
 .../gpu/drm/amd/dal/include/bios_parser_types.h    |  327 ++
 drivers/gpu/drm/amd/dal/include/dal_asic_id.h      |  117 +
 .../gpu/drm/amd/dal/include/dal_register_logger.h  |   43 +
 drivers/gpu/drm/amd/dal/include/dal_types.h        |  305 ++
 .../amd/dal/include/dc_clock_generator_interface.h |   77 +
 drivers/gpu/drm/amd/dal/include/dcs_types.h        |  742 +++
 drivers/gpu/drm/amd/dal/include/ddc_interface.h    |   74 +
 .../gpu/drm/amd/dal/include/ddc_service_types.h    |  221 +
 .../drm/amd/dal/include/display_clock_interface.h  |  186 +
 .../drm/amd/dal/include/display_path_interface.h   |  436 ++
 drivers/gpu/drm/amd/dal/include/dmcu_interface.h   |   87 +
 drivers/gpu/drm/amd/dal/include/dmcu_types.h       |  199 +
 drivers/gpu/drm/amd/dal/include/dpcd_defs.h        |  873 ++++
 .../gpu/drm/amd/dal/include/encoder_interface.h    |  278 ++
 drivers/gpu/drm/amd/dal/include/fixed31_32.h       |  389 ++
 drivers/gpu/drm/amd/dal/include/fixed32_32.h       |   82 +
 drivers/gpu/drm/amd/dal/include/gpio_interface.h   |   93 +
 .../drm/amd/dal/include/gpio_service_interface.h   |   81 +
 drivers/gpu/drm/amd/dal/include/gpio_types.h       |  341 ++
 drivers/gpu/drm/amd/dal/include/grph_csc_types.h   |   98 +
 .../drm/amd/dal/include/grph_object_ctrl_defs.h    |  593 +++
 drivers/gpu/drm/amd/dal/include/grph_object_defs.h |  328 ++
 drivers/gpu/drm/amd/dal/include/grph_object_id.h   |  277 ++
 .../drm/amd/dal/include/hw_sequencer_interface.h   |  388 ++
 .../gpu/drm/amd/dal/include/hw_sequencer_types.h   |  304 ++
 drivers/gpu/drm/amd/dal/include/i2caux_interface.h |  127 +
 drivers/gpu/drm/amd/dal/include/irq_interface.h    |   53 +
 .../drm/amd/dal/include/irq_service_interface.h    |   55 +
 .../drm/amd/dal/include/link_service_interface.h   |  202 +
 .../gpu/drm/amd/dal/include/link_service_types.h   |  427 ++
 drivers/gpu/drm/amd/dal/include/logger_interface.h |  153 +
 drivers/gpu/drm/amd/dal/include/logger_types.h     |  356 ++
 drivers/gpu/drm/amd/dal/include/scaler_types.h     |  196 +
 drivers/gpu/drm/amd/dal/include/set_mode_types.h   |  142 +
 drivers/gpu/drm/amd/dal/include/signal_types.h     |   59 +
 drivers/gpu/drm/amd/dal/include/vector.h           |  150 +
 drivers/gpu/drm/amd/dal/include/video_csc_types.h  |  135 +
 .../gpu/drm/amd/dal/include/video_gamma_types.h    |   57 +
 287 files changed, 93942 insertions(+), 30 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/dal/Kconfig
 create mode 100644 drivers/gpu/drm/amd/dal/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_target.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_helpers.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_status.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_asic_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_register_logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_clock_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_path_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed31_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed32_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/i2caux_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/scaler_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/signal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/vector.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_gamma_types.h

--
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org<mailto:dri-devel@lists.freedesktop.org>
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[-- Attachment #1.2: Type: text/html, Size: 57999 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 08/29] drm/amd/dal: I2C Aux Manager
  2016-02-11 17:19 ` [PATCH 08/29] drm/amd/dal: I2C Aux Manager Harry Wentland
@ 2016-02-11 20:19   ` Rob Clark
  2016-02-11 20:52     ` Daniel Vetter
  2016-02-17  3:23     ` Harry Wentland
  0 siblings, 2 replies; 87+ messages in thread
From: Rob Clark @ 2016-02-11 20:19 UTC (permalink / raw)
  To: Harry Wentland; +Cc: dri-devel

On Thu, Feb 11, 2016 at 12:19 PM, Harry Wentland <harry.wentland@amd.com> wrote:
> Implements low-level communication layer over I2C and Aux lines using
> GPIO handles.

so without actually looking too closely at this rather large patch (in
a rather huge patchset)..  I do wonder, why not i2c_adapter?  Kernel
already has an implementation of that on top of gpio's..

BR,
-R

> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
> ---
>  drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |  33 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     | 567 ++++++++++++
>  drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     | 119 +++
>  .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   | 788 +++++++++++++++++
>  .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |  56 ++
>  .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |  25 +
>  .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    | 954 +++++++++++++++++++++
>  .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |  58 ++
>  .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    | 172 ++++
>  .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |  43 +
>  .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   | 266 ++++++
>  .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |  39 +
>  .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    | 112 +++
>  .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |  33 +
>  drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         | 129 +++
>  drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |  67 ++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     | 121 +++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     | 113 +++
>  .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  | 286 ++++++
>  .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |  77 ++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  | 246 ++++++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |  80 ++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  | 614 +++++++++++++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |  81 ++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         | 529 ++++++++++++
>  drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         | 123 +++
>  26 files changed, 5731 insertions(+)
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
>  create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (29 preceding siblings ...)
  2016-02-11 20:02 ` [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Mike Lothian
@ 2016-02-11 20:52 ` Dave Airlie
  2016-02-11 21:06   ` Daniel Vetter
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
  2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
  32 siblings, 1 reply; 87+ messages in thread
From: Dave Airlie @ 2016-02-11 20:52 UTC (permalink / raw)
  To: Harry Wentland; +Cc: dri-devel

On 12 February 2016 at 03:19, Harry Wentland <harry.wentland@amd.com> wrote:
> This set of patches enables the new DAL display driver for amdgpu on Carrizo
> Tonga, and Fiji ASICs. This driver will allow us going forward to bring
> display features on the open amdgpu driver (mostly) on par with the Catalyst
> driver.
>
> This driver adds support for
> - Atomic KMS API
> - MST
> - HDMI 2.0
> - Better powerplay integration
> - Support of HW bandwidth formula on Carrizo
> - Better multi-display support and handling of co-functionality
> - Broader support of display dongles
> - Timing synchronization between DP and HDMI
>
> This patch series is based on Alex Deucher's drm-next-4.6-wip tree.
>
So the first minor criticism is this patch doesn't explain WHY.

Why does the Linux kernel need 93k lines of code to run the displays
when whole drivers don't even come close.

We've spent a lot of time ripping abstraction layers out of drivers (exynos
being the major one), what benefits does this major change bring to the
Linux kernel and the AMDGPU driver over and above a leaner, more focused
work.

If were even to consider merging this it would be at a guess considered
staging level material which would require a TODO list of major cleanups.

I do realise you've put a lot of work into this, but I think you are going to
get a lot of review pushback in the next few days and without knowing the
reasons this path was chosen it is going to be hard to take.

Dave.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 08/29] drm/amd/dal: I2C Aux Manager
  2016-02-11 20:19   ` Rob Clark
@ 2016-02-11 20:52     ` Daniel Vetter
  2016-02-17  3:23     ` Harry Wentland
  1 sibling, 0 replies; 87+ messages in thread
From: Daniel Vetter @ 2016-02-11 20:52 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel

On Thu, Feb 11, 2016 at 9:19 PM, Rob Clark <robdclark@gmail.com> wrote:
> On Thu, Feb 11, 2016 at 12:19 PM, Harry Wentland <harry.wentland@amd.com> wrote:
>> Implements low-level communication layer over I2C and Aux lines using
>> GPIO handles.
>
> so without actually looking too closely at this rather large patch (in
> a rather huge patchset)..  I do wonder, why not i2c_adapter?  Kernel
> already has an implementation of that on top of gpio's..

Later down there also seems to be a reinvention of i2c over dp aux or
something similar ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set
  2016-02-11 17:20 ` [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set Harry Wentland
@ 2016-02-11 21:00   ` Oded Gabbay
  2016-02-16 16:46     ` Harry Wentland
  0 siblings, 1 reply; 87+ messages in thread
From: Oded Gabbay @ 2016-02-11 21:00 UTC (permalink / raw)
  To: Harry Wentland; +Cc: Maling list - DRI developers

On Thu, Feb 11, 2016 at 7:20 PM, Harry Wentland <harry.wentland@amd.com> wrote:
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> Reviewed-by: Mykola Lysenko <mykola.lysenko@amd.com>
> ---
>  drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
> index 1cc9fd1054ab..da6c0116aa1a 100644
> --- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
> +++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
> @@ -366,16 +366,16 @@ static bool fill_rects_from_plane_state(
>         surface->clip_rect = surface->dst_rect;
>
>         switch (state->rotation) {
> -       case DRM_ROTATE_0:
> +       case BIT(DRM_ROTATE_0):
>                 surface->rotation = ROTATION_ANGLE_0;
>                 break;
> -       case DRM_ROTATE_90:
> +       case BIT(DRM_ROTATE_90):
>                 surface->rotation = ROTATION_ANGLE_90;
>                 break;
> -       case DRM_ROTATE_180:
> +       case BIT(DRM_ROTATE_180):
>                 surface->rotation = ROTATION_ANGLE_180;
>                 break;
> -       case DRM_ROTATE_270:
> +       case BIT(DRM_ROTATE_270):
>                 surface->rotation = ROTATION_ANGLE_270;
>                 break;
>         default:
> --
> 2.1.4
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

One minor suggestion for the V2 of this patch-set, please squash
patches 27-29 into the previous patches (relevant to the code they
change). No point in reviewing code of earlier patches that is later
going to be changed by a patch in the same patch-set.

Thanks,

     Oded
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-11 20:52 ` Dave Airlie
@ 2016-02-11 21:06   ` Daniel Vetter
  2016-02-12  0:57     ` Dave Airlie
  2016-02-12  5:34     ` Daniel Vetter
  0 siblings, 2 replies; 87+ messages in thread
From: Daniel Vetter @ 2016-02-11 21:06 UTC (permalink / raw)
  To: Dave Airlie; +Cc: dri-devel

On Thu, Feb 11, 2016 at 9:52 PM, Dave Airlie <airlied@gmail.com> wrote:
> On 12 February 2016 at 03:19, Harry Wentland <harry.wentland@amd.com> wrote:
>> This set of patches enables the new DAL display driver for amdgpu on Carrizo
>> Tonga, and Fiji ASICs. This driver will allow us going forward to bring
>> display features on the open amdgpu driver (mostly) on par with the Catalyst
>> driver.
>>
>> This driver adds support for
>> - Atomic KMS API
>> - MST
>> - HDMI 2.0
>> - Better powerplay integration
>> - Support of HW bandwidth formula on Carrizo
>> - Better multi-display support and handling of co-functionality
>> - Broader support of display dongles
>> - Timing synchronization between DP and HDMI
>>
>> This patch series is based on Alex Deucher's drm-next-4.6-wip tree.
>>
> So the first minor criticism is this patch doesn't explain WHY.
>
> Why does the Linux kernel need 93k lines of code to run the displays
> when whole drivers don't even come close.
>
> We've spent a lot of time ripping abstraction layers out of drivers (exynos
> being the major one), what benefits does this major change bring to the
> Linux kernel and the AMDGPU driver over and above a leaner, more focused
> work.
>
> If were even to consider merging this it would be at a guess considered
> staging level material which would require a TODO list of major cleanups.
>
> I do realise you've put a lot of work into this, but I think you are going to
> get a lot of review pushback in the next few days and without knowing the
> reasons this path was chosen it is going to be hard to take.

Yeah agreed, we need to figure out the why/how first. Assembling a
de-staging TODO is imo a second step. And the problem with that is
that before we can do a full TODO we need to remove all the os and drm
abstractions. I found delayed_work, timer, memory handling, pixel
formats (in multiple copies), the i2c stuff Rob noticed and there's
more I'm sure. With all that I just can't even see how the main DAL
structures connect and how that would sensibly map to drm concepts.
Which is most likely needed to make DAL properly atomic.

So de-staging DAL (if we decided this is the right approach) would be
multi-stage, with removal of the abstractions not needed first, then
taking a 2nd look and figuring out how to untangle the actual
concepts.

Aside: If all this abstraction is to make dal run in userspace for
testing or whatever - nouveau does this, we (Intel) want to do this
too for unit-testing, so there's definitely room for sharing the
tools. But the right approach imo is to just implement kernel services
(like timers) in userspace.

Another thing is that some of the features in here (hdmi 2.0, improved
dongle support) really should be in shared helpers. If we have that
hidden behind the dal abstraction it'll be pretty much impossible
(with major work, which is unreasonable to ask of other people trying
to get their own driver in) to extract&share it. And for sink handling
having multiple copies of the same code just doesn't make sense.

Anyway that's my quick thoughts from 2h of reading this. One wishlist:
Some design overview or diagram how dal structures connect would be
awesome as a reading aid.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 06/29] drm/amd/dal: Adapter Service
  2016-02-11 17:19 ` [PATCH 06/29] drm/amd/dal: Adapter Service Harry Wentland
@ 2016-02-12  0:26   ` Dave Airlie
  2016-02-12 14:30     ` Wentland, Harry
  0 siblings, 1 reply; 87+ messages in thread
From: Dave Airlie @ 2016-02-12  0:26 UTC (permalink / raw)
  To: Harry Wentland; +Cc: dri-devel

> +
> +/* Stores entire ASIC features by sets */
> +uint32_t adapter_feature_set[FEATURE_MAXIMUM/32];

Is this global, what about multiple GPUs in one machine,
is this per GPU or per system?

Dave.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-11 21:06   ` Daniel Vetter
@ 2016-02-12  0:57     ` Dave Airlie
  2016-02-12  5:34     ` Daniel Vetter
  1 sibling, 0 replies; 87+ messages in thread
From: Dave Airlie @ 2016-02-12  0:57 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: dri-devel

On 12 February 2016 at 07:06, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Thu, Feb 11, 2016 at 9:52 PM, Dave Airlie <airlied@gmail.com> wrote:
>> On 12 February 2016 at 03:19, Harry Wentland <harry.wentland@amd.com> wrote:
>>> This set of patches enables the new DAL display driver for amdgpu on Carrizo
>>> Tonga, and Fiji ASICs. This driver will allow us going forward to bring
>>> display features on the open amdgpu driver (mostly) on par with the Catalyst
>>> driver.
>>>
>>> This driver adds support for
>>> - Atomic KMS API
>>> - MST
>>> - HDMI 2.0
>>> - Better powerplay integration
>>> - Support of HW bandwidth formula on Carrizo
>>> - Better multi-display support and handling of co-functionality
>>> - Broader support of display dongles
>>> - Timing synchronization between DP and HDMI
>>>
>>> This patch series is based on Alex Deucher's drm-next-4.6-wip tree.
>>>
>> So the first minor criticism is this patch doesn't explain WHY.
>>
>> Why does the Linux kernel need 93k lines of code to run the displays
>> when whole drivers don't even come close.
>>
>> We've spent a lot of time ripping abstraction layers out of drivers (exynos
>> being the major one), what benefits does this major change bring to the
>> Linux kernel and the AMDGPU driver over and above a leaner, more focused
>> work.
>>
>> If were even to consider merging this it would be at a guess considered
>> staging level material which would require a TODO list of major cleanups.
>>
>> I do realise you've put a lot of work into this, but I think you are going to
>> get a lot of review pushback in the next few days and without knowing the
>> reasons this path was chosen it is going to be hard to take.
>
> Yeah agreed, we need to figure out the why/how first. Assembling a
> de-staging TODO is imo a second step. And the problem with that is
> that before we can do a full TODO we need to remove all the os and drm
> abstractions. I found delayed_work, timer, memory handling, pixel
> formats (in multiple copies), the i2c stuff Rob noticed and there's
> more I'm sure. With all that I just can't even see how the main DAL
> structures connect and how that would sensibly map to drm concepts.
> Which is most likely needed to make DAL properly atomic.
>
> So de-staging DAL (if we decided this is the right approach) would be
> multi-stage, with removal of the abstractions not needed first, then
> taking a 2nd look and figuring out how to untangle the actual
> concepts.
>
> Aside: If all this abstraction is to make dal run in userspace for
> testing or whatever - nouveau does this, we (Intel) want to do this
> too for unit-testing, so there's definitely room for sharing the
> tools. But the right approach imo is to just implement kernel services
> (like timers) in userspace.
>
> Another thing is that some of the features in here (hdmi 2.0, improved
> dongle support) really should be in shared helpers. If we have that
> hidden behind the dal abstraction it'll be pretty much impossible
> (with major work, which is unreasonable to ask of other people trying
> to get their own driver in) to extract&share it. And for sink handling
> having multiple copies of the same code just doesn't make sense.
>
> Anyway that's my quick thoughts from 2h of reading this. One wishlist:
> Some design overview or diagram how dal structures connect would be
> awesome as a reading aid.

Yes some overview of what the abstractions are and why they exist,

Follow things down the layers really makes for hard work, and in a lot of
places for not much benefit.

Dave.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-11 21:06   ` Daniel Vetter
  2016-02-12  0:57     ` Dave Airlie
@ 2016-02-12  5:34     ` Daniel Vetter
  2016-02-13  0:05       ` Wentland, Harry
  1 sibling, 1 reply; 87+ messages in thread
From: Daniel Vetter @ 2016-02-12  5:34 UTC (permalink / raw)
  To: Dave Airlie; +Cc: dri-devel

On Thu, Feb 11, 2016 at 10:06:14PM +0100, Daniel Vetter wrote:
> On Thu, Feb 11, 2016 at 9:52 PM, Dave Airlie <airlied@gmail.com> wrote:
> > On 12 February 2016 at 03:19, Harry Wentland <harry.wentland@amd.com> wrote:
> >> This set of patches enables the new DAL display driver for amdgpu on Carrizo
> >> Tonga, and Fiji ASICs. This driver will allow us going forward to bring
> >> display features on the open amdgpu driver (mostly) on par with the Catalyst
> >> driver.
> >>
> >> This driver adds support for
> >> - Atomic KMS API
> >> - MST
> >> - HDMI 2.0
> >> - Better powerplay integration
> >> - Support of HW bandwidth formula on Carrizo
> >> - Better multi-display support and handling of co-functionality
> >> - Broader support of display dongles
> >> - Timing synchronization between DP and HDMI
> >>
> >> This patch series is based on Alex Deucher's drm-next-4.6-wip tree.
> >>
> > So the first minor criticism is this patch doesn't explain WHY.
> >
> > Why does the Linux kernel need 93k lines of code to run the displays
> > when whole drivers don't even come close.
> >
> > We've spent a lot of time ripping abstraction layers out of drivers (exynos
> > being the major one), what benefits does this major change bring to the
> > Linux kernel and the AMDGPU driver over and above a leaner, more focused
> > work.
> >
> > If were even to consider merging this it would be at a guess considered
> > staging level material which would require a TODO list of major cleanups.
> >
> > I do realise you've put a lot of work into this, but I think you are going to
> > get a lot of review pushback in the next few days and without knowing the
> > reasons this path was chosen it is going to be hard to take.
> 
> Yeah agreed, we need to figure out the why/how first. Assembling a
> de-staging TODO is imo a second step. And the problem with that is
> that before we can do a full TODO we need to remove all the os and drm
> abstractions. I found delayed_work, timer, memory handling, pixel
> formats (in multiple copies), the i2c stuff Rob noticed and there's
> more I'm sure. With all that I just can't even see how the main DAL
> structures connect and how that would sensibly map to drm concepts.
> Which is most likely needed to make DAL properly atomic.

More stuff plain duplicated I spotted:
- some edid handling (probably because of the duplicated i2c, but probably
  also because dal).
- has it's own infoframe encoding it seems
- home-grown logging. Yes, DRM_DEBUG isn't the most awesome, but dynamic
  prinkt is pretty neat from what I understand and we should just move
  DRM_DEBUG over to that if you need more flexibility.

Cheers, Daniel

> So de-staging DAL (if we decided this is the right approach) would be
> multi-stage, with removal of the abstractions not needed first, then
> taking a 2nd look and figuring out how to untangle the actual
> concepts.
> 
> Aside: If all this abstraction is to make dal run in userspace for
> testing or whatever - nouveau does this, we (Intel) want to do this
> too for unit-testing, so there's definitely room for sharing the
> tools. But the right approach imo is to just implement kernel services
> (like timers) in userspace.
> 
> Another thing is that some of the features in here (hdmi 2.0, improved
> dongle support) really should be in shared helpers. If we have that
> hidden behind the dal abstraction it'll be pretty much impossible
> (with major work, which is unreasonable to ask of other people trying
> to get their own driver in) to extract&share it. And for sink handling
> having multiple copies of the same code just doesn't make sense.
> 
> Anyway that's my quick thoughts from 2h of reading this. One wishlist:
> Some design overview or diagram how dal structures connect would be
> awesome as a reading aid.
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* RE: [PATCH 06/29] drm/amd/dal: Adapter Service
  2016-02-12  0:26   ` Dave Airlie
@ 2016-02-12 14:30     ` Wentland, Harry
  0 siblings, 0 replies; 87+ messages in thread
From: Wentland, Harry @ 2016-02-12 14:30 UTC (permalink / raw)
  To: Dave Airlie, Deucher, Alexander; +Cc: dri-devel

Hi Dave,

There should be one instance of amdgpu per GPU, so one instance of DAL per GPU, hence this should be per GPU.

We haven't really done any multi-GPU testing with this code, though, but I briefly tried and can light up with two displays connected to a Tonga and Bonaire (Bonaire is supported on our internal tree but hasn't been merged into these patches yet).

Harry

-----Original Message-----
From: Dave Airlie [mailto:airlied@gmail.com] 
Sent: February 11, 2016 7:26 PM
To: Wentland, Harry <Harry.Wentland@amd.com>
Cc: dri-devel <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 06/29] drm/amd/dal: Adapter Service

> +
> +/* Stores entire ASIC features by sets */ uint32_t 
> +adapter_feature_set[FEATURE_MAXIMUM/32];

Is this global, what about multiple GPUs in one machine, is this per GPU or per system?

Dave.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-12  5:34     ` Daniel Vetter
@ 2016-02-13  0:05       ` Wentland, Harry
  2016-02-14 11:22         ` Jerome Glisse
                           ` (3 more replies)
  0 siblings, 4 replies; 87+ messages in thread
From: Wentland, Harry @ 2016-02-13  0:05 UTC (permalink / raw)
  To: Daniel Vetter, Dave Airlie
  Cc: Deucher, Alexander, Cheng, Tony, Lysenko, Mykola, dri-devel

[-- Attachment #1: Type: text/plain, Size: 7207 bytes --]

Hi Dave, Daniel, others,

The goal with DAL is to provide a unified, full featured display stack to service all of our Linux offerings. This driver will have to support our full feature set beyond what's supported by amdgpu, e.g.
  - synchronzied timings across different displays
  - freesync
  - solid support of 6 displays in any configuration (HDMI, DVI, DP, DP MST, etc)
  - solid support of 4k@60 timings on APUs
  - power features, such as
    - clock-accurate bandwidth formulas
    - improved interaction with powerplay to maximize power savings
- Improved audio and other infoframe related features
- Improved stability with powerplay since display hw is involved in the SMC hw interactions and improper programming sequences can lead to GPU hangs, etc.

The current amdgpu display stack grew somewhat organically and as such is not well suited to handling all of the hardware dependencies involved especially in areas like audio.  The drm abstractions used by the old code map less and less well to new hw pipelines.  Atomic helps, but if we are going to convert, it seemed like a good time to start fresh.

Our DC (Display Core in dc.h, etc.) is the framework to allow us to well represent current and future HW architectures. These don't always map one-to-one to DRM interfaces. For one we can't make the assumption that surfaces map one-to-one to pipes. 

The DAL internal abstractions were used since they match the abstractions used by our drivers for other OSes, pre and post silicon validation tools and HW team programming models. Keeping it as close to that as possible makes it easier to debug and validate and provides the most likely change of success in complex display configurations.

Please see the attached DC.png for an overview of the DAL design. 

For an atomic sequence you might want to look at
- enable/disable displays or change display config -> dc_commit_targets
    (in dc/core/dc.c, called from amdgpu_dm_atomic_commit in amdgpu_dm/amdgpu_dm_types.c)

- commit planes                                    -> dc_commit_surfaces_to_targets
    (in dc/core/dc_target.c, called from dm_dc_surface_commit in amdgpu_dm/amdgpu_dm_types.c)

- validate                                         -> dc_validate_resources
    (in dc/core/dc.c, called from amdgpu_dm_atomic_check in amdgpu_dm/amdgpu_dm_types.c)


There's still a bunch of legacy stuff in these patches that's on our list of things to refactor. Some of that is 
- dc/adapter
- dc/asic_capability
- dc/audio
- dc/bios
- dc/gpio

We should be able to cut the size of this code to about 1/3 of what it is now.

As for the LOC we have about
22k for HW programming
30k legacy stuff
6k  dc/calcs - autogenerated from formulas provided by HW team
15k includes
6k  amdgpu_dm
8k  dc/core

About 14k of those are blank lines (we have a habit of leaving lots of blank space) and 16k are comments.

Cheers,
Harry

________________________________________
From: Daniel Vetter <daniel.vetter@ffwll.ch> on behalf of Daniel Vetter <daniel@ffwll.ch>
Sent: Friday, February 12, 2016 12:34 AM
To: Dave Airlie
Cc: Wentland, Harry; dri-devel
Subject: Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga

On Thu, Feb 11, 2016 at 10:06:14PM +0100, Daniel Vetter wrote:
> On Thu, Feb 11, 2016 at 9:52 PM, Dave Airlie <airlied@gmail.com> wrote:
> > On 12 February 2016 at 03:19, Harry Wentland <harry.wentland@amd.com> wrote:
> >> This set of patches enables the new DAL display driver for amdgpu on Carrizo
> >> Tonga, and Fiji ASICs. This driver will allow us going forward to bring
> >> display features on the open amdgpu driver (mostly) on par with the Catalyst
> >> driver.
> >>
> >> This driver adds support for
> >> - Atomic KMS API
> >> - MST
> >> - HDMI 2.0
> >> - Better powerplay integration
> >> - Support of HW bandwidth formula on Carrizo
> >> - Better multi-display support and handling of co-functionality
> >> - Broader support of display dongles
> >> - Timing synchronization between DP and HDMI
> >>
> >> This patch series is based on Alex Deucher's drm-next-4.6-wip tree.
> >>
> > So the first minor criticism is this patch doesn't explain WHY.
> >
> > Why does the Linux kernel need 93k lines of code to run the displays
> > when whole drivers don't even come close.
> >
> > We've spent a lot of time ripping abstraction layers out of drivers (exynos
> > being the major one), what benefits does this major change bring to the
> > Linux kernel and the AMDGPU driver over and above a leaner, more focused
> > work.
> >
> > If were even to consider merging this it would be at a guess considered
> > staging level material which would require a TODO list of major cleanups.
> >
> > I do realise you've put a lot of work into this, but I think you are going to
> > get a lot of review pushback in the next few days and without knowing the
> > reasons this path was chosen it is going to be hard to take.
>
> Yeah agreed, we need to figure out the why/how first. Assembling a
> de-staging TODO is imo a second step. And the problem with that is
> that before we can do a full TODO we need to remove all the os and drm
> abstractions. I found delayed_work, timer, memory handling, pixel
> formats (in multiple copies), the i2c stuff Rob noticed and there's
> more I'm sure. With all that I just can't even see how the main DAL
> structures connect and how that would sensibly map to drm concepts.
> Which is most likely needed to make DAL properly atomic.

More stuff plain duplicated I spotted:
- some edid handling (probably because of the duplicated i2c, but probably
  also because dal).
- has it's own infoframe encoding it seems
- home-grown logging. Yes, DRM_DEBUG isn't the most awesome, but dynamic
  prinkt is pretty neat from what I understand and we should just move
  DRM_DEBUG over to that if you need more flexibility.

Cheers, Daniel

> So de-staging DAL (if we decided this is the right approach) would be
> multi-stage, with removal of the abstractions not needed first, then
> taking a 2nd look and figuring out how to untangle the actual
> concepts.
>
> Aside: If all this abstraction is to make dal run in userspace for
> testing or whatever - nouveau does this, we (Intel) want to do this
> too for unit-testing, so there's definitely room for sharing the
> tools. But the right approach imo is to just implement kernel services
> (like timers) in userspace.
>
> Another thing is that some of the features in here (hdmi 2.0, improved
> dongle support) really should be in shared helpers. If we have that
> hidden behind the dal abstraction it'll be pretty much impossible
> (with major work, which is unreasonable to ask of other people trying
> to get their own driver in) to extract&share it. And for sink handling
> having multiple copies of the same code just doesn't make sense.
>
> Anyway that's my quick thoughts from 2h of reading this. One wishlist:
> Some design overview or diagram how dal structures connect would be
> awesome as a reading aid.
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

[-- Attachment #2: DC.png --]
[-- Type: image/png, Size: 169043 bytes --]

[-- Attachment #3: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-13  0:05       ` Wentland, Harry
@ 2016-02-14 11:22         ` Jerome Glisse
  2016-02-14 13:23           ` Daniel Vetter
  2016-02-17  3:28           ` Harry Wentland
  2016-02-14 13:32         ` Rob Clark
                           ` (2 subsequent siblings)
  3 siblings, 2 replies; 87+ messages in thread
From: Jerome Glisse @ 2016-02-14 11:22 UTC (permalink / raw)
  To: Wentland, Harry
  Cc: dri-devel, Deucher, Alexander, Cheng, Tony, Lysenko, Mykola

On Sat, Feb 13, 2016 at 12:05:48AM +0000, Wentland, Harry wrote:
> Hi Dave, Daniel, others,

[...]

> There's still a bunch of legacy stuff in these patches that's on our list of things to refactor. Some of that is 
> - dc/adapter
> - dc/asic_capability
> - dc/audio
> - dc/bios
> - dc/gpio
> 
> We should be able to cut the size of this code to about 1/3 of what it is now.
> 
> As for the LOC we have about
> 22k for HW programming
> 30k legacy stuff
> 6k  dc/calcs - autogenerated from formulas provided by HW team
> 15k includes
> 6k  amdgpu_dm
> 8k  dc/core
> 
> About 14k of those are blank lines (we have a habit of leaving lots of blank space) and 16k are comments.

Cleaning up that is not enough, abstracting kernel API like kmalloc or i2c,
or similar, is a no go. If the current drm infrastructure does not suit your
need then you need to work on improving it to suit your need. You can not
redevelop a whole drm layer inside your code and expect to upstream it.

Linux device driver are about sharing infrastructure and trying to expose
it through common API to userspace.

So i strongly suggest that you start thinking on how to change the drm API
to suit your need and to start discussions about those changes. If you need
them then they will likely be usefull to others down the road.

Cheers,
Jérôme
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-14 11:22         ` Jerome Glisse
@ 2016-02-14 13:23           ` Daniel Vetter
  2016-02-17  3:28           ` Harry Wentland
  1 sibling, 0 replies; 87+ messages in thread
From: Daniel Vetter @ 2016-02-14 13:23 UTC (permalink / raw)
  To: Jerome Glisse; +Cc: Cheng, Tony, dri-devel, Deucher, Alexander, Lysenko, Mykola

On Sun, Feb 14, 2016 at 12:22 PM, Jerome Glisse <j.glisse@gmail.com> wrote:
>> There's still a bunch of legacy stuff in these patches that's on our list of things to refactor. Some of that is
>> - dc/adapter
>> - dc/asic_capability
>> - dc/audio
>> - dc/bios
>> - dc/gpio
>>
>> We should be able to cut the size of this code to about 1/3 of what it is now.
>>
>> As for the LOC we have about
>> 22k for HW programming
>> 30k legacy stuff
>> 6k  dc/calcs - autogenerated from formulas provided by HW team
>> 15k includes
>> 6k  amdgpu_dm
>> 8k  dc/core
>>
>> About 14k of those are blank lines (we have a habit of leaving lots of blank space) and 16k are comments.
>
> Cleaning up that is not enough, abstracting kernel API like kmalloc or i2c,
> or similar, is a no go. If the current drm infrastructure does not suit your
> need then you need to work on improving it to suit your need. You can not
> redevelop a whole drm layer inside your code and expect to upstream it.
>
> Linux device driver are about sharing infrastructure and trying to expose
> it through common API to userspace.
>
> So i strongly suggest that you start thinking on how to change the drm API
> to suit your need and to start discussions about those changes. If you need
> them then they will likely be usefull to others down the road.

A bit more context on why OS abstractions layers like dal here are
massive frowned upon:

First reason is that it makes live painful for everyone who tries to
refactor across the entire subsystem (which I do a lot, so that's what
I care about). For that you need to be able to understand every driver
fairly quickly, and that's only possible if all drivers use the same
concepts. Which means no abstraction layer, but directly
using&extending core drm constructs like
drm_framebuffer/crtc/encoder/bridge/connector/display_information.
Even if your dal concepts match 1:1 with those, if the link is only at
runtime or through pointers instead of through subclassing everything
becomes much more painful to understand. Note that this isn't a reason
against hw/driver specific additional concepts (all big drivers have
those), but against undue amounts of insolation between drm concepts
and driver concepts.

The other bit is the so-called midlayer design mistake,
https://lwn.net/Articles/336262/ which states that wedging an entire
such abstraction layer will also inevitably lead to bad design overall
(neglecting the practical troubles is causes for everyone else). DRM
suffered badly from the midlayer of old days due to compat with *bsd
in the core, which took years to fix up (and is still not completely
done). And we only ever merged 2 drivers who had midlayers like dal,
and both had special reasons:

- exynos was one of the very first armsoc kms drivers, and merged
pretty much for goodwill. Google was eventually fed up with the
midlayer in upstream and paid Collabora to nuke it.

- omapdrm reused the display support code already merged into upstream
in the fbdev subsytem, and that's why it had a midlayer. But Tomi is
now also in the process of removing this.

So even if all the cleanup is done (removal of duplicated code and the
OS abstraction layers) there's some really big reservations against
DAL as a concept itself. That was essentially what's Dave "why do we
need this" was all about. And to answer that you need in my opinion
better reasons "shared abstraction with $otheros/thing/whatever",
since if that's the only reason you argue against 20+ years of shared
experience in linux device driver development that this is a very bad
one.

Note again that this isn't against introducing additional
amd-speicific display concepts in the amd driver, or existing
concepts. Every driver does that. This is just against putting an
entire abstraction layer in-between drm core and your real display
driver.

The other big issue is that upstream really puts a lot of weight onto
continuity - no forking or wholesale rewrites every 1-2 years, instead
gradual change of what's already there. And I suspect the amount of
effort to get dal into a reasonable shape is on par with just adding
the new features you want to amdgpu directly one-by-one. Starting out
with amdgpu also has the added benefit that there's lots of howtos
and experience with converting an existing kms driver to atomic. We
don't really have that for DAL->atomic, and from reading through the
code I couldn't convince myself that the current code is really
atomic. Largely that's due to not using drm core concepts and
structures, but remapping things.

Anyway, I figured I type in a few more words to explain some of the
reasons behind the resistance to massive abstraction layers in kernel
device drivers.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-13  0:05       ` Wentland, Harry
  2016-02-14 11:22         ` Jerome Glisse
@ 2016-02-14 13:32         ` Rob Clark
  2016-02-14 13:51           ` Daniel Vetter
  2016-02-17  3:26           ` Harry Wentland
  2016-02-14 14:01         ` Daniel Vetter
  2016-02-14 21:44         ` Daniel Stone
  3 siblings, 2 replies; 87+ messages in thread
From: Rob Clark @ 2016-02-14 13:32 UTC (permalink / raw)
  To: Wentland, Harry
  Cc: dri-devel, Deucher, Alexander, Cheng, Tony, Lysenko, Mykola

On Fri, Feb 12, 2016 at 7:05 PM, Wentland, Harry <Harry.Wentland@amd.com> wrote:
>
> The current amdgpu display stack grew somewhat organically and as such is not well suited to handling all of the hardware dependencies involved especially in areas like audio.  The drm abstractions used by the old code map less and less well to new hw pipelines.  Atomic helps, but if we are going to convert, it seemed like a good time to start fresh.
>
> Our DC (Display Core in dc.h, etc.) is the framework to allow us to well represent current and future HW architectures. These don't always map one-to-one to DRM interfaces. For one we can't make the assumption that surfaces map one-to-one to pipes.

So, this sounds a bit vaguely like some things that I have discussed
from drm/msm.. where you might end up using multiple planes to scan
out a single surface, or multiplex a single plane between multiple
surfaces (or combinations thereof)..

I think what we'll end up doing is virtualizing planes so we advertise
to userspace more planes than actually exist, and at atomic update
time, dynamically assign pipes to planes, and reject things if
userspace asks for too many planes..  although this is getting into an
area where it helps to assume that there is a userspace component
which is familiar with your hw, which is true for android (and I think
some day wayland compositors will have to grow similar capability for
driver specific userspace plugin to make decisions about how to assign
planes).

Not sure if a similar approach would help you to fit better into the
kms/atomic framework?

BR,
-R
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-14 13:32         ` Rob Clark
@ 2016-02-14 13:51           ` Daniel Vetter
  2016-02-17  3:26           ` Harry Wentland
  1 sibling, 0 replies; 87+ messages in thread
From: Daniel Vetter @ 2016-02-14 13:51 UTC (permalink / raw)
  To: Rob Clark; +Cc: Cheng, Tony, dri-devel, Deucher, Alexander, Lysenko, Mykola

On Sun, Feb 14, 2016 at 2:32 PM, Rob Clark <robdclark@gmail.com> wrote:
> On Fri, Feb 12, 2016 at 7:05 PM, Wentland, Harry <Harry.Wentland@amd.com> wrote:
>> The current amdgpu display stack grew somewhat organically and as such is not well suited to handling all of the hardware dependencies involved especially in areas like audio.  The drm abstractions used by the old code map less and less well to new hw pipelines.  Atomic helps, but if we are going to convert, it seemed like a good time to start fresh.
>>
>> Our DC (Display Core in dc.h, etc.) is the framework to allow us to well represent current and future HW architectures. These don't always map one-to-one to DRM interfaces. For one we can't make the assumption that surfaces map one-to-one to pipes.
>
> So, this sounds a bit vaguely like some things that I have discussed
> from drm/msm.. where you might end up using multiple planes to scan
> out a single surface, or multiplex a single plane between multiple
> surfaces (or combinations thereof)..
>
> I think what we'll end up doing is virtualizing planes so we advertise
> to userspace more planes than actually exist, and at atomic update
> time, dynamically assign pipes to planes, and reject things if
> userspace asks for too many planes..  although this is getting into an
> area where it helps to assume that there is a userspace component
> which is familiar with your hw, which is true for android (and I think
> some day wayland compositors will have to grow similar capability for
> driver specific userspace plugin to make decisions about how to assign
> planes).
>
> Not sure if a similar approach would help you to fit better into the
> kms/atomic framework?

Hm, maybe I misread the code and the diagram, but to me it looked like
dc_surface == drm_plane. And you can already freely assign drm_planes
to display pipelines (represented by drm_crtc). That's btw also the
part where your atomic driver seems to seriously mismatch how drm
atomic is meant to be used, since you dig out the connector state when
commit plane states, which is a no-go.

dc_target otoh seems to not entirely match to drm_crtc, and contain
some of drm_display_info and drm_connector stuff too. At least from
cursory reading around in the code.

So not sure how this should all map, but like Rob said you can
internally virtualize stuff if really needed. But then you should
still pass around drm_plane_state in your low-level hw commit
functions and not dal-private structures to avoid the midlayer issues.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-13  0:05       ` Wentland, Harry
  2016-02-14 11:22         ` Jerome Glisse
  2016-02-14 13:32         ` Rob Clark
@ 2016-02-14 14:01         ` Daniel Vetter
  2016-02-17  3:32           ` Harry Wentland
  2016-02-14 21:44         ` Daniel Stone
  3 siblings, 1 reply; 87+ messages in thread
From: Daniel Vetter @ 2016-02-14 14:01 UTC (permalink / raw)
  To: Wentland, Harry
  Cc: dri-devel, Deucher, Alexander, Cheng, Tony, Lysenko, Mykola

top-level post since I can't reply to the diagram directly. So from
very cursor reading-around in the code I think you have a few
mismatches in how you map drm concepts to dal structures:

- cursor is just a drm_plane - step 0 of atomic support is universale
plane support, and you didn't do that in this patch series. Same holds
for video overlay support (which seems implemented but not exposed).

- drm_plane should probably match to both surface + target structs,
since how a plane is composited in the screen rect is a plane state

- stream should probably map to crtc

- for cases where you need 2 streams for 1 crtc or 2 surfaces for 1
plane internally remap them with some aux pointer. But imo still base
them on drm core structures (since in most cases you can expose them
all). You probably need a full remapping table to make this work, but
the state itself should still all be in extensions of core drm_*_state
structs

- drm_encoder probably matches to dc_link, but not sure. drm_encoder
is mostly just a convenience thing really, you can ignore it

- dc_sink seems to be the drm_connector, or well mostly. Here it gets
really unclear due to the massive amount of private code for
screen/sink handling that dal has.

Cheers, Daniel


On Sat, Feb 13, 2016 at 1:05 AM, Wentland, Harry <Harry.Wentland@amd.com> wrote:
> Hi Dave, Daniel, others,
>
> The goal with DAL is to provide a unified, full featured display stack to service all of our Linux offerings. This driver will have to support our full feature set beyond what's supported by amdgpu, e.g.
>   - synchronzied timings across different displays
>   - freesync
>   - solid support of 6 displays in any configuration (HDMI, DVI, DP, DP MST, etc)
>   - solid support of 4k@60 timings on APUs
>   - power features, such as
>     - clock-accurate bandwidth formulas
>     - improved interaction with powerplay to maximize power savings
> - Improved audio and other infoframe related features
> - Improved stability with powerplay since display hw is involved in the SMC hw interactions and improper programming sequences can lead to GPU hangs, etc.
>
> The current amdgpu display stack grew somewhat organically and as such is not well suited to handling all of the hardware dependencies involved especially in areas like audio.  The drm abstractions used by the old code map less and less well to new hw pipelines.  Atomic helps, but if we are going to convert, it seemed like a good time to start fresh.
>
> Our DC (Display Core in dc.h, etc.) is the framework to allow us to well represent current and future HW architectures. These don't always map one-to-one to DRM interfaces. For one we can't make the assumption that surfaces map one-to-one to pipes.
>
> The DAL internal abstractions were used since they match the abstractions used by our drivers for other OSes, pre and post silicon validation tools and HW team programming models. Keeping it as close to that as possible makes it easier to debug and validate and provides the most likely change of success in complex display configurations.
>
> Please see the attached DC.png for an overview of the DAL design.
>
> For an atomic sequence you might want to look at
> - enable/disable displays or change display config -> dc_commit_targets
>     (in dc/core/dc.c, called from amdgpu_dm_atomic_commit in amdgpu_dm/amdgpu_dm_types.c)
>
> - commit planes                                    -> dc_commit_surfaces_to_targets
>     (in dc/core/dc_target.c, called from dm_dc_surface_commit in amdgpu_dm/amdgpu_dm_types.c)
>
> - validate                                         -> dc_validate_resources
>     (in dc/core/dc.c, called from amdgpu_dm_atomic_check in amdgpu_dm/amdgpu_dm_types.c)
>
>
> There's still a bunch of legacy stuff in these patches that's on our list of things to refactor. Some of that is
> - dc/adapter
> - dc/asic_capability
> - dc/audio
> - dc/bios
> - dc/gpio
>
> We should be able to cut the size of this code to about 1/3 of what it is now.
>
> As for the LOC we have about
> 22k for HW programming
> 30k legacy stuff
> 6k  dc/calcs - autogenerated from formulas provided by HW team
> 15k includes
> 6k  amdgpu_dm
> 8k  dc/core
>
> About 14k of those are blank lines (we have a habit of leaving lots of blank space) and 16k are comments.
>
> Cheers,
> Harry
>
> ________________________________________
> From: Daniel Vetter <daniel.vetter@ffwll.ch> on behalf of Daniel Vetter <daniel@ffwll.ch>
> Sent: Friday, February 12, 2016 12:34 AM
> To: Dave Airlie
> Cc: Wentland, Harry; dri-devel
> Subject: Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
>
> On Thu, Feb 11, 2016 at 10:06:14PM +0100, Daniel Vetter wrote:
>> On Thu, Feb 11, 2016 at 9:52 PM, Dave Airlie <airlied@gmail.com> wrote:
>> > On 12 February 2016 at 03:19, Harry Wentland <harry.wentland@amd.com> wrote:
>> >> This set of patches enables the new DAL display driver for amdgpu on Carrizo
>> >> Tonga, and Fiji ASICs. This driver will allow us going forward to bring
>> >> display features on the open amdgpu driver (mostly) on par with the Catalyst
>> >> driver.
>> >>
>> >> This driver adds support for
>> >> - Atomic KMS API
>> >> - MST
>> >> - HDMI 2.0
>> >> - Better powerplay integration
>> >> - Support of HW bandwidth formula on Carrizo
>> >> - Better multi-display support and handling of co-functionality
>> >> - Broader support of display dongles
>> >> - Timing synchronization between DP and HDMI
>> >>
>> >> This patch series is based on Alex Deucher's drm-next-4.6-wip tree.
>> >>
>> > So the first minor criticism is this patch doesn't explain WHY.
>> >
>> > Why does the Linux kernel need 93k lines of code to run the displays
>> > when whole drivers don't even come close.
>> >
>> > We've spent a lot of time ripping abstraction layers out of drivers (exynos
>> > being the major one), what benefits does this major change bring to the
>> > Linux kernel and the AMDGPU driver over and above a leaner, more focused
>> > work.
>> >
>> > If were even to consider merging this it would be at a guess considered
>> > staging level material which would require a TODO list of major cleanups.
>> >
>> > I do realise you've put a lot of work into this, but I think you are going to
>> > get a lot of review pushback in the next few days and without knowing the
>> > reasons this path was chosen it is going to be hard to take.
>>
>> Yeah agreed, we need to figure out the why/how first. Assembling a
>> de-staging TODO is imo a second step. And the problem with that is
>> that before we can do a full TODO we need to remove all the os and drm
>> abstractions. I found delayed_work, timer, memory handling, pixel
>> formats (in multiple copies), the i2c stuff Rob noticed and there's
>> more I'm sure. With all that I just can't even see how the main DAL
>> structures connect and how that would sensibly map to drm concepts.
>> Which is most likely needed to make DAL properly atomic.
>
> More stuff plain duplicated I spotted:
> - some edid handling (probably because of the duplicated i2c, but probably
>   also because dal).
> - has it's own infoframe encoding it seems
> - home-grown logging. Yes, DRM_DEBUG isn't the most awesome, but dynamic
>   prinkt is pretty neat from what I understand and we should just move
>   DRM_DEBUG over to that if you need more flexibility.
>
> Cheers, Daniel
>
>> So de-staging DAL (if we decided this is the right approach) would be
>> multi-stage, with removal of the abstractions not needed first, then
>> taking a 2nd look and figuring out how to untangle the actual
>> concepts.
>>
>> Aside: If all this abstraction is to make dal run in userspace for
>> testing or whatever - nouveau does this, we (Intel) want to do this
>> too for unit-testing, so there's definitely room for sharing the
>> tools. But the right approach imo is to just implement kernel services
>> (like timers) in userspace.
>>
>> Another thing is that some of the features in here (hdmi 2.0, improved
>> dongle support) really should be in shared helpers. If we have that
>> hidden behind the dal abstraction it'll be pretty much impossible
>> (with major work, which is unreasonable to ask of other people trying
>> to get their own driver in) to extract&share it. And for sink handling
>> having multiple copies of the same code just doesn't make sense.
>>
>> Anyway that's my quick thoughts from 2h of reading this. One wishlist:
>> Some design overview or diagram how dal structures connect would be
>> awesome as a reading aid.
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-13  0:05       ` Wentland, Harry
                           ` (2 preceding siblings ...)
  2016-02-14 14:01         ` Daniel Vetter
@ 2016-02-14 21:44         ` Daniel Stone
  3 siblings, 0 replies; 87+ messages in thread
From: Daniel Stone @ 2016-02-14 21:44 UTC (permalink / raw)
  To: Wentland, Harry
  Cc: dri-devel, Deucher, Alexander, Cheng, Tony, Lysenko, Mykola

Hi Harry,

On 13 February 2016 at 00:05, Wentland, Harry <Harry.Wentland@amd.com> wrote:
> The goal with DAL is to provide a unified, full featured display stack to service all of our Linux offerings. This driver will have to support our full feature set beyond what's supported by amdgpu, e.g.
>   - synchronzied timings across different displays
>   - freesync
>   - solid support of 6 displays in any configuration (HDMI, DVI, DP, DP MST, etc)
>   - solid support of 4k@60 timings on APUs

As a very high-level comment, my worry is that you feel like DRM
doesn't supoort this so are inventing it in the DAL. This is
understandable, but the problem is that DRM will come up with a
different interface for things like genlock or FreeSync; one that is
unlikely to match the abstraction in the DAL.

If there are areas you feel core DRM does not address but need to be
supported, please start by working in the core and building out from
there.

Cheers,
Daniel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set
  2016-02-11 21:00   ` Oded Gabbay
@ 2016-02-16 16:46     ` Harry Wentland
  0 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 16:46 UTC (permalink / raw)
  To: Oded Gabbay; +Cc: Maling list - DRI developers

For sure. Thanks, Oded.

I'll send out squashed patches later today.

Harry

On 2016-02-11 04:00 PM, Oded Gabbay wrote:
> On Thu, Feb 11, 2016 at 7:20 PM, Harry Wentland <harry.wentland@amd.com> wrote:
>> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
>> Reviewed-by: Mykola Lysenko <mykola.lysenko@amd.com>
>> ---
>>   drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c | 8 ++++----
>>   1 file changed, 4 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
>> index 1cc9fd1054ab..da6c0116aa1a 100644
>> --- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
>> +++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
>> @@ -366,16 +366,16 @@ static bool fill_rects_from_plane_state(
>>          surface->clip_rect = surface->dst_rect;
>>
>>          switch (state->rotation) {
>> -       case DRM_ROTATE_0:
>> +       case BIT(DRM_ROTATE_0):
>>                  surface->rotation = ROTATION_ANGLE_0;
>>                  break;
>> -       case DRM_ROTATE_90:
>> +       case BIT(DRM_ROTATE_90):
>>                  surface->rotation = ROTATION_ANGLE_90;
>>                  break;
>> -       case DRM_ROTATE_180:
>> +       case BIT(DRM_ROTATE_180):
>>                  surface->rotation = ROTATION_ANGLE_180;
>>                  break;
>> -       case DRM_ROTATE_270:
>> +       case BIT(DRM_ROTATE_270):
>>                  surface->rotation = ROTATION_ANGLE_270;
>>                  break;
>>          default:
>> --
>> 2.1.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
> One minor suggestion for the V2 of this patch-set, please squash
> patches 27-29 into the previous patches (relevant to the code they
> change). No point in reviewing code of earlier patches that is later
> going to be changed by a patch in the same patch-set.
>
> Thanks,
>
>       Oded

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH v2 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (30 preceding siblings ...)
  2016-02-11 20:52 ` Dave Airlie
@ 2016-02-16 22:27 ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 01/26] drm/amd/dal: Add dal headers Harry Wentland
                     ` (25 more replies)
  2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
  32 siblings, 26 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

v2 Update:
This is just a squash of the three small fixes into the main patches to
make for an easier read. No other changes yet.


This set of patches enables the new DAL display driver for amdgpu on Carrizo
Tonga, and Fiji ASICs. This driver will allow us going forward to bring
display features on the open amdgpu driver (mostly) on par with the Catalyst
driver.

This driver adds support for 
- Atomic KMS API
- MST
- HDMI 2.0
- Better powerplay integration
- Support of HW bandwidth formula on Carrizo
- Better multi-display support and handling of co-functionality
- Broader support of display dongles
- Timing synchronization between DP and HDMI

This patch series is based on Alex Deucher's drm-next-4.6-wip tree.


Harry Wentland (26):
  drm/amd/dal: Add dal headers
  drm/amd/dal: Add DAL Basic Types and Logger
  drm/amd/dal: Fixed point arithmetic
  drm/amd/dal: Asic Capabilities
  drm/amd/dal: GPIO (General Purpose IO)
  drm/amd/dal: Adapter Service
  drm/amd/dal: BIOS Parser
  drm/amd/dal: I2C Aux Manager
  drm/amd/dal: IRQ Service
  drm/amd/dal: GPU
  drm/amd/dal: Audio
  drm/amd/dal: Bandwidth calculations
  drm/amd/dal: Add encoder HW programming
  drm/amd/dal: Add clock source HW programming
  drm/amd/dal: Add timing generator HW programming
  drm/amd/dal: Add surface HW programming
  drm/amd/dal: Add framebuffer compression HW programming
  drm/amd/dal: Add input pixel processing HW programming
  drm/amd/dal: Add output pixel processing HW programming
  drm/amd/dal: Add transform & scaler HW programming
  drm/amd/dal: Add Carrizo HW sequencer and resource
  drm/amd/dal: Add Tonga/Fiji HW sequencer and resource
  drm/amd/dal: Add empty encoder programming for virtual HW
  drm/amd/dal: Add display core
  drm/amd/dal: Adding amdgpu_dm for dal
  drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji

 drivers/gpu/drm/amd/amdgpu/Kconfig                 |    3 +
 drivers/gpu/drm/amd/amdgpu/Makefile                |   17 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h                |   10 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         |   69 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c            |    4 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c             |    5 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c            |   20 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h           |   54 +-
 drivers/gpu/drm/amd/amdgpu/vi.c                    |  250 +
 drivers/gpu/drm/amd/dal/Kconfig                    |   48 +
 drivers/gpu/drm/amd/dal/Makefile                   |   21 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile         |   17 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c      | 1468 ++++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h      |  168 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c  |  474 ++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c  |  820 ++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h  |  122 +
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c    |  480 ++
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h    |   36 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c |  457 ++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c    | 2577 ++++++++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h    |  100 +
 drivers/gpu/drm/amd/dal/dal_services.h             |  266 ++
 drivers/gpu/drm/amd/dal/dal_services_types.h       |   62 +
 drivers/gpu/drm/amd/dal/dc/Makefile                |   28 +
 drivers/gpu/drm/amd/dal/dc/adapter/Makefile        |   24 +
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.c   | 2089 ++++++++
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.h   |   71 +
 .../adapter/dce110/hw_ctx_adapter_service_dce110.c |  304 ++
 .../adapter/dce110/hw_ctx_adapter_service_dce110.h |   40 +
 .../diagnostics/hw_ctx_adapter_service_diag.c      |  133 +
 .../diagnostics/hw_ctx_adapter_service_diag.h      |   33 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.c    |  164 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.h    |   86 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.c  |  208 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.h  |   80 +
 .../gpu/drm/amd/dal/dc/asic_capability/Makefile    |   35 +
 .../amd/dal/dc/asic_capability/asic_capability.c   |  190 +
 .../dc/asic_capability/carrizo_asic_capability.c   |  147 +
 .../dc/asic_capability/carrizo_asic_capability.h   |   36 +
 .../dal/dc/asic_capability/tonga_asic_capability.c |  146 +
 .../dal/dc/asic_capability/tonga_asic_capability.h |   36 +
 drivers/gpu/drm/amd/dal/dc/audio/Makefile          |   22 +
 drivers/gpu/drm/amd/dal/dc/audio/audio.h           |  195 +
 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c      |  470 ++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c |  453 ++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h |   42 +
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c  | 1930 ++++++++
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h  |   47 +
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c    |  771 +++
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h    |  285 ++
 drivers/gpu/drm/amd/dal/dc/basics/Makefile         |   10 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.c     |  224 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.h     |   49 +
 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c     |  692 +++
 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c     |  223 +
 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c |  134 +
 drivers/gpu/drm/amd/dal/dc/basics/logger.c         |  954 ++++
 drivers/gpu/drm/amd/dal/dc/basics/logger.h         |   64 +
 .../gpu/drm/amd/dal/dc/basics/register_logger.c    |  197 +
 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c   |  116 +
 drivers/gpu/drm/amd/dal/dc/basics/vector.c         |  309 ++
 drivers/gpu/drm/amd/dal/dc/bios/Makefile           |   26 +
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c      | 5029 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h      |   84 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c   |  198 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h   |  108 +
 drivers/gpu/drm/amd/dal/dc/bios/command_table.c    | 2730 +++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/command_table.h    |  117 +
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.c |  285 ++
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.h |   90 +
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.c |  484 ++
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.h |   34 +
 .../dc/bios/dce110/command_table_helper_dce110.c   |  366 ++
 .../dc/bios/dce110/command_table_helper_dce110.h   |   34 +
 drivers/gpu/drm/amd/dal/dc/calcs/Makefile          |   10 +
 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 3941 +++++++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c        |  300 ++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c   | 1992 ++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h   |   74 +
 drivers/gpu/drm/amd/dal/dc/core/dc.c               |  932 ++++
 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c  |   56 +
 drivers/gpu/drm/amd/dal/dc/core/dc_link.c          | 1644 +++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c      | 1151 +++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c       | 1728 +++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c     |  201 +
 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c      | 1243 +++++
 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c          |  116 +
 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c        |  188 +
 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c       |  123 +
 drivers/gpu/drm/amd/dal/dc/core/dc_target.c        |  548 +++
 drivers/gpu/drm/amd/dal/dc/dc.h                    |  462 ++
 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h         |  277 ++
 drivers/gpu/drm/amd/dal/dc/dc_types.h              |  936 ++++
 drivers/gpu/drm/amd/dal/dc/dce100/Makefile         |   23 +
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.c    |  360 ++
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.h    |   36 +
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c    | 1135 +++++
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.h    |   43 +
 drivers/gpu/drm/amd/dal/dc/dce110/Makefile         |   15 +
 .../drm/amd/dal/dc/dce110/dce110_clock_source.c    | 1162 +++++
 .../drm/amd/dal/dc/dce110/dce110_clock_source.h    |   64 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.c  |  886 ++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.h  |   84 +
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 1658 +++++++
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h    |   36 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c     |   65 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h     |  100 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c  |  256 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c   |  872 ++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.c    | 1927 ++++++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.h    |  156 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c   |  965 ++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h   |  117 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c     |  272 ++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h     |  143 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c |  904 ++++
 .../drm/amd/dal/dc/dce110/dce110_opp_formatter.c   |  610 +++
 .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2474 ++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c    | 1238 +++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.h    |   46 +
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.c  | 1123 +++++
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.h  |  122 +
 .../amd/dal/dc/dce110/dce110_timing_generator.c    | 1864 ++++++++
 .../amd/dal/dc/dce110/dce110_timing_generator.h    |  234 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c   |   91 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.h   |   87 +
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.c |  851 ++++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.h |   51 +
 .../drm/amd/dal/dc/dce110/dce110_transform_gamut.c |  296 ++
 .../drm/amd/dal/dc/dce110/dce110_transform_scl.c   |  818 ++++
 .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c  |  531 +++
 drivers/gpu/drm/amd/dal/dc/dm_helpers.h            |   98 +
 drivers/gpu/drm/amd/dal/dc/dm_services.h           |  468 ++
 drivers/gpu/drm/amd/dal/dc/dm_services_types.h     |  167 +
 drivers/gpu/drm/amd/dal/dc/gpio/Makefile           |   32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c |  882 ++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h |   46 +
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c |   81 +
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h |   32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c |  366 ++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h |   47 +
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.c   |  400 ++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.h   |   34 +
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c              |  290 ++
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h              |   45 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c  |   97 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h  |   34 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.c  |   65 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.h  |   32 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c  |  101 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h  |   35 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.c    |   41 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.h    |   34 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h             |   48 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c        |  279 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c     |  386 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h     |   57 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c           |  104 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h           |   60 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c       |   93 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h       |   71 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c          |  407 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h          |  129 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c      |   92 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h      |   47 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c      |   85 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h      |   79 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c           |   87 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h           |   45 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c     |   77 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h     |   50 +
 drivers/gpu/drm/amd/dal/dc/gpio/irq.c              |  180 +
 drivers/gpu/drm/amd/dal/dc/gpio/irq.h              |   42 +
 drivers/gpu/drm/amd/dal/dc/gpu/Makefile            |   22 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c    |   92 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h    |   63 +
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c |   90 +
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h |   33 +
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.c   |  968 ++++
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.h   |   53 +
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c     |  205 +
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h     |   82 +
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c     |  127 +
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h     |   63 +
 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |   33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     |  567 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     |  119 +
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   |  788 +++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |   56 +
 .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |   25 +
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    |  954 ++++
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |   58 +
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    |  172 +
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |   43 +
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   |  266 ++
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |   39 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    |  112 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |   33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         |  129 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |   67 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     |  121 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     |  113 +
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  |  286 ++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |   77 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  |  246 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |   80 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  |  614 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |   81 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         |  529 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         |  123 +
 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h   |  510 ++
 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h          |   64 +
 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h      |  176 +
 drivers/gpu/drm/amd/dal/dc/inc/compressor.h        |  140 +
 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h           |   54 +
 drivers/gpu/drm/amd/dal/dc/inc/core_status.h       |   46 +
 drivers/gpu/drm/amd/dal/dc/inc/core_types.h        |  357 ++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h       |  151 +
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h        |   56 +
 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h       |  118 +
 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h      |  126 +
 drivers/gpu/drm/amd/dal/dc/inc/ipp.h               |  106 +
 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h      |  138 +
 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h         |   68 +
 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h         |   83 +
 drivers/gpu/drm/amd/dal/dc/inc/opp.h               |  308 ++
 drivers/gpu/drm/amd/dal/dc/inc/resource.h          |   80 +
 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h    |   88 +
 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h  |  155 +
 drivers/gpu/drm/amd/dal/dc/inc/transform.h         |  217 +
 drivers/gpu/drm/amd/dal/dc/irq/Makefile            |   21 +
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.c |  389 ++
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.h |   34 +
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c       |  177 +
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h       |   85 +
 drivers/gpu/drm/amd/dal/dc/irq_types.h             |  199 +
 drivers/gpu/drm/amd/dal/dc/virtual/Makefile        |    9 +
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.c  |  133 +
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.h  |   35 +
 .../amd/dal/dc/virtual/virtual_stream_encoder.c    |  124 +
 .../amd/dal/dc/virtual/virtual_stream_encoder.h    |   39 +
 .../amd/dal/include/adapter_service_interface.h    |  632 +++
 .../drm/amd/dal/include/adapter_service_types.h    |   71 +
 .../amd/dal/include/asic_capability_interface.h    |   58 +
 .../drm/amd/dal/include/asic_capability_types.h    |  134 +
 drivers/gpu/drm/amd/dal/include/audio_interface.h  |  184 +
 drivers/gpu/drm/amd/dal/include/audio_types.h      |  277 ++
 .../drm/amd/dal/include/bios_parser_interface.h    |   98 +
 .../gpu/drm/amd/dal/include/bios_parser_types.h    |  327 ++
 drivers/gpu/drm/amd/dal/include/dal_asic_id.h      |  117 +
 .../gpu/drm/amd/dal/include/dal_register_logger.h  |   43 +
 drivers/gpu/drm/amd/dal/include/dal_types.h        |  305 ++
 .../amd/dal/include/dc_clock_generator_interface.h |   77 +
 drivers/gpu/drm/amd/dal/include/dcs_types.h        |  742 +++
 drivers/gpu/drm/amd/dal/include/ddc_interface.h    |   74 +
 .../gpu/drm/amd/dal/include/ddc_service_types.h    |  221 +
 .../drm/amd/dal/include/display_clock_interface.h  |  186 +
 .../drm/amd/dal/include/display_path_interface.h   |  436 ++
 drivers/gpu/drm/amd/dal/include/dmcu_interface.h   |   87 +
 drivers/gpu/drm/amd/dal/include/dmcu_types.h       |  199 +
 drivers/gpu/drm/amd/dal/include/dpcd_defs.h        |  873 ++++
 .../gpu/drm/amd/dal/include/encoder_interface.h    |  278 ++
 drivers/gpu/drm/amd/dal/include/fixed31_32.h       |  389 ++
 drivers/gpu/drm/amd/dal/include/fixed32_32.h       |   82 +
 drivers/gpu/drm/amd/dal/include/gpio_interface.h   |   93 +
 .../drm/amd/dal/include/gpio_service_interface.h   |   81 +
 drivers/gpu/drm/amd/dal/include/gpio_types.h       |  341 ++
 drivers/gpu/drm/amd/dal/include/grph_csc_types.h   |   98 +
 .../drm/amd/dal/include/grph_object_ctrl_defs.h    |  593 +++
 drivers/gpu/drm/amd/dal/include/grph_object_defs.h |  328 ++
 drivers/gpu/drm/amd/dal/include/grph_object_id.h   |  277 ++
 .../drm/amd/dal/include/hw_sequencer_interface.h   |  388 ++
 .../gpu/drm/amd/dal/include/hw_sequencer_types.h   |  304 ++
 drivers/gpu/drm/amd/dal/include/i2caux_interface.h |  127 +
 drivers/gpu/drm/amd/dal/include/irq_interface.h    |   53 +
 .../drm/amd/dal/include/irq_service_interface.h    |   55 +
 .../drm/amd/dal/include/link_service_interface.h   |  202 +
 .../gpu/drm/amd/dal/include/link_service_types.h   |  427 ++
 drivers/gpu/drm/amd/dal/include/logger_interface.h |  153 +
 drivers/gpu/drm/amd/dal/include/logger_types.h     |  356 ++
 drivers/gpu/drm/amd/dal/include/scaler_types.h     |  196 +
 drivers/gpu/drm/amd/dal/include/set_mode_types.h   |  142 +
 drivers/gpu/drm/amd/dal/include/signal_types.h     |   59 +
 drivers/gpu/drm/amd/dal/include/vector.h           |  150 +
 drivers/gpu/drm/amd/dal/include/video_csc_types.h  |  135 +
 .../gpu/drm/amd/dal/include/video_gamma_types.h    |   57 +
 287 files changed, 93942 insertions(+), 30 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/dal/Kconfig
 create mode 100644 drivers/gpu/drm/amd/dal/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_target.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_helpers.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_status.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_asic_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_register_logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_clock_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_path_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed31_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed32_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/i2caux_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/scaler_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/signal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/vector.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_gamma_types.h

-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH v2 01/26] drm/amd/dal: Add dal headers
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 02/26] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
                     ` (24 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dal_services.h             | 266 ++++++
 drivers/gpu/drm/amd/dal/dal_services_types.h       |  62 ++
 drivers/gpu/drm/amd/dal/dc/dc.h                    | 462 ++++++++++
 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h         | 277 ++++++
 drivers/gpu/drm/amd/dal/dc/dc_types.h              | 936 +++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/dm_helpers.h            |  98 +++
 drivers/gpu/drm/amd/dal/dc/dm_services.h           | 485 +++++++++++
 drivers/gpu/drm/amd/dal/dc/dm_services_types.h     | 167 ++++
 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h   | 510 +++++++++++
 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h          |  64 ++
 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h      | 176 ++++
 drivers/gpu/drm/amd/dal/dc/inc/compressor.h        | 140 +++
 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h           |  54 ++
 drivers/gpu/drm/amd/dal/dc/inc/core_status.h       |  46 +
 drivers/gpu/drm/amd/dal/dc/inc/core_types.h        | 357 ++++++++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h       | 151 ++++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h        |  56 ++
 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h       | 118 +++
 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h      | 126 +++
 drivers/gpu/drm/amd/dal/dc/inc/ipp.h               | 106 +++
 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h      | 138 +++
 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h         |  68 ++
 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h         |  83 ++
 drivers/gpu/drm/amd/dal/dc/inc/opp.h               | 308 +++++++
 drivers/gpu/drm/amd/dal/dc/inc/resource.h          |  80 ++
 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h    |  88 ++
 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h  | 155 ++++
 drivers/gpu/drm/amd/dal/dc/inc/transform.h         | 217 +++++
 drivers/gpu/drm/amd/dal/dc/irq_types.h             | 199 +++++
 .../amd/dal/include/adapter_service_interface.h    | 632 ++++++++++++++
 .../drm/amd/dal/include/adapter_service_types.h    |  71 ++
 .../amd/dal/include/asic_capability_interface.h    |  58 ++
 .../drm/amd/dal/include/asic_capability_types.h    | 134 +++
 drivers/gpu/drm/amd/dal/include/audio_interface.h  | 184 ++++
 drivers/gpu/drm/amd/dal/include/audio_types.h      | 277 ++++++
 .../drm/amd/dal/include/bios_parser_interface.h    |  98 +++
 .../gpu/drm/amd/dal/include/bios_parser_types.h    | 327 +++++++
 drivers/gpu/drm/amd/dal/include/dal_asic_id.h      | 117 +++
 .../gpu/drm/amd/dal/include/dal_register_logger.h  |  43 +
 drivers/gpu/drm/amd/dal/include/dal_types.h        | 305 +++++++
 .../amd/dal/include/dc_clock_generator_interface.h |  77 ++
 drivers/gpu/drm/amd/dal/include/dcs_types.h        | 742 ++++++++++++++++
 drivers/gpu/drm/amd/dal/include/ddc_interface.h    |  74 ++
 .../gpu/drm/amd/dal/include/ddc_service_types.h    | 221 +++++
 .../drm/amd/dal/include/display_clock_interface.h  | 186 ++++
 .../drm/amd/dal/include/display_path_interface.h   | 436 ++++++++++
 drivers/gpu/drm/amd/dal/include/dmcu_interface.h   |  87 ++
 drivers/gpu/drm/amd/dal/include/dmcu_types.h       | 199 +++++
 drivers/gpu/drm/amd/dal/include/dpcd_defs.h        | 873 +++++++++++++++++++
 .../gpu/drm/amd/dal/include/encoder_interface.h    | 278 ++++++
 drivers/gpu/drm/amd/dal/include/fixed31_32.h       | 389 +++++++++
 drivers/gpu/drm/amd/dal/include/fixed32_32.h       |  82 ++
 drivers/gpu/drm/amd/dal/include/gpio_interface.h   |  93 ++
 .../drm/amd/dal/include/gpio_service_interface.h   |  81 ++
 drivers/gpu/drm/amd/dal/include/gpio_types.h       | 341 ++++++++
 drivers/gpu/drm/amd/dal/include/grph_csc_types.h   |  98 +++
 .../drm/amd/dal/include/grph_object_ctrl_defs.h    | 593 +++++++++++++
 drivers/gpu/drm/amd/dal/include/grph_object_defs.h | 328 ++++++++
 drivers/gpu/drm/amd/dal/include/grph_object_id.h   | 277 ++++++
 .../drm/amd/dal/include/hw_sequencer_interface.h   | 388 +++++++++
 .../gpu/drm/amd/dal/include/hw_sequencer_types.h   | 304 +++++++
 drivers/gpu/drm/amd/dal/include/i2caux_interface.h | 127 +++
 drivers/gpu/drm/amd/dal/include/irq_interface.h    |  53 ++
 .../drm/amd/dal/include/irq_service_interface.h    |  55 ++
 .../drm/amd/dal/include/link_service_interface.h   | 202 +++++
 .../gpu/drm/amd/dal/include/link_service_types.h   | 427 ++++++++++
 drivers/gpu/drm/amd/dal/include/logger_interface.h | 153 ++++
 drivers/gpu/drm/amd/dal/include/logger_types.h     | 356 ++++++++
 drivers/gpu/drm/amd/dal/include/scaler_types.h     | 196 +++++
 drivers/gpu/drm/amd/dal/include/set_mode_types.h   | 142 ++++
 drivers/gpu/drm/amd/dal/include/signal_types.h     |  59 ++
 drivers/gpu/drm/amd/dal/include/vector.h           | 150 ++++
 drivers/gpu/drm/amd/dal/include/video_csc_types.h  | 135 +++
 .../gpu/drm/amd/dal/include/video_gamma_types.h    |  57 ++
 74 files changed, 16498 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_helpers.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_status.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_asic_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_register_logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_clock_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_path_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed31_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed32_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/i2caux_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/scaler_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/signal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/vector.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_gamma_types.h

diff --git a/drivers/gpu/drm/amd/dal/dal_services.h b/drivers/gpu/drm/amd/dal/dal_services.h
new file mode 100644
index 000000000000..398e4e559455
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dal_services.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SERVICES_H__
+#define __DAL_SERVICES_H__
+
+/* DC headers*/
+#include "dc/dc_services.h"
+
+#include "dal_power_interface_types.h"
+
+#include "irq_types.h"
+#include "include/dal_types.h"
+
+/* TODO: investigate if it can be removed. */
+/* Undefine DEPRECATED because it conflicts with printk.h */
+#undef DEPRECATED
+
+/*
+ *
+ * interrupt services to register and unregister handlers
+ *
+ */
+
+/* the timer "interrupt" current implementation supports only
+'one-shot' type, and LOW level (asynchronous) context */
+void dal_register_timer_interrupt(
+	struct dc_context *ctx,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *handler_args);
+
+/*
+ *
+ * kernel memory manipulation
+ *
+ */
+
+/* Reallocate memory. The contents will remain unchanged.*/
+void *dc_service_realloc(struct dc_context *ctx, const void *ptr, uint32_t size);
+
+void dc_service_memmove(void *dst, const void *src, uint32_t size);
+
+void dc_service_memset(void *p, int32_t c, uint32_t count);
+
+int32_t dal_memcmp(const void *p1, const void *p2, uint32_t count);
+
+int32_t dal_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count);
+
+/*
+ *
+ * GPU registers access
+ *
+ */
+static inline uint32_t dal_read_reg(
+	const struct dc_context *ctx,
+	uint32_t address)
+{
+	uint32_t value = cgs_read_register(ctx->cgs_device, address);
+
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s 0x%x 0x%x\n", __func__, address, value);
+	}
+#endif
+	return value;
+}
+
+static inline uint32_t get_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (mask & reg_value) >> shift;
+}
+
+#define get_reg_field_value(reg_value, reg_name, reg_field)\
+	get_reg_field_value_ex(\
+		(reg_value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+static inline uint32_t set_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (reg_value & ~mask) | (mask & (value << shift));
+}
+
+#define set_reg_field_value(reg_value, value, reg_name, reg_field)\
+	(reg_value) = set_reg_field_value_ex(\
+		(reg_value),\
+		(value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+static inline void dal_write_reg(
+	const struct dc_context *ctx,
+	uint32_t address,
+	uint32_t value)
+{
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s 0x%x 0x%x\n", __func__, address, value);
+	}
+#endif
+	cgs_write_register(ctx->cgs_device, address, value);
+}
+
+static inline uint32_t dal_read_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index)
+{
+	return cgs_read_ind_register(ctx->cgs_device,addr_space,index);
+}
+
+static inline void dal_write_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index,
+	uint32_t value)
+{
+	cgs_write_ind_register(ctx->cgs_device,addr_space,index,value);
+}
+
+enum platform_method {
+	PM_GET_AVAILABLE_METHODS = 1 << 0,
+	PM_GET_LID_STATE = 1 << 1,
+	PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2
+};
+
+struct platform_info_params {
+	enum platform_method method;
+	void *data;
+};
+
+struct platform_info_brightness_caps {
+	uint8_t ac_level_percentage;
+	uint8_t dc_level_percentage;
+};
+
+struct platform_info_ext_brightness_caps {
+	struct platform_info_brightness_caps basic_caps;
+	struct data_point {
+		uint8_t luminance;
+		uint8_t	signal_level;
+	} data_points[99];
+
+	uint8_t	data_points_num;
+	uint8_t	min_input_signal;
+	uint8_t	max_input_signal;
+};
+
+bool dal_get_platform_info(
+	struct dc_context *ctx,
+	struct platform_info_params *params);
+
+
+static inline uint32_t dal_bios_cmd_table_para_revision(
+	struct dc_context *ctx,
+	uint32_t index)
+{
+	uint8_t frev;
+	uint8_t crev;
+
+	if (cgs_atom_get_cmd_table_revs(
+			ctx->cgs_device,
+			index,
+			&frev,
+			&crev) != 0)
+		return 0;
+
+	return crev;
+}
+
+/* Calls to notification */
+
+/* Notify display manager for hotplug event */
+void dal_notify_hotplug(
+	struct dc_context *ctx,
+	uint32_t display_index,
+	bool is_connected);
+
+
+void dal_notify_setmode_complete(
+	struct dc_context *ctx,
+	uint32_t h_total,
+	uint32_t v_total,
+	uint32_t h_active,
+	uint32_t v_active,
+	uint32_t pix_clk_in_khz);
+
+/* End of notification calls */
+
+/*
+ *
+ * Delay functions.
+ *
+ *
+ */
+
+/* Following the guidance:
+ * https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
+ *
+ * This is a busy wait for nano seconds and should be used only for
+ * extremely short ranges
+ */
+void dal_delay_in_nanoseconds(uint32_t nanoseconds);
+
+
+/*
+ *
+ * atombios services
+ *
+ */
+
+bool dal_exec_bios_cmd_table(
+	struct dc_context *ctx,
+	uint32_t index,
+	void *params);
+
+/*
+ *
+ * print-out services
+ *
+ */
+#define dal_log_to_buffer(buffer, size, fmt, args)\
+	vsnprintf(buffer, size, fmt, args)
+
+long dal_get_pid(void);
+long dal_get_tgid(void);
+
+/*
+ *
+ * general debug capabilities
+ *
+ */
+
+#endif /* __DAL_SERVICES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dal_services_types.h b/drivers/gpu/drm/amd/dal/dal_services_types.h
new file mode 100644
index 000000000000..89c73c651d09
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dal_services_types.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SERVICES_TYPES_H__
+#define __DAL_SERVICES_TYPES_H__
+
+#define INVALID_DISPLAY_INDEX 0xffffffff
+
+#if defined __KERNEL__
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <drm/drmP.h>
+
+#include "cgs_linux.h"
+
+#if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU)
+#define BIGENDIAN_CPU
+#elif defined(__LITTLE_ENDIAN) && !defined(LITTLEENDIAN_CPU)
+#define LITTLEENDIAN_CPU
+#endif
+
+#undef READ
+#undef WRITE
+#undef FRAME_SIZE
+
+#define dal_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__)
+
+#define dal_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__)
+
+#define dal_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__)
+
+#define dal_vlog(fmt, args) vprintk(fmt, args)
+
+#define dal_min(x, y) min(x, y)
+#define dal_max(x, y) max(x, y)
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dc.h b/drivers/gpu/drm/amd/dal/dc/dc.h
new file mode 100644
index 000000000000..61f13bd0af49
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc.h
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2012-14 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DC_INTERFACE_H_
+#define DC_INTERFACE_H_
+
+#include "dc_types.h"
+#include "dal_types.h"
+#include "audio_types.h"
+#include "logger_types.h"
+
+#define MAX_SINKS_PER_LINK 4
+
+/*******************************************************************************
+ * Display Core Interfaces
+ ******************************************************************************/
+struct dc_init_data {
+	struct dc_context *ctx;
+	struct adapter_service *adapter_srv;
+	uint8_t num_virtual_links;
+};
+
+struct dc_caps {
+    uint32_t max_targets;
+    uint32_t max_links;
+    uint32_t max_audios;
+};
+
+void dc_get_caps(const struct dc *dc, struct dc_caps *caps);
+
+struct dc *dc_create(const struct dal_init_data *init_params);
+void dc_destroy(struct dc **dc);
+
+/*******************************************************************************
+ * Surface Interfaces
+ ******************************************************************************/
+
+struct dc_surface {
+	bool visible;
+	bool flip_immediate;
+	struct dc_plane_address address;
+
+	struct scaling_taps scaling_quality;
+	struct rect src_rect;
+	struct rect dst_rect;
+	struct rect clip_rect;
+
+	union plane_size plane_size;
+	struct dc_tiling_info tiling_info;
+	struct plane_colorimetry colorimetry;
+
+	enum surface_pixel_format format;
+	enum dc_rotation_angle rotation;
+	enum plane_stereo_format stereo_format;
+
+	struct gamma_ramp gamma_correction; /* deprecated */
+	struct dc_gamma_ramp gamma;
+};
+
+/*
+ * This structure is filled in by dc_surface_get_status and contains
+ * the last requested address and the currently active address so the called
+ * can determine if there are any outstanding flips
+ */
+struct dc_surface_status {
+	struct dc_plane_address requested_address;
+	struct dc_plane_address current_address;
+	const struct dc_target *dc_target;
+};
+
+/*
+ * Create a new surface with default parameters;
+ */
+struct dc_surface *dc_create_surface(const struct dc *dc);
+const struct dc_surface_status* dc_surface_get_status(
+						struct dc_surface *dc_surface);
+
+void dc_surface_retain(const struct dc_surface *dc_surface);
+void dc_surface_release(const struct dc_surface *dc_surface);
+
+/*
+ * This structure holds a surface address.  There could be multiple addresses
+ * in cases such as Stereo 3D, Planar YUV, etc.  Other per-flip attributes such
+ * as frame durations and DCC format can also be set.
+ */
+struct dc_flip_addrs {
+	struct dc_plane_address address;
+	bool flip_immediate;
+	/* TODO: DCC format info */
+	/* TODO: add flip duration for FreeSync */
+};
+
+/*
+ * Optimized flip address update function.
+ *
+ * After this call:
+ *   Surface addresses and flip attributes are programmed.
+ *   Surface flip occur at next configured time (h_sync or v_sync flip)
+ */
+void dc_flip_surface_addrs(struct dc* dc,
+		const struct dc_surface *const surfaces[],
+		struct dc_flip_addrs flip_addrs[],
+		uint32_t count);
+
+/*
+ * Set up surface attributes and associate to a target
+ * The surfaces parameter is an absolute set of all surface active for the target.
+ * If no surfaces are provided, the target will be blanked; no memory read.
+ * Any flip related attribute changes must be done through this interface.
+ *
+ * After this call:
+ *   Surfaces attributes are programmed and configured to be composed into target.
+ *   This does not trigger a flip.  No surface address is programmed.
+ */
+bool dc_commit_surfaces_to_target(
+		struct dc *dc,
+		struct dc_surface *dc_surfaces[],
+		uint8_t surface_count,
+		struct dc_target *dc_target);
+
+/*******************************************************************************
+ * Target Interfaces
+ ******************************************************************************/
+#define MAX_STREAM_NUM 1
+
+struct dc_target {
+	uint8_t stream_count;
+	const struct dc_stream *streams[MAX_STREAM_NUM];
+};
+
+/*
+ * Target status is returned from dc_target_get_status in order to get the
+ * the IRQ source, current frame counter and currently attached surfaces.
+ */
+struct dc_target_status {
+	enum dc_irq_source page_flip_src;
+	enum dc_irq_source v_update_src;
+	uint32_t cur_frame_count;
+	const struct dc_surface *surfaces[MAX_SURFACE_NUM];
+	uint8_t surface_count;
+};
+
+struct dc_target *dc_create_target_for_streams(
+		struct dc_stream *dc_streams[],
+		uint8_t stream_count);
+
+/*
+ * Get the current target status.
+ */
+const struct dc_target_status *dc_target_get_status(
+					const struct dc_target* dc_target);
+
+void dc_target_retain(struct dc_target *dc_target);
+void dc_target_release(struct dc_target *dc_target);
+void dc_target_log(
+	const struct dc_target *dc_target,
+	struct dal_logger *dal_logger,
+	enum log_major log_major,
+	enum log_minor log_minor);
+
+uint8_t dc_get_current_target_count(const struct dc *dc);
+struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i);
+
+bool dc_target_is_connected_to_sink(
+		const struct dc_target *dc_target,
+		const struct dc_sink *dc_sink);
+
+uint8_t dc_target_get_link_index(const struct dc_target *dc_target);
+uint8_t dc_target_get_controller_id(const struct dc_target *dc_target);
+
+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target);
+enum dc_irq_source dc_target_get_irq_src(
+	const struct dc_target *dc_target, const enum irq_type irq_type);
+
+void dc_target_enable_memory_requests(struct dc_target *target);
+void dc_target_disable_memory_requests(struct dc_target *target);
+
+/*
+ * Structure to store surface/target associations for validation
+ */
+struct dc_validation_set {
+	const struct dc_target *target;
+	const struct dc_surface *surfaces[4];
+	uint8_t surface_count;
+};
+
+/*
+ * This function takes a set of resources and checks that they are cofunctional.
+ *
+ * After this call:
+ *   No hardware is programmed for call.  Only validation is done.
+ */
+bool dc_validate_resources(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count);
+
+/*
+ * Set up streams and links associated to targets to drive sinks
+ * The targets parameter is an absolute set of all active targets.
+ *
+ * After this call:
+ *   Phy, Encoder, Timing Generator are programmed and enabled.
+ *   New targets are enabled with blank stream; no memory read.
+ */
+bool dc_commit_targets(
+		struct dc *dc,
+		struct dc_target *targets[],
+		uint8_t target_count);
+
+/*******************************************************************************
+ * Stream Interfaces
+ ******************************************************************************/
+struct dc_stream {
+	const struct dc_sink *sink;
+	struct dc_crtc_timing timing;
+
+	struct rect src; /* viewport in target space*/
+	struct rect dst; /* stream addressable area */
+
+	struct audio_info audio_info;
+
+	/* TODO: dithering */
+	/* TODO: transfer function (CSC/regamma/gamut remap) */
+	/* TODO: custom INFO packets */
+	/* TODO: DRR/Freesync parameters */
+	/* TODO: ABM info (DMCU) */
+	/* TODO: PSR info */
+	/* TODO: CEA VIC */
+};
+
+/**
+ * Create a new default stream for the requested sink
+ */
+struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink);
+
+void dc_stream_retain(struct dc_stream *dc_stream);
+void dc_stream_release(struct dc_stream *dc_stream);
+
+void dc_update_stream(const struct dc_stream *dc_stream,
+		struct rect *src, struct rect *dst);
+
+/*******************************************************************************
+ * Link Interfaces
+ ******************************************************************************/
+
+/*
+ * A link contains one or more sinks and their connected status.
+ * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported.
+ */
+struct dc_link {
+	const struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK];
+	unsigned int sink_count;
+	const struct dc_sink *local_sink;
+	unsigned int link_index;
+	enum dc_connection_type type;
+	enum signal_type connector_signal;
+	enum dc_irq_source irq_source_hpd;
+	enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse  */
+};
+
+/*
+ * Return an enumerated dc_link.  dc_link order is constant and determined at
+ * boot time.  They cannot be created or destroyed.
+ * Use dc_get_caps() to get number of links.
+ */
+const struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index);
+
+/* Return id of physical connector represented by a dc_link at link_index.*/
+const struct graphics_object_id dc_get_link_id_at_index(
+		struct dc *dc, uint32_t link_index);
+
+/* Set backlight level of an embedded panel (eDP, LVDS). */
+bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level);
+
+/* Request DC to detect if there is a Panel connected.
+ * boot - If this call is during initial boot.
+ * Return false for any type of detection failure or MST detection
+ * true otherwise. True meaning further action is required (status update
+ * and OS notification).
+ */
+bool dc_link_detect(const struct dc_link *dc_link, bool boot);
+
+/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt).
+ * Return:
+ * true - Downstream port status changed. DM should call DC to do the
+ * detection.
+ * false - no change in Downstream port status. No further action required
+ * from DM. */
+bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link);
+
+bool dc_link_add_remote_sink(const struct dc_link *link, struct dc_sink *sink);
+
+void dc_link_remove_remote_sink(
+	const struct dc_link *link,
+	const struct dc_sink *sink);
+
+/* Used by diagnostics for virtual link at the moment */
+void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink);
+
+/*******************************************************************************
+ * Sink Interfaces - A sink corresponds to a display output device
+ ******************************************************************************/
+
+/*
+ * The sink structure contains EDID and other display device properties
+ */
+struct dc_sink {
+	enum signal_type sink_signal;
+	struct dc_edid dc_edid; /* raw edid */
+	struct dc_edid_caps edid_caps; /* parse display caps */
+};
+
+void dc_sink_retain(const struct dc_sink *sink);
+void dc_sink_release(const struct dc_sink *sink);
+
+const struct audio **dc_get_audios(struct dc *dc);
+
+struct dc_sink_init_data {
+	enum signal_type sink_signal;
+	const struct dc_link *link;
+	uint32_t dongle_max_pix_clk;
+	bool converter_disable_audio;
+};
+
+struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params);
+
+
+/*******************************************************************************
+ * Cursor interfaces - To manages the cursor within a target
+ ******************************************************************************/
+/* TODO: Deprecated once we switch to dc_set_cursor_position */
+bool dc_target_set_cursor_attributes(
+	struct dc_target *dc_target,
+	const struct dc_cursor_attributes *attributes);
+
+bool dc_target_set_cursor_position(
+	struct dc_target *dc_target,
+	const struct dc_cursor_position *position);
+
+/* Newer interfaces  */
+struct dc_cursor {
+	struct dc_plane_address address;
+	struct dc_cursor_attributes attributes;
+};
+
+/*
+ * Create a new cursor with default values for a given target.
+ */
+struct dc_cursor *dc_create_cursor_for_target(
+		const struct dc *dc,
+		struct dc_target *dc_target);
+
+/**
+ * Commit cursor attribute changes such as pixel format and dimensions and
+ * surface address.
+ *
+ * After this call:
+ *   Cursor address and format is programmed to the new values.
+ *   Cursor position is unmodified.
+ */
+bool dc_commit_cursor(
+		const struct dc *dc,
+		struct dc_cursor *cursor);
+
+/*
+ * Optimized cursor position update
+ *
+ * After this call:
+ *   Cursor position will be programmed as well as enable/disable bit.
+ */
+bool dc_set_cursor_position(
+		const struct dc *dc,
+		struct dc_cursor *cursor,
+		struct dc_cursor_position *pos);
+
+
+
+/*******************************************************************************
+ * Interrupt interfaces
+ ******************************************************************************/
+enum dc_irq_source dc_interrupt_to_irq_source(
+		struct dc *dc,
+		uint32_t src_id,
+		uint32_t ext_id);
+void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable);
+void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src);
+const enum dc_irq_source dc_get_hpd_irq_source_at_index(
+		struct dc *dc, uint32_t link_index);
+const struct dc_target *dc_get_target_on_irq_source(
+		const struct dc *dc,
+		enum dc_irq_source src);
+
+
+/*******************************************************************************
+ * Power Interfaces
+ ******************************************************************************/
+
+void dc_set_power_state(
+		struct dc *dc,
+		enum dc_acpi_cm_power_state power_state,
+		enum dc_video_power_state video_power_state);
+void dc_resume(const struct dc *dc);
+
+/*******************************************************************************
+ * DDC Interfaces
+ ******************************************************************************/
+
+const struct ddc_service *dc_get_ddc_at_index(
+		struct dc *dc, uint32_t link_index);
+
+/*
+ * DPCD access interfaces
+ */
+
+bool dc_read_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size);
+
+bool dc_write_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		const uint8_t *data,
+	uint32_t size);
+
+
+uint8_t dc_get_dig_index(const struct dc_stream *stream);
+
+enum signal_type  dc_get_display_signal(
+		const struct dc_stream *stream);
+
+enum gpio_ddc_line dc_get_ddc_line(
+		const struct dc_stream *stream);
+
+
+#endif /* DC_INTERFACE_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dc_bios_types.h b/drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
new file mode 100644
index 000000000000..53f047788b31
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DC_BIOS_TYPES_H
+#define DC_BIOS_TYPES_H
+
+/******************************************************************************
+ * Interface file for VBIOS implementations.
+ *
+ * The default implementation is inside DC.
+ * Display Manager (which instantiates DC) has the option to supply it's own
+ * (external to DC) implementation of VBIOS, which will be called by DC, using
+ * this interface.
+ * (The intended use is Diagnostics, but other uses may appear.)
+ *****************************************************************************/
+
+#include "include/bios_parser_types.h"
+
+
+struct dc_vbios_funcs {
+	uint8_t (*get_connectors_number)(struct dc_bios *bios);
+
+	void (*power_down)(struct dc_bios *bios);
+	void (*power_up)(struct dc_bios *bios);
+
+	uint8_t (*get_encoders_number)(struct dc_bios *bios);
+	uint32_t (*get_oem_ddc_lines_number)(struct dc_bios *bios);
+
+	struct graphics_object_id (*get_encoder_id)(
+		struct dc_bios *bios,
+		uint32_t i);
+	struct graphics_object_id (*get_connector_id)(
+		struct dc_bios *bios,
+		uint8_t connector_index);
+	uint32_t (*get_src_number)(
+		struct dc_bios *bios,
+		struct graphics_object_id id);
+	uint32_t (*get_dst_number)(
+		struct dc_bios *bios,
+		struct graphics_object_id id);
+
+	uint32_t (*get_gpio_record)(
+		struct dc_bios *dcb,
+		struct graphics_object_id id,
+		struct bp_gpio_cntl_info *gpio_record,
+		uint32_t record_size);
+
+	enum bp_result (*get_src_obj)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id, uint32_t index,
+		struct graphics_object_id *src_object_id);
+	enum bp_result (*get_dst_obj)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id, uint32_t index,
+		struct graphics_object_id *dest_object_id);
+	enum bp_result (*get_oem_ddc_info)(
+		struct dc_bios *bios,
+		uint32_t index,
+		struct graphics_object_i2c_info *info);
+
+	enum bp_result (*get_i2c_info)(
+		struct dc_bios *dcb,
+		struct graphics_object_id id,
+		struct graphics_object_i2c_info *info);
+
+	enum bp_result (*get_voltage_ddc_info)(
+		struct dc_bios *bios,
+		uint32_t index,
+		struct graphics_object_i2c_info *info);
+	enum bp_result (*get_thermal_ddc_info)(
+		struct dc_bios *bios,
+		uint32_t i2c_channel_id,
+		struct graphics_object_i2c_info *info);
+	enum bp_result (*get_hpd_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id id,
+		struct graphics_object_hpd_info *info);
+	enum bp_result (*get_device_tag)(
+		struct dc_bios *bios,
+		struct graphics_object_id connector_object_id,
+		uint32_t device_tag_index,
+		struct connector_device_tag_info *info);
+	enum bp_result (*get_firmware_info)(
+		struct dc_bios *bios,
+		struct firmware_info *info);
+	enum bp_result (*get_spread_spectrum_info)(
+		struct dc_bios *bios,
+		enum as_signal_type signal,
+		uint32_t index,
+		struct spread_spectrum_info *ss_info);
+	uint32_t (*get_ss_entry_number)(
+		struct dc_bios *bios,
+		enum as_signal_type signal);
+	enum bp_result (*get_embedded_panel_info)(
+		struct dc_bios *bios,
+		struct embedded_panel_info *info);
+	enum bp_result (*enum_embedded_panel_patch_mode)(
+		struct dc_bios *bios,
+		uint32_t index,
+		struct embedded_panel_patch_mode *mode);
+	enum bp_result (*get_gpio_pin_info)(
+		struct dc_bios *bios,
+		uint32_t gpio_id,
+		struct gpio_pin_info *info);
+	enum bp_result (*get_faked_edid_len)(
+		struct dc_bios *bios,
+		uint32_t *len);
+	enum bp_result (*get_faked_edid_buf)(
+		struct dc_bios *bios,
+		uint8_t *buff,
+		uint32_t len);
+	enum bp_result (*get_encoder_cap_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id,
+		struct bp_encoder_cap_info *info);
+	enum bp_result (*get_din_connector_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id id,
+		struct din_connector_info *info);
+
+	bool (*is_lid_open)(
+		struct dc_bios *bios);
+	bool (*is_lid_status_changed)(
+		struct dc_bios *bios);
+	bool (*is_display_config_changed)(
+		struct dc_bios *bios);
+	bool (*is_accelerated_mode)(
+		struct dc_bios *bios);
+	void (*set_scratch_lcd_scale)(
+		struct dc_bios *bios,
+		enum lcd_scale scale);
+	enum lcd_scale  (*get_scratch_lcd_scale)(
+		struct dc_bios *bios);
+	void (*get_bios_event_info)(
+		struct dc_bios *bios,
+		struct bios_event_info *info);
+	void (*update_requested_backlight_level)(
+		struct dc_bios *bios,
+		uint32_t backlight_8bit);
+	uint32_t (*get_requested_backlight_level)(
+		struct dc_bios *bios);
+	void (*take_backlight_control)(
+		struct dc_bios *bios,
+		bool cntl);
+	bool (*is_active_display)(
+		struct dc_bios *bios,
+		enum signal_type signal,
+		const struct connector_device_tag_info *device_tag);
+	enum controller_id (*get_embedded_display_controller_id)(
+		struct dc_bios *bios);
+	uint32_t (*get_embedded_display_refresh_rate)(
+		struct dc_bios *bios);
+	void (*set_scratch_connected)(
+		struct dc_bios *bios,
+		struct graphics_object_id connector_id,
+		bool connected,
+		const struct connector_device_tag_info *device_tag);
+	void (*prepare_scratch_active_and_requested)(
+		struct dc_bios *bios,
+		enum controller_id controller_id,
+		enum signal_type signal,
+		const struct connector_device_tag_info *device_tag);
+	void (*set_scratch_active_and_requested)(
+		struct dc_bios *bios);
+	void (*set_scratch_critical_state)(
+		struct dc_bios *bios,
+		bool state);
+	void (*set_scratch_acc_mode_change)(
+		struct dc_bios *bios);
+
+	bool (*is_device_id_supported)(
+		struct dc_bios *bios,
+		struct device_id id);
+
+	/* COMMANDS */
+
+	enum bp_result (*encoder_control)(
+		struct dc_bios *bios,
+		struct bp_encoder_control *cntl);
+	enum bp_result (*transmitter_control)(
+		struct dc_bios *bios,
+		struct bp_transmitter_control *cntl);
+	enum bp_result (*crt_control)(
+		struct dc_bios *bios,
+		enum engine_id engine_id,
+		bool enable,
+		uint32_t pixel_clock);
+	enum bp_result (*enable_crtc)(
+		struct dc_bios *bios,
+		enum controller_id id,
+		bool enable);
+	enum bp_result (*adjust_pixel_clock)(
+		struct dc_bios *bios,
+		struct bp_adjust_pixel_clock_parameters *bp_params);
+	enum bp_result (*set_pixel_clock)(
+		struct dc_bios *bios,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*set_dce_clock)(
+		struct dc_bios *bios,
+		struct bp_set_dce_clock_parameters *bp_params);
+	enum bp_result (*enable_spread_spectrum_on_ppll)(
+		struct dc_bios *bios,
+		struct bp_spread_spectrum_parameters *bp_params,
+		bool enable);
+	enum bp_result (*program_crtc_timing)(
+		struct dc_bios *bios,
+		struct bp_hw_crtc_timing_parameters *bp_params);
+	enum bp_result (*blank_crtc)(
+		struct dc_bios *bios,
+		struct bp_blank_crtc_parameters *bp_params,
+		bool blank);
+	enum bp_result (*set_overscan)(
+		struct dc_bios *bios,
+		struct bp_hw_crtc_overscan_parameters *bp_params);
+	enum bp_result (*crtc_source_select)(
+		struct dc_bios *bios,
+		struct bp_crtc_source_select *bp_params);
+	enum bp_result (*program_display_engine_pll)(
+		struct dc_bios *bios,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*get_divider_for_target_display_clock)(
+		struct dc_bios *bios,
+		struct bp_display_clock_parameters *bp_params);
+	enum signal_type (*dac_load_detect)(
+		struct dc_bios *bios,
+		struct graphics_object_id encoder,
+		struct graphics_object_id connector,
+		enum signal_type display_signal);
+	enum bp_result (*enable_memory_requests)(
+		struct dc_bios *bios,
+		enum controller_id controller_id,
+		bool enable);
+	enum bp_result (*external_encoder_control)(
+		struct dc_bios *bios,
+		struct bp_external_encoder_control *cntl);
+	enum bp_result (*enable_disp_power_gating)(
+		struct dc_bios *bios,
+		enum controller_id controller_id,
+		enum bp_pipe_control_action action);
+
+	void (*post_init)(struct dc_bios *bios);
+
+	struct integrated_info *(*create_integrated_info)(
+		struct dc_bios *bios);
+
+	void (*destroy_integrated_info)(
+		struct dc_bios *dcb,
+		struct integrated_info **info);
+};
+
+struct dc_bios {
+	const struct dc_vbios_funcs *funcs;
+};
+
+#endif /* DC_BIOS_TYPES_H */
diff --git a/drivers/gpu/drm/amd/dal/dc/dc_types.h b/drivers/gpu/drm/amd/dal/dc/dc_types.h
new file mode 100644
index 000000000000..c238531dc6c0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc_types.h
@@ -0,0 +1,936 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef DC_TYPES_H_
+#define DC_TYPES_H_
+
+#include "dm_services_types.h"
+#include "fixed32_32.h"
+#include "fixed31_32.h"
+#include "irq_types.h"
+
+/* forward declarations */
+struct dc;
+struct dc_surface;
+struct dc_target;
+struct dc_stream;
+struct dc_link;
+struct dc_sink;
+struct dal;
+
+/********************************
+ * Environment definitions
+ ********************************/
+enum dce_environment {
+	DCE_ENV_PRODUCTION_DRV = 0,
+	/* Emulation on FPGA, in "Maximus" System.
+	 * This environment enforces that *only* DC registers accessed.
+	 * (access to non-DC registers will hang FPGA) */
+	DCE_ENV_FPGA_MAXIMUS,
+	/* Emulation on real HW or on FPGA. Used by Diagnostics, enforces
+	 * requirements of Diagnostics team. */
+	DCE_ENV_DIAG
+};
+
+/* Note: use these macro definitions instead of direct comparison! */
+#define IS_FPGA_MAXIMUS_DC(dce_environment) \
+	(dce_environment == DCE_ENV_FPGA_MAXIMUS)
+
+#define IS_DIAG_DC(dce_environment) \
+	(IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG))
+
+/********************************/
+
+#define MAX_EDID_BUFFER_SIZE 512
+#define MAX_SURFACE_NUM 2
+#define NUM_PIXEL_FORMATS 10
+
+enum surface_color_space {
+	SURFACE_COLOR_SPACE_SRGB = 0x0000,
+	SURFACE_COLOR_SPACE_BT601 = 0x0001,
+	SURFACE_COLOR_SPACE_BT709 = 0x0002,
+	SURFACE_COLOR_SPACE_XVYCC_BT601 = 0x0004,
+	SURFACE_COLOR_SPACE_XVYCC_BT709 = 0x0008,
+	SURFACE_COLOR_SPACE_XRRGB = 0x0010
+};
+
+/*Displayable pixel format in fb*/
+enum surface_pixel_format {
+	SURFACE_PIXEL_FORMAT_GRPH_BEGIN = 0,
+	/*TOBE REMOVED paletta 256 colors*/
+	SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS =
+		SURFACE_PIXEL_FORMAT_GRPH_BEGIN,
+	/*16 bpp*/
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB1555,
+	/*16 bpp*/
+	SURFACE_PIXEL_FORMAT_GRPH_RGB565,
+	/*32 bpp*/
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB8888,
+	/*32 bpp swaped*/
+	SURFACE_PIXEL_FORMAT_GRPH_BGRA8888,
+
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010,
+	/*swaped*/
+	SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010,
+	/*TOBE REMOVED swaped, XR_BIAS has no differance
+	 * for pixel layout than previous and we can
+	 * delete this after discusion*/
+	SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS,
+	/*64 bpp */
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616,
+	/*swaped & float*/
+	SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F,
+	/*grow graphics here if necessary */
+
+	SURFACE_PIXEL_FORMAT_VIDEO_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr =
+		SURFACE_PIXEL_FORMAT_VIDEO_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCr,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbY,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrY,
+	/*grow 422/420 video here if necessary */
+	SURFACE_PIXEL_FORMAT_VIDEO_444_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb1555 =
+		SURFACE_PIXEL_FORMAT_VIDEO_444_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_CrYCb565,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb4444,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA5551,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb8888,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb2101010,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA1010102
+	/*grow 444 video here if necessary */
+};
+
+
+/* Pixel format */
+enum pixel_format {
+	/*graph*/
+	PIXEL_FORMAT_UNINITIALIZED,
+	PIXEL_FORMAT_INDEX8,
+	PIXEL_FORMAT_RGB565,
+	PIXEL_FORMAT_ARGB8888,
+	PIXEL_FORMAT_ARGB2101010,
+	PIXEL_FORMAT_ARGB2101010_XRBIAS,
+	PIXEL_FORMAT_FP16,
+	/*video*/
+	PIXEL_FORMAT_420BPP12,
+	PIXEL_FORMAT_422BPP16,
+	PIXEL_FORMAT_444BPP16,
+	PIXEL_FORMAT_444BPP32,
+	/*end of pixel format definition*/
+	PIXEL_FORMAT_INVALID,
+
+	PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8,
+	PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16,
+	PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12,
+	PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_444BPP32,
+	PIXEL_FORMAT_UNKNOWN
+};
+
+enum plane_stereo_format {
+	PLANE_STEREO_FORMAT_NONE = 0,
+	PLANE_STEREO_FORMAT_SIDE_BY_SIDE = 1,
+	PLANE_STEREO_FORMAT_TOP_AND_BOTTOM = 2,
+	PLANE_STEREO_FORMAT_FRAME_ALTERNATE = 3,
+	PLANE_STEREO_FORMAT_ROW_INTERLEAVED = 5,
+	PLANE_STEREO_FORMAT_COLUMN_INTERLEAVED = 6,
+	PLANE_STEREO_FORMAT_CHECKER_BOARD = 7
+};
+
+/* 3D format for view, typically define how L/R eye surface is arranged within
+ * frames
+ */
+enum view_3d_format {
+	VIEW_3D_FORMAT_NONE = 0,
+	VIEW_3D_FORMAT_FRAME_SEQUENTIAL,
+	VIEW_3D_FORMAT_SIDE_BY_SIDE,
+	VIEW_3D_FORMAT_TOP_AND_BOTTOM,
+	VIEW_3D_FORMAT_COUNT,
+	VIEW_3D_FORMAT_FIRST = VIEW_3D_FORMAT_FRAME_SEQUENTIAL
+};
+
+enum dc_pixel_encoding {
+	PIXEL_ENCODING_UNDEFINED,
+	PIXEL_ENCODING_RGB,
+	PIXEL_ENCODING_YCBCR422,
+	PIXEL_ENCODING_YCBCR444,
+	PIXEL_ENCODING_YCBCR420,
+	PIXEL_ENCODING_COUNT
+};
+
+/* TODO: Find way to calculate number of bits
+ *  Please increase if pixel_format enum increases
+ * num  from  PIXEL_FORMAT_INDEX8 to PIXEL_FORMAT_444BPP32
+ */
+
+union large_integer {
+	struct {
+		uint32_t low_part;
+		int32_t high_part;
+	};
+
+	struct {
+		uint32_t low_part;
+		int32_t high_part;
+	} u;
+
+	int64_t quad_part;
+};
+
+#define PHYSICAL_ADDRESS_LOC union large_integer
+
+enum dc_edid_connector_type {
+	EDID_CONNECTOR_UNKNOWN = 0,
+	EDID_CONNECTOR_ANALOG = 1,
+	EDID_CONNECTOR_DIGITAL = 10,
+	EDID_CONNECTOR_DVI = 11,
+	EDID_CONNECTOR_HDMIA = 12,
+	EDID_CONNECTOR_MDDI = 14,
+	EDID_CONNECTOR_DISPLAYPORT = 15
+};
+
+enum dc_edid_status {
+	EDID_OK,
+	EDID_BAD_INPUT,
+	EDID_NO_RESPONSE,
+	EDID_BAD_CHECKSUM,
+};
+
+struct plane_colorimetry {
+	enum surface_color_space color_space;
+	bool limited_range;
+};
+
+/* audio capability from EDID*/
+struct dc_cea_audio_mode {
+	uint8_t format_code; /* ucData[0] [6:3]*/
+	uint8_t channel_count; /* ucData[0] [2:0]*/
+	uint8_t sample_rate; /* ucData[1]*/
+	union {
+		uint8_t sample_size; /* for LPCM*/
+		/*  for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/
+		uint8_t max_bit_rate;
+		uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/
+	};
+};
+
+struct dc_edid {
+	uint32_t length;
+	uint8_t raw_edid[MAX_EDID_BUFFER_SIZE];
+};
+
+/* When speaker location data block is not available, DEFAULT_SPEAKER_LOCATION
+ * is used. In this case we assume speaker location are: front left, front
+ * right and front center. */
+#define DEFAULT_SPEAKER_LOCATION 5
+
+#define DC_MAX_AUDIO_DESC_COUNT 16
+
+#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20
+
+struct dc_edid_caps {
+	/* sink identification */
+	uint16_t manufacturer_id;
+	uint16_t product_id;
+	uint32_t serial_number;
+	uint8_t manufacture_week;
+	uint8_t manufacture_year;
+	uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS];
+
+	/* audio caps */
+	uint8_t speaker_flags;
+	uint32_t audio_mode_count;
+	struct dc_cea_audio_mode audio_modes[DC_MAX_AUDIO_DESC_COUNT];
+	uint32_t audio_latency;
+	uint32_t video_latency;
+
+	/*HDMI 2.0 caps*/
+	uint8_t lte_340mcsc_scramble;
+};
+
+struct scaling_taps {
+	uint32_t v_taps;
+	uint32_t h_taps;
+	uint32_t v_taps_c;
+	uint32_t h_taps_c;
+};
+
+struct scaling_ratios {
+	struct fixed31_32 horz;
+	struct fixed31_32 vert;
+	struct fixed31_32 horz_c;
+	struct fixed31_32 vert_c;
+};
+
+struct rect {
+	uint32_t x;
+	uint32_t y;
+	uint32_t width;
+	uint32_t height;
+};
+
+struct view {
+	uint32_t width;
+	uint32_t height;
+};
+
+struct dc_resolution {
+	uint32_t width;
+	uint32_t height;
+};
+
+
+struct dc_mode_flags {
+	/* note: part of refresh rate flag*/
+	uint32_t INTERLACE :1;
+	/* native display timing*/
+	uint32_t NATIVE :1;
+	/* preferred is the recommended mode, one per display */
+	uint32_t PREFERRED :1;
+	/* true if this mode should use reduced blanking timings
+	 *_not_ related to the Reduced Blanking adjustment*/
+	uint32_t REDUCED_BLANKING :1;
+	/* note: part of refreshrate flag*/
+	uint32_t VIDEO_OPTIMIZED_RATE :1;
+	/* should be reported to upper layers as mode_flags*/
+	uint32_t PACKED_PIXEL_FORMAT :1;
+	/*< preferred view*/
+	uint32_t PREFERRED_VIEW :1;
+	/* this timing should be used only in tiled mode*/
+	uint32_t TILED_MODE :1;
+	uint32_t DSE_MODE :1;
+	/* Refresh rate divider when Miracast sink is using a
+	 different rate than the output display device
+	 Must be zero for wired displays and non-zero for
+	 Miracast displays*/
+	uint32_t MIRACAST_REFRESH_DIVIDER;
+};
+
+struct dc_crtc_timing_flags {
+	uint32_t INTERLACE :1;
+	uint32_t HSYNC_POSITIVE_POLARITY :1; /* when set to 1,
+	 it is positive polarity --reversed with dal1 or video bios define*/
+	uint32_t VSYNC_POSITIVE_POLARITY :1; /* when set to 1,
+	 it is positive polarity --reversed with dal1 or video bios define*/
+
+	uint32_t HORZ_COUNT_BY_TWO:1;
+
+	uint32_t EXCLUSIVE_3D :1; /* if this bit set,
+	 timing can be driven in 3D format only
+	 and there is no corresponding 2D timing*/
+	uint32_t RIGHT_EYE_3D_POLARITY :1; /* 1 - means right eye polarity
+	 (right eye = '1', left eye = '0') */
+	uint32_t SUB_SAMPLE_3D :1; /* 1 - means left/right  images subsampled
+	 when mixed into 3D image. 0 - means summation (3D timing is doubled)*/
+	uint32_t USE_IN_3D_VIEW_ONLY :1; /* Do not use this timing in 2D View,
+	 because corresponding 2D timing also present in the list*/
+	uint32_t STEREO_3D_PREFERENCE :1; /* Means this is 2D timing
+	 and we want to match priority of corresponding 3D timing*/
+	uint32_t Y_ONLY :1;
+
+	uint32_t YCBCR420 :1; /* TODO: shouldn't need this flag, should be a separate pixel format */
+	uint32_t DTD_COUNTER :5; /* values 1 to 16 */
+
+	/* HDMI 2.0 - Support scrambling for TMDS character
+	 * rates less than or equal to 340Mcsc */
+	uint32_t LTE_340MCSC_SCRAMBLE:1;
+
+};
+
+enum dc_timing_standard {
+	TIMING_STANDARD_UNDEFINED,
+	TIMING_STANDARD_DMT,
+	TIMING_STANDARD_GTF,
+	TIMING_STANDARD_CVT,
+	TIMING_STANDARD_CVT_RB,
+	TIMING_STANDARD_CEA770,
+	TIMING_STANDARD_CEA861,
+	TIMING_STANDARD_HDMI,
+	TIMING_STANDARD_TV_NTSC,
+	TIMING_STANDARD_TV_NTSC_J,
+	TIMING_STANDARD_TV_PAL,
+	TIMING_STANDARD_TV_PAL_M,
+	TIMING_STANDARD_TV_PAL_CN,
+	TIMING_STANDARD_TV_SECAM,
+	TIMING_STANDARD_EXPLICIT,
+	/*!< For explicit timings from EDID, VBIOS, etc.*/
+	TIMING_STANDARD_USER_OVERRIDE,
+	/*!< For mode timing override by user*/
+	TIMING_STANDARD_MAX
+};
+
+enum dc_aspect_ratio {
+	ASPECT_RATIO_NO_DATA,
+	ASPECT_RATIO_4_3,
+	ASPECT_RATIO_16_9,
+	ASPECT_RATIO_64_27,
+	ASPECT_RATIO_256_135,
+	ASPECT_RATIO_FUTURE
+};
+
+enum dc_color_depth {
+	COLOR_DEPTH_UNDEFINED,
+	COLOR_DEPTH_666,
+	COLOR_DEPTH_888,
+	COLOR_DEPTH_101010,
+	COLOR_DEPTH_121212,
+	COLOR_DEPTH_141414,
+	COLOR_DEPTH_161616,
+	COLOR_DEPTH_COUNT
+};
+
+enum dc_timing_3d_format {
+	TIMING_3D_FORMAT_NONE,
+	TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/
+	TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/
+	TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/
+	/* for active DP-HDMI dongle*/
+	TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/
+	TIMING_3D_FORMAT_HW_FRAME_PACKING,
+	TIMING_3D_FORMAT_SW_FRAME_PACKING,
+	TIMING_3D_FORMAT_ROW_INTERLEAVE,
+	TIMING_3D_FORMAT_COLUMN_INTERLEAVE,
+	TIMING_3D_FORMAT_PIXEL_INTERLEAVE,
+	TIMING_3D_FORMAT_SIDE_BY_SIDE,
+	TIMING_3D_FORMAT_TOP_AND_BOTTOM,
+	TIMING_3D_FORMAT_SBS_SW_PACKED,
+	/* Side-by-side, packed by application/driver into 2D frame*/
+	TIMING_3D_FORMAT_TB_SW_PACKED,
+	/* Top-and-bottom, packed by application/driver into 2D frame*/
+
+	TIMING_3D_FORMAT_MAX,
+};
+
+enum dc_timing_source {
+	TIMING_SOURCE_UNDEFINED,
+
+	/* explicitly specifed by user, most important*/
+	TIMING_SOURCE_USER_FORCED,
+	TIMING_SOURCE_USER_OVERRIDE,
+	TIMING_SOURCE_CUSTOM,
+	TIMING_SOURCE_EXPLICIT,
+
+	/* explicitly specified by the display device, more important*/
+	TIMING_SOURCE_EDID_CEA_SVD_3D,
+	TIMING_SOURCE_EDID_CEA_SVD_PREFERRED,
+	TIMING_SOURCE_EDID_CEA_SVD_420,
+	TIMING_SOURCE_EDID_DETAILED,
+	TIMING_SOURCE_EDID_ESTABLISHED,
+	TIMING_SOURCE_EDID_STANDARD,
+	TIMING_SOURCE_EDID_CEA_SVD,
+	TIMING_SOURCE_EDID_CVT_3BYTE,
+	TIMING_SOURCE_EDID_4BYTE,
+	TIMING_SOURCE_VBIOS,
+	TIMING_SOURCE_CV,
+	TIMING_SOURCE_TV,
+	TIMING_SOURCE_HDMI_VIC,
+
+	/* implicitly specified by display device, still safe but less important*/
+	TIMING_SOURCE_DEFAULT,
+
+	/* only used for custom base modes */
+	TIMING_SOURCE_CUSTOM_BASE,
+
+	/* these timing might not work, least important*/
+	TIMING_SOURCE_RANGELIMIT,
+	TIMING_SOURCE_OS_FORCED,
+	TIMING_SOURCE_IMPLICIT,
+
+	/* only used by default mode list*/
+	TIMING_SOURCE_BASICMODE,
+
+	TIMING_SOURCE_COUNT
+};
+
+enum dc_timing_support_method {
+	TIMING_SUPPORT_METHOD_UNDEFINED,
+	TIMING_SUPPORT_METHOD_EXPLICIT,
+	TIMING_SUPPORT_METHOD_IMPLICIT,
+	TIMING_SUPPORT_METHOD_NATIVE
+};
+
+struct dc_mode_info {
+	uint32_t pixel_width;
+	uint32_t pixel_height;
+	uint32_t field_rate;
+	/* Vertical refresh rate for progressive modes.
+	* Field rate for interlaced modes.*/
+
+	enum dc_timing_standard timing_standard;
+	enum dc_timing_source timing_source;
+	struct dc_mode_flags flags;
+};
+
+/* TODO: assess necessity*/
+/*scanning type*/
+enum scanning_type {
+	SCANNING_TYPE_NODATA = 0,
+	SCANNING_TYPE_OVERSCAN,
+	SCANNING_TYPE_UNDERSCAN,
+	SCANNING_TYPE_FUTURE,
+	SCANNING_TYPE_UNDEFINED
+};
+
+struct dc_crtc_timing {
+	uint32_t h_total;
+	uint32_t h_border_left;
+	uint32_t h_addressable;
+	uint32_t h_border_right;
+	uint32_t h_front_porch;
+	uint32_t h_sync_width;
+
+	uint32_t v_total;
+	uint32_t v_border_top;
+	uint32_t v_addressable;
+	uint32_t v_border_bottom;
+	uint32_t v_front_porch;
+	uint32_t v_sync_width;
+
+	uint32_t pix_clk_khz;
+
+	uint32_t vic;
+	uint32_t hdmi_vic;
+	enum dc_timing_standard timing_standard;
+	enum dc_timing_3d_format timing_3d_format;
+	enum dc_color_depth display_color_depth;
+	enum dc_pixel_encoding pixel_encoding;
+	enum dc_aspect_ratio aspect_ratio;
+	enum scanning_type scan_type;
+
+	struct dc_crtc_timing_flags flags;
+};
+
+struct dc_mode_timing {
+	struct dc_mode_info mode_info;
+	struct dc_crtc_timing crtc_timing;
+};
+
+/* Rotation angle */
+enum dc_rotation_angle {
+	ROTATION_ANGLE_0 = 0,
+	ROTATION_ANGLE_90,
+	ROTATION_ANGLE_180,
+	ROTATION_ANGLE_270,
+	ROTATION_ANGLE_COUNT
+};
+
+struct dc_cursor_position {
+	uint32_t x;
+	uint32_t y;
+
+	uint32_t x_origin;
+	uint32_t y_origin;
+
+	/*
+	 * This parameter indicates whether HW cursor should be enabled
+	 */
+	bool enable;
+
+	/*
+	 * This parameter indicates whether cursor hot spot should be
+	 * programmed
+	 */
+	bool hot_spot_enable;
+};
+
+/* This enum is for programming CURSOR_MODE register field. */
+/* What this register should be programmed to depends on */
+/* OS requested cursor shape flags */
+/* and what we stored in the cursor surface. */
+enum dc_cursor_color_format {
+	CURSOR_MODE_MONO,
+	CURSOR_MODE_COLOR_1BIT_AND,
+	CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA,
+	CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA
+};
+
+union dc_cursor_attribute_flags {
+	struct {
+		uint32_t ENABLE_MAGNIFICATION:1;
+		uint32_t INVERSE_TRANSPARENT_CLAMPING:1;
+		uint32_t HORIZONTAL_MIRROR:1;
+		uint32_t VERTICAL_MIRROR:1;
+		uint32_t RESERVED:28;
+	} bits;
+	uint32_t value;
+};
+
+/* This is all the parameters required by DAL in order to */
+/* update the cursor attributes, */
+/* including the new cursor image surface address, size, */
+/* hotspot location, color format, etc. */
+struct dc_cursor_attributes {
+	PHYSICAL_ADDRESS_LOC address;
+
+	/* Width and height should correspond to cursor surface width x heigh */
+	uint32_t width;
+	uint32_t height;
+	uint32_t x_hot;
+	uint32_t y_hot;
+
+	enum dc_cursor_color_format color_format;
+
+	/* In case we support HW Cursor rotation in the future */
+	enum dc_rotation_angle rotation_angle;
+
+	union dc_cursor_attribute_flags attribute_flags;
+
+};
+
+
+enum dc_plane_addr_type {
+	PLN_ADDR_TYPE_GRAPHICS = 0,
+	PLN_ADDR_TYPE_GRPH_STEREO,
+	PLN_ADDR_TYPE_VIDEO_PROGRESSIVE,
+};
+
+struct dc_plane_address {
+	enum dc_plane_addr_type type;
+	union {
+		struct{
+			PHYSICAL_ADDRESS_LOC addr;
+		} grph;
+
+		/*stereo*/
+		struct {
+			PHYSICAL_ADDRESS_LOC left_addr;
+			PHYSICAL_ADDRESS_LOC right_addr;
+		} grph_stereo;
+
+		/*video  progressive*/
+		struct {
+			PHYSICAL_ADDRESS_LOC chroma_addr;
+			PHYSICAL_ADDRESS_LOC luma_addr;
+		} video_progressive;
+	};
+};
+
+enum dc_power_state {
+	DC_POWER_STATE_ON = 1,
+	DC_POWER_STATE_STANDBY,
+	DC_POWER_STATE_SUSPEND,
+	DC_POWER_STATE_OFF
+};
+
+/* DC PowerStates */
+enum dc_video_power_state {
+	DC_VIDEO_POWER_UNSPECIFIED = 0,
+	DC_VIDEO_POWER_ON = 1,
+	DC_VIDEO_POWER_STANDBY,
+	DC_VIDEO_POWER_SUSPEND,
+	DC_VIDEO_POWER_OFF,
+	DC_VIDEO_POWER_HIBERNATE,
+	DC_VIDEO_POWER_SHUTDOWN,
+	DC_VIDEO_POWER_ULPS,	/* BACO or Ultra-Light-Power-State */
+	DC_VIDEO_POWER_AFTER_RESET,
+	DC_VIDEO_POWER_MAXIMUM
+};
+
+enum dc_acpi_cm_power_state {
+	DC_ACPI_CM_POWER_STATE_D0 = 1,
+	DC_ACPI_CM_POWER_STATE_D1 = 2,
+	DC_ACPI_CM_POWER_STATE_D2 = 4,
+	DC_ACPI_CM_POWER_STATE_D3 = 8
+};
+
+struct view_port_alignment {
+	uint8_t x_width_size_alignment;
+	uint8_t y_height_size_alignment;
+	uint8_t x_start_alignment;
+	uint8_t y_start_alignment;
+};
+
+enum dc_connection_type {
+	dc_connection_none,
+	dc_connection_single,
+	dc_connection_mst_branch,
+	dc_connection_active_dongle
+};
+
+/*
+ * Gamma ramp representation in DC
+ *
+ * A gamma ramp is just a curve defined within the range of [min, max] with
+ * arbitrary precision.
+ *
+ * DM is responsible for providing DC with an interface to obtain any y value
+ * within that range with a selected precision.
+ *
+ * bit32 ------------------------------------------------- bit 0
+ *       [  padding  ][ exponent bits ][  fraction bits  ]
+ *
+ * DC specifies the input x value and precision to the callback function
+ * get_gamma_value as well as providing the context and DM returns the y
+ * value.
+ *
+ * If fraction_bits + exponent_bits exceed width of 32 bits, get_gamma_value
+ * returns 0.  If x is outside the bounds of [min, max], get_gamma_value
+ * returns 0.
+ *
+ */
+/* TODO: Deprecated */
+enum {
+	RGB_256X3X16 = 256,
+	DX_GAMMA_RAMP_MAX = 1025
+};
+
+enum gamma_ramp_type {
+	GAMMA_RAMP_UNINITIALIZED = 0,
+	GAMMA_RAMP_DEFAULT,
+	GAMMA_RAMP_RBG256X3X16,
+	GAMMA_RAMP_DXGI_1,
+};
+
+struct dxgi_rgb {
+	struct fixed32_32 red;
+	struct fixed32_32 green;
+	struct fixed32_32 blue;
+};
+
+struct gamma_ramp_dxgi_1 {
+	struct dxgi_rgb scale;
+	struct dxgi_rgb offset;
+	struct dxgi_rgb gamma_curve[DX_GAMMA_RAMP_MAX];
+};
+
+struct gamma_ramp_rgb256x3x16 {
+	uint16_t red[RGB_256X3X16];
+	uint16_t green[RGB_256X3X16];
+	uint16_t blue[RGB_256X3X16];
+};
+
+struct gamma_ramp {
+	enum gamma_ramp_type type;
+	union {
+		struct gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16;
+		struct gamma_ramp_dxgi_1 gamma_ramp_dxgi1;
+	};
+	uint32_t size;
+};
+
+
+struct dc_gamma_ramp {
+	uint32_t (*get_gamma_value) (
+			void *context,
+			uint8_t exponent_bits,
+			uint8_t fraction_bits,
+			uint32_t x);
+	void *context;
+	uint32_t min;
+	uint32_t max;
+};
+
+struct dc_csc_adjustments {
+	struct fixed31_32 contrast;
+	struct fixed31_32 saturation;
+	struct fixed31_32 brightness;
+	struct fixed31_32 hue;
+};
+
+
+enum {
+	MAX_LANES = 2,
+	MAX_COFUNC_PATH = 6,
+	LAYER_INDEX_PRIMARY = -1,
+};
+
+/* Scaling format */
+enum scaling_transformation {
+	SCALING_TRANSFORMATION_UNINITIALIZED,
+	SCALING_TRANSFORMATION_IDENTITY = 0x0001,
+	SCALING_TRANSFORMATION_CENTER_TIMING = 0x0002,
+	SCALING_TRANSFORMATION_FULL_SCREEN_SCALE = 0x0004,
+	SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE = 0x0008,
+	SCALING_TRANSFORMATION_DAL_DECIDE = 0x0010,
+	SCALING_TRANSFORMATION_INVALID = 0x80000000,
+
+	/* Flag the first and last */
+	SCALING_TRANSFORMATION_BEGING = SCALING_TRANSFORMATION_IDENTITY,
+	SCALING_TRANSFORMATION_END =
+		SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE
+};
+
+struct view_stereo_3d_support {
+	enum view_3d_format format;
+	struct {
+		uint32_t CLONE_MODE:1;
+		uint32_t SCALING:1;
+		uint32_t SINGLE_FRAME_SW_PACKED:1;
+	} features;
+};
+
+enum tiling_mode {
+	TILING_MODE_INVALID,
+	TILING_MODE_LINEAR,
+	TILING_MODE_TILED,
+	TILING_MODE_COUNT
+};
+
+struct view_position {
+	uint32_t x;
+	uint32_t y;
+};
+
+struct render_mode {
+	struct view view;
+	enum pixel_format pixel_format;
+};
+
+struct pixel_format_support {
+	bool INDEX8 :1;
+	bool RGB565 :1;
+	bool ARGB8888 :1;
+	bool ARGB2101010 :1;
+	bool ARGB2101010_XRBIAS :1;
+	bool FP16 :1;
+};
+
+struct stereo_3d_view {
+	enum view_3d_format view_3d_format;
+	union {
+		uint32_t raw;
+		struct /*stereo_3d_view_flags*/
+		{
+			bool SINGLE_FRAME_SW_PACKED :1;
+			bool EXCLUSIVE_3D :1;
+		} bits;
+	} flags;
+};
+
+/* TODO: These values come from hardware spec. We need to readdress this
+ * if they ever change.
+ */
+enum array_mode_values {
+	DC_ARRAY_UNDEFINED = 0,
+	DC_ARRAY_1D_TILED_THIN1 = 0x2,
+	DC_ARRAY_2D_TILED_THIN1 = 0x4,
+};
+
+
+enum tile_mode_values {
+	DC_ADDR_SURF_MICRO_TILING_DISPLAY = 0x0,
+	DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1,
+};
+
+enum tile_split_values {
+	DC_DISPLAY_MICRO_TILING = 0x0,
+	DC_THIN_MICRO_TILING = 0x1,
+	DC_DEPTH_MICRO_TILING = 0x2,
+	DC_ROTATED_MICRO_TILING = 0x3,
+};
+
+struct dc_tiling_info {
+
+	/* Specifies the number of memory banks for tiling
+	 *	purposes.
+	 * Only applies to 2D and 3D tiling modes.
+	 *	POSSIBLE VALUES: 2,4,8,16
+	 */
+	unsigned int num_banks;
+	/* Specifies the number of tiles in the x direction
+	 *	to be incorporated into the same bank.
+	 * Only applies to 2D and 3D tiling modes.
+	 *	POSSIBLE VALUES: 1,2,4,8
+	 */
+	unsigned int bank_width;
+	/* Specifies the number of tiles in the y direction to
+	 *	be incorporated into the same bank.
+	 * Only applies to 2D and 3D tiling modes.
+	 *	POSSIBLE VALUES: 1,2,4,8
+	 */
+	unsigned int bank_height;
+	/* Specifies the macro tile aspect ratio. Only applies
+	 * to 2D and 3D tiling modes.
+	 */
+	unsigned int tile_aspect;
+	/* Specifies the number of bytes that will be stored
+	 *	contiguously for each tile.
+	 * If the tile data requires more storage than this
+	 *	amount, it is split into multiple slices.
+	 * This field must not be larger than
+	 *	GB_ADDR_CONFIG.DRAM_ROW_SIZE.
+	 * Only applies to 2D and 3D tiling modes.
+	 * For color render targets, TILE_SPLIT >= 256B.
+	 */
+	enum tile_split_values tile_split;
+	/* Specifies the addressing within a tile.
+	 *	0x0 - DISPLAY_MICRO_TILING
+	 *	0x1 - THIN_MICRO_TILING
+	 *	0x2 - DEPTH_MICRO_TILING
+	 *	0x3 - ROTATED_MICRO_TILING
+	 */
+	enum tile_mode_values tile_mode;
+	/* Specifies the number of pipes and how they are
+	 *	interleaved in the surface.
+	 * Refer to memory addressing document for complete
+	 *	details and constraints.
+	 */
+	unsigned int pipe_config;
+	/* Specifies the tiling mode of the surface.
+	 * THIN tiles use an 8x8x1 tile size.
+	 * THICK tiles use an 8x8x4 tile size.
+	 * 2D tiling modes rotate banks for successive Z slices
+	 * 3D tiling modes rotate pipes and banks for Z slices
+	 * Refer to memory addressing document for complete
+	 *	details and constraints.
+	 */
+	enum array_mode_values array_mode;
+};
+
+union plane_size {
+	/* Grph or Video will be selected
+	 * based on format above:
+	 * Use Video structure if
+	 * format >= DalPixelFormat_VideoBegin
+	 * else use Grph structure
+	 */
+	struct {
+		struct rect surface_size;
+		/* Graphic surface pitch in pixels.
+		 * In LINEAR_GENERAL mode, pitch
+		 * is 32 pixel aligned.
+		 */
+		uint32_t surface_pitch;
+	} grph;
+
+	struct {
+		struct rect luma_size;
+		/* Graphic surface pitch in pixels.
+		 * In LINEAR_GENERAL mode, pitch is
+		 * 32 pixel aligned.
+		 */
+		uint32_t luma_pitch;
+
+		struct rect chroma_size;
+		/* Graphic surface pitch in pixels.
+		 * In LINEAR_GENERAL mode, pitch is
+		 * 32 pixel aligned.
+		 */
+		uint32_t chroma_pitch;
+	} video;
+};
+
+#endif /* DC_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_helpers.h b/drivers/gpu/drm/amd/dal/dc/dm_helpers.h
new file mode 100644
index 000000000000..b6ce51080b86
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dm_helpers.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/**
+ * This file defines helper functions provided by the Display Manager to
+ * Display Core.
+ */
+#ifndef __DM_HELPERS__
+#define __DM_HELPERS__
+
+#include "dc_types.h"
+#include "dc.h"
+
+struct dp_mst_stream_allocation_table;
+
+enum dc_edid_status dm_helpers_parse_edid_caps(
+	struct dc_context *ctx,
+	const struct dc_edid *edid,
+	struct dc_edid_caps *edid_caps);
+
+/*
+ * Writes payload allocation table in immediate downstream device.
+ */
+bool dm_helpers_dp_mst_write_payload_allocation_table(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		struct dp_mst_stream_allocation_table *proposed_table,
+		bool enable);
+
+/*
+ * Polls for ACT (allocation change trigger) handled and
+ */
+bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+		struct dc_context *ctx,
+		const struct dc_stream *stream);
+/*
+ * Sends ALLOCATE_PAYLOAD message.
+ */
+bool dm_helpers_dp_mst_send_payload_allocation(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		bool enable);
+
+void dm_helpers_dp_mst_handle_mst_hpd_rx_irq(
+		void *param);
+
+bool dm_helpers_dp_mst_start_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		bool boot);
+
+void dm_helpers_dp_mst_stop_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link);
+
+/**
+ * OS specific aux read callback.
+ */
+bool dm_helper_dp_read_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size);
+
+/**
+ * OS specific aux write callback.
+ */
+bool dm_helper_dp_write_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t size);
+
+#endif /* __DM_HELPERS__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services.h b/drivers/gpu/drm/amd/dal/dc/dm_services.h
new file mode 100644
index 000000000000..206c0b7df7c6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dm_services.h
@@ -0,0 +1,485 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/**
+ * This file defines external dependencies of Display Core.
+ */
+
+#ifndef __DM_SERVICES_H__
+
+#define __DM_SERVICES_H__
+
+/* TODO: remove when DC is complete. */
+#include "dm_services_types.h"
+#include "logger_interface.h"
+#include "include/dal_types.h"
+#include "irq_types.h"
+#include "link_service_types.h"
+
+#undef DEPRECATED
+
+/* if the pointer is not NULL, the allocated memory is zeroed */
+void *dm_alloc(struct dc_context *ctx, uint32_t size);
+
+/* reallocate memory. The contents will remain unchanged.*/
+void *dm_realloc(struct dc_context *ctx, const void *ptr, uint32_t size);
+
+void dm_free(struct dc_context *ctx, void *p);
+
+void dm_memset(void *p, int32_t c, uint32_t count);
+
+void dm_memmove(void *dst, const void *src, uint32_t size);
+
+int32_t dm_memcmp(const void *p1, const void *p2, uint32_t count);
+
+int32_t dm_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count);
+
+irq_handler_idx dm_register_interrupt(
+	struct dc_context *ctx,
+	struct dc_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *handler_args);
+
+void dm_unregister_interrupt(
+	struct dc_context *ctx,
+	enum dc_irq_source irq_source,
+	irq_handler_idx handler_idx);
+
+/*
+ *
+ * GPU registers access
+ *
+ */
+
+#define dm_read_reg(ctx, address)	\
+		dm_read_reg_func(ctx, address, __func__)
+
+static inline uint32_t dm_read_reg_func(
+	const struct dc_context *ctx,
+	uint32_t address,
+	const char *func_name)
+{
+	uint32_t value = cgs_read_register(ctx->cgs_device, address);
+
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s DC_READ_REG: 0x%x 0x%x\n", func_name, address, value);
+	}
+#endif
+	return value;
+}
+
+#define dm_write_reg(ctx, address, value)	\
+	dm_write_reg_func(ctx, address, value, __func__)
+
+static inline void dm_write_reg_func(
+	const struct dc_context *ctx,
+	uint32_t address,
+	uint32_t value,
+	const char *func_name)
+{
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s DC_WRITE_REG: 0x%x 0x%x\n", func_name, address, value);
+	}
+#endif
+	cgs_write_register(ctx->cgs_device, address, value);
+}
+
+static inline uint32_t dm_read_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index)
+{
+	return cgs_read_ind_register(ctx->cgs_device, addr_space, index);
+}
+
+static inline void dm_write_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index,
+	uint32_t value)
+{
+	cgs_write_ind_register(ctx->cgs_device, addr_space, index, value);
+}
+
+static inline uint32_t get_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (mask & reg_value) >> shift;
+}
+
+#define get_reg_field_value(reg_value, reg_name, reg_field)\
+	get_reg_field_value_ex(\
+		(reg_value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+static inline uint32_t set_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (reg_value & ~mask) | (mask & (value << shift));
+}
+
+#define set_reg_field_value(reg_value, value, reg_name, reg_field)\
+	(reg_value) = set_reg_field_value_ex(\
+		(reg_value),\
+		(value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+/*
+ * atombios services
+ */
+
+bool dm_exec_bios_cmd_table(
+	struct dc_context *ctx,
+	uint32_t index,
+	void *params);
+
+#ifdef BUILD_DAL_TEST
+uint32_t dm_bios_cmd_table_para_revision(
+struct dc_context *ctx,
+	uint32_t index);
+
+bool dm_bios_cmd_table_revision(
+	struct dc_context *ctx,
+	uint32_t index,
+	uint8_t *frev,
+	uint8_t *crev);
+#endif
+
+#ifndef BUILD_DAL_TEST
+static inline uint32_t dm_bios_cmd_table_para_revision(
+	struct dc_context *ctx,
+	uint32_t index)
+{
+	uint8_t frev;
+	uint8_t crev;
+
+	if (cgs_atom_get_cmd_table_revs(
+			ctx->cgs_device,
+			index,
+			&frev,
+			&crev) != 0)
+		return 0;
+
+	return crev;
+}
+#else
+uint32_t dm_bios_cmd_table_para_revision(
+		struct dc_context *ctx,
+		uint32_t index);
+#endif
+
+/**************************************
+ * Power Play (PP) interfaces
+ **************************************/
+
+enum dal_to_power_clocks_state {
+	PP_CLOCKS_STATE_INVALID,
+	PP_CLOCKS_STATE_ULTRA_LOW,
+	PP_CLOCKS_STATE_LOW,
+	PP_CLOCKS_STATE_NOMINAL,
+	PP_CLOCKS_STATE_PERFORMANCE
+};
+
+/* clocks in khz */
+struct dal_to_power_info {
+	enum dal_to_power_clocks_state required_clock;
+	uint32_t min_sclk;
+	uint32_t min_mclk;
+	uint32_t min_deep_sleep_sclk;
+};
+
+/* clocks in khz */
+struct power_to_dal_info {
+	uint32_t min_sclk;
+	uint32_t max_sclk;
+	uint32_t min_mclk;
+	uint32_t max_mclk;
+};
+
+/* clocks in khz */
+struct dal_system_clock_range {
+	uint32_t min_sclk;
+	uint32_t max_sclk;
+
+	uint32_t min_mclk;
+	uint32_t max_mclk;
+
+	uint32_t min_dclk;
+	uint32_t max_dclk;
+
+	/* Wireless Display */
+	uint32_t min_eclk;
+	uint32_t max_eclk;
+};
+
+/* clocks in khz */
+struct dal_to_power_dclk {
+	uint32_t optimal; /* input: best optimizes for stutter efficiency */
+	uint32_t minimal; /* input: the lowest clk that DAL can support */
+	uint32_t established; /* output: the actually set one */
+};
+
+/* DAL calls this function to notify PP about clocks it needs for the Mode Set.
+ * This is done *before* it changes DCE clock.
+ *
+ * If required clock is higher than current, then PP will increase the voltage.
+ *
+ * If required clock is lower than current, then PP will defer reduction of
+ * voltage until the call to dc_service_pp_post_dce_clock_change().
+ *
+ * \input - Contains clocks needed for Mode Set.
+ *
+ * \output - Contains clocks adjusted by PP which DAL should use for Mode Set.
+ *		Valid only if function returns zero.
+ *
+ * \returns	true - call is successful
+ *		false - call failed
+ */
+bool dm_pp_pre_dce_clock_change(
+	struct dc_context *ctx,
+	struct dal_to_power_info *input,
+	struct power_to_dal_info *output);
+
+struct dc_pp_single_disp_config {
+	enum signal_type signal;
+	uint8_t transmitter;
+	uint8_t ddi_channel_mapping;
+	uint8_t pipe_idx;
+	uint32_t src_height;
+	uint32_t src_width;
+	uint32_t v_refresh;
+	uint32_t sym_clock; /* HDMI only */
+	struct link_settings link_settings; /* DP only */
+};
+
+struct dc_pp_display_configuration {
+	bool nb_pstate_switch_disable;/* controls NB PState switch */
+	bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */
+	bool cpu_pstate_disable;
+	uint32_t cpu_pstate_separation_time;
+
+	uint32_t min_memory_clock_khz;
+	uint32_t min_engine_clock_khz;
+	uint32_t min_engine_clock_deep_sleep_khz;
+
+	uint32_t avail_mclk_switch_time_us;
+	uint32_t avail_mclk_switch_time_in_disp_active_us;
+
+	uint32_t disp_clk_khz;
+
+	bool all_displays_in_sync;
+
+	uint8_t display_count;
+	struct dc_pp_single_disp_config disp_configs[3];
+
+	/*Controller Index of primary display - used in MCLK SMC switching hang
+	 * SW Workaround*/
+	uint8_t crtc_index;
+	/*htotal*1000/pixelclk - used in MCLK SMC switching hang SW Workaround*/
+	uint32_t line_time_in_us;
+};
+
+enum dc_pp_clocks_state {
+	DC_PP_CLOCKS_STATE_INVALID = 0,
+	DC_PP_CLOCKS_STATE_ULTRA_LOW,
+	DC_PP_CLOCKS_STATE_LOW,
+	DC_PP_CLOCKS_STATE_NOMINAL,
+	DC_PP_CLOCKS_STATE_PERFORMANCE,
+
+	/* Starting from DCE11, Max 8 levels of DPM state supported. */
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_INVALID = DC_PP_CLOCKS_STATE_INVALID,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_0 = DC_PP_CLOCKS_STATE_ULTRA_LOW,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_1 = DC_PP_CLOCKS_STATE_LOW,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_2 = DC_PP_CLOCKS_STATE_NOMINAL,
+	/* to be backward compatible */
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_3 = DC_PP_CLOCKS_STATE_PERFORMANCE,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_4 = DC_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_5 = DC_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_6 = DC_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_7 = DC_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1,
+};
+
+struct dc_pp_static_clock_info {
+	uint32_t max_sclk_khz;
+	uint32_t max_mclk_khz;
+
+	 /* max possible display block clocks state */
+	enum dc_pp_clocks_state max_clocks_state;
+};
+
+/* The returned clocks range are 'static' system clocks which will be used for
+ * mode validation purposes.
+ *
+ * \returns	true - call is successful
+ *		false - call failed
+ */
+bool dc_service_get_system_clocks_range(
+	const struct dc_context *ctx,
+	struct dal_system_clock_range *sys_clks);
+
+enum dc_pp_clock_type {
+	DC_PP_CLOCK_TYPE_DISPLAY_CLK = 1,
+	DC_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */
+	DC_PP_CLOCK_TYPE_MEMORY_CLK
+};
+
+#define DC_DECODE_PP_CLOCK_TYPE(clk_type) \
+	(clk_type) == DC_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \
+	(clk_type) == DC_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \
+	(clk_type) == DC_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid"
+
+#define DC_PP_MAX_CLOCK_LEVELS 8
+
+struct dc_pp_clock_levels {
+	uint32_t num_levels;
+	uint32_t clocks_in_khz[DC_PP_MAX_CLOCK_LEVELS];
+};
+
+/* Gets valid clocks levels from pplib
+ *
+ * input: clk_type - display clk / sclk / mem clk
+ *
+ * output: array of valid clock levels for given type in ascending order,
+ * with invalid levels filtered out
+ *
+ */
+bool dm_pp_get_clock_levels_by_type(
+	const struct dc_context *ctx,
+	enum dc_pp_clock_type clk_type,
+	struct dc_pp_clock_levels *clk_level_info);
+
+
+bool dm_pp_apply_safe_state(
+		const struct dc_context *ctx);
+
+/* DAL calls this function to notify PP about completion of Mode Set.
+ * For PP it means that current DCE clocks are those which were returned
+ * by dc_service_pp_pre_dce_clock_change(), in the 'output' parameter.
+ *
+ * If the clocks are higher than before, then PP does nothing.
+ *
+ * If the clocks are lower than before, then PP reduces the voltage.
+ *
+ * \returns	true - call is successful
+ *		false - call failed
+ */
+bool dm_pp_apply_display_requirements(
+	const struct dc_context *ctx,
+	const struct dc_pp_display_configuration *pp_display_cfg);
+
+
+/****** end of PP interfaces ******/
+
+void dm_sleep_in_milliseconds(struct dc_context *ctx, uint32_t milliseconds);
+
+void dm_delay_in_microseconds(struct dc_context *ctx, uint32_t microseconds);
+
+enum platform_method {
+	PM_GET_AVAILABLE_METHODS = 1 << 0,
+	PM_GET_LID_STATE = 1 << 1,
+	PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2
+};
+
+struct platform_info_params {
+	enum platform_method method;
+	void *data;
+};
+
+struct platform_info_brightness_caps {
+	uint8_t ac_level_percentage;
+	uint8_t dc_level_percentage;
+};
+
+struct platform_info_ext_brightness_caps {
+	struct platform_info_brightness_caps basic_caps;
+	struct data_point {
+		uint8_t luminance;
+		uint8_t	signal_level;
+	} data_points[99];
+
+	uint8_t	data_points_num;
+	uint8_t	min_input_signal;
+	uint8_t	max_input_signal;
+};
+
+bool dm_get_platform_info(
+	struct dc_context *ctx,
+	struct platform_info_params *params);
+
+/*
+ *
+ * print-out services
+ *
+ */
+#define dm_log_to_buffer(buffer, size, fmt, args)\
+	vsnprintf(buffer, size, fmt, args)
+
+long dm_get_pid(void);
+long dm_get_tgid(void);
+
+/*
+ *
+ * general debug capabilities
+ *
+ */
+#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER)
+
+#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB)
+#define ASSERT_CRITICAL(expr) do {	\
+	if (WARN_ON(!(expr))) { \
+		kgdb_breakpoint(); \
+	} \
+} while (0)
+#else
+#define ASSERT_CRITICAL(expr) do {	\
+	if (WARN_ON(!(expr))) { \
+		; \
+	} \
+} while (0)
+#endif
+
+#if defined(CONFIG_DEBUG_KERNEL_DAL)
+#define ASSERT(expr) ASSERT_CRITICAL(expr)
+
+#else
+#define ASSERT(expr) WARN_ON(!(expr))
+#endif
+
+#define BREAK_TO_DEBUGGER() ASSERT(0)
+
+#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */
+
+#endif /* __DM_SERVICES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services_types.h b/drivers/gpu/drm/amd/dal/dc/dm_services_types.h
new file mode 100644
index 000000000000..bc458aa41a5d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dm_services_types.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DM_SERVICES_TYPES_H__
+#define __DM_SERVICES_TYPES_H__
+
+#define INVALID_DISPLAY_INDEX 0xffffffff
+
+#if defined __KERNEL__
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <drm/drmP.h>
+
+#include "cgs_linux.h"
+
+#if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU)
+#define BIGENDIAN_CPU
+#elif defined(__LITTLE_ENDIAN) && !defined(LITTLEENDIAN_CPU)
+#define LITTLEENDIAN_CPU
+#endif
+
+#undef READ
+#undef WRITE
+#undef FRAME_SIZE
+
+#define dm_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__)
+
+#define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__)
+
+#define dm_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__)
+
+#define dm_vlog(fmt, args) vprintk(fmt, args)
+
+#define dm_min(x, y) min(x, y)
+#define dm_max(x, y) max(x, y)
+
+#elif defined BUILD_DAL_TEST
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdio.h>
+
+#include <stdarg.h>
+
+#include "cgs_linux.h"
+
+#define LONG_MAX	((long)(~0UL>>1))
+#define LONG_MIN	(-LONG_MAX - 1)
+#define LLONG_MAX	((long long)(~0ULL>>1))
+#define LLONG_MIN	(-LLONG_MAX - 1)
+#define UINT_MAX	(~0U)
+
+typedef _Bool bool;
+enum { false, true };
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define LITTLEENDIAN_CPU 1
+
+#include <test_context.h>
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#define container_of(ptr, type, member) \
+	((type *)((char *)(ptr) - offsetof(type, member)))
+
+#define dal_test_not_implemented() \
+	printf("[DAL_TEST_NOT_IMPL]:%s\n", __func__)
+
+#define dm_output_to_console(fmt, ...) do { \
+	printf("[DAL_LOG]" fmt, ##__VA_ARGS__); } \
+	while (false)
+
+#define dm_error(fmt, ...) printf("[DAL_ERROR]" fmt, ##__VA_ARGS__)
+
+#define dm_output_to_console(fmt, ...) do { \
+			printf("[DAL_LOG]" fmt, ##__VA_ARGS__); } \
+				while (false)
+
+
+#define dm_debug(fmt, ...) printf("[DAL_DBG]" fmt, ##__VA_ARGS__)
+
+#define dm_vlog(fmt, args) vprintf(fmt, args)
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+#define dm_min(x, y) ({\
+	typeof(x) _min1 = (x);\
+	typeof(y) _min2 = (y);\
+	(void) (&_min1 == &_min2);\
+	_min1 < _min2 ? _min1 : _min2; })
+
+#define dm_max(x, y) ({\
+	typeof(x) _max1 = (x);\
+	typeof(y) _max2 = (y);\
+	(void) (&_max1 == &_max2);\
+	_max1 > _max2 ? _max1 : _max2; })
+
+/* division functions */
+
+static inline int64_t div64_s64(int64_t x, int64_t y)
+{
+	return x / y;
+}
+
+static inline uint64_t div64_u64(uint64_t x, uint64_t y)
+{
+	return x / y;
+}
+
+static inline uint64_t div_u64(uint64_t x, uint32_t y)
+{
+	return x / y;
+}
+
+static inline uint64_t div64_u64_rem(uint64_t x, uint64_t y, uint64_t *rem)
+{
+	if (rem)
+		*rem = x % y;
+	return x / y;
+}
+
+static inline uint64_t div_u64_rem(uint64_t x, uint32_t y, uint32_t *rem)
+{
+	if (rem)
+		*rem = x % y;
+	return x / y;
+}
+
+#define cpu_to_le16(do_nothing) do_nothing
+
+#define le16_to_cpu(do_nothing) do_nothing
+
+#define cpu_to_le32(do_nothing) do_nothing
+
+#define le32_to_cpu(do_nothing) do_nothing
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
new file mode 100644
index 000000000000..0d228ed0455c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/**
+ * Bandwidth and Watermark calculations interface.
+ * (Refer to "DCE11_mode_support.xlsm" from Perforce.)
+ */
+#ifndef __BANDWIDTH_CALCS_H__
+#define __BANDWIDTH_CALCS_H__
+
+#include "bw_fixed.h"
+/*******************************************************************************
+ * There are three types of input into Calculations:
+ * 1. per-DCE static values - these are "hardcoded" properties of the DCEIP
+ * 2. board-level values - these are generally coming from VBIOS parser
+ * 3. mode/configuration values - depending Mode, Scaling number of Displays etc.
+ ******************************************************************************/
+enum bw_defines {
+	/*Common*/
+	bw_def_no = 0,
+	bw_def_none = 0,
+	bw_def_yes = 1,
+	bw_def_ok = 1,
+	bw_def_high = 2,
+	bw_def_mid = 1,
+	bw_def_low = 0,
+
+	/*Internal*/
+	bw_defs_start = 255,
+	bw_def_underlay422,
+	bw_def_underlay420_luma,
+	bw_def_underlay420_chroma,
+	bw_def_underlay444,
+	bw_def_graphics,
+	bw_def_display_write_back420_luma,
+	bw_def_display_write_back420_chroma,
+	bw_def_portrait,
+	bw_def_hsr_mtn_4,
+	bw_def_hsr_mtn_h_taps,
+	bw_def_ceiling__h_taps_div_4___meq_hsr,
+	bw_def_invalid_linear_or_stereo_mode,
+	bw_def_invalid_rotation_or_bpp_or_stereo,
+	bw_def_vsr_mtn_v_taps,
+	bw_def_vsr_mtn_4,
+	bw_def_auto,
+	bw_def_manual,
+	bw_def_exceeded_allowed_maximum_sclk,
+	bw_def_exceeded_allowed_page_close_open,
+	bw_def_exceeded_allowed_outstanding_pte_req_queue_size,
+	bw_def_exceeded_allowed_maximum_bw,
+	bw_def_high_no_nbp_state_change,
+	bw_def_landscape,
+
+	/*Panning and bezel*/
+	bw_def_any_lines,
+
+	/*Underlay mode*/
+	bw_def_underlay_only,
+	bw_def_blended,
+	bw_def_blend,
+
+	/*Stereo mode*/
+	bw_def_mono,
+	bw_def_side_by_side,
+	bw_def_top_bottom,
+
+	/*Underlay surface type*/
+	bw_def_420,
+	bw_def_422,
+	bw_def_444,
+
+	/*Tiling mode*/
+	bw_def_linear,
+	bw_def_tiled,
+
+	bw_def_notok = -1,
+	bw_def_na = -1
+};
+
+struct bw_calcs_dceip {
+	struct bw_fixed dmif_request_buffer_size;
+	struct bw_fixed de_tiling_buffer;
+	bool dcfclk_request_generation;
+	uint32_t lines_interleaved_into_lb;
+	uint32_t chunk_width;
+	uint32_t number_of_graphics_pipes;
+	uint32_t number_of_underlay_pipes;
+	bool display_write_back_supported;
+	bool argb_compression_support;
+	struct bw_fixed underlay_vscaler_efficiency6_bit_per_component;
+	struct bw_fixed underlay_vscaler_efficiency8_bit_per_component;
+	struct bw_fixed underlay_vscaler_efficiency10_bit_per_component;
+	struct bw_fixed underlay_vscaler_efficiency12_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency6_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency8_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency10_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency12_bit_per_component;
+	struct bw_fixed alpha_vscaler_efficiency;
+	uint32_t max_dmif_buffer_allocated;
+	uint32_t graphics_dmif_size;
+	uint32_t underlay_luma_dmif_size;
+	uint32_t underlay_chroma_dmif_size;
+	bool pre_downscaler_enabled;
+	bool underlay_downscale_prefetch_enabled;
+	struct bw_fixed lb_write_pixels_per_dispclk;
+	struct bw_fixed lb_size_per_component444;
+	bool graphics_lb_nodownscaling_multi_line_prefetching;
+	struct bw_fixed stutter_and_dram_clock_state_change_gated_before_cursor;
+	struct bw_fixed underlay420_luma_lb_size_per_component;
+	struct bw_fixed underlay420_chroma_lb_size_per_component;
+	struct bw_fixed underlay422_lb_size_per_component;
+	struct bw_fixed cursor_chunk_width;
+	struct bw_fixed cursor_dcp_buffer_lines;
+	struct bw_fixed cursor_memory_interface_buffer_pixels;
+	struct bw_fixed underlay_maximum_width_efficient_for_tiling;
+	struct bw_fixed underlay_maximum_height_efficient_for_tiling;
+	struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display;
+	struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation;
+	struct bw_fixed minimum_outstanding_pte_request_limit;
+	struct bw_fixed maximum_total_outstanding_pte_requests_allowed_by_saw;
+	bool limit_excessive_outstanding_dmif_requests;
+	struct bw_fixed linear_mode_line_request_alternation_slice;
+	uint32_t scatter_gather_lines_of_pte_prefetching_in_linear_mode;
+	uint32_t display_write_back420_luma_mcifwr_buffer_size;
+	uint32_t display_write_back420_chroma_mcifwr_buffer_size;
+	struct bw_fixed request_efficiency;
+	struct bw_fixed dispclk_per_request;
+	struct bw_fixed dispclk_ramping_factor;
+	struct bw_fixed display_pipe_throughput_factor;
+	uint32_t scatter_gather_pte_request_rows_in_tiling_mode;
+	struct bw_fixed mcifwr_all_surfaces_burst_time; /* 0 todo: this is a bug*/
+};
+
+struct bw_calcs_vbios {
+	uint32_t dram_channel_width_in_bits;
+	uint32_t number_of_dram_channels;
+	uint32_t number_of_dram_banks;
+	struct bw_fixed high_yclk; /*MHz*/
+	struct bw_fixed mid_yclk; /*MHz*/
+	struct bw_fixed low_yclk; /*MHz*/
+	struct bw_fixed low_sclk; /*MHz*/
+	struct bw_fixed mid_sclk; /*MHz*/
+	struct bw_fixed high_sclk; /*MHz*/
+	struct bw_fixed low_voltage_max_dispclk; /*MHz*/
+	struct bw_fixed mid_voltage_max_dispclk; /*MHz*/
+	struct bw_fixed high_voltage_max_dispclk; /*MHz*/
+	struct bw_fixed data_return_bus_width;
+	struct bw_fixed trc;
+	struct bw_fixed dmifmc_urgent_latency;
+	struct bw_fixed stutter_self_refresh_exit_latency;
+	struct bw_fixed nbp_state_change_latency;
+	struct bw_fixed mcifwrmc_urgent_latency;
+	bool scatter_gather_enable;
+	struct bw_fixed down_spread_percentage;
+	uint32_t cursor_width;
+	uint32_t average_compression_rate;
+	uint32_t number_of_request_slots_gmc_reserves_for_dmif_per_channel;
+	struct bw_fixed blackout_duration;
+	struct bw_fixed maximum_blackout_recovery_time;
+};
+
+struct bw_calcs_mode_data_internal {
+	/* data for all displays */
+	uint32_t number_of_displays;
+	uint32_t graphics_rotation_angle;
+	uint32_t underlay_rotation_angle;
+	enum bw_defines display_synchronization_enabled;
+	enum bw_defines underlay_surface_type;
+	enum bw_defines panning_and_bezel_adjustment;
+	enum bw_defines graphics_tiling_mode;
+	bool graphics_interlace_mode;
+	uint32_t graphics_bytes_per_pixel;
+	uint32_t graphics_htaps;
+	uint32_t graphics_vtaps;
+	uint32_t graphics_lb_bpc;
+	uint32_t underlay_lb_bpc;
+	enum bw_defines underlay_tiling_mode;
+	uint32_t underlay_htaps;
+	uint32_t underlay_vtaps;
+	uint32_t underlay_src_width;
+	uint32_t underlay_src_height;
+	uint32_t underlay_pitch_in_pixels;
+	enum bw_defines underlay_stereo_mode;
+	bool d0_fbc_enable;
+	bool d0_lpt_enable;
+	uint32_t d0_htotal;
+	struct bw_fixed d0_pixel_rate;
+	uint32_t d0_graphics_src_width;
+	uint32_t d0_graphics_src_height;
+	struct bw_fixed d0_graphics_scale_ratio;
+	enum bw_defines d0_graphics_stereo_mode;
+	enum bw_defines d0_underlay_mode;
+	struct bw_fixed d0_underlay_scale_ratio;
+	uint32_t d1_htotal;
+	struct bw_fixed d1_pixel_rate;
+	uint32_t d1_graphics_src_width;
+	uint32_t d1_graphics_src_height;
+	struct bw_fixed d1_graphics_scale_ratio;
+	enum bw_defines d1_graphics_stereo_mode;
+	bool d1_display_write_back_dwb_enable;
+	enum bw_defines d1_underlay_mode;
+	struct bw_fixed d1_underlay_scale_ratio;
+	uint32_t d2_htotal;
+	struct bw_fixed d2_pixel_rate;
+	uint32_t d2_graphics_src_width;
+	uint32_t d2_graphics_src_height;
+	struct bw_fixed d2_graphics_scale_ratio;
+	enum bw_defines d2_graphics_stereo_mode;
+};
+
+
+struct bw_calcs_input_single_display {
+	uint32_t graphics_rotation_angle;
+	uint32_t underlay_rotation_angle;
+	enum bw_defines underlay_surface_type;
+	enum bw_defines panning_and_bezel_adjustment;
+	uint32_t graphics_bytes_per_pixel;
+	bool graphics_interlace_mode;
+	enum bw_defines graphics_tiling_mode;
+	uint32_t graphics_h_taps;
+	uint32_t graphics_v_taps;
+	uint32_t graphics_lb_bpc;
+	uint32_t underlay_lb_bpc;
+	enum bw_defines underlay_tiling_mode;
+	uint32_t underlay_h_taps;
+	uint32_t underlay_v_taps;
+	uint32_t underlay_src_width;
+	uint32_t underlay_src_height;
+	uint32_t underlay_pitch_in_pixels;
+	enum bw_defines underlay_stereo_mode;
+	bool fbc_enable;
+	bool lpt_enable;
+	uint32_t h_total;
+	struct bw_fixed pixel_rate;
+	uint32_t graphics_src_width;
+	uint32_t graphics_src_height;
+	struct bw_fixed graphics_scale_ratio;
+	enum bw_defines graphics_stereo_mode;
+	enum bw_defines underlay_mode;
+};
+
+#define BW_CALCS_MAX_NUM_DISPLAYS 3
+
+struct bw_calcs_mode_data {
+	/* data for all displays */
+	uint8_t number_of_displays;
+	bool display_synchronization_enabled;
+
+	struct bw_calcs_input_single_display
+				displays_data[BW_CALCS_MAX_NUM_DISPLAYS];
+};
+
+/*******************************************************************************
+ * Output data structure(s).
+ ******************************************************************************/
+#define maximum_number_of_surfaces 12
+/*Units : MHz, us */
+struct bw_calcs_results {
+	bool cpup_state_change_enable;
+	bool cpuc_state_change_enable;
+	bool nbp_state_change_enable;
+	bool stutter_mode_enable;
+	uint32_t y_clk_level;
+	uint32_t sclk_level;
+	uint32_t number_of_underlay_surfaces;
+	struct bw_fixed src_width_after_surface_type;
+	struct bw_fixed src_height_after_surface_type;
+	struct bw_fixed hsr_after_surface_type;
+	struct bw_fixed vsr_after_surface_type;
+	struct bw_fixed src_width_after_rotation;
+	struct bw_fixed src_height_after_rotation;
+	struct bw_fixed hsr_after_rotation;
+	struct bw_fixed vsr_after_rotation;
+	struct bw_fixed source_height_pixels;
+	struct bw_fixed hsr_after_stereo;
+	struct bw_fixed vsr_after_stereo;
+	struct bw_fixed source_width_in_lb;
+	struct bw_fixed lb_line_pitch;
+	struct bw_fixed underlay_maximum_source_efficient_for_tiling;
+	struct bw_fixed num_lines_at_frame_start;
+	struct bw_fixed min_dmif_size_in_time;
+	struct bw_fixed min_mcifwr_size_in_time;
+	struct bw_fixed total_requests_for_dmif_size;
+	struct bw_fixed peak_pte_request_to_eviction_ratio_limiting;
+	struct bw_fixed useful_pte_per_pte_request;
+	struct bw_fixed scatter_gather_pte_request_rows;
+	struct bw_fixed scatter_gather_row_height;
+	struct bw_fixed scatter_gather_pte_requests_in_vblank;
+	struct bw_fixed inefficient_linear_pitch_in_bytes;
+	struct bw_fixed inefficient_underlay_pitch_in_pixels;
+	struct bw_fixed minimum_underlay_pitch_padding_recommended_for_efficiency;
+	struct bw_fixed cursor_total_data;
+	struct bw_fixed cursor_total_request_groups;
+	struct bw_fixed scatter_gather_total_pte_requests;
+	struct bw_fixed scatter_gather_total_pte_request_groups;
+	struct bw_fixed tile_width_in_pixels;
+	struct bw_fixed dmif_total_number_of_data_request_page_close_open;
+	struct bw_fixed mcifwr_total_number_of_data_request_page_close_open;
+	struct bw_fixed bytes_per_page_close_open;
+	struct bw_fixed mcifwr_total_page_close_open_time;
+	struct bw_fixed total_requests_for_adjusted_dmif_size;
+	struct bw_fixed total_dmifmc_urgent_trips;
+	struct bw_fixed total_dmifmc_urgent_latency;
+	struct bw_fixed total_display_reads_required_data;
+	struct bw_fixed total_display_reads_required_dram_access_data;
+	struct bw_fixed total_display_writes_required_data;
+	struct bw_fixed total_display_writes_required_dram_access_data;
+	struct bw_fixed display_reads_required_data;
+	struct bw_fixed display_reads_required_dram_access_data;
+	struct bw_fixed dmif_total_page_close_open_time;
+	struct bw_fixed min_cursor_memory_interface_buffer_size_in_time;
+	struct bw_fixed min_read_buffer_size_in_time;
+	struct bw_fixed display_reads_time_for_data_transfer;
+	struct bw_fixed display_writes_time_for_data_transfer;
+	struct bw_fixed dmif_required_dram_bandwidth;
+	struct bw_fixed mcifwr_required_dram_bandwidth;
+	struct bw_fixed required_dmifmc_urgent_latency_for_page_close_open;
+	struct bw_fixed required_mcifmcwr_urgent_latency;
+	struct bw_fixed required_dram_bandwidth_gbyte_per_second;
+	struct bw_fixed dram_bandwidth;
+	struct bw_fixed dmif_required_sclk;
+	struct bw_fixed mcifwr_required_sclk;
+	struct bw_fixed required_sclk;
+	struct bw_fixed downspread_factor;
+	struct bw_fixed v_scaler_efficiency;
+	struct bw_fixed scaler_limits_factor;
+	struct bw_fixed display_pipe_pixel_throughput;
+	struct bw_fixed total_dispclk_required_with_ramping;
+	struct bw_fixed total_dispclk_required_without_ramping;
+	struct bw_fixed total_read_request_bandwidth;
+	struct bw_fixed total_write_request_bandwidth;
+	struct bw_fixed dispclk_required_for_total_read_request_bandwidth;
+	struct bw_fixed total_dispclk_required_with_ramping_with_request_bandwidth;
+	struct bw_fixed total_dispclk_required_without_ramping_with_request_bandwidth;
+	struct bw_fixed dispclk;
+	struct bw_fixed blackout_recovery_time;
+	struct bw_fixed min_pixels_per_data_fifo_entry;
+	struct bw_fixed sclk_deep_sleep;
+	struct bw_fixed chunk_request_time;
+	struct bw_fixed cursor_request_time;
+	struct bw_fixed line_source_pixels_transfer_time;
+	struct bw_fixed dmifdram_access_efficiency;
+	struct bw_fixed mcifwrdram_access_efficiency;
+	struct bw_fixed total_average_bandwidth_no_compression;
+	struct bw_fixed total_average_bandwidth;
+	struct bw_fixed total_stutter_cycle_duration;
+	struct bw_fixed stutter_burst_time;
+	struct bw_fixed time_in_self_refresh;
+	struct bw_fixed stutter_efficiency;
+	struct bw_fixed worst_number_of_trips_to_memory;
+	struct bw_fixed immediate_flip_time;
+	struct bw_fixed latency_for_non_dmif_clients;
+	struct bw_fixed latency_for_non_mcifwr_clients;
+	struct bw_fixed dmifmc_urgent_latency_supported_in_high_sclk_and_yclk;
+	struct bw_fixed nbp_state_dram_speed_change_margin;
+	struct bw_fixed display_reads_time_for_data_transfer_and_urgent_latency;
+	bool displays_match_flag[maximum_number_of_surfaces];
+	bool use_alpha[maximum_number_of_surfaces];
+	bool orthogonal_rotation[maximum_number_of_surfaces];
+	bool enable[maximum_number_of_surfaces];
+	bool access_one_channel_only[maximum_number_of_surfaces];
+	bool scatter_gather_enable_for_pipe[maximum_number_of_surfaces];
+	bool interlace_mode[maximum_number_of_surfaces];
+	bool display_pstate_change_enable[maximum_number_of_surfaces];
+	struct bw_fixed dmif_buffer_transfer_time[maximum_number_of_surfaces];
+	struct bw_fixed displays_with_same_mode[maximum_number_of_surfaces];
+	uint32_t bytes_per_pixel[maximum_number_of_surfaces];
+	struct bw_fixed h_total[maximum_number_of_surfaces];
+	struct bw_fixed pixel_rate[maximum_number_of_surfaces];
+	struct bw_fixed src_width[maximum_number_of_surfaces];
+	struct bw_fixed pitch_in_pixels[maximum_number_of_surfaces];
+	struct bw_fixed pitch_in_pixels_after_surface_type[maximum_number_of_surfaces];
+	struct bw_fixed src_height[maximum_number_of_surfaces];
+	struct bw_fixed scale_ratio[maximum_number_of_surfaces];
+	struct bw_fixed h_taps[maximum_number_of_surfaces];
+	struct bw_fixed v_taps[maximum_number_of_surfaces];
+	struct bw_fixed rotation_angle[maximum_number_of_surfaces];
+	uint32_t lb_bpc[maximum_number_of_surfaces];
+	struct bw_fixed compression_rate[maximum_number_of_surfaces];
+	struct bw_fixed hsr[maximum_number_of_surfaces];
+	struct bw_fixed vsr[maximum_number_of_surfaces];
+	struct bw_fixed source_width_rounded_up_to_chunks[maximum_number_of_surfaces];
+	struct bw_fixed source_width_pixels[maximum_number_of_surfaces];
+	struct bw_fixed source_height_rounded_up_to_chunks[maximum_number_of_surfaces];
+	struct bw_fixed display_bandwidth[maximum_number_of_surfaces];
+	struct bw_fixed request_bandwidth[maximum_number_of_surfaces];
+	struct bw_fixed bytes_per_request[maximum_number_of_surfaces];
+	struct bw_fixed useful_bytes_per_request[maximum_number_of_surfaces];
+	struct bw_fixed lines_interleaved_in_mem_access[maximum_number_of_surfaces];
+	struct bw_fixed latency_hiding_lines[maximum_number_of_surfaces];
+	struct bw_fixed lb_partitions[maximum_number_of_surfaces];
+	struct bw_fixed lb_partitions_max[maximum_number_of_surfaces];
+	struct bw_fixed dispclk_required_with_ramping[maximum_number_of_surfaces];
+	struct bw_fixed dispclk_required_without_ramping[maximum_number_of_surfaces];
+	struct bw_fixed data_buffer_size[maximum_number_of_surfaces];
+	struct bw_fixed outstanding_chunk_request_limit[maximum_number_of_surfaces];
+	struct bw_fixed urgent_watermark[maximum_number_of_surfaces];
+	struct bw_fixed stutter_exit_watermark[maximum_number_of_surfaces];
+	struct bw_fixed nbp_state_change_watermark[maximum_number_of_surfaces];
+	struct bw_fixed v_filter_init[maximum_number_of_surfaces];
+	struct bw_fixed stutter_cycle_duration[maximum_number_of_surfaces];
+	struct bw_fixed average_bandwidth[maximum_number_of_surfaces];
+	struct bw_fixed average_bandwidth_no_compression[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_pte_request_limit[maximum_number_of_surfaces];
+	struct bw_fixed lb_size_per_component[maximum_number_of_surfaces];
+	struct bw_fixed memory_chunk_size_in_bytes[maximum_number_of_surfaces];
+	struct bw_fixed pipe_chunk_size_in_bytes[maximum_number_of_surfaces];
+	struct bw_fixed number_of_trips_to_memory_for_getting_apte_row[maximum_number_of_surfaces];
+	struct bw_fixed adjusted_data_buffer_size[maximum_number_of_surfaces];
+	struct bw_fixed adjusted_data_buffer_size_in_memory[maximum_number_of_surfaces];
+	struct bw_fixed pixels_per_data_fifo_entry[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_pte_requests_in_row[maximum_number_of_surfaces];
+	struct bw_fixed pte_request_per_chunk[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_page_width[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_page_height[maximum_number_of_surfaces];
+	struct bw_fixed lb_lines_in_per_line_out_in_beginning_of_frame[maximum_number_of_surfaces];
+	struct bw_fixed lb_lines_in_per_line_out_in_middle_of_frame[maximum_number_of_surfaces];
+	struct bw_fixed cursor_width_pixels[maximum_number_of_surfaces];
+	bool line_buffer_prefetch[maximum_number_of_surfaces];
+	struct bw_fixed minimum_latency_hiding[maximum_number_of_surfaces];
+	struct bw_fixed maximum_latency_hiding[maximum_number_of_surfaces];
+	struct bw_fixed minimum_latency_hiding_with_cursor[maximum_number_of_surfaces];
+	struct bw_fixed maximum_latency_hiding_with_cursor[maximum_number_of_surfaces];
+	struct bw_fixed src_pixels_for_first_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed src_pixels_for_last_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed src_data_for_first_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed src_data_for_last_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed active_time[maximum_number_of_surfaces];
+	struct bw_fixed horizontal_blank_and_chunk_granularity_factor[maximum_number_of_surfaces];
+	struct bw_fixed cursor_latency_hiding[maximum_number_of_surfaces];
+	struct bw_fixed dmif_burst_time[3][3];
+	struct bw_fixed mcifwr_burst_time[3][3];
+	struct bw_fixed line_source_transfer_time[maximum_number_of_surfaces][3][3];
+	struct bw_fixed dram_speed_change_line_source_transfer_time[maximum_number_of_surfaces][3][3];
+	struct bw_fixed min_dram_speed_change_margin[3][3];
+	struct bw_fixed dram_speed_change_margin[3][3];
+	struct bw_fixed dispclk_required_for_dram_speed_change[3][3];
+	struct bw_fixed blackout_duration_margin[3][3];
+	struct bw_fixed dispclk_required_for_blackout_duration[3][3];
+	struct bw_fixed dispclk_required_for_blackout_recovery[3][3];
+	struct bw_fixed dmif_required_sclk_for_urgent_latency[6];
+};
+
+struct bw_watermarks {
+	uint32_t a_mark;
+	uint32_t b_mark;
+};
+
+struct bw_calcs_output {
+	bool cpuc_state_change_enable;
+	bool cpup_state_change_enable;
+	bool stutter_mode_enable;
+	bool nbp_state_change_enable;
+	bool all_displays_in_sync;
+	struct bw_watermarks urgent_wm_ns[4];
+	struct bw_watermarks stutter_exit_wm_ns[4];
+	struct bw_watermarks nbp_state_change_wm_ns[4];
+	uint32_t required_sclk;
+	uint32_t required_sclk_deep_sleep;
+	uint32_t required_yclk;
+	uint32_t dispclk_khz;
+	int32_t required_blackout_duration_us;
+};
+
+
+/**
+ * Initialize structures with data which will NOT change at runtime.
+ */
+void bw_calcs_init(
+	struct bw_calcs_dceip *bw_dceip,
+	struct bw_calcs_vbios *bw_vbios);
+
+/**
+ * Return:
+ *	true -	Display(s) configuration supported.
+ *		In this case 'calcs_output' contains data for HW programming
+ *	false - Display(s) configuration not supported (not enough bandwidth).
+ */
+bool bw_calcs(
+	struct dc_context *ctx,
+	const struct bw_calcs_dceip *dceip,
+	const struct bw_calcs_vbios *vbios,
+	const struct bw_calcs_mode_data *mode_data,
+	struct bw_calcs_output *calcs_output);
+
+
+#endif /* __BANDWIDTH_CALCS_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
new file mode 100644
index 000000000000..ff271cc0aea1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef BW_FIXED_H_
+#define BW_FIXED_H_
+
+struct bw_fixed {
+	int64_t value;
+};
+
+struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3);
+
+struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3);
+
+struct bw_fixed bw_int_to_fixed(int64_t value);
+
+int32_t bw_fixed_to_int(struct bw_fixed value);
+
+struct bw_fixed bw_frc_to_fixed(int64_t num, int64_t denum);
+
+struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw);
+
+struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2);
+
+struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_floor2(const struct bw_fixed arg, const struct bw_fixed significance);
+struct bw_fixed bw_ceil2(const struct bw_fixed arg, const struct bw_fixed significance);
+
+bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2);
+
+
+#endif //BW_FIXED_H_
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h b/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
new file mode 100644
index 000000000000..0120ee23e6be
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_CLOCK_SOURCE_H__
+#define __DC_CLOCK_SOURCE_H__
+
+#include "dc_types.h"
+#include "include/grph_object_id.h"
+#include "include/bios_parser_types.h"
+
+struct clock_source;
+
+struct spread_spectrum_data {
+	uint32_t percentage;		/*> In unit of 0.01% or 0.001%*/
+	uint32_t percentage_divider;	/*> 100 or 1000	*/
+	uint32_t freq_range_khz;
+	uint32_t modulation_freq_hz;
+
+	struct spread_spectrum_flags flags;
+};
+
+struct delta_sigma_data {
+	uint32_t feedback_amount;
+	uint32_t nfrac_amount;
+	uint32_t ds_frac_size;
+	uint32_t ds_frac_amount;
+};
+
+/**
+ *  Pixel Clock Parameters structure
+ *  These parameters are required as input
+ *  when calculating Pixel Clock Dividers for requested Pixel Clock
+ */
+struct pixel_clk_flags {
+	uint32_t ENABLE_SS:1;
+	uint32_t DISPLAY_BLANKED:1;
+	uint32_t PROGRAM_PIXEL_CLOCK:1;
+	uint32_t PROGRAM_ID_CLOCK:1;
+};
+
+/**
+ *  Display Port HW De spread of Reference Clock related Parameters structure
+ *  Store it once at boot for later usage
+  */
+struct csdp_ref_clk_ds_params {
+	bool hw_dso_n_dp_ref_clk;
+/* Flag for HW De Spread enabled (if enabled SS on DP Reference Clock)*/
+	uint32_t avg_dp_ref_clk_khz;
+/* Average DP Reference clock (in KHz)*/
+	uint32_t ss_percentage_on_dp_ref_clk;
+/* DP Reference clock SS percentage
+ * (not to be mixed with DP IDCLK SS from PLL Settings)*/
+	uint32_t ss_percentage_divider;
+/* DP Reference clock SS percentage divider */
+};
+
+struct pixel_clk_params {
+	uint32_t requested_pix_clk; /* in KHz */
+/*> Requested Pixel Clock
+ * (based on Video Timing standard used for requested mode)*/
+	uint32_t requested_sym_clk; /* in KHz */
+/*> Requested Sym Clock (relevant only for display port)*/
+	uint32_t dp_ref_clk; /* in KHz */
+/*> DP reference clock - calculated only for DP signal for specific cases*/
+	struct graphics_object_id encoder_object_id;
+/*> Encoder object Id - needed by VBIOS Exec table*/
+	enum signal_type signal_type;
+/*> signalType -> Encoder Mode - needed by VBIOS Exec table*/
+	enum controller_id controller_id;
+/*> ControllerId - which controller using this PLL*/
+	enum dc_color_depth color_depth;
+	struct csdp_ref_clk_ds_params de_spread_params;
+/*> de-spread info, relevant only for on-the-fly tune-up pixel rate*/
+
+	struct pixel_clk_flags flags;
+};
+
+/**
+ *  Pixel Clock Dividers structure with desired Pixel Clock
+ *  (adjusted after VBIOS exec table),
+ *  with actually calculated Clock and reference Crystal frequency
+ */
+struct pll_settings {
+	uint32_t actual_pix_clk;
+	uint32_t adjusted_pix_clk;
+	uint32_t calculated_pix_clk;
+	uint32_t vco_freq;
+	uint32_t reference_freq;
+	uint32_t reference_divider;
+	uint32_t feedback_divider;
+	uint32_t fract_feedback_divider;
+	uint32_t pix_clk_post_divider;
+	uint32_t ss_percentage;
+	bool use_external_clk;
+};
+
+struct calc_pll_clock_source_init_data {
+	struct dc_bios *bp;
+	uint32_t min_pix_clk_pll_post_divider;
+	uint32_t max_pix_clk_pll_post_divider;
+	uint32_t min_pll_ref_divider;
+	uint32_t max_pll_ref_divider;
+	uint32_t min_override_input_pxl_clk_pll_freq_khz;
+/* if not 0, override the firmware info */
+
+	uint32_t max_override_input_pxl_clk_pll_freq_khz;
+/* if not 0, override the firmware info */
+
+	uint32_t num_fract_fb_divider_decimal_point;
+/* number of decimal point for fractional feedback divider value */
+
+	uint32_t num_fract_fb_divider_decimal_point_precision;
+/* number of decimal point to round off for fractional feedback divider value*/
+	struct dc_context *ctx;
+
+};
+
+struct calc_pll_clock_source {
+	uint32_t ref_freq_khz;
+	uint32_t min_pix_clock_pll_post_divider;
+	uint32_t max_pix_clock_pll_post_divider;
+	uint32_t min_pll_ref_divider;
+	uint32_t max_pll_ref_divider;
+
+	uint32_t max_vco_khz;
+	uint32_t min_vco_khz;
+	uint32_t min_pll_input_freq_khz;
+	uint32_t max_pll_input_freq_khz;
+
+	uint32_t fract_fb_divider_decimal_points_num;
+	uint32_t fract_fb_divider_factor;
+	uint32_t fract_fb_divider_precision;
+	uint32_t fract_fb_divider_precision_factor;
+	struct dc_context *ctx;
+};
+
+struct clock_source_funcs {
+	bool (*cs_power_down)(
+			struct clock_source *);
+	bool (*program_pix_clk)(struct clock_source *,
+			struct pixel_clk_params *, struct pll_settings *);
+	uint32_t (*get_pix_clk_dividers)(
+			struct clock_source *,
+			struct pixel_clk_params *,
+			struct pll_settings *);
+};
+
+struct clock_source {
+	struct clock_source_funcs *funcs;
+	struct dc_context *ctx;
+	enum clock_source_id id;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/compressor.h b/drivers/gpu/drm/amd/dal/dc/inc/compressor.h
new file mode 100644
index 000000000000..4992ffde7c9a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/compressor.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMPRESSOR_H__
+#define __DAL_COMPRESSOR_H__
+
+#include "include/grph_object_id.h"
+
+enum fbc_compress_ratio {
+	FBC_COMPRESS_RATIO_INVALID = 0,
+	FBC_COMPRESS_RATIO_1TO1 = 1,
+	FBC_COMPRESS_RATIO_2TO1 = 2,
+	FBC_COMPRESS_RATIO_4TO1 = 4,
+	FBC_COMPRESS_RATIO_8TO1 = 8,
+};
+
+union fbc_physical_address {
+	struct {
+		uint32_t low_part;
+		int32_t high_part;
+	} addr;
+};
+
+struct compr_addr_and_pitch_params {
+	uint32_t inst;
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+};
+
+struct fbc_lpt_config {
+	uint32_t mem_channels_num;
+	uint32_t banks_num;
+	uint32_t chan_interleave_size;
+	uint32_t row_size;
+};
+
+struct fbc_input_info {
+	bool dynamic_fbc_buffer_alloc;
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+	uint32_t active_targets_num;
+	struct fbc_lpt_config lpt_config;
+};
+
+struct fbc_requested_compressed_size {
+	uint32_t preferred_size;
+	uint32_t preferred_size_alignment;
+	uint32_t min_size;
+	uint32_t min_size_alignment;
+	union {
+		struct {
+			/*Above preferred_size must be allocated in FB pool */
+			uint32_t PREFERRED_MUST_BE_FRAME_BUFFER_POOL:1;
+			/*Above min_size must be allocated in FB pool */
+			uint32_t MIN_MUST_BE_FRAME_BUFFER_POOL:1;
+		} flags;
+		uint32_t bits;
+	};
+};
+
+struct fbc_compressed_surface_info {
+	union fbc_physical_address compressed_surface_address;
+	uint32_t allocated_size;
+	union {
+		struct {
+			uint32_t FB_POOL:1; /*Allocated in FB Pool */
+			uint32_t DYNAMIC_ALLOC:1; /*Dynamic allocation */
+		} allocation_flags;
+		uint32_t bits;
+	};
+};
+
+enum fbc_hw_max_resolution_supported {
+	FBC_MAX_X = 3840,
+	FBC_MAX_Y = 2400
+};
+
+struct fbc_max_resolution_supported {
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+};
+
+struct compressor {
+	struct dc_context *ctx;
+	uint32_t attached_inst;
+	bool is_enabled;
+
+	union {
+		uint32_t raw;
+		struct {
+			uint32_t FBC_SUPPORT:1;
+			uint32_t FB_POOL:1;
+			uint32_t DYNAMIC_ALLOC:1;
+			uint32_t LPT_SUPPORT:1;
+			uint32_t LPT_MC_CONFIG:1;
+			uint32_t DUMMY_BACKEND:1;
+			uint32_t CLK_GATING_DISABLED:1;
+
+		} bits;
+	} options;
+
+	union fbc_physical_address compr_surface_address;
+
+	uint32_t embedded_panel_h_size;
+	uint32_t embedded_panel_v_size;
+	uint32_t memory_bus_width;
+	uint32_t banks_num;
+	uint32_t raw_size;
+	uint32_t channel_interleave_size;
+	uint32_t dram_channels_num;
+
+	uint32_t allocated_size;
+	uint32_t preferred_requested_size;
+	uint32_t lpt_channels_num;
+	enum fbc_compress_ratio min_compress_ratio;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h b/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
new file mode 100644
index 000000000000..3e66ad7ea72d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __CORE_DC_H__
+#define __CORE_DC_H__
+
+#include "core_types.h"
+#include "hw_sequencer.h"
+
+struct dc {
+	struct dc_context *ctx;
+
+	uint8_t link_count;
+	struct core_link *links[MAX_PIPES * 2];
+
+	/* TODO: determine max number of targets*/
+	struct validate_context current_context;
+	struct resource_pool res_pool;
+
+	/*Power State*/
+	enum dc_video_power_state previous_power_state;
+	enum dc_video_power_state current_power_state;
+
+	/* Inputs into BW and WM calculations. */
+	struct bw_calcs_dceip bw_dceip;
+	struct bw_calcs_vbios bw_vbios;
+
+	/* HW functions */
+	struct hw_sequencer_funcs hwss;
+};
+
+#endif /* __CORE_DC_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_status.h b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h
new file mode 100644
index 000000000000..9682cf866886
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _CORE_STATUS_H_
+#define _CORE_STATUS_H_
+
+enum dc_status {
+	DC_OK = 1,
+
+	DC_NO_CONTROLLER_RESOURCE,
+	DC_NO_STREAM_ENG_RESOURCE,
+	DC_NO_STREAM_AUDIO_RESOURCE,
+	DC_NO_CLOCK_SOURCE_RESOURCE,
+	DC_FAIL_CONTROLLER_VALIDATE,
+	DC_FAIL_ENC_VALIDATE,
+	DC_FAIL_ATTACH_SURFACES,
+	DC_NO_DP_LINK_BANDWIDTH,
+	DC_EXCEED_DONGLE_MAX_CLK,
+	DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */
+
+	DC_ERROR_UNEXPECTED = -1
+};
+
+#endif /* _CORE_STATUS_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
new file mode 100644
index 000000000000..7d63ebb8e789
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _CORE_TYPES_H_
+#define _CORE_TYPES_H_
+
+#include "dc.h"
+#include "bandwidth_calcs.h"
+#include "ddc_service_types.h"
+
+struct core_stream;
+/********* core_target *************/
+
+#define CONST_DC_TARGET_TO_CORE(dc_target) \
+	container_of(dc_target, const struct core_target, public)
+#define DC_TARGET_TO_CORE(dc_target) \
+	container_of(dc_target, struct core_target, public)
+
+#define MAX_PIPES 6
+#define MAX_STREAMS 6
+#define MAX_CLOCK_SOURCES 7
+
+struct core_target {
+	struct dc_target public;
+	struct dc_target_status status;
+
+	struct dc_context *ctx;
+};
+
+/********* core_surface **********/
+#define DC_SURFACE_TO_CORE(dc_surface) \
+	container_of(dc_surface, struct core_surface, public)
+
+struct core_surface {
+	struct dc_surface public;
+	struct dc_surface_status status;
+	struct dc_context *ctx;
+};
+
+void enable_surface_flip_reporting(struct dc_surface *dc_surface,
+		uint32_t controller_id);
+
+/********* core_stream ************/
+#include "grph_object_id.h"
+#include "link_encoder.h"
+#include "stream_encoder.h"
+#include "clock_source.h"
+#include "audio_interface.h"
+#include "scaler_types.h"
+#include "hw_sequencer_types.h"
+#include "opp.h"
+
+#define DC_STREAM_TO_CORE(dc_stream) container_of( \
+	dc_stream, struct core_stream, public)
+
+#define PIXEL_CLOCK	27030
+
+struct core_stream {
+	struct dc_stream public;
+
+	/* field internal to DC */
+	const struct core_sink *sink;
+
+	struct clock_source *clock_source;
+
+	struct mem_input *mi;
+	struct input_pixel_processor *ipp;
+	struct transform *xfm;
+	struct output_pixel_processor *opp;
+	struct timing_generator *tg;
+	struct stream_encoder *stream_enc;
+	struct display_clock *dis_clk;
+
+	struct overscan_info overscan;
+	struct scaling_ratios ratios;
+	struct rect viewport;
+	struct scaling_taps taps;
+	enum pixel_format format;
+
+	uint8_t controller_idx;
+
+	struct audio *audio;
+
+	enum signal_type signal;
+
+	/* TODO: move these members into appropriate places (work in progress)*/
+	/* timing validation (HDMI only) */
+	uint32_t max_tmds_clk_from_edid_in_mhz;
+	/* maximum supported deep color depth for HDMI */
+	enum dc_color_depth max_hdmi_deep_color;
+	/* maximum supported pixel clock for HDMI */
+	uint32_t max_hdmi_pixel_clock;
+	/* end of TODO */
+
+	/*TODO: AUTO merge if possible*/
+	struct pixel_clk_params pix_clk_params;
+	struct pll_settings pll_settings;
+
+	/*fmt*/
+	/*TODO: AUTO new codepath in apply_context to hw to
+	 * generate these bw unrelated/no fail params*/
+	struct bit_depth_reduction_params bit_depth_params;/* used by DCP and FMT */
+	struct clamping_and_pixel_encoding_params clamping;
+	struct hw_info_frame info_frame;
+	struct encoder_info_frame encoder_info_frame;
+
+	struct audio_output audio_output;
+	struct dc_context *ctx;
+};
+
+
+/************ core_sink *****************/
+
+#define DC_SINK_TO_CORE(dc_sink) \
+	container_of(dc_sink, struct core_sink, public)
+
+struct core_sink {
+	/** The public, read-only (for DM) area of sink. **/
+	struct dc_sink public;
+	/** End-of-public area. **/
+
+	/** The 'protected' area - read/write access, for use only inside DC **/
+	/* not used for now */
+	struct core_link *link;
+	struct dc_context *ctx;
+	uint32_t dongle_max_pix_clk;
+	bool converter_disable_audio;
+};
+
+/************ link *****************/
+#define DC_LINK_TO_CORE(dc_link) container_of(dc_link, struct core_link, public)
+
+struct link_init_data {
+	const struct dc *dc;
+	struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */
+	uint32_t connector_index; /* this will be mapped to the HPD pins */
+	uint32_t link_index; /* this is mapped to DAL display_index
+				TODO: remove it when DC is complete. */
+	struct adapter_service *adapter_srv;
+};
+
+struct link_caps {
+	/* support for Spread Spectrum(SS) */
+	bool ss_supported;
+	/* DP link settings (laneCount, linkRate, Spread) */
+	uint32_t lane_count;
+	uint32_t rate;
+	uint32_t spread;
+	enum dpcd_revision dpcd_revision;
+};
+
+struct dpcd_caps {
+	union dpcd_rev dpcd_rev;
+	union max_lane_count max_ln_count;
+
+	/* dongle type (DP converter, CV smart dongle) */
+	enum display_dongle_type dongle_type;
+	/* Dongle's downstream count. */
+	union sink_count sink_count;
+	/* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER,
+	indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/
+	bool is_dp_hdmi_s3d_converter;
+
+	bool allow_invalid_MSA_timing_param;
+	bool panel_mode_edp;
+	uint32_t sink_dev_id;
+	uint32_t branch_dev_id;
+	int8_t branch_dev_name[6];
+};
+
+union dp_wa {
+	struct {
+		/* keep DP receiver powered up on DisplayOutput */
+		uint32_t KEEP_RECEIVER_POWERED:1;
+
+		/* TODO: may add other member in.*/
+	} bits;
+	uint32_t raw;
+};
+
+/* DP MST stream allocation (payload bandwidth number) */
+struct link_mst_stream_allocation {
+	/* DIG front */
+	const struct stream_encoder *stream_enc;
+	/* associate DRM payload table with DC stream encoder */
+	uint8_t vcp_id;
+	/* number of slots required for the DP stream in transport packet */
+	uint8_t slot_count;
+};
+
+/* DP MST stream allocation table */
+struct link_mst_stream_allocation_table {
+	/* number of DP video streams */
+	int stream_count;
+	/* array of stream allocations */
+	struct link_mst_stream_allocation
+	stream_allocations[MAX_CONTROLLER_NUM];
+};
+
+struct core_link {
+	struct dc_link public;
+	const struct dc *dc;
+
+	struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/
+
+	struct adapter_service *adapter_srv;
+	struct link_encoder *link_enc;
+	struct ddc_service *ddc;
+	struct graphics_object_id link_id;
+	union ddi_channel_mapping ddi_channel_mapping;
+	struct connector_device_tag_info device_tag;
+	/* caps is the same as reported_link_cap. link_traing use
+	 * reported_link_cap. Will clean up.  TODO */
+	struct link_settings reported_link_cap;
+	struct link_settings verified_link_cap;
+	struct link_settings max_link_setting;
+	struct link_settings cur_link_settings;
+	struct lane_settings ln_setting;
+	struct dpcd_caps dpcd_caps;
+	unsigned int dpcd_sink_count;
+
+	enum edp_revision edp_revision;
+
+	/* MST record stream using this link */
+	struct link_flags {
+		bool dp_keep_receiver_powered;
+	} wa_flags;
+	struct link_mst_stream_allocation_table mst_stream_alloc_table;
+};
+
+#define DC_LINK_TO_LINK(dc_link) container_of(dc_link, struct core_link, public)
+
+struct core_link *link_create(const struct link_init_data *init_params);
+void link_destroy(struct core_link **link);
+
+enum dc_status dc_link_validate_mode_timing(
+		const struct core_sink *sink,
+		struct core_link *link,
+		const struct dc_crtc_timing *timing);
+
+void core_link_resume(struct core_link *link);
+
+void core_link_enable_stream(
+		struct core_link *link,
+		struct core_stream *stream);
+
+void core_link_disable_stream(
+		struct core_link *link,
+		struct core_stream *stream);
+
+/********** DAL Core*********************/
+#include "display_clock_interface.h"
+
+struct resource_pool;
+struct validate_context;
+
+struct resource_funcs {
+	void (*destruct)(struct resource_pool *pool);
+	struct link_encoder *(*link_enc_create)(
+			const struct encoder_init_data *init);
+	void (*link_enc_destroy)(struct link_encoder **enc);
+	enum dc_status (*validate_with_context)(
+					const struct dc *dc,
+					const struct dc_validation_set set[],
+					uint8_t set_count,
+					struct validate_context *context);
+
+	enum dc_status (*validate_bandwidth)(
+					const struct dc *dc,
+					struct validate_context *context);
+};
+
+struct resource_pool {
+	struct scaler_filter * scaler_filter;
+
+	struct mem_input *mis[MAX_PIPES];
+	struct input_pixel_processor *ipps[MAX_PIPES];
+	struct transform *transforms[MAX_PIPES];
+	struct output_pixel_processor *opps[MAX_PIPES];
+	struct timing_generator *timing_generators[MAX_STREAMS];
+	struct stream_encoder *stream_enc[MAX_PIPES * 2];
+
+	uint8_t controller_count;
+	uint8_t stream_enc_count;
+
+	union supported_stream_engines stream_engines;
+
+	struct clock_source *clock_sources[MAX_CLOCK_SOURCES];
+	uint8_t clk_src_count;
+
+	struct audio *audios[MAX_STREAMS];
+	uint8_t audio_count;
+
+	struct display_clock *display_clock;
+	struct adapter_service *adapter_srv;
+	struct irq_service *irqs;
+
+	struct resource_funcs *funcs;
+};
+
+struct controller_ctx {
+	struct core_surface *surface;
+	struct core_stream *stream;
+	struct flags {
+		bool unchanged;
+		bool timing_changed;
+	} flags;
+};
+
+struct resource_context {
+	struct resource_pool pool;
+	struct controller_ctx controller_ctx[MAX_PIPES];
+	union supported_stream_engines used_stream_engines;
+	bool is_stream_enc_acquired[MAX_PIPES * 2];
+	bool is_audio_acquired[MAX_STREAMS];
+	uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES];
+ };
+
+struct target_flags {
+	bool unchanged;
+};
+struct validate_context {
+	struct core_target *targets[MAX_PIPES];
+	struct target_flags target_flags[MAX_PIPES];
+	uint8_t target_count;
+
+	struct resource_context res_ctx;
+
+	struct bw_calcs_mode_data bw_mode_data;
+	/* The output from BW and WM calculations. */
+	struct bw_calcs_output bw_results;
+};
+
+
+#endif /* _CORE_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
new file mode 100644
index 000000000000..18104d6fa6d3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DDC_SERVICE_H__
+#define __DAL_DDC_SERVICE_H__
+
+#include "include/ddc_service_types.h"
+#include "include/i2caux_interface.h"
+
+#define EDID_SEGMENT_SIZE 256
+
+struct ddc_service;
+struct adapter_service;
+struct graphics_object_id;
+enum ddc_result;
+struct av_sync_data;
+struct dp_receiver_id_info;
+
+struct i2c_payloads;
+struct aux_payloads;
+
+struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count);
+struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p);
+uint32_t  dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p);
+void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p);
+
+struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count);
+struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p);
+uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p);
+void dal_ddc_aux_payloads_destroy(struct aux_payloads **p);
+
+void dal_ddc_i2c_payloads_add(
+		struct i2c_payloads *payloads,
+		uint32_t address,
+		uint32_t len,
+		uint8_t *data,
+		bool write);
+
+void dal_ddc_aux_payloads_add(
+		struct aux_payloads *payloads,
+		uint32_t address,
+		uint32_t len,
+		uint8_t *data,
+		bool write);
+
+struct ddc_service_init_data {
+	struct adapter_service *as;
+	struct graphics_object_id id;
+	struct dc_context *ctx;
+};
+
+struct ddc_service *dal_ddc_service_create(
+		struct ddc_service_init_data *ddc_init_data);
+
+void dal_ddc_service_destroy(struct ddc_service **ddc);
+
+enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc);
+
+void dal_ddc_service_set_transaction_type(
+		struct ddc_service *ddc,
+		enum ddc_transaction_type type);
+
+bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc);
+
+uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc);
+
+uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc);
+
+void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf);
+
+void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
+		struct ddc_service *ddc,
+		struct display_sink_capability *sink_cap);
+
+bool dal_ddc_service_query_ddc_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		uint8_t *write_buf,
+		uint32_t write_size,
+		uint8_t *read_buf,
+		uint32_t read_size);
+
+bool dal_ddc_service_get_dp_receiver_id_info(
+		struct ddc_service *ddc,
+		struct dp_receiver_id_info *info);
+
+enum ddc_result dal_ddc_service_read_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t len);
+
+enum ddc_result dal_ddc_service_write_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t len);
+
+void dal_ddc_service_write_scdc_data(
+		struct ddc_service *ddc_service,
+		uint32_t pix_clk,
+		bool lte_340_scramble);
+
+void dal_ddc_service_read_scdc_data(
+		struct ddc_service *ddc_service);
+
+void ddc_service_set_dongle_type(struct ddc_service *ddc,
+		enum display_dongle_type dongle_type);
+
+void dal_ddc_service_set_ddc_pin(
+		struct ddc_service *ddc_service,
+		struct ddc *ddc);
+
+struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service);
+void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service);
+
+enum ddc_result dal_ddc_service_read_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t len);
+enum ddc_result dal_ddc_service_write_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t len);
+
+#endif /* __DAL_DDC_SERVICE_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
new file mode 100644
index 000000000000..682c0b432bdb
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_LINK_DP_H__
+#define __DC_LINK_DP_H__
+
+struct core_link;
+struct core_stream;
+struct link_settings;
+
+bool dp_hbr_verify_link_cap(
+	struct core_link *link,
+	struct link_settings *known_limit_link_setting);
+
+bool dp_validate_mode_timing(
+	struct core_link *link,
+	const struct dc_crtc_timing *timing);
+
+void decide_link_settings(
+	struct core_stream *stream,
+	struct link_settings *link_setting);
+
+bool perform_link_training(
+	struct core_link *link,
+	const struct link_settings *link_setting,
+	bool skip_video_pattern);
+
+bool is_mst_supported(struct core_link *link);
+
+void detect_dp_sink_caps(struct core_link *link);
+
+bool is_dp_active_dongle(const struct core_link *link);
+
+#endif /* __DC_LINK_DP_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
new file mode 100644
index 000000000000..17cb10f117e1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef GAMMA_TYPES_H_
+
+#define GAMMA_TYPES_H_
+
+#include "dc_types.h"
+#include "dm_services_types.h"
+
+/* TODO: Used in IPP and OPP */
+struct dev_c_lut {
+	uint8_t red;
+	uint8_t green;
+	uint8_t blue;
+};
+
+struct dev_c_lut16 {
+	uint16_t red;
+	uint16_t green;
+	uint16_t blue;
+};
+
+struct regamma_ramp {
+	uint16_t gamma[RGB_256X3X16 * 3];
+};
+
+/* used by Graphics and Overlay gamma */
+struct gamma_coeff {
+	int32_t gamma[3];
+	int32_t a0[3]; /* index 0 for red, 1 for green, 2 for blue */
+	int32_t a1[3];
+	int32_t a2[3];
+	int32_t a3[3];
+};
+
+struct regamma_lut {
+	union {
+		struct {
+			uint32_t GRAPHICS_DEGAMMA_SRGB :1;
+			uint32_t OVERLAY_DEGAMMA_SRGB :1;
+			uint32_t GAMMA_RAMP_ARRAY :1;
+			uint32_t APPLY_DEGAMMA :1;
+			uint32_t RESERVED :28;
+		} bits;
+		uint32_t value;
+	} features;
+
+	union {
+		struct regamma_ramp regamma_ramp;
+		struct gamma_coeff gamma_coeff;
+	};
+};
+
+union gamma_flag {
+	struct {
+		uint32_t config_is_changed :1;
+		uint32_t both_pipe_req :1;
+		uint32_t regamma_update :1;
+		uint32_t gamma_update :1;
+		uint32_t reserved :28;
+	} bits;
+	uint32_t u_all;
+};
+
+enum graphics_regamma_adjust {
+	GRAPHICS_REGAMMA_ADJUST_BYPASS = 0, GRAPHICS_REGAMMA_ADJUST_HW, /* without adjustments */
+	GRAPHICS_REGAMMA_ADJUST_SW /* use adjustments */
+};
+
+enum graphics_gamma_lut {
+	GRAPHICS_GAMMA_LUT_LEGACY = 0, /* use only legacy LUT */
+	GRAPHICS_GAMMA_LUT_REGAMMA, /* use only regamma LUT */
+	GRAPHICS_GAMMA_LUT_LEGACY_AND_REGAMMA /* use legacy & regamma LUT's */
+};
+
+enum graphics_degamma_adjust {
+	GRAPHICS_DEGAMMA_ADJUST_BYPASS = 0, GRAPHICS_DEGAMMA_ADJUST_HW, /*without adjustments */
+	GRAPHICS_DEGAMMA_ADJUST_SW /* use adjustments */
+};
+
+struct gamma_parameters {
+	union gamma_flag flag;
+	enum pixel_format surface_pixel_format; /*OS surface pixel format*/
+	struct regamma_lut regamma;
+
+	enum graphics_regamma_adjust regamma_adjust_type;
+	enum graphics_degamma_adjust degamma_adjust_type;
+
+	enum graphics_gamma_lut selected_gamma_lut;
+
+	bool disable_adjustments;
+
+	/* here we grow with parameters if necessary */
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
new file mode 100644
index 000000000000..8460dd729e91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HW_SEQUENCER_H__
+#define __DC_HW_SEQUENCER_H__
+#include "core_types.h"
+
+struct gamma_parameters;
+
+enum pipe_gating_control {
+	PIPE_GATING_CONTROL_DISABLE = 0,
+	PIPE_GATING_CONTROL_ENABLE,
+	PIPE_GATING_CONTROL_INIT
+};
+
+
+struct hw_sequencer_funcs {
+
+	enum dc_status (*apply_ctx_to_hw)(
+			const struct dc *dc, struct validate_context *context);
+
+	void (*reset_hw_ctx)(
+				struct dc *dc,
+				struct validate_context *context,
+				uint8_t target_count);
+
+	bool (*set_plane_config)(
+				const struct dc *dc,
+				struct core_surface *surface,
+				struct core_target *target);
+
+	bool (*update_plane_address)(
+				const struct dc *dc,
+				const struct core_surface *surface,
+				struct core_target *target);
+
+	bool (*set_gamma_ramp)(
+				struct input_pixel_processor *ipp,
+				struct output_pixel_processor *opp,
+				const struct gamma_ramp *ramp,
+				const struct gamma_parameters *params);
+
+	void (*power_down)(struct dc *dc);
+
+	void (*enable_accelerated_mode)(struct dc *dc);
+
+	void (*enable_timing_synchronization)(
+					struct dc_context *dc_ctx,
+					uint32_t timing_generator_num,
+					struct timing_generator *tgs[]);
+
+	/* backlight control */
+	void (*encoder_set_lcd_backlight_level)(
+		struct link_encoder *enc, uint32_t level);
+
+
+	void (*crtc_switch_to_clk_src)(struct clock_source *, uint8_t);
+
+	/* power management */
+	void (*clock_gating_power_up)(struct dc_context *ctx, bool enable);
+
+	void (*enable_display_pipe_clock_gating)(
+					struct dc_context *ctx,
+					bool clock_gating);
+
+	bool (*enable_display_power_gating)(
+					struct dc_context *ctx,
+					uint8_t controller_id,
+					struct dc_bios *dcb,
+					enum pipe_gating_control power_gating);
+
+	void (*program_bw)(struct dc *dc, struct validate_context *context);
+
+	void (*enable_stream)(struct core_stream *stream);
+
+	void (*disable_stream)(struct core_stream *stream);
+
+	void (*enable_fe_clock)(
+		struct dc_context *ctx, uint8_t controller_id, bool enable);
+
+	bool (*pipe_control_lock)(
+				struct dc_context *ctx,
+				uint8_t controller_idx,
+				uint32_t control_mask,
+				bool lock);
+
+	void (*set_blender_mode)(
+				struct dc_context *ctx,
+				uint8_t controller_id,
+				uint32_t mode);
+
+	void (*set_displaymarks)(
+				const struct dc *dc,
+				struct validate_context *context);
+
+	void (*set_display_clock)(struct validate_context *context);
+};
+
+bool dc_construct_hw_sequencer(
+				struct adapter_service *adapter_serv,
+				struct dc *dc);
+
+
+#endif /* __DC_HW_SEQUENCER_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/ipp.h b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h
new file mode 100644
index 000000000000..8e7cc31dfb9c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h
@@ -0,0 +1,106 @@
+
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IPP_H__
+#define __DAL_IPP_H__
+
+#include "include/grph_object_id.h"
+#include "include/grph_csc_types.h"
+#include "include/video_csc_types.h"
+#include "include/hw_sequencer_types.h"
+
+struct dev_c_lut;
+
+#define MAXTRIX_COEFFICIENTS_NUMBER 12
+#define MAXTRIX_COEFFICIENTS_WRAP_NUMBER (MAXTRIX_COEFFICIENTS_NUMBER + 4)
+#define MAX_OVL_MATRIX_COUNT 12
+
+/* IPP RELATED */
+struct input_pixel_processor {
+	struct  dc_context *ctx;
+	uint32_t inst;
+	struct ipp_funcs *funcs;
+};
+
+enum wide_gamut_degamma_mode {
+	/*  00  - BITS1:0 Bypass */
+	WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_BYPASS,
+	/*  0x1 - PWL gamma ROM A */
+	WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_PWL_ROM_A,
+	/*  0x2 - PWL gamma ROM B */
+	WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_PWL_ROM_B,
+	/*  00  - BITS5:4 Bypass */
+	WIDE_GAMUT_DEGAMMA_MODE_OVL_BYPASS,
+	/*  0x1 - PWL gamma ROM A */
+	WIDE_GAMUT_DEGAMMA_MODE_OVL_PWL_ROM_A,
+	/*  0x2 - PWL gamma ROM B */
+	WIDE_GAMUT_DEGAMMA_MODE_OVL_PWL_ROM_B,
+};
+
+struct dcp_video_matrix {
+	enum ovl_color_space color_space;
+	int32_t value[MAXTRIX_COEFFICIENTS_NUMBER];
+};
+
+struct ipp_funcs {
+
+	/* CURSOR RELATED */
+	bool (*ipp_cursor_set_position)(
+		struct input_pixel_processor *ipp,
+		const struct dc_cursor_position *position);
+
+	bool (*ipp_cursor_set_attributes)(
+		struct input_pixel_processor *ipp,
+		const struct dc_cursor_attributes *attributes);
+
+	/* DEGAMMA RELATED */
+	bool (*ipp_set_degamma)(
+		struct input_pixel_processor *ipp,
+		const struct gamma_parameters *params,
+		bool force_bypass);
+
+	void (*ipp_program_prescale)(
+		struct input_pixel_processor *ipp,
+		enum pixel_format pixel_format);
+
+	void (*ipp_set_legacy_input_gamma_mode)(
+			struct input_pixel_processor *ipp,
+			bool is_legacy);
+
+	bool (*ipp_set_legacy_input_gamma_ramp)(
+		struct input_pixel_processor *ipp,
+		const struct gamma_ramp *gamma_ramp,
+		const struct gamma_parameters *params);
+
+	bool (*ipp_set_palette)(
+		struct input_pixel_processor *ipp,
+		const struct dev_c_lut *palette,
+		uint32_t start,
+		uint32_t length,
+		enum pixel_format surface_pixel_format);
+};
+
+#endif /* __DAL_IPP_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
new file mode 100644
index 000000000000..d60c59463fc2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef LINK_ENCODER_H_
+#define LINK_ENCODER_H_
+
+#include "grph_object_defs.h"
+#include "signal_types.h"
+#include "dc_types.h"
+
+struct dc_context;
+struct adapter_service;
+struct encoder_set_dp_phy_pattern_param;
+struct link_mst_stream_allocation_table;
+struct link_settings;
+struct link_training_settings;
+struct core_stream;
+
+struct encoder_init_data {
+	struct adapter_service *adapter_service;
+	enum channel_id channel;
+	struct graphics_object_id connector;
+	enum hpd_source_id hpd_source;
+	/* TODO: in DAL2, here was pointer to EventManagerInterface */
+	struct graphics_object_id encoder;
+	struct dc_context *ctx;
+	enum transmitter transmitter;
+};
+
+struct encoder_feature_support {
+	union {
+		struct {
+			/* 1 - external encoder; 0 - internal encoder */
+			uint32_t EXTERNAL_ENCODER:1;
+			uint32_t ANALOG_ENCODER:1;
+			uint32_t STEREO_SYNC:1;
+			/* check the DDC data pin
+			 * when performing DP Sink detection */
+			uint32_t DP_SINK_DETECT_POLL_DATA_PIN:1;
+			/* CPLIB authentication
+			 * for external DP chip supported */
+			uint32_t CPLIB_DP_AUTHENTICATION:1;
+			uint32_t IS_HBR2_CAPABLE:1;
+			uint32_t IS_HBR2_VALIDATED:1;
+			uint32_t IS_TPS3_CAPABLE:1;
+			uint32_t IS_AUDIO_CAPABLE:1;
+			uint32_t IS_VCE_SUPPORTED:1;
+			uint32_t IS_CONVERTER:1;
+			uint32_t IS_Y_ONLY_CAPABLE:1;
+			uint32_t IS_YCBCR_CAPABLE:1;
+		} bits;
+		uint32_t raw;
+	} flags;
+	/* maximum supported deep color depth */
+	enum dc_color_depth max_deep_color;
+	/* maximum supported clock */
+	uint32_t max_pixel_clock;
+};
+
+struct link_enc_status {
+	int dummy; /*TODO*/
+};
+struct link_encoder {
+	struct link_encoder_funcs *funcs;
+	struct adapter_service *adapter_service;
+	int32_t aux_channel_offset;
+	struct dc_context *ctx;
+	struct graphics_object_id id;
+	struct graphics_object_id connector;
+	uint32_t input_signals;
+	uint32_t output_signals;
+	enum engine_id preferred_engine;
+	struct encoder_feature_support features;
+	enum transmitter transmitter;
+	enum hpd_source_id hpd_source;
+};
+
+struct link_encoder_funcs {
+	bool (*validate_output_with_stream)(struct link_encoder *enc,
+		struct core_stream *stream);
+	void (*hw_init)(struct link_encoder *enc);
+	void (*setup)(struct link_encoder *enc,
+		enum signal_type signal);
+	void (*enable_tmds_output)(struct link_encoder *enc,
+		enum clock_source_id clock_source,
+		enum dc_color_depth color_depth,
+		bool hdmi,
+		bool dual_link,
+		uint32_t pixel_clock);
+	void (*enable_dp_output)(struct link_encoder *enc,
+		const struct link_settings *link_settings,
+		enum clock_source_id clock_source);
+	void (*enable_dp_mst_output)(struct link_encoder *enc,
+		const struct link_settings *link_settings,
+		enum clock_source_id clock_source);
+	void (*disable_output)(struct link_encoder *link_enc,
+		enum signal_type signal);
+	void (*dp_set_lane_settings)(struct link_encoder *enc,
+		const struct link_training_settings *link_settings);
+	void (*dp_set_phy_pattern)(struct link_encoder *enc,
+		const struct encoder_set_dp_phy_pattern_param *para);
+	void (*update_mst_stream_allocation_table)(
+		struct link_encoder *enc,
+		const struct link_mst_stream_allocation_table *table);
+	void (*set_lcd_backlight_level) (struct link_encoder *enc,
+		uint32_t level);
+	void (*backlight_control) (struct link_encoder *enc,
+		bool enable);
+	void (*power_control) (struct link_encoder *enc,
+		bool power_up);
+	void (*connect_dig_be_to_fe)(struct link_encoder *enc,
+		enum engine_id engine,
+		bool connect);
+};
+
+#endif /* LINK_ENCODER_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
new file mode 100644
index 000000000000..d9a48c037c3e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_LINK_HWSS_H__
+#define __DC_LINK_HWSS_H__
+
+#include "inc/core_status.h"
+
+enum dc_status core_link_read_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t size);
+
+enum dc_status core_link_write_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t size);
+
+void dp_enable_link_phy(
+	struct core_link *link,
+	enum signal_type signal,
+	const struct link_settings *link_settings);
+
+void dp_receiver_power_ctrl(struct core_link *link, bool on);
+
+void dp_disable_link_phy(struct core_link *link, enum signal_type signal);
+
+void dp_disable_link_phy_mst(struct core_link *link, struct core_stream *stream);
+
+bool dp_set_hw_training_pattern(
+	struct core_link *link,
+	enum hw_dp_training_pattern pattern);
+
+void dp_set_hw_lane_settings(
+	struct core_link *link,
+	const struct link_training_settings *link_settings);
+
+void dp_set_hw_test_pattern(
+	struct core_link *link,
+	enum dp_test_pattern test_pattern);
+
+enum dp_panel_mode dp_get_panel_mode(struct core_link *link);
+
+#endif /* __DC_LINK_HWSS_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h b/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
new file mode 100644
index 000000000000..7d6335d3bcf4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_MEM_INPUT_H__
+#define __DAL_MEM_INPUT_H__
+
+#include "include/grph_object_id.h"
+#include "dc.h"
+
+struct mem_input {
+	struct mem_input_funcs *funcs;
+	struct dc_context *ctx;
+	uint32_t inst;
+};
+
+struct mem_input_funcs {
+	void (*mem_input_program_safe_display_marks)(struct mem_input *mi);
+	void (*mem_input_program_display_marks)(
+		struct mem_input *mem_input,
+		struct bw_watermarks nbp,
+		struct bw_watermarks stutter,
+		struct bw_watermarks urgent,
+		uint32_t h_total,
+		uint32_t pixel_clk_in_khz,
+		uint32_t pstate_blackout_duration_ns);
+	void (*mem_input_allocate_dmif_buffer)(
+			struct mem_input *mem_input,
+			struct dc_crtc_timing *timing,
+			uint32_t paths_num);
+	void (*mem_input_deallocate_dmif_buffer)(
+		struct mem_input *mem_input, uint32_t paths_num);
+	bool (*mem_input_program_surface_flip_and_addr)(
+		struct mem_input *mem_input,
+		const struct dc_plane_address *address,
+		bool flip_immediate);
+	bool (*mem_input_program_surface_config)(
+		struct mem_input *mem_input,
+		enum surface_pixel_format format,
+		struct dc_tiling_info *tiling_info,
+		union plane_size *plane_size,
+		enum dc_rotation_angle rotation);
+};
+
+enum stutter_mode_type {
+	STUTTER_MODE_LEGACY = 0X00000001,
+	STUTTER_MODE_ENHANCED = 0X00000002,
+	STUTTER_MODE_FID_NBP_STATE = 0X00000004,
+	STUTTER_MODE_WATERMARK_NBP_STATE = 0X00000008,
+	STUTTER_MODE_SINGLE_DISPLAY_MODEL = 0X00000010,
+	STUTTER_MODE_MIXED_DISPLAY_MODEL = 0X00000020,
+	STUTTER_MODE_DUAL_DMIF_BUFFER = 0X00000040,
+	STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION = 0X00000080,
+	STUTTER_MODE_NO_ADVANCED_REQUEST = 0X00000100,
+	STUTTER_MODE_NO_LB_RESET = 0X00000200,
+	STUTTER_MODE_DISABLED = 0X00000400,
+	STUTTER_MODE_AGGRESSIVE_MARKS = 0X00000800,
+	STUTTER_MODE_URGENCY = 0X00001000,
+	STUTTER_MODE_QUAD_DMIF_BUFFER = 0X00002000,
+	STUTTER_MODE_NOT_USED = 0X00008000
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/opp.h b/drivers/gpu/drm/amd/dal/dc/inc/opp.h
new file mode 100644
index 000000000000..b097983246df
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/opp.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_OPP_H__
+#define __DAL_OPP_H__
+
+#include "dc_types.h"
+#include "grph_object_id.h"
+#include "grph_csc_types.h"
+#include "dm_services_types.h"
+
+struct fixed31_32;
+struct gamma_parameters;
+
+/* TODO: Need cleanup */
+
+enum clamping_range {
+	CLAMPING_FULL_RANGE = 0,	   /* No Clamping */
+	CLAMPING_LIMITED_RANGE_8BPC,   /* 8  bpc: Clamping 1  to FE */
+	CLAMPING_LIMITED_RANGE_10BPC, /* 10 bpc: Clamping 4  to 3FB */
+	CLAMPING_LIMITED_RANGE_12BPC, /* 12 bpc: Clamping 10 to FEF */
+	/* Use programmable clampping value on FMT_CLAMP_COMPONENT_R/G/B. */
+	CLAMPING_LIMITED_RANGE_PROGRAMMABLE
+};
+
+struct clamping_and_pixel_encoding_params {
+	enum dc_pixel_encoding pixel_encoding; /* Pixel Encoding */
+	enum clamping_range clamping_level; /* Clamping identifier */
+	enum dc_color_depth c_depth; /* Deep color use. */
+};
+
+struct bit_depth_reduction_params {
+	struct {
+		/* truncate/round */
+		/* trunc/round enabled*/
+		uint32_t TRUNCATE_ENABLED:1;
+		/* 2 bits: 0=6 bpc, 1=8 bpc, 2 = 10bpc*/
+		uint32_t TRUNCATE_DEPTH:2;
+		/* truncate or round*/
+		uint32_t TRUNCATE_MODE:1;
+
+		/* spatial dither */
+		/* Spatial Bit Depth Reduction enabled*/
+		uint32_t SPATIAL_DITHER_ENABLED:1;
+		/* 2 bits: 0=6 bpc, 1 = 8 bpc, 2 = 10bpc*/
+		uint32_t SPATIAL_DITHER_DEPTH:2;
+		/* 0-3 to select patterns*/
+		uint32_t SPATIAL_DITHER_MODE:2;
+		/* Enable RGB random dithering*/
+		uint32_t RGB_RANDOM:1;
+		/* Enable Frame random dithering*/
+		uint32_t FRAME_RANDOM:1;
+		/* Enable HighPass random dithering*/
+		uint32_t HIGHPASS_RANDOM:1;
+
+		/* temporal dither*/
+		 /* frame modulation enabled*/
+		uint32_t FRAME_MODULATION_ENABLED:1;
+		/* same as for trunc/spatial*/
+		uint32_t FRAME_MODULATION_DEPTH:2;
+		/* 2/4 gray levels*/
+		uint32_t TEMPORAL_LEVEL:1;
+		uint32_t FRC25:2;
+		uint32_t FRC50:2;
+		uint32_t FRC75:2;
+	} flags;
+
+	uint32_t r_seed_value;
+	uint32_t b_seed_value;
+	uint32_t g_seed_value;
+};
+
+
+
+enum wide_gamut_regamma_mode {
+	/*  0x0  - BITS2:0 Bypass */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS,
+	/*  0x1  - Fixed curve sRGB 2.4 */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24,
+	/*  0x2  - Fixed curve xvYCC 2.22 */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22,
+	/*  0x3  - Programmable control A */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A,
+	/*  0x4  - Programmable control B */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B,
+	/*  0x0  - BITS6:4 Bypass */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_BYPASS,
+	/*  0x1  - Fixed curve sRGB 2.4 */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_SRGB24,
+	/*  0x2  - Fixed curve xvYCC 2.22 */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_XYYCC22,
+	/*  0x3  - Programmable control A */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_A,
+	/*  0x4  - Programmable control B */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_B
+};
+
+struct pwl_result_data {
+	struct fixed31_32 red;
+	struct fixed31_32 green;
+	struct fixed31_32 blue;
+
+	struct fixed31_32 delta_red;
+	struct fixed31_32 delta_green;
+	struct fixed31_32 delta_blue;
+
+	uint32_t red_reg;
+	uint32_t green_reg;
+	uint32_t blue_reg;
+
+	uint32_t delta_red_reg;
+	uint32_t delta_green_reg;
+	uint32_t delta_blue_reg;
+};
+
+struct gamma_pixel {
+	struct fixed31_32 r;
+	struct fixed31_32 g;
+	struct fixed31_32 b;
+};
+
+struct gamma_curve {
+	uint32_t offset;
+	uint32_t segments_num;
+};
+
+struct curve_points {
+	struct fixed31_32 x;
+	struct fixed31_32 y;
+	struct fixed31_32 offset;
+	struct fixed31_32 slope;
+
+	uint32_t custom_float_x;
+	uint32_t custom_float_y;
+	uint32_t custom_float_offset;
+	uint32_t custom_float_slope;
+};
+
+enum channel_name {
+	CHANNEL_NAME_RED,
+	CHANNEL_NAME_GREEN,
+	CHANNEL_NAME_BLUE
+};
+
+struct custom_float_format {
+	uint32_t mantissa_bits;
+	uint32_t exponenta_bits;
+	bool sign;
+};
+
+struct custom_float_value {
+	uint32_t mantissa;
+	uint32_t exponenta;
+	uint32_t value;
+	bool negative;
+};
+
+struct hw_x_point {
+	uint32_t custom_float_x;
+	uint32_t custom_float_x_adjusted;
+	struct fixed31_32 x;
+	struct fixed31_32 adjusted_x;
+	struct fixed31_32 regamma_y_red;
+	struct fixed31_32 regamma_y_green;
+	struct fixed31_32 regamma_y_blue;
+
+};
+
+struct pwl_float_data_ex {
+	struct fixed31_32 r;
+	struct fixed31_32 g;
+	struct fixed31_32 b;
+	struct fixed31_32 delta_r;
+	struct fixed31_32 delta_g;
+	struct fixed31_32 delta_b;
+};
+
+enum hw_point_position {
+	/* hw point sits between left and right sw points */
+	HW_POINT_POSITION_MIDDLE,
+	/* hw point lays left from left (smaller) sw point */
+	HW_POINT_POSITION_LEFT,
+	/* hw point lays stays from right (bigger) sw point */
+	HW_POINT_POSITION_RIGHT
+};
+
+struct gamma_point {
+	int32_t left_index;
+	int32_t right_index;
+	enum hw_point_position pos;
+	struct fixed31_32 coeff;
+};
+
+struct pixel_gamma_point {
+	struct gamma_point r;
+	struct gamma_point g;
+	struct gamma_point b;
+};
+
+struct gamma_coefficients {
+	struct fixed31_32 a0[3];
+	struct fixed31_32 a1[3];
+	struct fixed31_32 a2[3];
+	struct fixed31_32 a3[3];
+	struct fixed31_32 user_gamma[3];
+	struct fixed31_32 user_contrast;
+	struct fixed31_32 user_brightness;
+};
+
+struct csc_adjustments {
+	struct fixed31_32 contrast;
+	struct fixed31_32 saturation;
+	struct fixed31_32 brightness;
+	struct fixed31_32 hue;
+};
+
+struct pwl_float_data {
+	struct fixed31_32 r;
+	struct fixed31_32 g;
+	struct fixed31_32 b;
+};
+
+
+/* TODO: Use when we redefine the OPP interface */
+enum opp_regamma {
+	OPP_REGAMMA_BYPASS = 0,
+	OPP_REGAMMA_SRGB,
+	OPP_REGAMMA_3_6,
+	OPP_REGAMMA_PQ,
+	OPP_REGAMMA_PQ_INTERIM,
+};
+
+struct output_pixel_processor {
+	struct dc_context *ctx;
+	uint32_t inst;
+	struct opp_funcs *funcs;
+};
+
+enum fmt_stereo_action {
+	FMT_STEREO_ACTION_ENABLE = 0,
+	FMT_STEREO_ACTION_DISABLE,
+	FMT_STEREO_ACTION_UPDATE_POLARITY
+};
+
+struct opp_funcs {
+	void (*opp_power_on_regamma_lut)(
+		struct output_pixel_processor *opp,
+		bool power_on);
+
+	bool (*opp_set_regamma)(
+		struct output_pixel_processor *opp,
+		const struct gamma_ramp *ramp,
+		const struct gamma_parameters *params,
+		bool force_bypass);
+
+	bool (*opp_map_legacy_and_regamma_hw_to_x_user)(
+		struct output_pixel_processor *opp,
+		const struct gamma_ramp *gamma_ramp,
+		const struct gamma_parameters *params);
+
+	void (*opp_set_csc_adjustment)(
+		struct output_pixel_processor *opp,
+		const struct grph_csc_adjustment *adjust);
+
+	void (*opp_set_csc_default)(
+		struct output_pixel_processor *opp,
+		const struct default_adjustment *default_adjust);
+
+	/* FORMATTER RELATED */
+	void (*opp_program_bit_depth_reduction)(
+		struct output_pixel_processor *opp,
+		const struct bit_depth_reduction_params *params);
+
+	void (*opp_program_clamping_and_pixel_encoding)(
+		struct output_pixel_processor *opp,
+		const struct clamping_and_pixel_encoding_params *params);
+
+
+	void (*opp_set_dyn_expansion)(
+		struct output_pixel_processor *opp,
+		enum color_space color_sp,
+		enum dc_color_depth color_dpth,
+		enum signal_type signal);
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/resource.h b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
new file mode 100644
index 000000000000..bda92e3c4f66
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ */
+
+#ifndef DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_
+#define DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_
+
+#include "core_types.h"
+#include "core_status.h"
+#include "core_dc.h"
+
+/* TODO unhardcode, 4 for CZ*/
+#define MEMORY_TYPE_MULTIPLIER 4
+
+bool dc_construct_resource_pool(struct adapter_service *adapter_serv,
+				struct dc *dc,
+				uint8_t num_virtual_links);
+
+void build_scaling_params(
+	const struct dc_surface *surface,
+	struct core_stream *stream);
+
+void build_scaling_params_for_context(
+	const struct dc *dc,
+	struct validate_context *context);
+
+void unreference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source);
+
+void reference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source);
+
+bool is_same_timing(
+	const struct dc_crtc_timing *timing1,
+	const struct dc_crtc_timing *timing2);
+
+struct clock_source *find_used_clk_src_for_sharing(
+		struct validate_context *context,
+		struct core_stream *stream);
+
+bool logical_attach_surfaces_to_target(
+		struct dc_surface *surfaces[],
+		uint8_t surface_count,
+		struct dc_target *dc_target);
+
+void pplib_apply_safe_state(const struct dc *dc);
+
+void pplib_apply_display_requirements(
+	const struct dc *dc,
+	const struct validate_context *context);
+
+void build_info_frame(struct core_stream *stream);
+
+enum dc_status map_resources(
+	const struct dc *dc,
+	struct validate_context *context);
+
+#endif /* DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
new file mode 100644
index 000000000000..6bb1d007de21
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
@@ -0,0 +1,88 @@
+/*
+ * stream_encoder.h
+ *
+ */
+
+#ifndef STREAM_ENCODER_H_
+#define STREAM_ENCODER_H_
+
+#include "include/hw_sequencer_types.h"
+
+struct dc_bios;
+struct dc_context;
+struct dc_crtc_timing;
+
+
+struct encoder_info_packet {
+	bool valid;
+	uint8_t hb0;
+	uint8_t hb1;
+	uint8_t hb2;
+	uint8_t hb3;
+	uint8_t sb[28];
+};
+
+struct encoder_info_frame {
+	/* auxiliary video information */
+	struct encoder_info_packet avi;
+	struct encoder_info_packet gamut;
+	struct encoder_info_packet vendor;
+	/* source product description */
+	struct encoder_info_packet spd;
+	/* video stream configuration */
+	struct encoder_info_packet vsc;
+};
+
+struct encoder_unblank_param {
+	struct hw_crtc_timing crtc_timing;
+	struct link_settings link_settings;
+};
+
+struct encoder_set_dp_phy_pattern_param {
+	enum dp_test_pattern dp_phy_pattern;
+	const uint8_t *custom_pattern;
+	uint32_t custom_pattern_size;
+	enum dp_panel_mode dp_panel_mode;
+};
+
+
+struct stream_encoder {
+	struct stream_encoder_funcs *funcs;
+	struct dc_context *ctx;
+	struct dc_bios *bp;
+	enum engine_id id;
+};
+
+struct stream_encoder_funcs {
+	void (*dp_set_stream_attribute)(
+		struct stream_encoder *enc,
+		struct dc_crtc_timing *crtc_timing);
+	void (*hdmi_set_stream_attribute)(
+		struct stream_encoder *enc,
+		struct dc_crtc_timing *crtc_timing,
+		bool enable_audio);
+	void (*dvi_set_stream_attribute)(
+		struct stream_encoder *enc,
+		struct dc_crtc_timing *crtc_timing,
+		bool is_dual_link);
+	void (*set_mst_bandwidth)(
+		struct stream_encoder *enc,
+		struct fixed31_32 avg_time_slots_per_mtp);
+	void (*update_hdmi_info_packets)(
+		struct stream_encoder *enc,
+		const struct encoder_info_frame *info_frame);
+	void (*stop_hdmi_info_packets)(
+		struct stream_encoder *enc);
+	void (*update_dp_info_packets)(
+		struct stream_encoder *enc,
+		const struct encoder_info_frame *info_frame);
+	void (*stop_dp_info_packets)(
+		struct stream_encoder *enc);
+	void (*dp_blank)(
+		struct stream_encoder *enc);
+	void (*dp_unblank)(
+		struct stream_encoder *enc,
+		const struct encoder_unblank_param *param);
+};
+
+#endif /* STREAM_ENCODER_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h b/drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
new file mode 100644
index 000000000000..e9ca16938572
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TIMING_GENERATOR_TYPES_H__
+#define __DAL_TIMING_GENERATOR_TYPES_H__
+
+#include "include/grph_csc_types.h"
+
+struct dc_bios;
+
+/**
+ *  These parameters are required as input when doing blanking/Unblanking
+*/
+struct crtc_black_color {
+	uint32_t black_color_r_cr;
+	uint32_t black_color_g_y;
+	uint32_t black_color_b_cb;
+};
+
+/* Contains CRTC vertical/horizontal pixel counters */
+struct crtc_position {
+	uint32_t vertical_count;
+	uint32_t horizontal_count;
+	uint32_t nominal_vcount;
+};
+
+
+enum dcp_gsl_purpose {
+	DCP_GSL_PURPOSE_SURFACE_FLIP = 0,
+	DCP_GSL_PURPOSE_STEREO3D_PHASE,
+	DCP_GSL_PURPOSE_UNDEFINED
+};
+
+struct dcp_gsl_params {
+	enum sync_source gsl_group;
+	enum dcp_gsl_purpose gsl_purpose;
+	bool timing_server;
+	bool overlay_present;
+	bool gsl_paused;
+};
+
+#define LEFT_EYE_3D_PRIMARY_SURFACE 1
+#define RIGHT_EYE_3D_PRIMARY_SURFACE 0
+
+enum test_pattern_dyn_range {
+	TEST_PATTERN_DYN_RANGE_VESA = 0,
+	TEST_PATTERN_DYN_RANGE_CEA
+};
+
+enum test_pattern_mode {
+	TEST_PATTERN_MODE_COLORSQUARES_RGB = 0,
+	TEST_PATTERN_MODE_COLORSQUARES_YCBCR601,
+	TEST_PATTERN_MODE_COLORSQUARES_YCBCR709,
+	TEST_PATTERN_MODE_VERTICALBARS,
+	TEST_PATTERN_MODE_HORIZONTALBARS,
+	TEST_PATTERN_MODE_SINGLERAMP_RGB,
+	TEST_PATTERN_MODE_DUALRAMP_RGB
+};
+
+enum test_pattern_color_format {
+	TEST_PATTERN_COLOR_FORMAT_BPC_6 = 0,
+	TEST_PATTERN_COLOR_FORMAT_BPC_8,
+	TEST_PATTERN_COLOR_FORMAT_BPC_10,
+	TEST_PATTERN_COLOR_FORMAT_BPC_12
+};
+
+enum controller_dp_test_pattern {
+	CONTROLLER_DP_TEST_PATTERN_D102 = 0,
+	CONTROLLER_DP_TEST_PATTERN_SYMBOLERROR,
+	CONTROLLER_DP_TEST_PATTERN_PRBS7,
+	CONTROLLER_DP_TEST_PATTERN_COLORSQUARES,
+	CONTROLLER_DP_TEST_PATTERN_VERTICALBARS,
+	CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS,
+	CONTROLLER_DP_TEST_PATTERN_COLORRAMP,
+	CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+	CONTROLLER_DP_TEST_PATTERN_RESERVED_8,
+	CONTROLLER_DP_TEST_PATTERN_RESERVED_9,
+	CONTROLLER_DP_TEST_PATTERN_RESERVED_A,
+	CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA
+};
+
+enum crtc_state {
+	CRTC_STATE_VBLANK = 0,
+	CRTC_STATE_VACTIVE
+};
+
+struct timing_generator {
+	struct timing_generator_funcs *funcs;
+	struct dc_bios *bp;
+	struct dc_context *ctx;
+};
+
+
+struct dc_crtc_timing;
+
+struct timing_generator_funcs {
+	bool (*validate_timing)(struct timing_generator *tg,
+							const struct dc_crtc_timing *timing);
+	void (*program_timing)(struct timing_generator *tg,
+							const struct dc_crtc_timing *timing,
+							bool use_vbios);
+	bool (*enable_crtc)(struct timing_generator *tg);
+	bool (*disable_crtc)(struct timing_generator *tg);
+	bool (*is_counter_moving)(struct timing_generator *tg);
+	void (*get_position)(struct timing_generator *tg,
+								int32_t *h_position,
+								int32_t *v_position);
+	uint32_t (*get_frame_count)(struct timing_generator *tg);
+	void (*set_early_control)(struct timing_generator *tg,
+							   uint32_t early_cntl);
+	void (*wait_for_state)(struct timing_generator *tg,
+							enum crtc_state state);
+	bool (*set_blank)(struct timing_generator *tg,
+					   bool enable_blanking);
+	void (*set_overscan_blank_color) (struct timing_generator *tg, enum color_space black_color);
+	void (*set_blank_color)(struct timing_generator *tg, enum color_space black_color);
+	void (*set_colors)(struct timing_generator *tg,
+						const struct crtc_black_color *blank_color,
+						const struct crtc_black_color *overscan_color);
+
+	void (*disable_vga)(struct timing_generator *tg);
+	bool (*did_triggered_reset_occur)(struct timing_generator *tg);
+	void (*setup_global_swap_lock)(struct timing_generator *tg,
+							const struct dcp_gsl_params *gsl_params);
+	void (*enable_reset_trigger)(struct timing_generator *tg,
+						const struct trigger_params *trigger_params);
+	void (*disable_reset_trigger)(struct timing_generator *tg);
+	void (*tear_down_global_swap_lock)(struct timing_generator *tg);
+	void (*enable_advanced_request)(struct timing_generator *tg,
+					bool enable, const struct dc_crtc_timing *timing);
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/transform.h b/drivers/gpu/drm/amd/dal/dc/inc/transform.h
new file mode 100644
index 000000000000..22803575ed72
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/transform.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TRANSFORM_H__
+#define __DAL_TRANSFORM_H__
+
+#include "include/scaler_types.h"
+#include "include/grph_csc_types.h"
+#include "calcs/scaler_filter.h"
+#include "grph_object_id.h"
+
+struct bit_depth_reduction_params;
+
+enum scaling_type {
+	SCALING_TYPE_NO_SCALING = 0,
+	SCALING_TYPE_UPSCALING,
+	SCALING_TYPE_DOWNSCALING
+};
+
+struct transform {
+	struct transform_funcs *funcs;
+	struct dc_context *ctx;
+	uint32_t inst;
+	struct scaler_filter *filter;
+};
+
+
+struct scaler_taps_and_ratio {
+	uint32_t h_tap;
+	uint32_t v_tap;
+	uint32_t lo_ratio;
+	uint32_t hi_ratio;
+};
+
+struct scaler_taps {
+	uint32_t h_tap;
+	uint32_t v_tap;
+};
+
+struct sclv_ratios_inits {
+	uint32_t chroma_enable;
+	uint32_t h_int_scale_ratio_luma;
+	uint32_t h_int_scale_ratio_chroma;
+	uint32_t v_int_scale_ratio_luma;
+	uint32_t v_int_scale_ratio_chroma;
+	struct init_int_and_frac h_init_luma;
+	struct init_int_and_frac h_init_chroma;
+	struct init_int_and_frac v_init_luma;
+	struct init_int_and_frac v_init_chroma;
+	struct init_int_and_frac h_init_lumabottom;
+	struct init_int_and_frac h_init_chromabottom;
+	struct init_int_and_frac v_init_lumabottom;
+	struct init_int_and_frac v_init_chromabottom;
+};
+
+enum lb_pixel_depth {
+	/* do not change the values because it is used as bit vector */
+	LB_PIXEL_DEPTH_18BPP = 1,
+	LB_PIXEL_DEPTH_24BPP = 2,
+	LB_PIXEL_DEPTH_30BPP = 4,
+	LB_PIXEL_DEPTH_36BPP = 8
+};
+
+
+struct raw_gamma_ramp_rgb {
+       uint32_t red;
+       uint32_t green;
+       uint32_t blue;
+};
+
+enum raw_gamma_ramp_type {
+       GAMMA_RAMP_TYPE_UNINITIALIZED,
+       GAMMA_RAMP_TYPE_DEFAULT,
+       GAMMA_RAMP_TYPE_RGB256,
+       GAMMA_RAMP_TYPE_FIXED_POINT
+};
+
+#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256
+struct raw_gamma_ramp {
+       enum raw_gamma_ramp_type type;
+       struct raw_gamma_ramp_rgb rgb_256[NUM_OF_RAW_GAMMA_RAMP_RGB_256];
+       uint32_t size;
+};
+
+
+/* Colorimetry */
+enum colorimetry {
+       COLORIMETRY_NO_DATA = 0,
+       COLORIMETRY_ITU601 = 1,
+       COLORIMETRY_ITU709 = 2,
+       COLORIMETRY_EXTENDED = 3
+};
+
+/* ColorimetryEx */
+enum colorimetry_ex {
+       COLORIMETRY_EX_XVYCC601 = 0,
+       COLORIMETRY_EX_XVYCC709 = 1,
+       COLORIMETRY_EX_SYCC601 = 2,
+       COLORIMETRY_EX_ADOBEYCC601 = 3,
+       COLORIMETRY_EX_ADOBERGB = 4,
+       COLORIMETRY_EX_RESERVED5 = 5,
+       COLORIMETRY_EX_RESERVED6 = 6,
+       COLORIMETRY_EX_RESERVED7 = 7
+};
+
+enum ds_color_space {
+       DS_COLOR_SPACE_UNKNOWN = 0,
+       DS_COLOR_SPACE_SRGB_FULLRANGE = 1,
+       DS_COLOR_SPACE_SRGB_LIMITEDRANGE,
+       DS_COLOR_SPACE_YPBPR601,
+       DS_COLOR_SPACE_YPBPR709,
+       DS_COLOR_SPACE_YCBCR601,
+       DS_COLOR_SPACE_YCBCR709,
+       DS_COLOR_SPACE_NMVPU_SUPERAA,
+       DS_COLOR_SPACE_YCBCR601_YONLY,
+       DS_COLOR_SPACE_YCBCR709_YONLY/*same as YCbCr, but Y in Full range*/
+};
+
+
+enum active_format_info {
+       ACTIVE_FORMAT_NO_DATA = 0,
+       ACTIVE_FORMAT_VALID = 1
+};
+
+/* Active format aspect ratio */
+enum active_format_aspect_ratio {
+       ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE = 8,
+       ACTIVE_FORMAT_ASPECT_RATIO_4_3 = 9,
+       ACTIVE_FORMAT_ASPECT_RATIO_16_9 = 0XA,
+       ACTIVE_FORMAT_ASPECT_RATIO_14_9 = 0XB
+};
+
+enum bar_info {
+       BAR_INFO_NOT_VALID = 0,
+       BAR_INFO_VERTICAL_VALID = 1,
+       BAR_INFO_HORIZONTAL_VALID = 2,
+       BAR_INFO_BOTH_VALID = 3
+};
+
+enum picture_scaling {
+       PICTURE_SCALING_UNIFORM = 0,
+       PICTURE_SCALING_HORIZONTAL = 1,
+       PICTURE_SCALING_VERTICAL = 2,
+       PICTURE_SCALING_BOTH = 3
+};
+
+/* RGB quantization range */
+enum rgb_quantization_range {
+       RGB_QUANTIZATION_DEFAULT_RANGE = 0,
+       RGB_QUANTIZATION_LIMITED_RANGE = 1,
+       RGB_QUANTIZATION_FULL_RANGE = 2,
+       RGB_QUANTIZATION_RESERVED = 3
+};
+
+/* YYC quantization range */
+enum yyc_quantization_range {
+       YYC_QUANTIZATION_LIMITED_RANGE = 0,
+       YYC_QUANTIZATION_FULL_RANGE = 1,
+       YYC_QUANTIZATION_RESERVED2 = 2,
+       YYC_QUANTIZATION_RESERVED3 = 3
+};
+
+struct transform_funcs {
+	bool (*transform_power_up)(struct transform *xfm);
+
+	bool (*transform_set_scaler)(
+		struct transform *xfm,
+		const struct scaler_data *data);
+
+	void (*transform_set_scaler_bypass)(struct transform *xfm);
+
+	bool (*transform_update_viewport)(
+		struct transform *xfm,
+		const struct rect *view_port,
+		bool is_fbc_attached);
+
+	void (*transform_set_scaler_filter)(
+		struct transform *xfm,
+		struct scaler_filter *filter);
+
+	void (*transform_set_gamut_remap)(
+		struct transform *xfm,
+		const struct grph_csc_adjustment *adjust);
+
+	bool (*transform_set_pixel_storage_depth)(
+		struct transform *xfm,
+		enum lb_pixel_depth depth,
+		const struct bit_depth_reduction_params *bit_depth_params);
+
+	bool (*transform_get_current_pixel_storage_depth)(
+		struct transform *xfm,
+		enum lb_pixel_depth *depth);
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/irq_types.h b/drivers/gpu/drm/amd/dal/dc/irq_types.h
new file mode 100644
index 000000000000..35a099166613
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq_types.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_TYPES_H__
+#define __DAL_IRQ_TYPES_H__
+
+struct dc_context;
+
+typedef void (*interrupt_handler)(void *);
+
+typedef void *irq_handler_idx;
+#define DAL_INVALID_IRQ_HANDLER_IDX NULL
+
+
+/* The order of the IRQ sources is important and MUST match the one's
+of base driver */
+enum dc_irq_source {
+	/* Use as mask to specify invalid irq source */
+	DC_IRQ_SOURCE_INVALID = 0,
+
+	DC_IRQ_SOURCE_HPD1,
+	DC_IRQ_SOURCE_HPD2,
+	DC_IRQ_SOURCE_HPD3,
+	DC_IRQ_SOURCE_HPD4,
+	DC_IRQ_SOURCE_HPD5,
+	DC_IRQ_SOURCE_HPD6,
+
+	DC_IRQ_SOURCE_HPD1RX,
+	DC_IRQ_SOURCE_HPD2RX,
+	DC_IRQ_SOURCE_HPD3RX,
+	DC_IRQ_SOURCE_HPD4RX,
+	DC_IRQ_SOURCE_HPD5RX,
+	DC_IRQ_SOURCE_HPD6RX,
+
+	DC_IRQ_SOURCE_I2C_DDC1,
+	DC_IRQ_SOURCE_I2C_DDC2,
+	DC_IRQ_SOURCE_I2C_DDC3,
+	DC_IRQ_SOURCE_I2C_DDC4,
+	DC_IRQ_SOURCE_I2C_DDC5,
+	DC_IRQ_SOURCE_I2C_DDC6,
+
+	DC_IRQ_SOURCE_AZALIA0,
+	DC_IRQ_SOURCE_AZALIA1,
+	DC_IRQ_SOURCE_AZALIA2,
+	DC_IRQ_SOURCE_AZALIA3,
+	DC_IRQ_SOURCE_AZALIA4,
+	DC_IRQ_SOURCE_AZALIA5,
+
+	DC_IRQ_SOURCE_DPSINK1,
+	DC_IRQ_SOURCE_DPSINK2,
+	DC_IRQ_SOURCE_DPSINK3,
+	DC_IRQ_SOURCE_DPSINK4,
+	DC_IRQ_SOURCE_DPSINK5,
+	DC_IRQ_SOURCE_DPSINK6,
+
+	DC_IRQ_SOURCE_CRTC1VSYNC,
+	DC_IRQ_SOURCE_CRTC2VSYNC,
+	DC_IRQ_SOURCE_CRTC3VSYNC,
+	DC_IRQ_SOURCE_CRTC4VSYNC,
+	DC_IRQ_SOURCE_CRTC5VSYNC,
+	DC_IRQ_SOURCE_CRTC6VSYNC,
+	DC_IRQ_SOURCE_TIMER,
+
+	DC_IRQ_SOURCE_PFLIP_FIRST,
+	DC_IRQ_SOURCE_PFLIP1 = DC_IRQ_SOURCE_PFLIP_FIRST,
+	DC_IRQ_SOURCE_PFLIP2,
+	DC_IRQ_SOURCE_PFLIP3,
+	DC_IRQ_SOURCE_PFLIP4,
+	DC_IRQ_SOURCE_PFLIP5,
+	DC_IRQ_SOURCE_PFLIP6,
+	DC_IRQ_SOURCE_PFLIP_UNDERLAY0,
+	DC_IRQ_SOURCE_PFLIP_LAST = DC_IRQ_SOURCE_PFLIP_UNDERLAY0,
+
+	DC_IRQ_SOURCE_GPIOPAD0,
+	DC_IRQ_SOURCE_GPIOPAD1,
+	DC_IRQ_SOURCE_GPIOPAD2,
+	DC_IRQ_SOURCE_GPIOPAD3,
+	DC_IRQ_SOURCE_GPIOPAD4,
+	DC_IRQ_SOURCE_GPIOPAD5,
+	DC_IRQ_SOURCE_GPIOPAD6,
+	DC_IRQ_SOURCE_GPIOPAD7,
+	DC_IRQ_SOURCE_GPIOPAD8,
+	DC_IRQ_SOURCE_GPIOPAD9,
+	DC_IRQ_SOURCE_GPIOPAD10,
+	DC_IRQ_SOURCE_GPIOPAD11,
+	DC_IRQ_SOURCE_GPIOPAD12,
+	DC_IRQ_SOURCE_GPIOPAD13,
+	DC_IRQ_SOURCE_GPIOPAD14,
+	DC_IRQ_SOURCE_GPIOPAD15,
+	DC_IRQ_SOURCE_GPIOPAD16,
+	DC_IRQ_SOURCE_GPIOPAD17,
+	DC_IRQ_SOURCE_GPIOPAD18,
+	DC_IRQ_SOURCE_GPIOPAD19,
+	DC_IRQ_SOURCE_GPIOPAD20,
+	DC_IRQ_SOURCE_GPIOPAD21,
+	DC_IRQ_SOURCE_GPIOPAD22,
+	DC_IRQ_SOURCE_GPIOPAD23,
+	DC_IRQ_SOURCE_GPIOPAD24,
+	DC_IRQ_SOURCE_GPIOPAD25,
+	DC_IRQ_SOURCE_GPIOPAD26,
+	DC_IRQ_SOURCE_GPIOPAD27,
+	DC_IRQ_SOURCE_GPIOPAD28,
+	DC_IRQ_SOURCE_GPIOPAD29,
+	DC_IRQ_SOURCE_GPIOPAD30,
+
+	DC_IRQ_SOURCE_DC1UNDERFLOW,
+	DC_IRQ_SOURCE_DC2UNDERFLOW,
+	DC_IRQ_SOURCE_DC3UNDERFLOW,
+	DC_IRQ_SOURCE_DC4UNDERFLOW,
+	DC_IRQ_SOURCE_DC5UNDERFLOW,
+	DC_IRQ_SOURCE_DC6UNDERFLOW,
+
+	DC_IRQ_SOURCE_DMCU_SCP,
+	DC_IRQ_SOURCE_VBIOS_SW,
+
+	DC_IRQ_SOURCE_VUPDATE1,
+	DC_IRQ_SOURCE_VUPDATE2,
+	DC_IRQ_SOURCE_VUPDATE3,
+	DC_IRQ_SOURCE_VUPDATE4,
+	DC_IRQ_SOURCE_VUPDATE5,
+	DC_IRQ_SOURCE_VUPDATE6,
+
+	DAL_IRQ_SOURCES_NUMBER
+};
+
+enum irq_type
+{
+	IRQ_TYPE_PFLIP = DC_IRQ_SOURCE_PFLIP1,
+	IRQ_TYPE_VUPDATE = DC_IRQ_SOURCE_VUPDATE1,
+};
+
+#define DAL_VALID_IRQ_SRC_NUM(src) \
+	((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID)
+
+/* Number of Page Flip IRQ Sources. */
+#define DAL_PFLIP_IRQ_SRC_NUM \
+	(DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1)
+
+/* the number of contexts may be expanded in the future based on needs */
+enum dc_interrupt_context {
+	INTERRUPT_LOW_IRQ_CONTEXT = 0,
+	INTERRUPT_HIGH_IRQ_CONTEXT,
+	INTERRUPT_CONTEXT_NUMBER
+};
+
+enum dc_interrupt_porlarity {
+	INTERRUPT_POLARITY_DEFAULT = 0,
+	INTERRUPT_POLARITY_LOW = INTERRUPT_POLARITY_DEFAULT,
+	INTERRUPT_POLARITY_HIGH,
+	INTERRUPT_POLARITY_BOTH
+};
+
+#define DC_DECODE_INTERRUPT_POLARITY(int_polarity) \
+	(int_polarity == INTERRUPT_POLARITY_LOW) ? "Low" : \
+	(int_polarity == INTERRUPT_POLARITY_HIGH) ? "High" : \
+	(int_polarity == INTERRUPT_POLARITY_BOTH) ? "Both" : "Invalid"
+
+struct dc_timer_interrupt_params {
+	uint32_t micro_sec_interval;
+	enum dc_interrupt_context int_context;
+};
+
+struct dc_interrupt_params {
+	/* The polarity *change* which will trigger an interrupt.
+	 * If 'requested_polarity == INTERRUPT_POLARITY_BOTH', then
+	 * 'current_polarity' must be initialised. */
+	enum dc_interrupt_porlarity requested_polarity;
+	/* If 'requested_polarity == INTERRUPT_POLARITY_BOTH',
+	 * 'current_polarity' should contain the current state, which means
+	 * the interrupt will be triggered when state changes from what is,
+	 * in 'current_polarity'. */
+	enum dc_interrupt_porlarity current_polarity;
+	enum dc_irq_source irq_source;
+	enum dc_interrupt_context int_context;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h b/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
new file mode 100644
index 000000000000..8ebbe650c124
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
@@ -0,0 +1,632 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ADAPTER_SERVICE_INTERFACE_H__
+#define __DAL_ADAPTER_SERVICE_INTERFACE_H__
+
+#include "grph_object_ctrl_defs.h"
+#include "gpio_interface.h"
+#include "ddc_interface.h"
+#include "irq_interface.h"
+#include "bios_parser_interface.h"
+#include "adapter_service_types.h"
+#include "dal_types.h"
+#include "asic_capability_types.h"
+
+/* forward declaration */
+struct i2caux;
+struct adapter_service;
+
+
+/*
+ * enum adapter_feature_id
+ *
+ * Definition of all adapter features
+ *
+ * The enumeration defines the IDs of all the adapter features. The enum
+ * organizes all the features into several feature sets. The range of feature
+ * set N is from ((N-1)*32+1) to (N*32). Because there may be three value-type
+ * feature, boolean-type, unsigned char-type and unsinged int-type, the number
+ * of features should be 32, 4 and 1 in the feature set accordingly.
+ *
+ * In a boolean-type feature set N, the enumeration value of the feature should
+ * be ((N-1)*32+1), ((N-1)*32+2), ..., (N*32).
+ *
+ * In an unsigned char-type feature set N, the enumeration value of the
+ * feature should be ((N-1)*32+1), ((N-1)*32+8), ((N-1)*32+16) and (N*32).
+ *
+ * In an unsigned int-type feature set N, the enumeration value of the feature
+ * should be ((N-1)*32+1)
+ */
+enum adapter_feature_id {
+	FEATURE_UNKNOWN = 0,
+
+	/* Boolean set, up to 32 entries */
+	FEATURE_ENABLE_HW_EDID_POLLING = 1,
+	FEATURE_SET_01_START = FEATURE_ENABLE_HW_EDID_POLLING,
+	FEATURE_DP_SINK_DETECT_POLL_DATA_PIN,
+	FEATURE_UNDERFLOW_INTERRUPT,
+	FEATURE_ALLOW_WATERMARK_ADJUSTMENT,
+	FEATURE_LIGHT_SLEEP,
+	FEATURE_DCP_DITHER_FRAME_RANDOM_ENABLE,
+	FEATURE_DCP_DITHER_RGB_RANDOM_ENABLE,
+	FEATURE_DCP_DITHER_HIGH_PASS_RANDOM_ENABLE,
+	FEATURE_DETECT_REQUIRE_HPD_HIGH,
+	FEATURE_LINE_BUFFER_ENHANCED_PIXEL_DEPTH, /* 10th */
+	FEATURE_MAXIMIZE_URGENCY_WATERMARKS,
+	FEATURE_MAXIMIZE_STUTTER_MARKS,
+	FEATURE_MAXIMIZE_NBP_MARKS,
+	FEATURE_RESTORE_USAGE_I2C_SW_ENGINE,
+	FEATURE_USE_MAX_DISPLAY_CLK,
+	FEATURE_ALLOW_EDP_RESOURCE_SHARING,
+	FEATURE_SUPPORT_DP_YUV,
+	FEATURE_SUPPORT_DP_Y_ONLY,
+	FEATURE_DISABLE_DP_GTC_SYNC,
+	FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, /* 20th */
+	FEATURE_ENABLE_DFS_BYPASS,
+	FEATURE_LB_HIGH_RESOLUTION,
+	FEATURE_DP_DISPLAY_FORCE_SS_ENABLE,
+	FEATURE_REPORT_CE_MODE_ONLY,
+	FEATURE_ALLOW_OPTIMIZED_MODE_AS_DEFAULT,
+	FEATURE_DDC_READ_FORCE_REPEATED_START,
+	FEATURE_FORCE_TIMING_RESYNC,
+	FEATURE_TMDS_DISABLE_DITHERING,
+	FEATURE_HDMI_DISABLE_DITHERING,
+	FEATURE_DP_DISABLE_DITHERING, /* 30th */
+	FEATURE_EMBEDDED_DISABLE_DITHERING,
+	FEATURE_DISABLE_AZ_CLOCK_GATING, /* 32th. This set is full */
+	FEATURE_SET_01_END = FEATURE_SET_01_START + 31,
+
+	/* Boolean set, up to 32 entries */
+	FEATURE_WIRELESS_ENABLE = FEATURE_SET_01_END + 1,
+	FEATURE_SET_02_START = FEATURE_WIRELESS_ENABLE,
+	FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT,
+	FEATURE_WIRELESS_LIMIT_720P,
+	FEATURE_WIRELESS_ENABLE_COMPRESSED_AUDIO,
+	FEATURE_WIRELESS_INCLUDE_UNVERIFIED_TIMINGS,
+	FEATURE_MODIFY_TIMINGS_FOR_WIRELESS,
+	FEATURE_ALLOW_SELF_REFRESH,
+	FEATURE_ALLOW_DYNAMIC_PIXEL_ENCODING_CHANGE,
+	FEATURE_ALLOW_HSYNC_VSYNC_ADJUSTMENT,
+	FEATURE_FORCE_PSR, /* 10th */
+	FEATURE_PREFER_3D_TIMING,
+	FEATURE_VARI_BRIGHT_ENABLE,
+	FEATURE_PSR_ENABLE,
+	FEATURE_EDID_STRESS_READ,
+	FEATURE_DP_FRAME_PACK_STEREO3D,
+	FEATURE_ALLOW_HDMI_WITHOUT_AUDIO,
+	FEATURE_RESTORE_USAGE_I2C_SW_ENGING,
+	FEATURE_ABM_2_0,
+	FEATURE_SUPPORT_MIRABILIS,
+	FEATURE_LOAD_DMCU_FIRMWARE, /* 20th */
+	FEATURE_ENABLE_GPU_SCALING,
+	FEATURE_DONGLE_SINK_COUNT_CHECK,
+	FEATURE_INSTANT_UP_SCALE_DOWN_SCALE,
+	FEATURE_TILED_DISPLAY,
+	FEATURE_CHANGE_I2C_SPEED_CONTROL,
+	FEATURE_REPORT_SINGLE_SELECTED_TIMING,
+	FEATURE_ALLOW_HDMI_HIGH_CLK_DP_DONGLE,
+	FEATURE_SUPPORT_EXTERNAL_PANEL_DRR,
+	FEATURE_SUPPORT_SMOOTH_BRIGHTNESS,
+	FEATURE_ALLOW_DIRECT_MEMORY_ACCESS_TRIG, /* 30th */
+	FEATURE_POWER_GATING_LB_PORTION, /* 31nd. One more left. */
+	FEATURE_SET_02_END = FEATURE_SET_02_START + 31,
+
+	/* UInt set, 1 entry: DCP Bit Depth Reduction Mode */
+	FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE = FEATURE_SET_02_END + 1,
+	FEATURE_SET_03_START = FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE,
+	FEATURE_SET_03_END = FEATURE_SET_03_START + 31,
+
+	/* UInt set, 1 entry: DCP Dither Mode */
+	FEATURE_DCP_DITHER_MODE = FEATURE_SET_03_END + 1,
+	FEATURE_SET_04_START = FEATURE_DCP_DITHER_MODE,
+	FEATURE_SET_04_END = FEATURE_SET_04_START + 31,
+
+	/* UInt set, 1 entry: DCP Programming WA(workaround) */
+	FEATURE_DCP_PROGRAMMING_WA = FEATURE_SET_04_END + 1,
+	FEATURE_SET_06_START = FEATURE_DCP_PROGRAMMING_WA,
+	FEATURE_SET_06_END = FEATURE_SET_06_START + 31,
+
+	/* UInt set, 1 entry: Maximum co-functional non-DP displays */
+	FEATURE_MAX_COFUNC_NON_DP_DISPLAYS = FEATURE_SET_06_END + 1,
+	FEATURE_SET_07_START = FEATURE_MAX_COFUNC_NON_DP_DISPLAYS,
+	FEATURE_SET_07_END = FEATURE_SET_07_START + 31,
+
+	/* UInt set, 1 entry: Number of supported HDMI connection */
+	FEATURE_SUPPORTED_HDMI_CONNECTION_NUM = FEATURE_SET_07_END + 1,
+	FEATURE_SET_08_START = FEATURE_SUPPORTED_HDMI_CONNECTION_NUM,
+	FEATURE_SET_08_END = FEATURE_SET_08_START + 31,
+
+	/* UInt set, 1 entry: Maximum number of controllers */
+	FEATURE_MAX_CONTROLLER_NUM = FEATURE_SET_08_END + 1,
+	FEATURE_SET_09_START = FEATURE_MAX_CONTROLLER_NUM,
+	FEATURE_SET_09_END = FEATURE_SET_09_START + 31,
+
+	/* UInt set, 1 entry: Type of DRR support */
+	FEATURE_DRR_SUPPORT = FEATURE_SET_09_END + 1,
+	FEATURE_SET_10_START = FEATURE_DRR_SUPPORT,
+	FEATURE_SET_10_END = FEATURE_SET_10_START + 31,
+
+	/* UInt set, 1 entry: Stutter mode support */
+	FEATURE_STUTTER_MODE = FEATURE_SET_10_END + 1,
+	FEATURE_SET_11_START = FEATURE_STUTTER_MODE,
+	FEATURE_SET_11_END = FEATURE_SET_11_START + 31,
+
+	/* UInt set, 1 entry: Measure PSR setup time */
+	FEATURE_PSR_SETUP_TIME_TEST = FEATURE_SET_11_END + 1,
+	FEATURE_SET_12_START = FEATURE_PSR_SETUP_TIME_TEST,
+	FEATURE_SET_12_END = FEATURE_SET_12_START + 31,
+
+	/* Boolean set, up to 32 entries */
+	FEATURE_POWER_GATING_PIPE_IN_TILE = FEATURE_SET_12_END + 1,
+	FEATURE_SET_13_START = FEATURE_POWER_GATING_PIPE_IN_TILE,
+	FEATURE_USE_PPLIB,
+	FEATURE_DISABLE_LPT_SUPPORT,
+	FEATURE_DUMMY_FBC_BACKEND,
+	FEATURE_DISABLE_FBC_COMP_CLK_GATE,
+	FEATURE_DPMS_AUDIO_ENDPOINT_CONTROL,
+	FEATURE_PIXEL_PERFECT_OUTPUT,
+	FEATURE_8BPP_SUPPORTED,
+	FEATURE_SET_13_END = FEATURE_SET_13_START + 31,
+
+	/* UInt set, 1 entry: Display preferred view
+	 * 0: no preferred view
+	 * 1: native and preferred timing of embedded display will have high
+	 *    priority, so other displays will support it always
+	 */
+	FEATURE_DISPLAY_PREFERRED_VIEW = FEATURE_SET_13_END + 1,
+	FEATURE_SET_15_START = FEATURE_DISPLAY_PREFERRED_VIEW,
+	FEATURE_SET_15_END = FEATURE_SET_15_START + 31,
+
+	/* UInt set, 1 entry: DAL optimization */
+	FEATURE_OPTIMIZATION = FEATURE_SET_15_END + 1,
+	FEATURE_SET_16_START = FEATURE_OPTIMIZATION,
+	FEATURE_SET_16_END = FEATURE_SET_16_START + 31,
+
+	/* UInt set, 1 entry: Performance measurement */
+	FEATURE_PERF_MEASURE = FEATURE_SET_16_END + 1,
+	FEATURE_SET_17_START = FEATURE_PERF_MEASURE,
+	FEATURE_SET_17_END = FEATURE_SET_17_START + 31,
+
+	/* UInt set, 1 entry: Minimum backlight value [0-255] */
+	FEATURE_MIN_BACKLIGHT_LEVEL = FEATURE_SET_17_END + 1,
+	FEATURE_SET_18_START = FEATURE_MIN_BACKLIGHT_LEVEL,
+	FEATURE_SET_18_END = FEATURE_SET_18_START + 31,
+
+	/* UInt set, 1 entry: Maximum backlight value [0-255] */
+	FEATURE_MAX_BACKLIGHT_LEVEL = FEATURE_SET_18_END + 1,
+	FEATURE_SET_19_START = FEATURE_MAX_BACKLIGHT_LEVEL,
+	FEATURE_SET_19_END = FEATURE_SET_19_START + 31,
+
+	/* UInt set, 1 entry: AMB setting
+	 *
+	 * Each byte will control the ABM configuration to use for a specific
+	 * ABM level.
+	 *
+	 * HW team provided 12 different ABM min/max reduction pairs to choose
+	 * between for each ABM level.
+	 *
+	 * ABM level Byte Setting
+	 *       1    0   Default = 0 (setting 3), can be override to 1-12
+	 *       2    1   Default = 0 (setting 7), can be override to 1-12
+	 *       3    2   Default = 0 (setting 8), can be override to 1-12
+	 *       4    3   Default = 0 (setting 10), can be override to 1-12
+	 *
+	 * For example,
+	 * FEATURE_PREFERRED_ABM_CONFIG_SET = 0x0C060500, this represents:
+	 * ABM level 1 use default setting (setting 3)
+	 * ABM level 2 uses setting 5
+	 * ABM level 3 uses setting 6
+	 * ABM level 4 uses setting 12
+	 * Internal use only!
+	 */
+	FEATURE_PREFERRED_ABM_CONFIG_SET = FEATURE_SET_19_END + 1,
+	FEATURE_SET_20_START = FEATURE_PREFERRED_ABM_CONFIG_SET,
+	FEATURE_SET_20_END = FEATURE_SET_20_START + 31,
+
+	/* UInt set, 1 entry: Change SW I2C speed */
+	FEATURE_CHANGE_SW_I2C_SPEED = FEATURE_SET_20_END + 1,
+	FEATURE_SET_21_START = FEATURE_CHANGE_SW_I2C_SPEED,
+	FEATURE_SET_21_END = FEATURE_SET_21_START + 31,
+
+	/* UInt set, 1 entry: Change HW I2C speed */
+	FEATURE_CHANGE_HW_I2C_SPEED = FEATURE_SET_21_END + 1,
+	FEATURE_SET_22_START = FEATURE_CHANGE_HW_I2C_SPEED,
+	FEATURE_SET_22_END = FEATURE_SET_22_START + 31,
+
+	/* UInt set, 1 entry:
+	 * When PSR issue occurs, it is sometimes hard to debug since the
+	 * failure occurs immediately at boot. Use this setting to skip or
+	 * postpone PSR functionality and re-enable through DSAT. */
+	FEATURE_DEFAULT_PSR_LEVEL = FEATURE_SET_22_END + 1,
+	FEATURE_SET_23_START = FEATURE_DEFAULT_PSR_LEVEL,
+	FEATURE_SET_23_END = FEATURE_SET_23_START + 31,
+
+	/* UInt set, 1 entry: Allowed pixel clock range for LVDS */
+	FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE = FEATURE_SET_23_END + 1,
+	FEATURE_SET_24_START = FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE,
+	FEATURE_SET_24_END = FEATURE_SET_24_START + 31,
+
+	/* UInt set, 1 entry: Max number of clock sources */
+	FEATURE_MAX_CLOCK_SOURCE_NUM = FEATURE_SET_24_END + 1,
+	FEATURE_SET_25_START = FEATURE_MAX_CLOCK_SOURCE_NUM,
+	FEATURE_SET_25_END = FEATURE_SET_25_START + 31,
+
+	/* UInt set, 1 entry: Select the ABM configuration to use.
+	 *
+	 * This feature set is used to allow packaging option to be defined
+	 * to allow OEM to select between the default ABM configuration or
+	 * alternative predefined configurations that may be more aggressive.
+	 *
+	 * Note that this regkey is meant for external use to select the
+	 * configuration OEM wants. Whereas the other PREFERRED_ABM_CONFIG_SET
+	 * key is only used for internal use and allows full reconfiguration.
+	 */
+	FEATURE_ABM_CONFIG = FEATURE_SET_25_END + 1,
+	FEATURE_SET_26_START = FEATURE_ABM_CONFIG,
+	FEATURE_SET_26_END = FEATURE_SET_26_START + 31,
+
+	/* UInt set, 1 entry: Select the default speed in which smooth
+	 * brightness feature should converge towards target backlight level.
+	 *
+	 * For example, a setting of 500 means it takes 500ms to transition
+	 * from current backlight level to the new requested backlight level.
+	 */
+	FEATURE_SMOOTH_BRTN_ADJ_TIME_IN_MS = FEATURE_SET_26_END + 1,
+	FEATURE_SET_27_START = FEATURE_SMOOTH_BRTN_ADJ_TIME_IN_MS,
+	FEATURE_SET_27_END = FEATURE_SET_27_START + 31,
+
+	/* Set 28: UInt set, 1 entry: Allow runtime parameter to force specific
+	 * Static Screen Event triggers for test purposes. */
+	FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS = FEATURE_SET_27_END + 1,
+	FEATURE_SET_28_START = FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS,
+	FEATURE_SET_28_END = FEATURE_SET_28_START + 31,
+
+	FEATURE_MAXIMUM
+};
+
+/* Adapter Service type of DRR support*/
+enum as_drr_support {
+	AS_DRR_SUPPORT_DISABLED = 0x0,
+	AS_DRR_SUPPORT_ENABLED = 0x1,
+	AS_DRR_SUPPORT_MIN_FORCED_FPS = 0xA
+};
+
+/* Adapter service initialize data structure*/
+struct as_init_data {
+	struct hw_asic_id hw_init_data;
+	struct bp_init_data bp_init_data;
+	struct dc_context *ctx;
+	struct bdf_info bdf_info;
+	const struct dal_override_parameters *display_param;
+	struct dc_bios *vbios_override;
+	enum dce_environment dce_environment;
+};
+
+/* Create adapter service */
+struct adapter_service *dal_adapter_service_create(
+	struct as_init_data *init_data);
+
+/* Destroy adapter service and objects it contains */
+void dal_adapter_service_destroy(
+	struct adapter_service **as);
+
+/* Get the DCE version of current ASIC */
+enum dce_version dal_adapter_service_get_dce_version(
+	const struct adapter_service *as);
+
+enum dce_environment dal_adapter_service_get_dce_environment(
+	const struct adapter_service *as);
+
+/* Get firmware information from BIOS */
+bool dal_adapter_service_get_firmware_info(
+	struct adapter_service *as,
+	struct firmware_info *info);
+
+
+/* functions to get a total number of objects of specific type */
+uint8_t dal_adapter_service_get_connectors_num(
+	struct adapter_service *as);
+
+/* Get number of controllers */
+uint8_t dal_adapter_service_get_controllers_num(
+	struct adapter_service *as);
+
+/* Get number of clock sources */
+uint8_t dal_adapter_service_get_clock_sources_num(
+	struct adapter_service *as);
+
+/* Get number of controllers */
+uint8_t dal_adapter_service_get_func_controllers_num(
+	struct adapter_service *as);
+
+/* Get number of stream engines */
+uint8_t dal_adapter_service_get_stream_engines_num(
+	struct adapter_service *as);
+
+/* functions to get object id based on object index */
+struct graphics_object_id dal_adapter_service_get_connector_obj_id(
+	struct adapter_service *as,
+	uint8_t connector_index);
+
+/* Get number of spread spectrum entries from BIOS */
+uint32_t dal_adapter_service_get_ss_info_num(
+	struct adapter_service *as,
+	enum as_signal_type signal);
+
+/* Get spread spectrum info from BIOS */
+bool dal_adapter_service_get_ss_info(
+	struct adapter_service *as,
+	enum as_signal_type signal,
+	uint32_t idx,
+	struct spread_spectrum_info *info);
+
+/* Check if DFS bypass is enabled */
+bool dal_adapter_service_is_dfs_bypass_enabled(struct adapter_service *as);
+
+/* Get memory controller latency */
+uint32_t dal_adapter_service_get_mc_latency(
+	struct adapter_service *as);
+
+/* Get the video RAM bit width set on the ASIC */
+uint32_t dal_adapter_service_get_asic_vram_bit_width(
+	struct adapter_service *as);
+
+/* Get the bug flags set on this ASIC */
+struct asic_bugs dal_adapter_service_get_asic_bugs(
+	struct adapter_service *as);
+
+/* Get efficiency of DRAM */
+uint32_t dal_adapter_service_get_dram_bandwidth_efficiency(
+	struct adapter_service *as);
+
+/* Get multiplier for the memory type */
+uint32_t dal_adapter_service_get_memory_type_multiplier(
+	struct adapter_service *as);
+
+/* Get parameters for bandwidth tuning */
+bool dal_adapter_service_get_bandwidth_tuning_params(
+	struct adapter_service *as,
+	union bandwidth_tuning_params *params);
+
+/* Get integrated information on BIOS */
+bool dal_adapter_service_get_integrated_info(
+	struct adapter_service *as,
+	struct integrated_info *info);
+
+/* Return if a given feature is supported by the ASIC */
+bool dal_adapter_service_is_feature_supported(
+	enum adapter_feature_id feature_id);
+
+/* Get the cached value of a given feature */
+bool dal_adapter_service_get_feature_value(
+	const enum adapter_feature_id feature_id,
+	void *data,
+	uint32_t size);
+
+/* Get a copy of ASIC feature flags */
+struct asic_feature_flags dal_adapter_service_get_feature_flags(
+	struct adapter_service *as);
+
+/* Obtain DDC */
+struct ddc *dal_adapter_service_obtain_ddc(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+/* Release DDC */
+void dal_adapter_service_release_ddc(
+	struct adapter_service *as,
+	struct ddc *ddc);
+
+/* Obtain HPD interrupt request */
+struct irq *dal_adapter_service_obtain_hpd_irq(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+/* Release interrupt request */
+void dal_adapter_service_release_irq(
+	struct adapter_service *as,
+	struct irq *irq);
+
+/* Obtain GPIO */
+struct gpio *dal_adapter_service_obtain_gpio(
+	struct adapter_service *as,
+	enum gpio_id id,
+	uint32_t en);
+
+/* Obtain GPIO for stereo3D*/
+struct gpio *dal_adapter_service_obtain_stereo_gpio(struct adapter_service *as);
+
+/* Release GPIO */
+void dal_adapter_service_release_gpio(
+		struct adapter_service *as,
+		struct gpio *gpio);
+
+/* Get SW I2C speed */
+uint32_t dal_adapter_service_get_sw_i2c_speed(struct adapter_service *as);
+
+/* Get HW I2C speed */
+uint32_t dal_adapter_service_get_hw_i2c_speed(struct adapter_service *as);
+
+/* Get line buffer size */
+uint32_t dal_adapter_service_get_line_buffer_size(struct adapter_service *as);
+
+/* Get information on audio support */
+union audio_support dal_adapter_service_get_audio_support(
+		struct adapter_service *as);
+
+/* Get I2C information from BIOS */
+bool dal_adapter_service_get_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	struct graphics_object_i2c_info *i2c_info);
+
+/* Get bios parser handler */
+struct dc_bios *dal_adapter_service_get_bios_parser(
+	struct adapter_service *as);
+
+/* Get i2c aux handler */
+struct i2caux *dal_adapter_service_get_i2caux(
+	struct adapter_service *as);
+
+struct dal_asic_runtime_flags dal_adapter_service_get_asic_runtime_flags(
+	struct adapter_service *as);
+
+bool dal_adapter_service_initialize_hw_data(
+	struct adapter_service *as);
+
+struct graphics_object_id dal_adapter_service_enum_fake_path_resource(
+	struct adapter_service *as,
+	uint32_t index);
+
+struct graphics_object_id dal_adapter_service_enum_stereo_sync_object(
+	struct adapter_service *as,
+	uint32_t index);
+
+struct graphics_object_id dal_adapter_service_enum_sync_output_object(
+	struct adapter_service *as,
+	uint32_t index);
+
+struct graphics_object_id dal_adapter_service_enum_audio_object(
+	struct adapter_service *as,
+	uint32_t index);
+
+void dal_adapter_service_update_audio_connectivity(
+	struct adapter_service *as,
+	uint32_t number_of_audio_capable_display_path);
+
+bool dal_adapter_service_has_embedded_display_connector(
+	struct adapter_service *as);
+
+bool dal_adapter_service_get_embedded_panel_info(
+	struct adapter_service *as,
+	struct embedded_panel_info *info);
+
+bool dal_adapter_service_enum_embedded_panel_patch_mode(
+	struct adapter_service *as,
+	uint32_t index,
+	struct embedded_panel_patch_mode *mode);
+
+bool dal_adapter_service_get_faked_edid_len(
+	struct adapter_service *as,
+	uint32_t *len);
+
+bool dal_adapter_service_get_faked_edid_buf(
+	struct adapter_service *as,
+	uint8_t *buf,
+	uint32_t len);
+
+uint32_t dal_adapter_service_get_max_cofunc_non_dp_displays(void);
+
+uint32_t dal_adapter_service_get_single_selected_timing_signals(void);
+
+bool dal_adapter_service_get_device_tag(
+	struct adapter_service *as,
+	struct graphics_object_id connector_object_id,
+	uint32_t device_tag_index,
+	struct connector_device_tag_info *info);
+
+bool dal_adapter_service_is_device_id_supported(
+	struct adapter_service *as,
+	struct device_id id);
+
+bool dal_adapter_service_is_meet_underscan_req(struct adapter_service *as);
+
+bool dal_adapter_service_underscan_for_hdmi_only(struct adapter_service *as);
+
+uint32_t dal_adapter_service_get_src_num(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+struct graphics_object_id dal_adapter_service_get_src_obj(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	uint32_t index);
+
+/* Is this Fusion ASIC */
+bool dal_adapter_service_is_fusion(struct adapter_service *as);
+
+/* Is this ASIC support dynamic DFSbypass switch */
+bool dal_adapter_service_is_dfsbyass_dynamic(struct adapter_service *as);
+
+/* Reports whether driver settings allow requested optimization */
+bool dal_adapter_service_should_optimize(
+		struct adapter_service *as, enum optimization_feature feature);
+
+/* Determine if driver is in accelerated mode */
+bool dal_adapter_service_is_in_accelerated_mode(struct adapter_service *as);
+
+struct ddc *dal_adapter_service_obtain_ddc_from_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_i2c_info *info);
+
+struct bdf_info dal_adapter_service_get_adapter_info(
+	struct adapter_service *as);
+
+
+/* Determine if this ASIC needs to wait on PLL lock bit */
+bool dal_adapter_service_should_psr_skip_wait_for_pll_lock(
+	struct adapter_service *as);
+
+#define SIZEOF_BACKLIGHT_LUT 101
+#define ABSOLUTE_BACKLIGHT_MAX 255
+#define DEFAULT_MIN_BACKLIGHT 12
+#define DEFAULT_MAX_BACKLIGHT 255
+#define BACKLIGHT_CURVE_COEFFB 100
+#define BACKLIGHT_CURVE_COEFFA_FACTOR 10000
+#define BACKLIGHT_CURVE_COEFFB_FACTOR 100
+
+struct panel_backlight_levels {
+	uint32_t ac_level_percentage;
+	uint32_t dc_level_percentage;
+};
+
+bool dal_adapter_service_is_lid_open(struct adapter_service *as);
+
+bool dal_adapter_service_get_panel_backlight_default_levels(
+	struct adapter_service *as,
+	struct panel_backlight_levels *levels);
+
+bool dal_adapter_service_get_panel_backlight_boundaries(
+	struct adapter_service *as,
+	struct panel_backlight_boundaries *boundaries);
+
+uint32_t dal_adapter_service_get_view_port_pixel_granularity(
+	struct adapter_service *as);
+
+uint32_t dal_adapter_service_get_num_of_path_per_dp_mst_connector(
+		struct adapter_service *as);
+
+uint32_t dal_adapter_service_get_num_of_underlays(
+		struct adapter_service *as);
+
+bool dal_adapter_service_get_encoder_cap_info(
+		struct adapter_service *as,
+		struct graphics_object_id id,
+		struct graphics_object_encoder_cap_info *info);
+
+bool dal_adapter_service_is_mc_tuning_req(struct adapter_service *as);
+
+#endif /* __DAL_ADAPTER_SERVICE_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/adapter_service_types.h b/drivers/gpu/drm/amd/dal/include/adapter_service_types.h
new file mode 100644
index 000000000000..4cb4b4b6eeed
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/adapter_service_types.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ADAPTER_SERVICE_TYPES_H__
+#define __DAL_ADAPTER_SERVICE_TYPES_H__
+
+/* TODO: include signal_types.h and remove this enum */
+enum as_signal_type {
+	AS_SIGNAL_TYPE_NONE = 0L, /* no signal */
+	AS_SIGNAL_TYPE_DVI,
+	AS_SIGNAL_TYPE_HDMI,
+	AS_SIGNAL_TYPE_LVDS,
+	AS_SIGNAL_TYPE_DISPLAY_PORT,
+	AS_SIGNAL_TYPE_GPU_PLL,
+	AS_SIGNAL_TYPE_UNKNOWN
+};
+
+/*
+ * Struct used for algorithm of Bandwidth tuning parameters
+ * the sequence of the fields is binded with runtime parameter.
+ */
+union bandwidth_tuning_params {
+	struct bandwidth_tuning_params_struct {
+		uint32_t read_delay_stutter_off_usec;
+		uint32_t ignore_hblank_time;/*bool*/
+		uint32_t extra_reordering_latency_usec;
+		uint32_t extra_mc_latency_usec;
+		uint32_t data_return_bandwidth_eff;/*in %*/
+		uint32_t dmif_request_bandwidth_eff;/*in %*/
+		uint32_t sclock_latency_multiplier;/*in unit of 0.01*/
+		uint32_t mclock_latency_multiplier;/*in unit of 0.01*/
+		uint32_t fix_latency_multiplier;/*in unit of 0.01*/
+		 /*in unit represent in watermark*/
+		uint32_t use_urgency_watermark_offset;
+	} tuning_info;
+	uint32_t arr_info[sizeof(struct bandwidth_tuning_params_struct)
+		/ sizeof(uint32_t)];
+};
+
+union audio_support {
+	struct {
+		uint32_t DP_AUDIO:1;
+		uint32_t HDMI_AUDIO_ON_DONGLE:1;
+		uint32_t HDMI_AUDIO_NATIVE:1;
+	} bits;
+	uint32_t raw;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h b/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
new file mode 100644
index 000000000000..bdeaaf9066a2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of enc software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and enc permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ASIC_CAPABILITY_INTERFACE_H__
+#define __DAL_ASIC_CAPABILITY_INTERFACE_H__
+
+/* Include */
+#include "include/asic_capability_types.h"
+
+/* Forward declaration */
+struct hw_asic_id;
+
+
+/* ASIC capability */
+struct asic_capability {
+	struct dc_context *ctx;
+	struct asic_caps caps;
+	struct asic_stereo_3d_caps stereo_3d_caps;
+	struct asic_bugs bugs;
+	struct dal_asic_runtime_flags runtime_flags;
+	uint32_t data[ASIC_DATA_MAX_NUMBER];
+};
+
+
+/**
+ * Interfaces
+ */
+
+/* Create and initialize ASIC capability */
+struct asic_capability *dal_asic_capability_create(struct hw_asic_id *init,
+		struct dc_context *ctx);
+
+/* Destroy ASIC capability and free memory space */
+void dal_asic_capability_destroy(struct asic_capability **cap);
+
+#endif /* __DAL_ASIC_CAPABILITY_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/asic_capability_types.h b/drivers/gpu/drm/amd/dal/include/asic_capability_types.h
new file mode 100644
index 000000000000..1cb977618bdf
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/asic_capability_types.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_ASIC_CAPABILITY_TYPES_H__
+#define __DAL_ASIC_CAPABILITY_TYPES_H__
+
+/*
+ * ASIC Capabilities
+ */
+struct asic_caps {
+	bool CONSUMER_SINGLE_SELECTED_TIMING:1;
+	bool UNDERSCAN_ADJUST:1;
+	bool DELTA_SIGMA_SUPPORT:1;
+	bool PANEL_SELF_REFRESH_SUPPORTED:1;
+	bool IS_FUSION:1;
+	bool DP_MST_SUPPORTED:1;
+	bool UNDERSCAN_FOR_HDMI_ONLY:1;
+	bool DVI_CLOCK_SHARE_CAPABILITY:1;
+	bool SUPPORT_CEA861E_FINAL:1;
+	bool MIRABILIS_SUPPORTED:1;
+	bool MIRABILIS_ENABLED_BY_DEFAULT:1;
+	bool DEVICE_TAG_REMAP_SUPPORTED:1;
+	bool HEADLESS_NO_OPM_SUPPORTED:1;
+	bool WIRELESS_LIMIT_TO_720P:1;
+	bool WIRELESS_FULL_TIMING_ADJUSTMENT:1;
+	bool WIRELESS_TIMING_ADJUSTMENT:1;
+	bool WIRELESS_COMPRESSED_AUDIO:1;
+	bool VCE_SUPPORTED:1;
+	bool HPD_CHECK_FOR_EDID:1;
+	bool NO_VCC_OFF_HPD_POLLING:1;
+	bool NEED_MC_TUNING:1;
+	bool SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT:1;
+	bool DFSBYPASS_DYNAMIC_SUPPORT:1;
+	bool SUPPORT_8BPP:1;
+};
+
+
+/*
+ * ASIC Stereo 3D Caps
+ */
+struct asic_stereo_3d_caps {
+	bool SUPPORTED:1;
+	bool DISPLAY_BASED_ON_WS:1;
+	bool HDMI_FRAME_PACK:1;
+	bool INTERLACE_FRAME_PACK:1;
+	bool DISPLAYPORT_FRAME_PACK:1;
+	bool DISPLAYPORT_FRAME_ALT:1;
+	bool INTERLEAVE:1;
+};
+
+
+/*
+ * ASIC Bugs
+ */
+struct asic_bugs {
+	bool MST_SYMBOL_MISALIGNMENT:1;
+	bool PSR_2X_LANE_GANGING:1;
+	bool LB_WA_IS_SUPPORTED:1;
+	bool ROM_REGISTER_ACCESS:1;
+	bool PSR_WA_OVERSCAN_CRC_ERROR:1;
+};
+
+
+/*
+ * ASIC Data
+ */
+enum asic_data {
+	ASIC_DATA_FIRST = 0,
+	ASIC_DATA_CONTROLLERS_NUM = ASIC_DATA_FIRST,
+	ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM,
+	ASIC_DATA_DCE_VERSION,
+	ASIC_DATA_DCE_VERSION_MINOR,
+	ASIC_DATA_VRAM_TYPE,
+	ASIC_DATA_VRAM_BITWIDTH,
+	ASIC_DATA_FEATURE_FLAGS,
+	ASIC_DATA_LINEBUFFER_NUM,
+	ASIC_DATA_LINEBUFFER_SIZE,
+	ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY,
+	ASIC_DATA_MC_LATENCY,
+	ASIC_DATA_MC_LATENCY_SLOW,
+	ASIC_DATA_CLOCKSOURCES_NUM,
+	ASIC_DATA_MEMORYTYPE_MULTIPLIER,
+	ASIC_DATA_STUTTERMODE,
+	ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR,
+	ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS,
+	ASIC_DATA_REVISION_ID,
+	ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE,
+	ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY,
+	ASIC_DATA_DIGFE_NUM,
+	ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM,
+	ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN,
+	ASIC_DATA_NUM_OF_VIDEO_PLANES,
+	ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ,
+	ASIC_DATA_MAX_NUMBER /* end of enum */
+};
+
+
+/*
+ * ASIC Feature Flags
+ */
+struct asic_feature_flags {
+	union {
+		uint32_t raw;
+		struct {
+			uint32_t LEGACY_CLIENT:1;
+			uint32_t PACKED_PIXEL_FORMAT:1;
+			uint32_t WORKSTATION_STEREO:1;
+			uint32_t WORKSTATION:1;
+		} bits;
+	};
+};
+
+#endif /* __DAL_ASIC_CAPABILITY_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/audio_interface.h b/drivers/gpu/drm/amd/dal/include/audio_interface.h
new file mode 100644
index 000000000000..bf2176279f0e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/audio_interface.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUDIO_INTERFACE_H__
+#define __DAL_AUDIO_INTERFACE_H__
+
+#include "audio_types.h"
+#include "adapter_service_interface.h"
+#include "signal_types.h"
+#include "link_service_types.h"
+
+/* forward declaration */
+struct audio;
+struct dal_adapter_service;
+
+/*****  audio initialization data  *****/
+/*
+ * by audio, it means audio endpoint id. ASIC may have many endpoints.
+ * upper sw layer will create one audio object instance for each endpoints.
+ * ASIC support internal audio only. So enum number is used to differ
+ * each endpoint
+ */
+struct audio_init_data {
+	struct adapter_service *as;
+	struct graphics_object_id audio_stream_id;
+	struct dc_context *ctx;
+};
+
+enum audio_result {
+	AUDIO_RESULT_OK,
+	AUDIO_RESULT_ERROR,
+};
+
+/****** audio object create, destroy ******/
+struct audio *dal_audio_create(
+	const struct audio_init_data *init_data);
+
+void dal_audio_destroy(
+	struct audio **audio);
+
+/****** graphics object interface ******/
+const struct graphics_object_id dal_audio_get_graphics_object_id(
+	const struct audio *audio);
+
+/* Enumerate Graphics Object supported Input/Output Signal Types */
+uint32_t dal_audio_enumerate_input_signals(
+	struct audio *audio);
+
+uint32_t dal_audio_enumerate_output_signals(
+	struct audio *audio);
+
+/*  Check if signal supported by GraphicsObject  */
+bool dal_audio_is_input_signal_supported(
+	struct audio *audio,
+	enum signal_type signal);
+
+bool dal_audio_is_output_signal_supported(
+	struct audio *audio,
+	enum signal_type signal);
+
+
+/***** programming interface *****/
+
+/* perform power up sequence (boot up, resume, recovery) */
+enum audio_result dal_audio_power_up(
+	struct audio *audio);
+
+/* perform power down (shut down, stand by) */
+enum audio_result dal_audio_power_down(
+	struct audio *audio);
+
+/* setup audio */
+enum audio_result dal_audio_setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info);
+
+/* enable audio */
+enum audio_result dal_audio_enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+/* disable audio */
+enum audio_result dal_audio_disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+/* enable azalia audio endpoint */
+enum audio_result dal_audio_enable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id);
+
+/* disable azalia audio endpoint */
+enum audio_result dal_audio_disable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id);
+
+/* unmute audio */
+enum audio_result dal_audio_unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+/* mute audio */
+enum audio_result dal_audio_mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+
+/***** information interface *****/
+
+struct audio_feature_support dal_audio_get_supported_features(
+	struct audio *audio);
+
+/* get audio bandwidth information */
+void dal_audio_check_audio_bandwidth(
+	struct audio *audio,
+	const struct audio_crtc_info *info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates);
+
+/* Enable multi channel split */
+void dal_audio_enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable);
+
+/* get current multi channel split. */
+enum audio_result dal_audio_get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping);
+
+/* set payload value for the unsolicited response */
+void dal_audio_set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload);
+
+/*Assign GTC group and enable GTC value embedding*/
+void dal_audio_enable_gtc_embedding_with_group(
+	struct audio *audio,
+	uint32_t group_num,
+	uint32_t audio_latency);
+
+/* Disable GTC value embedding */
+void dal_audio_disable_gtc_embedding(
+	struct audio *audio);
+
+/* Update audio wall clock source */
+void dal_audio_setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/audio_types.h b/drivers/gpu/drm/amd/dal/include/audio_types.h
new file mode 100644
index 000000000000..54f5546a574c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/audio_types.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AUDIO_TYPES_H__
+#define __AUDIO_TYPES_H__
+
+#include "grph_object_defs.h"
+#include "signal_types.h"
+
+#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20
+#define MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 18
+#define MULTI_CHANNEL_SPLIT_NO_ASSO_INFO 0xFFFFFFFF
+
+
+struct audio_pll_hw_settings {
+	uint32_t feed_back_divider;
+	uint32_t step_size_integer;
+	uint32_t step_size_fraction;
+	uint32_t step_range;
+};
+
+struct audio_clock_info {
+	/* pixel clock frequency*/
+	uint32_t pixel_clock_in_10khz;
+	/* N - 32KHz audio */
+	uint32_t n_32khz;
+	/* CTS - 32KHz audio*/
+	uint32_t cts_32khz;
+	uint32_t n_44khz;
+	uint32_t cts_44khz;
+	uint32_t n_48khz;
+	uint32_t cts_48khz;
+};
+
+struct azalia_clock_info {
+	uint32_t pixel_clock_in_10khz;
+	uint32_t audio_dto_phase;
+	uint32_t audio_dto_module;
+	uint32_t audio_dto_wall_clock_ratio;
+};
+
+enum audio_dto_source {
+	DTO_SOURCE_UNKNOWN = 0,
+	DTO_SOURCE_ID0,
+	DTO_SOURCE_ID1,
+	DTO_SOURCE_ID2,
+	DTO_SOURCE_ID3,
+	DTO_SOURCE_ID4,
+	DTO_SOURCE_ID5
+};
+
+union audio_sample_rates {
+	struct sample_rates {
+		uint8_t RATE_32:1;
+		uint8_t RATE_44_1:1;
+		uint8_t RATE_48:1;
+		uint8_t RATE_88_2:1;
+		uint8_t RATE_96:1;
+		uint8_t RATE_176_4:1;
+		uint8_t RATE_192:1;
+	} rate;
+
+	uint8_t all;
+};
+
+enum audio_format_code {
+	AUDIO_FORMAT_CODE_FIRST = 1,
+	AUDIO_FORMAT_CODE_LINEARPCM = AUDIO_FORMAT_CODE_FIRST,
+
+	AUDIO_FORMAT_CODE_AC3,
+	/*Layers 1 & 2 */
+	AUDIO_FORMAT_CODE_MPEG1,
+	/*MPEG1 Layer 3 */
+	AUDIO_FORMAT_CODE_MP3,
+	/*multichannel */
+	AUDIO_FORMAT_CODE_MPEG2,
+	AUDIO_FORMAT_CODE_AAC,
+	AUDIO_FORMAT_CODE_DTS,
+	AUDIO_FORMAT_CODE_ATRAC,
+	AUDIO_FORMAT_CODE_1BITAUDIO,
+	AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS,
+	AUDIO_FORMAT_CODE_DTS_HD,
+	AUDIO_FORMAT_CODE_MAT_MLP,
+	AUDIO_FORMAT_CODE_DST,
+	AUDIO_FORMAT_CODE_WMAPRO,
+	AUDIO_FORMAT_CODE_LAST,
+	AUDIO_FORMAT_CODE_COUNT =
+		AUDIO_FORMAT_CODE_LAST - AUDIO_FORMAT_CODE_FIRST
+};
+
+struct audio_mode {
+	 /* ucData[0] [6:3] */
+	enum audio_format_code format_code;
+	/* ucData[0] [2:0] */
+	uint8_t channel_count;
+	/* ucData[1] */
+	union audio_sample_rates sample_rates;
+	union {
+		/* for LPCM */
+		uint8_t sample_size;
+		/* for Audio Formats 2-8 (Max bit rate divided by 8 kHz) */
+		uint8_t max_bit_rate;
+		/* for Audio Formats 9-15 */
+		uint8_t vendor_specific;
+	};
+};
+
+struct audio_speaker_flags {
+    uint32_t FL_FR:1;
+    uint32_t LFE:1;
+    uint32_t FC:1;
+    uint32_t RL_RR:1;
+    uint32_t RC:1;
+    uint32_t FLC_FRC:1;
+    uint32_t RLC_RRC:1;
+    uint32_t SUPPORT_AI:1;
+};
+
+struct audio_speaker_info {
+    uint32_t ALLSPEAKERS:7;
+    uint32_t SUPPORT_AI:1;
+};
+
+struct audio_info_flags {
+
+	union {
+
+		struct audio_speaker_flags speaker_flags;
+		struct audio_speaker_info   info;
+
+		uint8_t all;
+	};
+};
+
+
+/*struct audio_info_flags {
+	struct audio_speaker_flags {
+		uint32_t FL_FR:1;
+		uint32_t LFE:1;
+		uint32_t FC:1;
+		uint32_t RL_RR:1;
+		uint32_t RC:1;
+		uint32_t FLC_FRC:1;
+		uint32_t RLC_RRC:1;
+		uint32_t SUPPORT_AI:1;
+	};
+
+	struct audio_speaker_info {
+		uint32_t ALLSPEAKERS:7;
+		uint32_t SUPPORT_AI:1;
+	};
+
+	union {
+		struct audio_speaker_flags speaker_flags;
+		struct audio_speaker_info info;
+	};
+};
+*/
+
+union audio_cea_channels {
+	uint8_t all;
+	struct audio_cea_channels_bits {
+		uint32_t FL:1;
+		uint32_t FR:1;
+		uint32_t LFE:1;
+		uint32_t FC:1;
+		uint32_t RL_RC:1;
+		uint32_t RR:1;
+		uint32_t RC_RLC_FLC:1;
+		uint32_t RRC_FRC:1;
+	} channels;
+};
+
+struct audio_info {
+	struct audio_info_flags flags;
+	uint32_t video_latency;
+	uint32_t audio_latency;
+	uint32_t display_index;
+	uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS];
+	uint32_t manufacture_id;
+	uint32_t product_id;
+	/* PortID used for ContainerID when defined */
+	uint32_t port_id[2];
+	uint32_t mode_count;
+	/* this field must be last in this struct */
+	struct audio_mode modes[DC_MAX_AUDIO_DESC_COUNT];
+};
+
+struct audio_crtc_info {
+	uint32_t h_total;
+	uint32_t h_active;
+	uint32_t v_active;
+	uint32_t pixel_repetition;
+	uint32_t requested_pixel_clock; /* in KHz */
+	uint32_t calculated_pixel_clock; /* in KHz */
+	uint32_t refresh_rate;
+	enum dc_color_depth color_depth;
+	bool interlaced;
+};
+
+/* PLL information required for AZALIA DTO calculation */
+
+struct audio_pll_info {
+	uint32_t dp_dto_source_clock_in_khz;
+	uint32_t feed_back_divider;
+	enum audio_dto_source dto_source;
+	bool ss_enabled;
+	uint32_t ss_percentage;
+	uint32_t ss_percentage_divider;
+};
+
+struct audio_channel_associate_info {
+	union {
+		struct {
+			uint32_t ALL_CHANNEL_FL:4;
+			uint32_t ALL_CHANNEL_FR:4;
+			uint32_t ALL_CHANNEL_FC:4;
+			uint32_t ALL_CHANNEL_Sub:4;
+			uint32_t ALL_CHANNEL_SL:4;
+			uint32_t ALL_CHANNEL_SR:4;
+			uint32_t ALL_CHANNEL_BL:4;
+			uint32_t ALL_CHANNEL_BR:4;
+		} bits;
+		uint32_t u32all;
+	};
+};
+
+struct audio_output {
+	/* Front DIG id. */
+	enum engine_id engine_id;
+	/* encoder output signal */
+	enum signal_type signal;
+	/* video timing */
+	struct audio_crtc_info crtc_info;
+	/* PLL for audio */
+	struct audio_pll_info pll_info;
+};
+
+struct audio_feature_support {
+	/* supported engines*/
+	uint32_t ENGINE_DIGA:1;
+	uint32_t ENGINE_DIGB:1;
+	uint32_t ENGINE_DIGC:1;
+	uint32_t ENGINE_DIGD:1;
+	uint32_t ENGINE_DIGE:1;
+	uint32_t ENGINE_DIGF:1;
+	uint32_t ENGINE_DIGG:1;
+	uint32_t MULTISTREAM_AUDIO:1;
+};
+
+enum audio_payload {
+	CHANNEL_SPLIT_MAPPINGCHANG = 0x9,
+};
+
+#endif /* __AUDIO_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h b/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
new file mode 100644
index 000000000000..e4291b9ff320
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_INTERFACE_H__
+#define __DAL_BIOS_PARSER_INTERFACE_H__
+
+#include "dc_bios_types.h"
+
+struct adapter_service;
+struct bios_parser;
+
+struct bp_init_data {
+	struct dc_context *ctx;
+	uint8_t *bios;
+};
+
+struct dc_bios *dal_bios_parser_create(
+	struct bp_init_data *init,
+	struct adapter_service *as);
+
+void dal_bios_parser_destroy(
+	struct dc_bios **dcb);
+
+/*****************************************************************************/
+/* Interfaces of BIOS Parser Helper */
+bool dal_bios_parser_is_lid_open(
+	struct bios_parser *bp);
+bool dal_bios_parser_is_lid_status_changed(
+	struct bios_parser *bp);
+bool dal_bios_parser_is_display_config_changed(
+	struct bios_parser *bp);
+bool dal_bios_parser_is_accelerated_mode(
+	struct bios_parser *bp);
+void dal_bios_parser_set_scratch_lcd_scale(
+	struct bios_parser *bp,
+	enum lcd_scale scale);
+enum lcd_scale  dal_bios_parser_get_scratch_lcd_scale(
+	struct bios_parser *bp);
+void dal_bios_parser_get_bios_event_info(
+	struct bios_parser *bp,
+	struct bios_event_info *info);
+void dal_bios_parser_update_requested_backlight_level(
+	struct bios_parser *bp,
+	uint32_t backlight_8bit);
+uint32_t dal_bios_parser_get_requested_backlight_level(
+	struct bios_parser *bp);
+void dal_bios_parser_take_backlight_control(
+	struct bios_parser *bp,
+	bool cntl);
+bool dal_bios_parser_is_active_display(
+	struct bios_parser *bp,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag);
+enum controller_id dal_bios_parser_get_embedded_display_controller_id(
+	struct bios_parser *bp);
+uint32_t dal_bios_parser_get_embedded_display_refresh_rate(
+	struct bios_parser *bp);
+void dal_bios_parser_set_scratch_connected(
+	struct bios_parser *bp,
+	struct graphics_object_id connector_id,
+	bool connected,
+	const struct connector_device_tag_info *device_tag);
+void dal_bios_parser_prepare_scratch_active_and_requested(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag);
+void dal_bios_parser_set_scratch_active_and_requested(
+	struct bios_parser *bp);
+void dal_bios_parser_set_scratch_critical_state(
+	struct bios_parser *bp,
+	bool state);
+void dal_bios_parser_set_scratch_acc_mode_change(
+	struct bios_parser *bp);
+
+#endif /* __DAL_BIOS_PARSER_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/bios_parser_types.h b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h
new file mode 100644
index 000000000000..550ac874985b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_TYPES_H__
+
+#define __DAL_BIOS_PARSER_TYPES_H__
+
+#include "dm_services.h"
+#include "include/signal_types.h"
+#include "include/grph_object_ctrl_defs.h"
+#include "include/gpio_types.h"
+#include "include/adapter_service_types.h" /* for as_signal_type */
+#include "include/link_service_types.h"
+
+enum bp_result {
+	BP_RESULT_OK = 0, /* There was no error */
+	BP_RESULT_BADINPUT, /*Bad input parameter */
+	BP_RESULT_BADBIOSTABLE, /* Bad BIOS table */
+	BP_RESULT_UNSUPPORTED, /* BIOS Table is not supported */
+	BP_RESULT_NORECORD, /* Record can't be found */
+	BP_RESULT_FAILURE
+};
+
+enum bp_encoder_control_action {
+	/* direct VBIOS translation! Just to simplify the translation */
+	ENCODER_CONTROL_DISABLE = 0,
+	ENCODER_CONTROL_ENABLE,
+	ENCODER_CONTROL_SETUP,
+	ENCODER_CONTROL_INIT
+};
+
+enum bp_transmitter_control_action {
+	/* direct VBIOS translation! Just to simplify the translation */
+	TRANSMITTER_CONTROL_DISABLE = 0,
+	TRANSMITTER_CONTROL_ENABLE,
+	TRANSMITTER_CONTROL_BACKLIGHT_OFF,
+	TRANSMITTER_CONTROL_BACKLIGHT_ON,
+	TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS,
+	TRANSMITTER_CONTROL_LCD_SETF_TEST_START,
+	TRANSMITTER_CONTROL_LCD_SELF_TEST_STOP,
+	TRANSMITTER_CONTROL_INIT,
+	TRANSMITTER_CONTROL_DEACTIVATE,
+	TRANSMITTER_CONTROL_ACTIAVATE,
+	TRANSMITTER_CONTROL_SETUP,
+	TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS,
+	/* ATOM_TRANSMITTER_ACTION_POWER_ON. This action is for eDP only
+	 * (power up the panel)
+	 */
+	TRANSMITTER_CONTROL_POWER_ON,
+	/* ATOM_TRANSMITTER_ACTION_POWER_OFF. This action is for eDP only
+	 * (power down the panel)
+	 */
+	TRANSMITTER_CONTROL_POWER_OFF
+};
+
+enum bp_external_encoder_control_action {
+	EXTERNAL_ENCODER_CONTROL_DISABLE = 0,
+	EXTERNAL_ENCODER_CONTROL_ENABLE = 1,
+	EXTERNAL_ENCODER_CONTROL_INIT = 0x7,
+	EXTERNAL_ENCODER_CONTROL_SETUP = 0xf,
+	EXTERNAL_ENCODER_CONTROL_UNBLANK = 0x10,
+	EXTERNAL_ENCODER_CONTROL_BLANK = 0x11,
+	EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT = 0x12
+};
+
+enum bp_pipe_control_action {
+	ASIC_PIPE_DISABLE = 0,
+	ASIC_PIPE_ENABLE,
+	ASIC_PIPE_INIT
+};
+
+struct bp_encoder_control {
+	enum bp_encoder_control_action action;
+	enum engine_id engine_id;
+	enum transmitter transmitter;
+	enum signal_type signal;
+	enum lane_count lanes_number;
+	enum dc_color_depth color_depth;
+	bool enable_dp_audio;
+	uint32_t pixel_clock; /* khz */
+};
+
+struct bp_external_encoder_control {
+	enum bp_external_encoder_control_action action;
+	enum engine_id engine_id;
+	enum link_rate link_rate;
+	enum lane_count lanes_number;
+	enum signal_type signal;
+	enum dc_color_depth color_depth;
+	bool coherent;
+	struct graphics_object_id encoder_id;
+	struct graphics_object_id connector_obj_id;
+	uint32_t pixel_clock; /* in KHz */
+};
+
+struct bp_crtc_source_select {
+	enum engine_id engine_id;
+	enum controller_id controller_id;
+	/* from GPU Tx aka asic_signal */
+	enum signal_type signal;
+	/* sink_signal may differ from asicSignal if Translator encoder */
+	enum signal_type sink_signal;
+	enum display_output_bit_depth display_output_bit_depth;
+	bool enable_dp_audio;
+};
+
+struct bp_transmitter_control {
+	enum bp_transmitter_control_action action;
+	enum engine_id engine_id;
+	enum transmitter transmitter; /* PhyId */
+	enum lane_count lanes_number;
+	enum clock_source_id pll_id; /* needed for DCE 4.0 */
+	enum signal_type signal;
+	enum dc_color_depth color_depth; /* not used for DCE6.0 */
+	enum hpd_source_id hpd_sel; /* ucHPDSel, used for DCe6.0 */
+	struct graphics_object_id connector_obj_id;
+	/* symClock; in 10kHz, pixel clock, in HDMI deep color mode, it should
+	 * be pixel clock * deep_color_ratio (in KHz)
+	 */
+	uint32_t pixel_clock;
+	uint32_t lane_select;
+	uint32_t lane_settings;
+	bool coherent;
+	bool multi_path;
+	bool single_pll_mode;
+};
+
+struct bp_blank_crtc_parameters {
+	enum controller_id controller_id;
+	uint32_t black_color_rcr;
+	uint32_t black_color_gy;
+	uint32_t black_color_bcb;
+};
+
+struct bp_hw_crtc_timing_parameters {
+	enum controller_id controller_id;
+	/* horizontal part */
+	uint32_t h_total;
+	uint32_t h_addressable;
+	uint32_t h_overscan_left;
+	uint32_t h_overscan_right;
+	uint32_t h_sync_start;
+	uint32_t h_sync_width;
+
+	/* vertical part */
+	uint32_t v_total;
+	uint32_t v_addressable;
+	uint32_t v_overscan_top;
+	uint32_t v_overscan_bottom;
+	uint32_t v_sync_start;
+	uint32_t v_sync_width;
+
+	struct timing_flags {
+		uint32_t INTERLACE:1;
+		uint32_t PIXEL_REPETITION:4;
+		uint32_t HSYNC_POSITIVE_POLARITY:1;
+		uint32_t VSYNC_POSITIVE_POLARITY:1;
+		uint32_t HORZ_COUNT_BY_TWO:1;
+	} flags;
+};
+
+struct bp_hw_crtc_overscan_parameters {
+	enum controller_id controller_id;
+	uint32_t h_overscan_left;
+	uint32_t h_overscan_right;
+	uint32_t v_overscan_top;
+	uint32_t v_overscan_bottom;
+};
+
+struct bp_adjust_pixel_clock_parameters {
+	/* Input: Signal Type - to be converted to Encoder mode */
+	enum signal_type signal_type;
+	/* Input: Encoder object id */
+	struct graphics_object_id encoder_object_id;
+	/* Input: Pixel Clock (requested Pixel clock based on Video timing
+	 * standard used) in KHz
+	 */
+	uint32_t pixel_clock;
+	/* Output: Adjusted Pixel Clock (after VBIOS exec table) in KHz */
+	uint32_t adjusted_pixel_clock;
+	/* Output: If non-zero, this refDiv value should be used to calculate
+	 * other ppll params */
+	uint32_t reference_divider;
+	/* Output: If non-zero, this postDiv value should be used to calculate
+	 * other ppll params */
+	uint32_t pixel_clock_post_divider;
+	/* Input: Enable spread spectrum */
+	bool ss_enable;
+};
+
+struct bp_pixel_clock_parameters {
+	enum controller_id controller_id; /* (Which CRTC uses this PLL) */
+	enum clock_source_id pll_id; /* Clock Source Id */
+	/* signal_type -> Encoder Mode - needed by VBIOS Exec table */
+	enum signal_type signal_type;
+	/* Adjusted Pixel Clock (after VBIOS exec table)
+	 * that becomes Target Pixel Clock (KHz) */
+	uint32_t target_pixel_clock;
+	/* Calculated Reference divider of Display PLL */
+	uint32_t reference_divider;
+	/* Calculated Feedback divider of Display PLL */
+	uint32_t feedback_divider;
+	/* Calculated Fractional Feedback divider of Display PLL */
+	uint32_t fractional_feedback_divider;
+	/* Calculated Pixel Clock Post divider of Display PLL */
+	uint32_t pixel_clock_post_divider;
+	struct graphics_object_id encoder_object_id; /* Encoder object id */
+	/* VBIOS returns a fixed display clock when DFS-bypass feature
+	 * is enabled (KHz) */
+	uint32_t dfs_bypass_display_clock;
+	/* color depth to support HDMI deep color */
+	enum transmitter_color_depth color_depth;
+
+	struct program_pixel_clock_flags {
+		uint32_t FORCE_PROGRAMMING_OF_PLL:1;
+		/* Use Engine Clock as source for Display Clock when
+		 * programming PLL */
+		uint32_t USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK:1;
+		/* Use external reference clock (refDivSrc for PLL) */
+		uint32_t SET_EXTERNAL_REF_DIV_SRC:1;
+		/* Force program PHY PLL only */
+		uint32_t PROGRAM_PHY_PLL_ONLY:1;
+		/* Support for YUV420 */
+		uint32_t SUPPORT_YUV_420:1;
+		/* Use XTALIN reference clock source */
+		uint32_t SET_XTALIN_REF_SRC:1;
+		/* Use GENLK reference clock source */
+		uint32_t SET_GENLOCK_REF_DIV_SRC:1;
+	} flags;
+};
+
+struct bp_display_clock_parameters {
+	uint32_t target_display_clock; /* KHz */
+	/* Actual Display Clock set due to clock divider granularity KHz */
+	uint32_t actual_display_clock;
+	/* Actual Post Divider ID used to generate the actual clock */
+	uint32_t actual_post_divider_id;
+};
+
+enum bp_dce_clock_type {
+	DCECLOCK_TYPE_DISPLAY_CLOCK = 0,
+	DCECLOCK_TYPE_DPREFCLK      = 1
+};
+
+/* DCE Clock Parameters structure for SetDceClock Exec command table */
+struct bp_set_dce_clock_parameters {
+	enum clock_source_id pll_id; /* Clock Source Id */
+	/* Display clock or DPREFCLK value */
+	uint32_t target_clock_frequency;
+	/* Clock to set: =0: DISPCLK  =1: DPREFCLK  =2: PIXCLK */
+	enum bp_dce_clock_type clock_type;
+
+	struct set_dce_clock_flags {
+		uint32_t USE_GENERICA_AS_SOURCE_FOR_DPREFCLK:1;
+		/* Use XTALIN reference clock source */
+		uint32_t USE_XTALIN_AS_SOURCE_FOR_DPREFCLK:1;
+		/* Use PCIE reference clock source */
+		uint32_t USE_PCIE_AS_SOURCE_FOR_DPREFCLK:1;
+		/* Use GENLK reference clock source */
+		uint32_t USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK:1;
+	} flags;
+};
+
+struct spread_spectrum_flags {
+	/* 1 = Center Spread; 0 = down spread */
+	uint32_t CENTER_SPREAD:1;
+	/* 1 = external; 0 = internal */
+	uint32_t EXTERNAL_SS:1;
+	/* 1 = delta-sigma type parameter; 0 = ver1 */
+	uint32_t DS_TYPE:1;
+};
+
+struct bp_spread_spectrum_parameters {
+	enum clock_source_id pll_id;
+	uint32_t percentage;
+	uint32_t ds_frac_amount;
+
+	union {
+		struct {
+			uint32_t step;
+			uint32_t delay;
+			uint32_t range; /* In Hz unit */
+		} ver1;
+		struct {
+			uint32_t feedback_amount;
+			uint32_t nfrac_amount;
+			uint32_t ds_frac_size;
+		} ds;
+	};
+
+	struct spread_spectrum_flags flags;
+};
+
+struct bp_encoder_cap_info {
+	uint32_t DP_HBR2_CAP:1;
+	uint32_t DP_HBR2_EN:1;
+	uint32_t RESERVED:30;
+};
+
+struct bp_gpio_cntl_info {
+	uint32_t id;
+	enum gpio_pin_output_state state;
+};
+
+#endif /*__DAL_BIOS_PARSER_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_asic_id.h b/drivers/gpu/drm/amd/dal/include/dal_asic_id.h
new file mode 100644
index 000000000000..78f88b129a35
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_asic_id.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ASIC_ID_H__
+#define __DAL_ASIC_ID_H__
+
+/*
+ * ASIC internal revision ID
+ */
+
+/* DCE80 (based on ci_id.h in Perforce) */
+
+#define	CI_BONAIRE_M_A0 0x14
+#define	CI_BONAIRE_M_A1	0x15
+#define	CI_HAWAII_P_A0	0x28
+
+#define CI_UNKNOWN	0xFF
+
+#define ASIC_REV_IS_BONAIRE_M(rev) \
+	((rev >= CI_BONAIRE_M_A0) && (rev < CI_HAWAII_P_A0))
+
+#define ASIC_REV_IS_HAWAII_P(rev) \
+	(rev >= CI_HAWAII_P_A0)
+
+/* KV1 with Spectre GFX core, 8-8-1-2 (CU-Pix-Primitive-RB) */
+#define KV_SPECTRE_A0 0x01
+
+/* KV2 with Spooky GFX core, including downgraded from Spectre core,
+ * 3-4-1-1 (CU-Pix-Primitive-RB) */
+#define KV_SPOOKY_A0 0x41
+
+/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define KB_KALINDI_A0 0x81
+
+/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define KB_KALINDI_A1 0x82
+
+/* BV with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define BV_KALINDI_A2 0x85
+
+/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define ML_GODAVARI_A0 0xA1
+
+/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define ML_GODAVARI_A1 0xA2
+
+#define KV_UNKNOWN 0xFF
+
+#define ASIC_REV_IS_KALINDI(rev) \
+	((rev >= KB_KALINDI_A0) && (rev < KV_UNKNOWN))
+
+#define ASIC_REV_IS_BHAVANI(rev) \
+	((rev >= BV_KALINDI_A2) && (rev < ML_GODAVARI_A0))
+
+#define ASIC_REV_IS_GODAVARI(rev) \
+	((rev >= ML_GODAVARI_A0) && (rev < KV_UNKNOWN))
+
+/* VI Family */
+/* DCE10 */
+#define VI_TONGA_P_A0 20
+#define VI_TONGA_P_A1 21
+#define VI_FIJI_P_A0 60
+
+#define ASIC_REV_IS_TONGA_P(eChipRev) ((eChipRev >= VI_TONGA_P_A0) && \
+		(eChipRev < 40))
+#define ASIC_REV_IS_FIJI_P(eChipRev) ((eChipRev >= VI_FIJI_P_A0) && \
+		(eChipRev < 80))
+
+/* DCE11 */
+#define CZ_CARRIZO_A0 0x01
+
+#define STONEY_A0 0x61
+#define CZ_UNKNOWN 0xFF
+
+#define ASIC_REV_IS_STONEY(rev) \
+	((rev >= STONEY_A0) && (rev < CZ_UNKNOWN))
+
+/*
+ * ASIC chip ID
+ */
+/* DCE80 */
+#define DEVICE_ID_KALINDI_9834 0x9834
+#define DEVICE_ID_TEMASH_9839 0x9839
+#define DEVICE_ID_TEMASH_983D 0x983D
+
+
+/* Asic Family IDs for different asic family. */
+#define FAMILY_CI 120 /* Sea Islands: Hawaii (P), Bonaire (M) */
+#define FAMILY_KV 125 /* Fusion => Kaveri: Spectre, Spooky; Kabini: Kalindi */
+#define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */
+#define FAMILY_CZ 135 /* Carrizo */
+
+#define	FAMILY_UNKNOWN 0xFF
+
+#endif /* __DAL_ASIC_ID_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_register_logger.h b/drivers/gpu/drm/amd/dal/include/dal_register_logger.h
new file mode 100644
index 000000000000..176d811327af
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_register_logger.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_REGISTER_LOGGER__
+#define __DAL_REGISTER_LOGGER__
+
+/****************
+ * API functions
+ ***************/
+
+/* dal_reg_logger_push - begin Register Logging */
+void dal_reg_logger_push(const char *caller_func);
+/* dal_reg_logger_pop - stop Register Logging */
+void dal_reg_logger_pop(void);
+
+
+/* for internal use of the Logger only */
+void dal_reg_logger_rw_count_increment(void);
+bool dal_reg_logger_should_dump_register(void);
+
+#endif /* __DAL_REGISTER_LOGGER__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_types.h b/drivers/gpu/drm/amd/dal/include/dal_types.h
new file mode 100644
index 000000000000..373977685b70
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_types.h
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TYPES_H__
+#define __DAL_TYPES_H__
+
+#include "signal_types.h"
+#include "dc_types.h"
+
+struct dal_logger;
+struct dc_bios;
+
+enum dce_version {
+	DCE_VERSION_UNKNOWN = (-1),
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	DCE_VERSION_10_0,
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	DCE_VERSION_11_0,
+#endif
+	DCE_VERSION_MAX
+};
+
+/*
+ * ASIC Runtime Flags
+ */
+struct dal_asic_runtime_flags {
+	union {
+		uint32_t raw;
+		struct {
+			uint32_t EMULATE_REPLUG_ON_CAP_CHANGE:1;
+			uint32_t SUPPORT_XRBIAS:1;
+			uint32_t SKIP_POWER_DOWN_ON_RESUME:1;
+			uint32_t FULL_DETECT_ON_RESUME:1;
+			uint32_t GSL_FRAMELOCK:1;
+			uint32_t NO_LOW_BPP_MODES:1;
+			uint32_t BLOCK_ON_INITIAL_DETECTION:1;
+			uint32_t OPTIMIZED_DISPLAY_PROGRAMMING_ON_BOOT:1;
+			uint32_t DRIVER_CONTROLLED_BRIGHTNESS:1;
+			uint32_t MODIFIABLE_FRAME_DURATION:1;
+			uint32_t MIRACAST_SUPPORTED:1;
+			uint32_t CONNECTED_STANDBY_SUPPORTED:1;
+			uint32_t GNB_WAKEUP_SUPPORTED:1;
+		} bits;
+	} flags;
+};
+
+struct hw_asic_id {
+	uint32_t chip_id;
+	uint32_t chip_family;
+	uint32_t pci_revision_id;
+	uint32_t hw_internal_rev;
+	uint32_t vram_type;
+	uint32_t vram_width;
+	uint32_t feature_flags;
+	struct dal_asic_runtime_flags runtime_flags;
+	uint32_t fake_paths_num;
+	void *atombios_base_address;
+};
+
+/* this is pci information. BDF stands for BUS,DEVICE,FUNCTION*/
+
+struct bdf_info {
+	uint16_t BUS_NUMBER:8;
+	uint16_t DEVICE_NUMBER:5;
+	uint16_t FUNCTION_NUMBER:3;
+};
+
+#define DAL_PARAM_INVALID_INT 0x80000000
+
+/* shift values for bool override parameter mask
+ * bmask is for this struct,if we touch this feature
+ * bval indicates every bit fields for this struct too,1 is enable this feature
+ * amdgpu.disp_bval=1594, amdgpu.disp_bmask=1594 ,
+ * finally will show log like this:
+ * Overridden FEATURE_LIGHT_SLEEP is enabled now
+ * Overridden FEATURE_USE_MAX_DISPLAY_CLK is enabled now
+ * Overridden FEATURE_ENABLE_DFS_BYPASS is enabled now
+ * Overridden FEATURE_POWER_GATING_PIPE_IN_TILE is enabled now
+ * Overridden FEATURE_USE_PPLIB is enabled now
+ * Overridden FEATURE_DISABLE_LPT_SUPPORT is enabled now
+ * Overridden FEATURE_DUMMY_FBC_BACKEND is enabled now */
+enum bool_param_shift {
+	DAL_PARAM_MAXIMIZE_STUTTER_MARKS = 0,
+	DAL_PARAM_LIGHT_SLEEP,
+	DAL_PARAM_MAXIMIZE_URGENCY_WATERMARKS,
+	DAL_PARAM_USE_MAX_DISPLAY_CLK,
+	DAL_PARAM_ENABLE_DFS_BYPASS,
+	DAL_PARAM_POWER_GATING_PIPE_IN_TILE,
+	DAL_PARAM_POWER_GATING_LB_PORTION,
+	DAL_PARAM_PSR_ENABLE,
+	DAL_PARAM_VARI_BRIGHT_ENABLE,
+	DAL_PARAM_USE_PPLIB,
+	DAL_PARAM_DISABLE_LPT_SUPPORT,
+	DAL_PARAM_DUMMY_FBC_BACKEND,
+	DAL_PARAM_ENABLE_GPU_SCALING,
+	DAL_BOOL_PARAM_MAX
+};
+
+/* array index for integer override parameters*/
+enum int_param_array_index {
+	DAL_PARAM_MAX_COFUNC_NON_DP_DISPLAYS = 0,
+	DAL_PARAM_DRR_SUPPORT,
+	DAL_INT_PARAM_MAX
+};
+
+struct dal_override_parameters {
+	uint32_t bool_param_enable_mask;
+	uint32_t bool_param_values;
+	uint32_t int_param_values[DAL_INT_PARAM_MAX];
+};
+
+
+struct dal_init_data {
+	struct hw_asic_id asic_id;
+	struct view_port_alignment vp_alignment;
+	struct bdf_info bdf_info;
+	struct dal_override_parameters display_param;
+	void *driver; /* ctx */
+	void *cgs_device;
+	uint8_t num_virtual_links;
+	/* If 'vbios_override' not NULL, it will be called instead
+	 * of the real VBIOS. Intended use is Diagnostics on FPGA. */
+	struct dc_bios *vbios_override;
+	enum dce_environment dce_environment;
+};
+
+struct dal_dc_init_data {
+	struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */
+	struct adapter_service *adapter_srv;
+};
+
+struct dal_dev_c_lut {
+	uint8_t red;
+	uint8_t green;
+	uint8_t blue;
+	uint8_t reserved;
+};
+
+struct dal_dev_gamma_lut {
+	uint16_t red;
+	uint16_t green;
+	uint16_t blue;
+};
+
+struct dc_context {
+	struct dc *dc;
+
+	void *driver_context; /* e.g. amdgpu_device */
+
+	struct dal_logger *logger;
+	void *cgs_device;
+
+	enum dce_environment dce_environment;
+};
+
+/* Wireless display structs */
+
+union dal_remote_display_cea_mode_bitmap {
+	struct {
+		uint32_t CEA_640X480_60P:1;/*0*/
+		uint32_t CEA_720X480_60P:1;/*1*/
+		uint32_t CEA_720X480_60I:1;/*2*/
+		uint32_t CEA_720X576_50P:1;/*3*/
+		uint32_t CEA_720X576_50I:1;/*4*/
+		uint32_t CEA_1280X720_30P:1;/*5*/
+		uint32_t CEA_1280X720_60P:1;/*6*/
+		uint32_t CEA_1920X1080_30P:1;/*7*/
+		uint32_t CEA_1920X1080_60P:1;/*8*/
+		uint32_t CEA_1920X1080_60I:1;/*9*/
+		uint32_t CEA_1280X720_25P:1;/*10*/
+		uint32_t CEA_1280X728_50P:1;/*11*/
+		uint32_t CEA_1920X1080_25P:1;/*12*/
+		uint32_t CEA_1920X1080_50P:1;/*13*/
+		uint32_t CEA_1920X1080_50I:1;/*14*/
+		uint32_t CEA_1280X1024_24P:1;/*15*/
+		uint32_t CEA_1920X1080_24P:1;/*16*/
+		uint32_t RESERVED:15;/*[17-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_vesa_mode_bitmap {
+	struct {
+		uint32_t VESA_800X600_30P:1;/*0*/
+		uint32_t VESA_800X600_60P:1;/*1*/
+		uint32_t VESA_1024X768_30P:1;/*2*/
+		uint32_t VESA_1024X768_60P:1;/*3*/
+		uint32_t VESA_1152X864_30P:1;/*4*/
+		uint32_t VESA_1152X864_60P:1;/*5*/
+		uint32_t VESA_1280X768_30P:1;/*6*/
+		uint32_t VESA_1280X768_60P:1;/*7*/
+		uint32_t VESA_1280X800_30P:1;/*8*/
+		uint32_t VESA_1280X800_60P:1;/*9*/
+		uint32_t VESA_1360X768_30P:1;/*10*/
+		uint32_t VESA_1360X768_60P:1;/*11*/
+		uint32_t VESA_1366X768_30P:1;/*12*/
+		uint32_t VESA_1366X768_60P:1;/*13*/
+		uint32_t VESA_1280X1024_30P:1;/*14*/
+		uint32_t VESA_1280X1024_60P:1;/*15*/
+		uint32_t VESA_1400X1050_30P:1;/*16*/
+		uint32_t VESA_1400X1050_60P:1;/*17*/
+		uint32_t VESA_1440X900_30P:1;/*18*/
+		uint32_t VESA_1440X900_60P:1;/*19*/
+		uint32_t VESA_1600X900_30P:1;/*20*/
+		uint32_t VESA_1600X900_60P:1;/*21*/
+		uint32_t VESA_1600X1200_30P:1;/*22*/
+		uint32_t VESA_1600X1200_60P:1;/*23*/
+		uint32_t VESA_1680X1024_30P:1;/*24*/
+		uint32_t VESA_1680X1024_60P:1;/*25*/
+		uint32_t VESA_1680X1050_30P:1;/*26*/
+		uint32_t VESA_1680X1050_60P:1;/*27*/
+		uint32_t VESA_1920X1200_30P:1;/*28*/
+		uint32_t VESA_1920X1200_60P:1;/*29*/
+		uint32_t RESERVED:2;/*[30-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_hh_mode_bitmap {
+	struct {
+		uint32_t HH_800X480_30P:1;/*0*/
+		uint32_t HH_800X480_60P:1;/*1*/
+		uint32_t HH_854X480_30P:1;/*2*/
+		uint32_t HH_854X480_60P:1;/*3*/
+		uint32_t HH_864X480_30P:1;/*4*/
+		uint32_t HH_864X480_60P:1;/*5*/
+		uint32_t HH_640X360_30P:1;/*6*/
+		uint32_t HH_640X360_60P:1;/*7*/
+		uint32_t HH_960X540_30P:1;/*8*/
+		uint32_t HH_960X540_60P:1;/*9*/
+		uint32_t HH_848X480_30P:1;/*10*/
+		uint32_t HH_848X480_60P:1;/*11*/
+		uint32_t RESERVED:20;/*[12-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_stereo_3d_mode_bitmap {
+	struct {
+		uint32_t STEREO_1920X1080_24P_TOP_AND_BOTTOM:1;/*0*/
+		uint32_t STEREO_1280X720_60P_TOP_AND_BOTTOM:1;/*1*/
+		uint32_t STEREO_1280X720_50P_TOP_AND_BOTTOM:1;/*2*/
+		uint32_t STEREO_1920X1080_24X2P_FRAME_ALTERNATE:1;/*3*/
+		uint32_t STEREO_1280X720_60X2P_FRAME_ALTERNATE:1;/*4*/
+		uint32_t STEREO_1280X720_30X2P_FRAME_ALTERNATE:1;/*5*/
+		uint32_t STEREO_1280X720_50X2P_FRAME_ALTERNATE:1;/*6*/
+		uint32_t STEREO_1280X720_25X2P_FRAME_ALTERNATE:1;/*7*/
+		uint32_t STEREO_1920X1080_24P_FRAME_PACKING:1;/* 8*/
+		uint32_t STEREO_1280X720_60P_FRAME_PACKING:1;/* 9*/
+		uint32_t STEREO_1280X720_30P_FRAME_PACKING:1;/*10*/
+		uint32_t STEREO_1280X720_50P_FRAME_PACKING:1;/*11*/
+		uint32_t STEREO_1280X720_25P_FRAME_PACKING:1;/*12*/
+		uint32_t RESERVED:19; /*[13-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_audio_bitmap {
+	struct {
+		uint32_t LPCM_44100HZ_16BITS_2_CHANNELS:1;/*0*/
+		uint32_t LPCM_48000HZ_16BITS_2_CHANNELS:1;/*1*/
+		uint32_t AAC_48000HZ_16BITS_2_CHANNELS:1;/*2*/
+		uint32_t AAC_48000HZ_16BITS_4_CHANNELS:1;/*3*/
+		uint32_t AAC_48000HZ_16BITS_6_CHANNELS:1;/*4*/
+		uint32_t AAC_48000HZ_16BITS_8_CHANNELS:1;/*5*/
+		uint32_t AC3_48000HZ_16BITS_2_CHANNELS:1;/*6*/
+		uint32_t AC3_48000HZ_16BITS_4_CHANNELS:1;/*7*/
+		uint32_t AC3_48000HZ_16BITS_6_CHANNELS:1;/*8*/
+		uint32_t RESERVED:23;/*[9-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+struct dal_remote_display_receiver_capability {
+	union dal_remote_display_cea_mode_bitmap cea_mode;
+	union dal_remote_display_vesa_mode_bitmap vesa_mode;
+	union dal_remote_display_hh_mode_bitmap hh_mode;
+	union dal_remote_display_stereo_3d_mode_bitmap stereo_3d_mode;
+	union dal_remote_display_audio_bitmap audio;
+};
+
+#endif /* __DAL_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h b/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
new file mode 100644
index 000000000000..b7fb9ff16a97
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_CLOCK_GENERATOR_INTERFACE_H__
+#define __DC_CLOCK_GENERATOR_INTERFACE_H__
+
+#include "grph_object_ctrl_defs.h"
+#include "set_mode_types.h"
+
+/* Parameter for programming the DCCP_DISP_SLOW_SELECT*/
+struct dccg_mapping_params {
+	uint32_t controllers_num;
+	enum controller_id *controllers;
+};
+
+/* Parameters related to HW DeSpread of DP Reference Clock*/
+struct dccg_dp_ref_clk_ds_params {
+	struct {
+		/* Flag for Enabled SS on DP Reference Clock*/
+		bool SS_ENABLED:1;
+		/* Flag for HW De Spread enabled
+		 * (if enabled SS on DP Reference Clock)*/
+		bool DS_ENABLED:1;
+		/* Flag for HW De Spread Calculations enabled for DS_DTO_INCR
+		 * and DS_DTO_MODULO (if 0 SW programs DS_DTO_INCR and
+		 * DS_DTO_MODULO)*/
+		bool DS_CALCULATIONS:1;
+	} flags;
+	/*DP Reference clock SS percentage
+	 * (if enabled downspread on DP Reference Clock)*/
+	uint32_t ss_percentage;
+	/*DP Reference clock SS percentage Divider (1000 or 100)*/
+	uint32_t ss_percentage_divider;
+};
+
+struct dc_clock_generator;
+
+void dal_dc_clock_generator_destroy(struct dc_clock_generator **dc);
+void dal_dc_clock_generator_set_display_pipe_mapping(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_mapping_params *params);
+bool dal_dc_clock_generator_get_dp_ref_clk_ds_params(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_dp_ref_clk_ds_params *params);
+bool dal_dc_clock_generator_enable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen,
+	uint32_t dprefclk);
+void dal_dc_clock_generator_disable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen);
+void dal_dc_clock_generator_set_gtc_group_offset(
+	struct dc_clock_generator *dc_clk_gen,
+	enum gtc_group group_num,
+	uint32_t offset);
+
+#endif /* __DC_CLOCK_GENERATOR_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dcs_types.h b/drivers/gpu/drm/amd/dal/include/dcs_types.h
new file mode 100644
index 000000000000..8c650571ff69
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dcs_types.h
@@ -0,0 +1,742 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DCS_TYPES_H__
+#define __DAL_DCS_TYPES_H__
+
+#include "signal_types.h"
+
+#include "dc_types.h"
+
+#define NUM_OF_BYTE_EDID_COLOR_CHARACTERISTICS 10
+#define MAX_NUMBER_OF_HDMI_VSDB_3D_EXTENDED_SUPPORT 21
+#define MAX_NUMBER_OF_HDMI_VSDB_VICS 7
+
+struct drr_config {
+	/* minimum frame per second for dynamic
+	 * refresh rate feature; 0 if drr support not found*/
+	uint32_t min_fps_in_microhz;
+	bool force_lock_on_event;
+	bool lock_to_master_vsync;
+
+	struct {
+		uint8_t FORCED_BY_REGKEY_OR_ESCAPE:1;
+		uint8_t FORCED_BY_VBIOS:1;
+		uint8_t SUPPORTED_BY_EDID:1;
+	} support_method;
+};
+
+struct timing_limits {
+	uint32_t min_pixel_clock_in_khz;
+	uint32_t max_pixel_clock_in_khz;
+};
+
+struct vendor_product_id_info {
+	uint32_t manufacturer_id;
+	uint32_t product_id;
+	uint32_t serial_id;
+	uint32_t manufacture_week;
+	uint32_t manufacture_year;
+};
+
+struct display_range_limits {
+	uint32_t min_v_rate_hz;
+	uint32_t max_v_rate_hz;
+	uint32_t min_h_rate_khz;
+	uint32_t max_h_rateIn_khz;
+	uint32_t max_pix_clk_khz;
+	bool use_override;
+};
+
+struct monitor_user_select_limits {
+	bool use_ati_override;
+	uint32_t max_h_res;
+	uint32_t max_v_res;
+	uint32_t max_refresh_rate;
+};
+
+enum edid_screen_aspect_ratio {
+	EDID_SCREEN_AR_UNKNOWN = 0,
+	EDID_SCREEN_AR_PROJECTOR,
+	EDID_SCREEN_AR_16X9,
+	EDID_SCREEN_AR_16X10,
+	EDID_SCREEN_AR_4X3,
+	EDID_SCREEN_AR_5X4,
+	EDID_SCREEN_AR_9X16,
+	EDID_SCREEN_AR_10X16,
+	EDID_SCREEN_AR_3X4,
+	EDID_SCREEN_AR_4X5
+};
+
+struct edid_screen_info {
+	enum edid_screen_aspect_ratio aspect_ratio;
+	uint32_t width;
+	uint32_t height;
+};
+
+struct display_characteristics {
+	uint8_t gamma;
+	uint8_t color_characteristics[NUM_OF_BYTE_EDID_COLOR_CHARACTERISTICS];
+};
+
+union cv_smart_dongle_modes {
+	uint8_t all;
+	struct cv_smart_dongle_switches {
+		uint8_t MODE_1080I:1;
+		uint8_t MODE_720P:1;
+		uint8_t MODE_540P:1;
+		uint8_t MODE_480P:1;
+		uint8_t MODE_480I:1;
+		uint8_t MODE_16_9:1;
+	} switches;
+};
+
+struct cea_audio_mode {
+	uint8_t format_code; /* ucData[0] [6:3]*/
+	uint8_t channel_count; /* ucData[0] [2:0]*/
+	uint8_t sample_rate; /* ucData[1]*/
+	union {
+		uint8_t sample_size; /* for LPCM*/
+		/*  for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/
+		uint8_t max_bit_rate;
+		uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/
+	};
+};
+
+union cea_speaker_allocation_data_block {
+	struct {
+		uint32_t FL_FR:1;
+		uint32_t LFE:1;
+		uint32_t FC:1;
+		uint32_t RL_RR:1;
+		uint32_t RC:1;
+		uint32_t FLC_FRC:1;
+		uint32_t RLC_RRC:1;
+	} bits;
+	uint32_t raw;
+};
+
+struct cea_colorimetry_data_block {
+	struct {
+		uint32_t XV_YCC601:1;
+		uint32_t XV_YCC709:1;
+		uint32_t S_YCC601:1;
+		uint32_t ADOBE_YCC601:1;
+		uint32_t ADOBE_RGB:1;
+
+	} flag;
+	struct {
+		uint32_t MD0:1;
+		uint32_t MD1:1;
+		uint32_t MD2:1;
+		uint32_t MD3:1;
+	} metadata_flag;
+};
+
+union cea_video_capability_data_block {
+	struct {
+		uint8_t S_CE0:1;
+		uint8_t S_CE1:1;
+		uint8_t S_IT0:1;
+		uint8_t S_IT1:1;
+		uint8_t S_PT0:1;
+		uint8_t S_PT1:1;
+		uint8_t QS:1;
+		uint8_t QY:1;
+	} bits;
+	uint8_t raw;
+};
+
+enum stereo_3d_multi_presence {
+	STEREO_3D_MULTI_NOT_PRESENT = 0,
+	STEREO_3D_MULTI_ALL_FORMATS,
+	STEREO_3D_MULTI_MASKED_FORMATS,
+	STEREO_3D_MULTI_RESERVED
+};
+
+enum cea_hdmi_vic {
+	CEA_HDMI_VIC_RESERVED = 0,
+	CEA_HDMI_VIC_4KX2K_30,
+	CEA_HDMI_VIC_4KX2K_25,
+	CEA_HDMI_VIC_4KX2K_24,
+	CEA_HDMI_VIC_4KX2K_24_SMPTE
+};
+
+struct cea_hdmi_vsdb_extended_caps {
+	uint32_t reserved;
+	uint32_t image_size;
+	enum stereo_3d_multi_presence stereo_3d_multi_present;
+	bool stereo_3d_present;
+	uint32_t hdmi_3d_len;
+	uint32_t hdmi_vic_len;
+};
+
+struct cea_vendor_specific_data_block {
+
+	uint32_t ieee_id;
+
+	struct commonent_phy {
+		uint32_t PHY_ADDR_A:4;
+		uint32_t PHY_ADDR_B:4;
+		uint32_t PHY_ADDR_C:4;
+		uint32_t PHY_ADDR_D:4;
+	} commonent_phy_addr;
+
+	struct byte6 {
+		uint32_t SUPPORTS_AI:1;
+		uint32_t DC_48BIT:1;
+		uint32_t DC_36BIT:1;
+		uint32_t DC_30BIT:1;
+		uint32_t DC_Y444:1;
+		uint32_t DVI_DUAL:1;
+		uint32_t RESERVED:2;
+	} byte6;/* link capabilities*/
+	bool byte6_valid;
+
+	uint32_t max_tmds_clk_mhz;
+
+	struct byte8 {
+		uint32_t LATENCY_FIELDS_PRESENT:1;
+		uint32_t ILATENCY_FIELDS_PRESENT:1;
+		uint32_t HDMI_VIDEO_PRESENT:1;
+		uint32_t RESERVED:1;
+		uint32_t CNC3_GAME:1;
+		uint32_t CNC2_CINEMA:1;
+		uint32_t CNC1_PHOTO:1;
+		uint32_t CNC0_GRAPHICS:1;
+	} byte8;
+	/*bit 6-7: latency flags to indicate valid latency fields*/
+	/*bit 5: support of additional video format capabilities*/
+	/* bit 0-3: flags indicating which content type is supported*/
+	uint32_t video_latency;
+	uint32_t audio_latency;
+	uint32_t i_video_latency;
+	uint32_t i_audio_latency;
+
+	struct cea_hdmi_vsdb_extended_caps hdmi_vsdb_extended_caps;
+
+	enum stereo_3d_multi_presence stereo_3d_multi_present;
+
+	struct {
+		bool FRAME_PACKING:1;
+		bool SIDE_BY_SIDE_HALF:1;
+		bool TOP_AND_BOTTOM:1;
+	} stereo_3d_all_support;
+	uint16_t stereo_3d_mask;
+
+	enum cea_hdmi_vic hdmi_vic[MAX_NUMBER_OF_HDMI_VSDB_VICS];
+	struct stereo_3d_extended_support {
+		struct {
+			bool FRAME_PACKING:1;
+			bool SIDE_BY_SIDE_HALF:1;
+			bool TOP_AND_BOTTOM:1;
+		} format;
+		uint32_t vic_index;
+		uint32_t value;
+		uint32_t size;
+	} stereo_3d_extended_support[MAX_NUMBER_OF_HDMI_VSDB_3D_EXTENDED_SUPPORT];
+};
+
+struct cea861_support {
+
+	uint32_t revision;
+	union {
+		struct {
+			uint32_t NATIVE_COUNT:4;
+			uint32_t BASE_AUDIO:1;
+			uint32_t YCRCB444:1;
+			uint32_t YCRCB422:1;
+			uint32_t UNDER_SCAN:1;
+		} features;
+		uint8_t raw_features;
+	};
+};
+
+struct dcs_customized_mode {
+	struct {
+		uint32_t READ_ONLY:1;
+		uint32_t ADD_BY_DRIVER:1;
+		uint32_t INTERLACED:1;
+		uint32_t BASE_MODE:1;
+	} flags;
+	struct dc_mode_info base_mode_info;
+	struct dc_mode_info customized_mode_info;
+};
+
+struct dcs_override_mode_timing {
+	/* possible timing standards, bit vector of TimingStandard*/
+	uint32_t possible_timing_standards;
+	/* indicate driver default timing is used , no override*/
+	bool use_driver_default_timing;
+	struct dc_mode_timing mode_timing;
+};
+
+struct dcs_override_mode_timing_list {
+	uint32_t max_num_overrides;
+	uint32_t num_overrides;
+	struct dcs_override_mode_timing mode_timings[1];
+};
+
+/* "interface type" is different from Signal Type because
+ * an "interface type" can be driven by more than one Signal Type.
+ * For example, INTERFACE_TYPE_DVI can be driven by
+ * Single or Dual link DVI signal. */
+enum dcs_interface_type {
+	INTERFACE_TYPE_VGA = 0,
+	INTERFACE_TYPE_DVI,
+	INTERFACE_TYPE_CV,
+	INTERFACE_TYPE_TV,
+	INTERFACE_TYPE_LVDS,
+	INTERFACE_TYPE_DP,
+	INTERFACE_TYPE_WIRELESS,
+	INTERFACE_TYPE_CF,
+	INTERFACE_TYPE_EDP
+};
+
+
+union panel_misc_info {
+	struct {
+		uint32_t H_CUT_OFF:1;
+		uint32_t H_SYNC_POLARITY:1;/*0=Active High, 1=Active Low*/
+		uint32_t V_SYNC_POLARITY:1; /*0=Active High, 1=Active Low*/
+		uint32_t V_CUT_OFF:1;
+		uint32_t H_REPLICATION_BY_2:1;
+		uint32_t V_REPLICATION_BY_2:1;
+		uint32_t COMPOSITE_SYNC:1;
+		uint32_t INTERLACE:1;
+		uint32_t DOUBLE_CLOCK:1;
+		uint32_t RGB888:1;
+		uint32_t GREY_LEVEL:2;
+		uint32_t SPATIAL:1;
+		uint32_t TEMPORAL:1;
+		uint32_t API_ENABLED:1;
+	} bits;
+	uint32_t raw;
+};
+
+union hdtv_mode_support {
+	struct {
+		uint32_t HDTV_SUPPORT_480I:1;
+		uint32_t HDTV_SUPPORT_480P:1;
+		uint32_t HDTV_SUPPORT_576I25:1;
+		uint32_t HDTV_SUPPORT_576P50:1;
+		uint32_t HDTV_SUPPORT_720P:1;
+		uint32_t HDTV_SUPPORT_720P50:1;
+		uint32_t HDTV_SUPPORT_1080I:1;
+		uint32_t HDTV_SUPPORT_1080I25:1;
+		uint32_t HDTV_SUPPORT_1080P:1;
+		uint32_t HDTV_SUPPORT_1080P50:1;
+		uint32_t HDTV_SUPPORT_1080P24:1;
+		uint32_t HDTV_SUPPORT_1080P25:1;
+		uint32_t HDTV_SUPPORT_1080P30:1;
+		uint32_t HDTV_SUPPORT_16X9:1;
+	} bits;
+	uint32_t raw;
+};
+
+enum edid_retrieve_status {
+	EDID_RETRIEVE_SUCCESS = 0,
+	EDID_RETRIEVE_FAIL,
+	EDID_RETRIEVE_SAME_EDID,
+	EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS
+};
+
+#define DCS_DECODE_EDID_RETRIEVE_STATUS(status) \
+	(status == EDID_RETRIEVE_SUCCESS) ? "EDID_RETRIEVE_SUCCESS" : \
+	(status == EDID_RETRIEVE_FAIL) ? "EDID_RETRIEVE_FAIL" : \
+	(status == EDID_RETRIEVE_SAME_EDID) ? "EDID_RETRIEVE_SAME_EDID" : \
+	(status == EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS) ? \
+		"EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS" : "Unknown"
+
+
+#ifndef TV_SIGNALFORMAT_DEFINED
+#define TV_SIGNALFORMAT_DEFINED
+enum tv_signal_format {
+	TV_SIGNAL_FORMAT_UNKNOWN,
+	TV_SIGNAL_FORMAT_NTSC,
+	TV_SIGNAL_FORMAT_NTSC_J,
+	TV_SIGNAL_FORMAT_PAL,
+	TV_SIGNAL_FORMAT_PAL_M,
+	TV_SIGNAL_FORMAT_PAL_CN,
+	TV_SIGNAL_FORMAT_SECAM
+};
+#endif
+
+enum tv_signal_format_result {
+	TV_SIGNAL_FORMAT_RESULT_OK,
+	TV_SIGNAL_FORMAT_SET_MODE_REQ,
+	TV_SIGNAL_FORMAT_REBOOT_REQ,
+	TV_SIGNAL_FORMAT_ERROR
+};
+
+enum pixel_encoding_mask {
+	PIXEL_ENCODING_MASK_YCBCR444 = 0x01,
+	PIXEL_ENCODING_MASK_YCBCR422 = 0x02,
+	PIXEL_ENCODING_MASK_RGB = 0x04,
+};
+
+struct display_pixel_encoding_support {
+	uint32_t mask;
+};
+
+enum color_depth_index {
+	COLOR_DEPTH_INDEX_UNKNOWN,
+	COLOR_DEPTH_INDEX_666 = 0x01,
+	COLOR_DEPTH_INDEX_888 = 0x02,
+	COLOR_DEPTH_INDEX_101010 = 0x04,
+	COLOR_DEPTH_INDEX_121212 = 0x08,
+	COLOR_DEPTH_INDEX_141414 = 0x10,
+	COLOR_DEPTH_INDEX_161616 = 0x20,
+	COLOR_DEPTH_INDEX_LAST = 0x40,
+};
+
+struct display_color_depth_support {
+	uint32_t mask;
+	bool deep_color_native_res_only;
+};
+
+struct display_color_and_pixel_support {
+	struct display_color_depth_support color_depth_support;
+	struct display_pixel_encoding_support pixel_encoding_support;
+	bool deep_color_y444_support;
+};
+
+enum dcs_packed_pixel_format {
+	DCS_PACKED_PIXEL_FORMAT_NOT_PACKED = 0,
+	DCS_PACKED_PIXEL_FORMAT_SPLIT_G70_B54_R70_B10 = 1,
+	DCS_PACKED_PIXEL_FORMAT_R70_G76 = 2,
+	DCS_PACKED_PIXEL_FORMAT_SPLIT_B70_G10_R70_G76 = 3,
+	DCS_PACKED_PIXEL_FORMAT_G70_B54_R70_B10 = 4,
+	DCS_PACKED_PIXEL_FORMAT_G70_B54 = 5,
+	DCS_PACKED_PIXEL_FORMAT_B70_R30_G70_R74 = 6,
+	DCS_PACKED_PIXEL_FORMAT_B70_G70_R70 = 7,
+	DCS_PACKED_PIXEL_FORMAT_B70_R32_G70_R76 = 8,
+};
+
+enum monitor_manufacturer_id {
+	MONITOR_MANUFACTURER_ID_0 = 0x0000,
+	MONITOR_MANUFACTURER_ID_1 = 0x3834,
+	MONITOR_MANUFACTURER_ID_2 = 0x4d24,
+	MONITOR_MANUFACTURER_ID_3 = 0x293E,
+	MONITOR_MANUFACTURER_ID_4 = 0x635a,
+	MONITOR_MANUFACTURER_ID_5 = 0x1006,
+	MONITOR_MANUFACTURER_ID_6 = 0xc32a,
+	MONITOR_MANUFACTURER_ID_7 = 0x4d24,
+	MONITOR_MANUFACTURER_ID_8 = 0x110e,
+	MONITOR_MANUFACTURER_ID_9 = 0xaf0d,
+	MONITOR_MANUFACTURER_ID_10 = 0x6D1E,
+	MONITOR_MANUFACTURER_ID_11 = 0xA338,
+	MONITOR_MANUFACTURER_ID_12 = 0xC315,
+	MONITOR_MANUFACTURER_ID_13 = 0xD94D,
+	MONITOR_MANUFACTURER_ID_14 = 0x104D,
+	MONITOR_MANUFACTURER_ID_15 = 0x855C,
+	MONITOR_MANUFACTURER_ID_16 = 0x4251,
+	MONITOR_MANUFACTURER_ID_17 = 0xA934,
+	MONITOR_MANUFACTURER_ID_18 = 0x0C41,
+	/* TODO: Update when EDID is available */
+	MONITOR_MANUFACTURER_ID_19 = 0xDEAD,
+	MONITOR_MANUFACTURER_ID_20 = 0x6904,
+	MONITOR_MANUFACTURER_ID_21 = 0xAC10,
+	MONITOR_MANUFACTURER_ID_22 = 0x2D4C,
+	MONITOR_MANUFACTURER_ID_23 = 0x144E,
+	MONITOR_MANUFACTURER_ID_24 = 0x6c50,
+	MONITOR_MANUFACTURER_ID_26 = 0x0c41,
+	MONITOR_MANUFACTURER_ID_27 = 0x143E,
+	MONITOR_MANUFACTURER_ID_25 = 0xffff,
+	MONITOR_MANUFACTURER_ID_28 = 0x3421,
+	MONITOR_MANUFACTURER_ID_29 = 0x2D19,
+	MONITOR_MANUFACTURER_ID_30 = 0x8B52,
+	MONITOR_MANUFACTURER_ID_31 = 0x7204,
+	MONITOR_MANUFACTURER_ID_32 = 0xF022,
+	MONITOR_MANUFACTURER_ID_33 = 0x0E11,
+	MONITOR_MANUFACTURER_ID_34 = 0xD241,
+	MONITOR_MANUFACTURER_ID_35 = 0xAE30,
+	MONITOR_MANUFACTURER_ID_36 = 0xF91E,
+	MONITOR_MANUFACTURER_ID_37 = 0xAB4C,
+};
+
+enum monitor_product_id {
+	MONITOR_PRODUCT_ID_0 = 0x0000,
+	MONITOR_PRODUCT_ID_1 = 0x0BCC,
+	MONITOR_PRODUCT_ID_2 = 0x251F,
+	MONITOR_PRODUCT_ID_3 = 0x5241,
+	MONITOR_PRODUCT_ID_4 = 0x6919,
+	MONITOR_PRODUCT_ID_5 = 0xee18,
+	MONITOR_PRODUCT_ID_6 = 0xf008,
+	MONITOR_PRODUCT_ID_7 = 0x2f0c,
+	MONITOR_PRODUCT_ID_7_2 = 0x3411,
+	MONITOR_PRODUCT_ID_9 = 0x4208,
+	MONITOR_PRODUCT_ID_10 = 0xE51D,
+	MONITOR_PRODUCT_ID_11 = 0x7E22,
+	MONITOR_PRODUCT_ID_12 = 0x0E23,
+	MONITOR_PRODUCT_ID_13 = 0x9d08,
+	MONITOR_PRODUCT_ID_14 = 0x9236,
+	MONITOR_PRODUCT_ID_15 = 0x9227,
+	MONITOR_PRODUCT_ID_16 = 0x0220,
+	MONITOR_PRODUCT_ID_17 = 0x4920,
+	MONITOR_PRODUCT_ID_18 = 0x251f,
+	MONITOR_PRODUCT_ID_19 = 0x1395,
+	MONITOR_PRODUCT_ID_20 = 0xc04e,
+	MONITOR_PRODUCT_ID_21 = 0x5787,
+	MONITOR_PRODUCT_ID_22 = 0x5A71,
+	MONITOR_PRODUCT_ID_23 = 0x6622,
+	MONITOR_PRODUCT_ID_24 = 0x20C1,
+	MONITOR_PRODUCT_ID_25 = 0x2110,
+	MONITOR_PRODUCT_ID_26 = 0x2006,
+	MONITOR_PRODUCT_ID_27 = 0x1827,
+	MONITOR_PRODUCT_ID_28 = 0x0EA0,
+	MONITOR_PRODUCT_ID_29 = 0x03D0,
+	MONITOR_PRODUCT_ID_30 = 0x01D2,
+	MONITOR_PRODUCT_ID_31 = 0x2801,
+	MONITOR_PRODUCT_ID_32 = 0x0FB3,
+	MONITOR_PRODUCT_ID_33 = 0x0FB1,
+	MONITOR_PRODUCT_ID_34 = 0xA045,
+	MONITOR_PRODUCT_ID_35 = 0x0001,
+	MONITOR_PRODUCT_ID_36 = 0xA296,
+	MONITOR_PRODUCT_ID_38 = 0x21DC,
+	MONITOR_PRODUCT_ID_37 = 0x21EA,
+	MONITOR_PRODUCT_ID_39 = 0x4093,
+	MONITOR_PRODUCT_ID_40 = 0x4094,
+	MONITOR_PRODUCT_ID_41 = 0x4094,
+	MONITOR_PRODUCT_ID_42 = 0x32A2,
+	MONITOR_PRODUCT_ID_43 = 0xE009,
+	MONITOR_PRODUCT_ID_44 = 0xA010,
+	MONITOR_PRODUCT_ID_45 = 0x405C,
+	MONITOR_PRODUCT_ID_46 = 0xF017,
+	MONITOR_PRODUCT_ID_47 = 0xD026,
+	MONITOR_PRODUCT_ID_48 = 0x4036,
+	MONITOR_PRODUCT_ID_49 = 0x4065,
+	MONITOR_PRODUCT_ID_50 = 0xA02A,
+	MONITOR_PRODUCT_ID_51 = 0xA02C,
+	MONITOR_PRODUCT_ID_46_HDMI = 0xF016,
+	MONITOR_PRODUCT_ID_53 = 0xF048,
+	MONITOR_PRODUCT_ID_54 = 0xA0A2,
+	MONITOR_PRODUCT_ID_55 = 0x4083,
+	MONITOR_PRODUCT_ID_56 = 0x0E74,
+	MONITOR_PRODUCT_ID_57 = 0x2771,
+	MONITOR_PRODUCT_ID_58 = 0x0814,
+	MONITOR_PRODUCT_ID_59 = 0xffff,
+	MONITOR_PRODUCT_ID_60 = 0x3339,
+	MONITOR_PRODUCT_ID_61 = 0x01F5,
+	MONITOR_PRODUCT_ID_62 = 0x02A5,
+	MONITOR_PRODUCT_ID_63 = 0x06AC,
+	MONITOR_PRODUCT_ID_64 = 0x04D5,
+	MONITOR_PRODUCT_ID_65 = 0x079D,
+	MONITOR_PRODUCT_ID_66 = 0x079F,
+	MONITOR_PRODUCT_ID_67 = 0x0797,
+	MONITOR_PRODUCT_ID_68 = 0x0B80,
+	MONITOR_PRODUCT_ID_69 = 0x7D06,
+	MONITOR_PRODUCT_ID_70 = 0x0131,
+	MONITOR_PRODUCT_ID_71 = 0x8545,
+	MONITOR_PRODUCT_ID_72 = 0x0002,
+	MONITOR_PRODUCT_ID_73 = 0x0125,
+	MONITOR_PRODUCT_ID_74 = 0x00D0,
+	MONITOR_PRODUCT_ID_75 = 0x26F7,
+	MONITOR_PRODUCT_ID_76 = 0x26F9,
+	MONITOR_PRODUCT_ID_77 = 0x2807,
+	MONITOR_PRODUCT_ID_78 = 0x26F3,
+	MONITOR_PRODUCT_ID_79 = 0x2676,
+	MONITOR_PRODUCT_ID_80 = 0x0A72,
+	MONITOR_PRODUCT_ID_81 = 0x2693,
+	MONITOR_PRODUCT_ID_82 = 0x2615,
+	MONITOR_PRODUCT_ID_83 = 0x2613,
+	MONITOR_PRODUCT_ID_84 = 0x262D,
+	MONITOR_PRODUCT_ID_85 = 0x264B,
+	MONITOR_PRODUCT_ID_86 = 0x2869,
+	MONITOR_PRODUCT_ID_87 = 0x286C,
+	MONITOR_PRODUCT_ID_88 = 0x288F,
+	MONITOR_PRODUCT_ID_89 = 0x2954,
+	MONITOR_PRODUCT_ID_90 = 0x6522,
+	MONITOR_PRODUCT_ID_91 = 0x0FAE,
+	MONITOR_PRODUCT_ID_92 = 0x0A0C,
+	MONITOR_PRODUCT_ID_93 = 0x00BF,
+	MONITOR_PRODUCT_ID_94 = 0x0,
+};
+
+enum monitor_patch_type {
+	MONITOR_PATCH_TYPE_NONE,
+	MONITOR_PATCH_TYPE_ERROR_CHECKSUM,
+	MONITOR_PATCH_TYPE_HDTV_WITH_PURE_DFP_EDID,
+	MONITOR_PATCH_TYPE_DO_NOT_USE_DETAILED_TIMING,
+	MONITOR_PATCH_TYPE_DO_NOT_USE_RANGE_LIMITATION,
+	MONITOR_PATCH_TYPE_EDID_EXTENTION_ERROR_CHECK_SUM,
+	MONITOR_PATCH_TYPE_TURN_OFF_DISPLAY_BEFORE_MODE_CHANGE,
+	MONITOR_PATCH_TYPE_RESTRICT_VESA_MODE_TIMING,
+	MONITOR_PATCH_TYPE_DO_NOT_USE_EDID_MAX_PIX_CLK,
+	MONITOR_PATCH_TYPE_VENDOR_0,
+	MONITOR_PATCH_TYPE_RANDOM_CRT,
+	MONITOR_PATCH_TYPE_VENDOR_1,
+	MONITOR_PATCH_TYPE_LIMIT_PANEL_SUPPORT_RGB_ONLY,
+	MONITOR_PATCH_TYPE_PACKED_PIXEL_FORMAT,
+	MONITOR_PATCH_TYPE_LARGE_PANEL,
+	MONITOR_PATCH_TYPE_STEREO_SUPPORT,
+	/* 0 (default) - mean patch will not be applied, however it can be
+	 * explicitly set to 1
+	 */
+	MONITOR_PATCH_TYPE_DUAL_EDID_PANEL,
+	MONITOR_PATCH_TYPE_IGNORE_19X12_STD_TIMING,
+	MONITOR_PATCH_TYPE_MULTIPLE_PACKED_TYPE,
+	MONITOR_PATCH_TYPE_RESET_TX_ON_DISPLAY_POWER_ON,
+	MONITOR_PATCH_TYPE_VENDOR_2,
+	MONITOR_PATCH_TYPE_RESTRICT_PROT_DUAL_LINK_DVI,
+	MONITOR_PATCH_TYPE_FORCE_LINK_RATE,
+	MONITOR_PATCH_TYPE_DELAY_AFTER_DP_RECEIVER_POWER_UP,
+	MONITOR_PATCH_TYPE_KEEP_DP_RECEIVER_POWERED,
+	MONITOR_PATCH_TYPE_DELAY_BEFORE_READ_EDID,
+	MONITOR_PATCH_TYPE_DELAY_AFTER_PIXEL_FORMAT_CHANGE,
+	MONITOR_PATCH_TYPE_INCREASE_DEFER_WRITE_RETRY_I2C_OVER_AUX,
+	MONITOR_PATCH_TYPE_NO_DEFAULT_TIMINGS,
+	MONITOR_PATCH_TYPE_ADD_CEA861_DETAILED_TIMING_VIC16,
+	MONITOR_PATCH_TYPE_ADD_CEA861_DETAILED_TIMING_VIC31,
+	MONITOR_PATCH_TYPE_DELAY_BEFORE_UNMUTE,
+	MONITOR_PATCH_TYPE_RETRY_LINK_TRAINING_ON_FAILURE,
+	MONITOR_PATCH_TYPE_ALLOW_AUX_WHEN_HPD_LOW,
+	MONITOR_PATCH_TYPE_TILED_DISPLAY,
+	MONITOR_PATCH_TYPE_DISABLE_PSR_ENTRY_ABORT,
+	MONITOR_PATCH_TYPE_EDID_EXTENTION_ERROR_CHECKSUM,
+	MONITOR_PATCH_TYPE_ALLOW_ONLY_CE_MODE,
+	MONITOR_PATCH_TYPE_VID_STREAM_DIFFER_TO_SYNC,
+	MONITOR_PATCH_TYPE_EXTRA_DELAY_ON_DISCONNECT,
+	MONITOR_PATCH_TYPE_DELAY_AFTER_DISABLE_BACKLIGHT_DFS_BYPASS,
+	MONITOR_PATCH_TYPE_SINGLE_MODE_PACKED_PIXEL
+};
+
+/* Single entry in the monitor table */
+struct monitor_patch_info {
+	enum monitor_manufacturer_id manufacturer_id;
+	enum monitor_product_id product_id;
+	enum monitor_patch_type type;
+	uint32_t param;
+};
+
+union dcs_monitor_patch_flags {
+        struct {
+                bool ERROR_CHECKSUM:1;
+                bool HDTV_WITH_PURE_DFP_EDID:1;
+                bool DO_NOT_USE_DETAILED_TIMING:1;
+                bool DO_NOT_USE_RANGE_LIMITATION:1;
+                bool EDID_EXTENTION_ERROR_CHECKSUM:1;
+                bool TURN_OFF_DISPLAY_BEFORE_MODE_CHANGE:1;
+                bool RESTRICT_VESA_MODE_TIMING:1;
+                bool DO_NOT_USE_EDID_MAX_PIX_CLK:1;
+                bool VENDOR_0:1;
+                bool RANDOM_CRT:1;/* 10 bits used including this one-*/
+                bool VENDOR_1:1;
+                bool LIMIT_PANEL_SUPPORT_RGB_ONLY:1;
+                bool PACKED_PIXEL_FORMAT:1;
+                bool LARGE_PANEL:1;
+                bool STEREO_SUPPORT:1;
+                bool DUAL_EDID_PANEL:1;
+                bool IGNORE_19X12_STD_TIMING:1;
+                bool MULTIPLE_PACKED_TYPE:1;
+                bool RESET_TX_ON_DISPLAY_POWER_ON:1;
+                bool ALLOW_ONLY_CE_MODE:1;/* 20 bits used including this one*/
+                bool RESTRICT_PROT_DUAL_LINK_DVI:1;
+                bool FORCE_LINK_RATE:1;
+                bool DELAY_AFTER_DP_RECEIVER_POWER_UP:1;
+                bool KEEP_DP_RECEIVER_POWERED:1;
+                bool DELAY_BEFORE_READ_EDID:1;
+                bool DELAY_AFTER_PIXEL_FORMAT_CHANGE:1;
+                bool INCREASE_DEFER_WRITE_RETRY_I2C_OVER_AUX:1;
+                bool NO_DEFAULT_TIMINGS:1;
+                bool ADD_CEA861_DETAILED_TIMING_VIC16:1;
+                bool ADD_CEA861_DETAILED_TIMING_VIC31:1; /* 30 bits*/
+                bool DELAY_BEFORE_UNMUTE:1;
+                bool RETRY_LINK_TRAINING_ON_FAILURE:1;
+                bool ALLOW_AUX_WHEN_HPD_LOW:1;
+                bool TILED_DISPLAY:1;
+                bool DISABLE_PSR_ENTRY_ABORT:1;
+                bool INTERMITTENT_EDID_ERROR:1;/* 36 bits total*/
+                bool VID_STREAM_DIFFER_TO_SYNC:1;/* 37 bits total*/
+                bool EXTRA_DELAY_ON_DISCONNECT:1;/* 38 bits total*/
+                bool DELAY_AFTER_DISABLE_BACKLIGHT_DFS_BYPASS:1;/* 39 bits total*/
+        } flags;
+        uint64_t raw;
+};
+
+struct dcs_edid_supported_max_bw {
+	uint32_t pix_clock_khz;
+	uint32_t bits_per_pixel;
+};
+
+struct dcs_stereo_3d_features {
+	struct {
+/* 3D Format supported by monitor (implies supported by driver)*/
+		uint32_t SUPPORTED:1;
+/* 3D Format supported on all timings
+(no need to check every timing for 3D support)*/
+		uint32_t ALL_TIMINGS:1;
+/* 3D Format supported in clone mode*/
+		uint32_t CLONE_MODE:1;
+/* Scaling allowed when driving 3D Format*/
+		uint32_t SCALING:1;
+/* Left and right images packed by SW within single frame*/
+		uint32_t SINGLE_FRAME_SW_PACKED:1;
+	} flags;
+};
+
+struct dcs_container_id {
+	/*128bit GUID in binary form*/
+	uint8_t guid[16];
+	/* 8 byte port ID -> ELD.PortID*/
+	uint32_t port_id[2];
+	/* 2 byte manufacturer name -> ELD.ManufacturerName*/
+	uint16_t manufacturer_name;
+	/* 2 byte product code -> ELD.ProductCode*/
+	uint16_t product_code;
+};
+
+struct dcs_display_tile {
+/*unique Id of Tiled Display. 0 - means display is not part in Tiled Display*/
+	uint64_t id;
+	uint32_t rows;/* size of Tiled Display in tiles*/
+	uint32_t cols;/* size of Tiled Display in tiles*/
+	uint32_t width;/* size of current Tile in pixels*/
+	uint32_t height;/* size of current Tile in pixels*/
+	uint32_t row;/* location of current Tile*/
+	uint32_t col;/* location of current Tile*/
+	struct {
+		/*in pixels*/
+		uint32_t left;
+		uint32_t right;
+		uint32_t top;
+		uint32_t bottom;
+	} bezel;/* bezel information of current tile*/
+
+	struct {
+		uint32_t SEPARATE_ENCLOSURE:1;
+		uint32_t BEZEL_INFO_PRESENT:1;
+		uint32_t CAN_SCALE:1;
+	} flags;
+
+	struct {
+		uint32_t manufacturer_id;
+		uint32_t product_id;
+		uint32_t serial_id;
+	} topology_id;
+};
+
+#endif /* __DAL_DCS_TYPES_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/include/ddc_interface.h b/drivers/gpu/drm/amd/dal/include/ddc_interface.h
new file mode 100644
index 000000000000..22fd31f6de7f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/ddc_interface.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DDC_INTERFACE_H__
+#define __DAL_DDC_INTERFACE_H__
+
+#include "gpio_types.h"
+
+struct ddc;
+
+enum gpio_result dal_ddc_open(
+	struct ddc *ddc,
+	enum gpio_mode mode,
+	enum gpio_ddc_config_type config_type);
+
+enum gpio_result dal_ddc_get_clock(
+	const struct ddc *ddc,
+	uint32_t *value);
+
+enum gpio_result dal_ddc_set_clock(
+	const struct ddc *ddc,
+	uint32_t value);
+
+enum gpio_result dal_ddc_get_data(
+	const struct ddc *ddc,
+	uint32_t *value);
+
+enum gpio_result dal_ddc_set_data(
+	const struct ddc *ddc,
+	uint32_t value);
+
+enum gpio_result dal_ddc_change_mode(
+	struct ddc *ddc,
+	enum gpio_mode mode);
+
+bool dal_ddc_is_hw_supported(
+	const struct ddc *ddc);
+
+enum gpio_ddc_line dal_ddc_get_line(
+	const struct ddc *ddc);
+
+bool dal_ddc_check_line_aborted(
+	const struct ddc *ddc);
+
+enum gpio_result dal_ddc_set_config(
+	struct ddc *ddc,
+	enum gpio_ddc_config_type config_type);
+
+void dal_ddc_close(
+	struct ddc *ddc);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/ddc_service_types.h b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h
new file mode 100644
index 000000000000..cbdb6dfe4ff3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_DDC_SERVICE_TYPES_H__
+#define __DAL_DDC_SERVICE_TYPES_H__
+
+#define DP_BRANCH_DEVICE_ID_1 0x0010FA
+#define DP_BRANCH_DEVICE_ID_2 0x0022B9
+#define DP_SINK_DEVICE_ID_1 0x4CE000
+#define DP_BRANCH_DEVICE_ID_3 0x00001A
+#define DP_BRANCH_DEVICE_ID_4 0x0080e1
+#define DP_BRANCH_DEVICE_ID_5 0x006037
+#define DP_SINK_DEVICE_ID_2 0x001CF8
+
+
+enum ddc_result {
+	DDC_RESULT_UNKNOWN = 0,
+	DDC_RESULT_SUCESSFULL,
+	DDC_RESULT_FAILED_CHANNEL_BUSY,
+	DDC_RESULT_FAILED_TIMEOUT,
+	DDC_RESULT_FAILED_PROTOCOL_ERROR,
+	DDC_RESULT_FAILED_NACK,
+	DDC_RESULT_FAILED_INCOMPLETE,
+	DDC_RESULT_FAILED_OPERATION,
+	DDC_RESULT_FAILED_INVALID_OPERATION,
+	DDC_RESULT_FAILED_BUFFER_OVERFLOW
+};
+
+enum ddc_service_type {
+	DDC_SERVICE_TYPE_CONNECTOR,
+	DDC_SERVICE_TYPE_DISPLAY_PORT_MST,
+};
+
+enum ddc_transaction_type {
+	DDC_TRANSACTION_TYPE_NONE = 0,
+	DDC_TRANSACTION_TYPE_I2C,
+	DDC_TRANSACTION_TYPE_I2C_OVER_AUX,
+	DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER,
+	DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER
+};
+
+enum display_dongle_type {
+	DISPLAY_DONGLE_NONE = 0,
+	/* Active converter types*/
+	DISPLAY_DONGLE_DP_VGA_CONVERTER,
+	DISPLAY_DONGLE_DP_DVI_CONVERTER,
+	DISPLAY_DONGLE_DP_HDMI_CONVERTER,
+	/* DP-HDMI/DVI passive dongles (Type 1 and Type 2)*/
+	DISPLAY_DONGLE_DP_DVI_DONGLE,
+	DISPLAY_DONGLE_DP_HDMI_DONGLE,
+	/* Other types of dongle*/
+	DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE,
+};
+
+enum dcs_dpcd_revision {
+	DCS_DPCD_REV_10 = 0x10,
+	DCS_DPCD_REV_11 = 0x11,
+	DCS_DPCD_REV_12 = 0x12
+};
+
+/**
+ * display sink capability
+ */
+struct display_sink_capability {
+	/* dongle type (DP converter, CV smart dongle) */
+	enum display_dongle_type dongle_type;
+
+	/**********************************************************
+	 capabilities going INTO SINK DEVICE (stream capabilities)
+	 **********************************************************/
+	/* Dongle's downstream count. */
+	uint32_t downstrm_sink_count;
+	/* Is dongle's downstream count info field (downstrm_sink_count)
+	 * valid. */
+	bool downstrm_sink_count_valid;
+
+	/* Maximum additional audio delay in microsecond (us) */
+	uint32_t additional_audio_delay;
+	/* Audio latency value in microsecond (us) */
+	uint32_t audio_latency;
+	/* Interlace video latency value in microsecond (us) */
+	uint32_t video_latency_interlace;
+	/* Progressive video latency value in microsecond (us) */
+	uint32_t video_latency_progressive;
+	/* Dongle caps: Maximum pixel clock supported over dongle for HDMI */
+	uint32_t max_hdmi_pixel_clock;
+	/* Dongle caps: Maximum deep color supported over dongle for HDMI */
+	enum dc_color_depth max_hdmi_deep_color;
+
+	/************************************************************
+	 capabilities going OUT OF SOURCE DEVICE (link capabilities)
+	 ************************************************************/
+	/* support for Spread Spectrum(SS) */
+	bool ss_supported;
+	/* DP link settings (laneCount, linkRate, Spread) */
+	uint32_t dp_link_lane_count;
+	uint32_t dp_link_rate;
+	uint32_t dp_link_spead;
+
+	enum dcs_dpcd_revision dpcd_revision;
+	/* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER,
+	indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/
+	bool is_dp_hdmi_s3d_converter;
+	/* to check if we have queried the display capability
+	 * for eDP panel already. */
+	bool is_edp_sink_cap_valid;
+
+	enum ddc_transaction_type transaction_type;
+	enum signal_type signal;
+};
+
+struct dp_receiver_id_info {
+	uint32_t dpcd_rev;
+	uint32_t sink_id;
+	int8_t sink_id_str[6];
+	int8_t sink_hw_revision;
+	int8_t sink_fw_revision[2];
+	uint32_t branch_id;
+	int8_t branch_name[6];
+	enum display_dongle_type dongle_type;
+};
+
+struct av_sync_data {
+	uint8_t av_granularity;/* DPCD 00023h */
+	uint8_t aud_dec_lat1;/* DPCD 00024h */
+	uint8_t aud_dec_lat2;/* DPCD 00025h */
+	uint8_t aud_pp_lat1;/* DPCD 00026h */
+	uint8_t aud_pp_lat2;/* DPCD 00027h */
+	uint8_t vid_inter_lat;/* DPCD 00028h */
+	uint8_t vid_prog_lat;/* DPCD 00029h */
+	uint8_t aud_del_ins1;/* DPCD 0002Bh */
+	uint8_t aud_del_ins2;/* DPCD 0002Ch */
+	uint8_t aud_del_ins3;/* DPCD 0002Dh */
+};
+
+/** EDID retrieval related constants, also used by MstMgr **/
+
+#define DDC_EDID_SEGMENT_SIZE 256
+#define DDC_EDID_BLOCK_SIZE 128
+#define DDC_EDID_BLOCKS_PER_SEGMENT \
+	(DDC_EDID_SEGMENT_SIZE / DDC_EDID_BLOCK_SIZE)
+
+#define DDC_EDID_EXT_COUNT_OFFSET 0x7E
+
+#define DDC_EDID_ADDRESS_START 0x50
+#define DDC_EDID_ADDRESS_END 0x52
+#define DDC_EDID_SEGMENT_ADDRESS 0x30
+
+/* signatures for Edid 1x */
+#define DDC_EDID1X_VENDORID_SIGNATURE_OFFSET 8
+#define DDC_EDID1X_VENDORID_SIGNATURE_LEN 4
+#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_OFFSET 126
+#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_LEN 2
+#define DDC_EDID1X_CHECKSUM_OFFSET 127
+/* signatures for Edid 20*/
+#define DDC_EDID_20_SIGNATURE_OFFSET 0
+#define DDC_EDID_20_SIGNATURE 0x20
+
+#define DDC_EDID20_VENDORID_SIGNATURE_OFFSET 1
+#define DDC_EDID20_VENDORID_SIGNATURE_LEN 4
+#define DDC_EDID20_CHECKSUM_OFFSET 255
+#define DDC_EDID20_CHECKSUM_LEN 1
+
+/*DP to VGA converter*/
+static const uint8_t DP_VGA_CONVERTER_ID_1[] = "mVGAa";
+/*DP to Dual link DVI converter*/
+static const uint8_t DP_DVI_CONVERTER_ID_1[] = "m2DVIa";
+/*Travis*/
+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
+/*Nutmeg*/
+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
+/*DP to VGA converter*/
+static const uint8_t DP_VGA_CONVERTER_ID_4[] = "DpVga";
+/*DP to Dual link DVI converter*/
+static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa";
+/*DP to Dual link DVI converter 2*/
+static const uint8_t DP_DVI_CONVERTER_ID_42[] = "v2DVIa";
+
+static const uint8_t DP_SINK_DEV_STRING_ID2_REV0[] = "\0\0\0\0\0\0";
+
+/* Identifies second generation PSR TCON from Parade: Device ID string:
+ * yy-xx-**-**-**-**
+ */
+/* xx - Hw ID high byte */
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_HIGH_BYTE =
+	0x06;
+
+/* yy - HW ID low byte, the same silicon has several package/feature flavors */
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE1 =
+	0x61;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE2 =
+	0x62;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE3 =
+	0x63;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE4 =
+	0x72;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE5 =
+	0x73;
+
+#endif /* __DAL_DDC_SERVICE_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/display_clock_interface.h b/drivers/gpu/drm/amd/dal/include/display_clock_interface.h
new file mode 100644
index 000000000000..211847cefe80
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/display_clock_interface.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DISPLAY_CLOCK_INTERFACE_H__
+#define __DISPLAY_CLOCK_INTERFACE_H__
+
+#include "hw_sequencer_types.h"
+#include "grph_object_defs.h"
+#include "signal_types.h"
+#include "scaler_types.h"
+
+/* Timing related information*/
+struct dc_timing_params {
+	uint32_t INTERLACED:1;
+	uint32_t HCOUNT_BY_TWO:1;
+	uint32_t PIXEL_REPETITION:4; /*< values 1 to 10 supported*/
+	uint32_t PREFETCH:1;
+
+	uint32_t h_total;
+	uint32_t h_addressable;
+	uint32_t h_sync_width;
+};
+
+/* Scaling related information*/
+struct dc_scaling_params {
+	uint32_t h_overscan_right;
+	uint32_t h_overscan_left;
+	uint32_t h_taps;
+	uint32_t v_taps;
+};
+
+/*Display Request Mode (1 and 2 valid when scaler is OFF)*/
+enum display_request_mode {
+	REQUEST_ONLY_AT_EVERY_READ_POINTER_INCREMENT = 0,
+	REQUEST_WAITING_FOR_THE_FIRST_READ_POINTER_ONLY,
+	REQUEST_WITHOUT_WAITING_FOR_READ_POINTER
+};
+
+/* FBC minimum CompressionRatio*/
+enum fbc_compression_ratio {
+	FBC_COMPRESSION_NOT_USED = 0,
+	FBC_MINIMUM_COMPRESSION_RATIO_1 = 1,
+	FBC_MINIMUM_COMPRESSION_RATIO_2 = 2,
+	FBC_MINIMUM_COMPRESSION_RATIO_4 = 4,
+	FBC_MINIMUM_COMPRESSION_RATIO_8 = 8
+};
+
+/* VScalerEfficiency */
+enum v_scaler_efficiency {
+	V_SCALER_EFFICIENCY_LB36BPP = 0,
+	V_SCALER_EFFICIENCY_LB30BPP = 1,
+	V_SCALER_EFFICIENCY_LB24BPP = 2,
+	V_SCALER_EFFICIENCY_LB18BPP = 3
+};
+
+/* Parameters required for minimum Engine
+ * and minimum Display clock calculations*/
+struct min_clock_params {
+	uint32_t id;
+	uint32_t requested_pixel_clock; /* in KHz */
+	uint32_t actual_pixel_clock; /* in KHz */
+	struct view source_view;
+	struct view dest_view;
+	struct dc_timing_params timing_info;
+	struct dc_scaling_params scaling_info;
+	struct color_quality color_info;
+	enum signal_type signal_type;
+	enum dc_color_depth deep_color_depth;
+	enum v_scaler_efficiency scaler_efficiency;
+	bool line_buffer_prefetch_enabled;
+};
+
+/* Enumerations for Source selection of the Display clock */
+enum display_clock_source_select {
+	USE_PIXEL_CLOCK_PLL = 0,
+	USE_EXTERNAL_CLOCK,
+	USE_ENGINE_CLOCK
+};
+
+/* Result of Minimum System and Display clock calculations.
+ * Minimum System clock and Display clock, source and path to be used
+ * for Display clock*/
+struct minimum_clocks_calculation_result {
+	uint32_t min_sclk_khz;
+	uint32_t min_dclk_khz;
+	uint32_t min_mclk_khz;
+	uint32_t min_deep_sleep_sclk;
+};
+
+/* Enumeration of all clocks states */
+enum clocks_state {
+	CLOCKS_STATE_INVALID,
+	CLOCKS_STATE_ULTRA_LOW,
+	CLOCKS_STATE_LOW,
+	CLOCKS_STATE_NOMINAL,
+	CLOCKS_STATE_PERFORMANCE
+};
+
+/* Structure containing all state-dependent clocks
+ * (dependent on "enum clocks_state") */
+struct state_dependent_clocks {
+	uint32_t display_clk_khz;
+	uint32_t pixel_clk_khz;
+};
+
+struct display_clock_state {
+	uint32_t DFS_BYPASS_ACTIVE:1;
+};
+
+struct display_clock;
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+struct display_clock *dal_display_clock_dce110_create(
+	struct dc_context *ctx,
+	struct adapter_service *as);
+#endif
+
+void dal_display_clock_destroy(struct display_clock **to_destroy);
+bool dal_display_clock_validate(
+	struct display_clock *disp_clk,
+	struct min_clock_params *params);
+uint32_t dal_display_clock_calculate_min_clock(
+	struct display_clock *disp_clk,
+	uint32_t path_num,
+	struct min_clock_params *params);
+uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk);
+void dal_display_clock_set_clock(
+	struct display_clock *disp_clk,
+	uint32_t requested_clock_khz);
+uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk);
+enum clocks_state dal_display_clock_get_min_clocks_state(
+	struct display_clock *disp_clk);
+enum clocks_state dal_display_clock_get_required_clocks_state(
+	struct display_clock *disp_clk,
+	struct state_dependent_clocks *req_clocks);
+bool dal_display_clock_set_min_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state clocks_state);
+uint32_t dal_display_clock_get_dp_ref_clk_frequency(
+	struct display_clock *disp_clk);
+/*the second parameter of "switchreferenceclock" is
+ * a dummy argument for all pre dce 6.0 versions*/
+void dal_display_clock_switch_reference_clock(
+	struct display_clock *disp_clk,
+	bool use_external_ref_clk,
+	uint32_t requested_clock_khz);
+void dal_display_clock_set_dp_ref_clock_source(
+	struct display_clock *disp_clk,
+	enum clock_source_id clk_src);
+void dal_display_clock_store_max_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state max_clocks_state);
+void dal_display_clock_set_clock_state(
+	struct display_clock *disp_clk,
+	struct display_clock_state clk_state);
+struct display_clock_state dal_display_clock_get_clock_state(
+	struct display_clock *disp_clk);
+uint32_t dal_display_clock_get_dfs_bypass_threshold(
+	struct display_clock *disp_clk);
+void dal_display_clock_invalid_clock_state(
+	struct display_clock *disp_clk);
+
+
+#endif /* __DISPLAY_CLOCK_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/display_path_interface.h b/drivers/gpu/drm/amd/dal/include/display_path_interface.h
new file mode 100644
index 000000000000..7bf2ef28f455
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/display_path_interface.h
@@ -0,0 +1,436 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DISPLAY_PATH_INTERFACE_H__
+#define __DISPLAY_PATH_INTERFACE_H__
+
+#include "display_path_types.h"
+#include "dcs_types.h"
+#include "grph_object_ctrl_defs.h"
+#include "signal_types.h"
+#include "controller_types.h"
+
+struct encoder;
+struct controller;
+struct connector;
+struct audio;
+struct clock_source;
+struct link_service;
+struct goc_link_service_data;
+struct drr_config;
+
+struct display_path;
+
+struct display_path *dal_display_path_create(void);
+
+struct display_path *dal_display_path_clone(
+	const struct display_path *self,
+	bool copy_active_state);
+
+void dal_display_path_destroy(
+	struct display_path **to_destroy);
+
+bool dal_display_path_validate(
+	struct display_path *path,
+	enum signal_type sink_signal);
+
+bool dal_display_path_add_link(
+	struct display_path *path,
+	struct encoder *encoder);
+
+bool dal_display_path_add_connector(
+	struct display_path *path,
+	struct connector *connector);
+
+struct connector *dal_display_path_get_connector(
+	struct display_path *path);
+
+int32_t dal_display_path_acquire(
+	struct display_path *path);
+
+bool dal_display_path_is_acquired(
+	const struct display_path *path);
+
+int32_t dal_display_path_get_ref_counter(
+	const struct display_path *path);
+
+int32_t dal_display_path_release(
+	struct display_path *path);
+
+void dal_display_path_release_resources(
+	struct display_path *path);
+
+void dal_display_path_acquire_links(
+	struct display_path *path);
+
+bool dal_display_path_is_source_blanked(
+	const struct display_path *path);
+
+bool dal_display_path_is_source_unblanked(
+	const struct display_path *path);
+
+void dal_display_path_set_source_blanked(
+	struct display_path *path,
+	enum display_tri_state state);
+
+bool dal_display_path_is_target_blanked(
+	const struct display_path *path);
+
+bool dal_display_path_is_target_unblanked(
+	const struct display_path *path);
+
+void dal_display_path_set_target_blanked(
+	struct display_path *path,
+	enum display_tri_state state);
+
+bool dal_display_path_is_target_powered_on(
+	const struct display_path *path);
+
+bool dal_display_path_is_target_powered_off(
+	const struct display_path *path);
+
+void dal_display_path_set_target_powered_on(
+	struct display_path *path,
+	enum display_tri_state state);
+
+bool dal_display_path_is_target_connected(
+	const struct display_path *path);
+
+void dal_display_path_set_target_connected(
+	struct display_path *path,
+	bool c);
+
+uint32_t dal_display_path_get_display_index(
+	const struct display_path *path);
+
+void dal_display_path_set_display_index(
+	struct display_path *path,
+	uint32_t index);
+
+struct connector_device_tag_info *dal_display_path_get_device_tag(
+	struct display_path *path);
+
+void dal_display_path_set_device_tag(
+	struct display_path *path,
+	struct connector_device_tag_info tag);
+
+enum clock_sharing_group dal_display_path_get_clock_sharing_group(
+	const struct display_path *path);
+
+void dal_display_path_set_clock_sharing_group(
+	struct display_path *path,
+	enum clock_sharing_group clock);
+
+union display_path_properties dal_display_path_get_properties(
+	const struct display_path *path);
+
+void dal_display_path_set_properties(
+	struct display_path *path,
+	union display_path_properties p);
+
+struct dcs *dal_display_path_get_dcs(
+	const struct display_path *path);
+
+void dal_display_path_set_dcs(
+	struct display_path *path,
+	struct dcs *dcs);
+
+uint32_t dal_display_path_get_number_of_links(
+	const struct display_path *path);
+
+void dal_display_path_set_controller(
+	struct display_path *path,
+	struct controller *controller);
+
+struct controller *dal_display_path_get_controller(
+	const struct display_path *path);
+
+void dal_display_path_set_clock_source(
+	struct display_path *path,
+	struct clock_source *clock);
+
+struct clock_source *dal_display_path_get_clock_source(
+	const struct display_path *path);
+
+void dal_display_path_set_alt_clock_source(
+	struct display_path *path,
+	struct clock_source *clock);
+
+struct clock_source *dal_display_path_get_alt_clock_source(
+	const struct display_path *path);
+
+void dal_display_path_set_fbc_info(
+	struct display_path *path,
+	struct fbc_info *clock);
+
+struct fbc_info *dal_display_path_get_fbc_info(
+	struct display_path *path);
+
+void dal_display_path_set_drr_config(
+	struct display_path *path,
+	struct drr_config *clock);
+
+void dal_display_path_get_drr_config(
+	const struct display_path *path,
+	struct drr_config *clock);
+
+void dal_display_path_set_static_screen_triggers(
+	struct display_path *path,
+	const struct static_screen_events *events);
+
+void dal_display_path_get_static_screen_triggers(
+	const struct display_path *path,
+	struct static_screen_events *events);
+
+bool dal_display_path_is_psr_supported(
+	const struct display_path *path);
+
+bool dal_display_path_is_drr_supported(
+	const struct display_path *path);
+
+void dal_display_path_set_link_service_data(
+	struct display_path *path,
+	uint32_t idx,
+	const struct goc_link_service_data *data);
+
+bool dal_display_path_get_link_service_data(
+	const struct display_path *path,
+	uint32_t idx,
+	struct goc_link_service_data *data);
+
+struct link_service *dal_display_path_get_link_query_interface(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_link_query_interface(
+	struct display_path *path,
+	uint32_t idx,
+	struct link_service *link);
+
+struct link_service *dal_display_path_get_link_config_interface(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct link_service *dal_display_path_get_link_service_interface(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_upstream_encoder(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_upstream_object(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_downstream_encoder(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_downstream_object(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct audio *dal_display_path_get_audio(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_audio(
+	struct display_path *path,
+	uint32_t idx,
+	struct audio *a);
+
+struct audio *dal_display_path_get_audio_object(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_audio_active_state(
+	struct display_path *path,
+	uint32_t idx,
+	bool state);
+
+enum engine_id dal_display_path_get_stream_engine(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_stream_engine(
+	struct display_path *path,
+	uint32_t idx,
+	enum engine_id id);
+
+bool dal_display_path_is_link_active(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_link_active_state(
+	struct display_path *path,
+	uint32_t idx,
+	bool state);
+
+enum signal_type dal_display_path_get_config_signal(
+	const struct display_path *path,
+	uint32_t idx);
+
+enum signal_type dal_display_path_get_query_signal(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct link_service *dal_display_path_get_mst_link_service(
+	const struct display_path *path);
+
+void dal_display_path_set_sync_output_object(
+	struct display_path *path,
+	enum sync_source o_source,
+	struct encoder *o_object);
+
+struct encoder *dal_display_path_get_sync_output_object(
+	const struct display_path *path);
+
+void dal_display_path_set_stereo_sync_object(
+	struct display_path *path,
+	struct encoder *stereo_sync);
+
+struct encoder *dal_display_path_get_stereo_sync_object(
+	const struct display_path *path);
+
+void dal_display_path_set_sync_input_source(
+	struct display_path *path,
+	enum sync_source s);
+
+enum sync_source dal_display_path_get_sync_input_source(
+	const struct display_path *path);
+
+void dal_display_path_set_sync_output_source(
+	struct display_path *path,
+	enum sync_source s);
+
+enum sync_source dal_display_path_get_sync_output_source(
+	const struct display_path *path);
+
+bool dal_display_path_set_pixel_clock_safe_range(
+	struct display_path *path,
+	struct pixel_clock_safe_range *range);
+
+bool dal_display_path_get_pixel_clock_safe_range(
+	const struct display_path *path,
+	struct pixel_clock_safe_range *range);
+
+void dal_display_path_set_ddi_channel_mapping(
+	struct display_path *path,
+	union ddi_channel_mapping mapping);
+
+bool dal_display_path_set_sink_signal(
+	struct display_path *path,
+	enum signal_type sink_signal);
+
+enum signal_type dal_display_path_sink_signal_to_asic_signal(
+	struct display_path *path,
+	enum signal_type sink_signal);
+
+enum signal_type dal_display_path_sink_signal_to_link_signal(
+	struct display_path *path,
+	enum signal_type sink_signal,
+	uint32_t idx);
+
+enum signal_type dal_display_path_downstream_to_upstream_signal(
+	struct display_path *path,
+	enum signal_type signal,
+	uint32_t idx);
+
+bool dal_display_path_is_audio_present(
+	const struct display_path *path,
+	uint32_t *audio_pin);
+
+bool dal_display_path_is_dp_auth_supported(
+	struct display_path *path);
+
+bool dal_display_path_is_vce_supported(
+	const struct display_path *path);
+
+bool dal_display_path_is_sls_capable(
+	const struct display_path *path);
+
+bool dal_display_path_is_gen_lock_capable(
+	const struct display_path *path);
+
+struct transmitter_configuration dal_display_path_get_transmitter_configuration(
+	const struct display_path *path,
+	bool physical);
+
+bool dal_display_path_is_ss_supported(
+	const struct display_path *path);
+
+bool dal_display_path_is_ss_configurable(
+	const struct display_path *path);
+
+void dal_display_path_set_ss_support(
+	struct display_path *path,
+	bool s);
+
+enum signal_type dal_display_path_get_active_signal(
+	struct display_path *path,
+	uint32_t idx);
+
+bool dal_display_path_contains_object(
+	struct display_path *path,
+	struct graphics_object_id id);
+
+/* Multi-plane declarations.
+ * This structure should also be used for Stereo. */
+struct display_path_plane {
+	struct controller *controller;
+	/* During dal_tm_acquire_plane_resources() set blnd_mode, because
+	 * "layer index" is known at that point, and we must decide how
+	 * "controller" should do the blending */
+	enum blender_mode blnd_mode;
+	/* Some use-cases allow to power-gate FE.
+	 * For example, with Full Screen Video on Underlay we can
+	 * disable the 'root' plane.
+	 * This flag indicates that FE should be power-gated */
+	bool disabled;
+};
+
+bool dal_display_path_add_plane(
+	struct display_path *path,
+	struct display_path_plane *plane);
+
+uint8_t dal_display_path_get_number_of_planes(
+	const struct display_path *path);
+
+struct display_path_plane *dal_display_path_get_plane_at_index(
+	const struct display_path *path,
+	uint8_t index);
+
+struct controller *dal_display_path_get_controller_for_layer_index(
+	const struct display_path *path,
+	uint8_t layer_index);
+
+void dal_display_path_release_planes(
+	struct display_path *path);
+
+void dal_display_path_release_non_root_planes(
+	struct display_path *path);
+
+#endif /* __DISPLAY_PATH_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dmcu_interface.h b/drivers/gpu/drm/amd/dal/include/dmcu_interface.h
new file mode 100644
index 000000000000..c712cc25e731
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dmcu_interface.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DMCU_INTERFACE_H__
+#define __DAL_DMCU_INTERFACE_H__
+
+#include "grph_object_defs.h"
+#include "dmcu_types.h"
+
+/* Interface functions */
+
+/* DMCU setup related interface functions */
+struct dmcu *dal_dmcu_create(
+	struct dmcu_init_data *init_data);
+void dal_dmcu_destroy(struct dmcu **dmcu);
+void dal_dmcu_release_hw(struct dmcu *dmcu);
+
+void dal_dmcu_power_up(struct dmcu *dmcu);
+void dal_dmcu_power_down(struct dmcu *dmcu);
+
+void dal_dmcu_configure_wait_loop(
+		struct dmcu *dmcu,
+		uint32_t display_clock);
+
+/* PSR feature related interface functions */
+void dal_dmcu_psr_setup(
+		struct dmcu *dmcu,
+		struct dmcu_context *dmcu_context);
+void dal_dmcu_psr_enable(struct dmcu *dmcu);
+void dal_dmcu_psr_disable(struct dmcu *dmcu);
+void dal_dmcu_psr_block(struct dmcu *dmcu, bool block_psr);
+bool dal_dmcu_psr_is_blocked(struct dmcu *dmcu);
+void dal_dmcu_psr_set_level(
+		struct dmcu *dmcu,
+		union dmcu_psr_level psr_level);
+void dal_dmcu_psr_allow_power_down_crtc(
+		struct dmcu *dmcu,
+		bool should_allow_crtc_power_down);
+bool dal_dmcu_psr_submit_command(
+		struct dmcu *dmcu,
+		struct dmcu_context *dmcu_context,
+		struct dmcu_config_data *config_data);
+void dal_dmcu_psr_get_config_data(
+		struct dmcu *dmcu,
+		uint32_t v_total,
+		struct dmcu_config_data *config_data);
+
+/* ABM feature related interface functions */
+void dal_dmcu_abm_enable(
+		struct dmcu *dmcu,
+		enum controller_id controller_id,
+		uint32_t vsync_rate_hz);
+void dal_dmcu_abm_disable(struct dmcu *dmcu);
+bool dal_dmcu_abm_enable_smooth_brightness(struct dmcu *dmcu);
+bool dal_dmcu_abm_disable_smooth_brightness(struct dmcu *dmcu);
+void dal_dmcu_abm_varibright_control(
+		struct dmcu *dmcu,
+		const struct varibright_control *varibright_control);
+bool dal_dmcu_abm_set_backlight_level(
+		struct dmcu *dmcu,
+		uint8_t backlight_8_bit);
+uint8_t dal_dmcu_abm_get_user_backlight_level(struct dmcu *dmcu);
+uint8_t dal_dmcu_abm_get_current_backlight_level(struct dmcu *dmcu);
+
+#endif /* __DAL_DMCU_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dmcu_types.h b/drivers/gpu/drm/amd/dal/include/dmcu_types.h
new file mode 100644
index 000000000000..1f3107d5b9b8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dmcu_types.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DMCU_TYPES_H__
+#define __DAL_DMCU_TYPES_H__
+
+/* Forward declaration */
+struct dmcu;
+
+/* Required information for creation and initialization of a controller */
+struct dmcu_init_data {
+	struct dal_context *dal_context;
+	struct adapter_service *as;
+	uint32_t max_engine_clock_in_khz;
+};
+
+/* Interface structure defines */
+
+enum dmcu_action {
+	DMCU_ACTION_PSR_ENABLE,
+	DMCU_ACTION_PSR_EXIT,
+	DMCU_ACTION_PSR_RFB_UPDATE,
+	DMCU_ACTION_PSR_SET,
+	DMCU_ACTION_PSR_CLEAR_COUNT,
+	DMCU_ACTION_PSR_COUNT_REQUEST,
+	DMCU_ACTION_PSR_STATE_REQUEST,
+	DMCU_ACTION_PSR_SET_LEVEL,
+	DMCU_ACTION_PSR_ADVANCE_STATE,
+	DMCU_ACTION_PSR_SET_WAITLOOP
+};
+
+enum dmcu_output {
+	DMCU_OUTPUT_PSR_ACK,
+	DMCU_OUTPUT_PSR_NACK,
+	DMCU_OUTPUT_PSR_AUX_ERR,
+	DMCU_OUTPUT_PSR_COUNT_STATUS,
+	DMCU_OUTPUT_PSR_STATE_STATUS,
+	DMCU_OUTPUT_PSR_RFB_UPDATE_ERR,
+	DMCU_OUTPUT_PSR_ERR,
+	DMCU_OUTPUT_PSR_GET_REPLY,
+	DMCU_OUTPUT_PSR_ENTRY_ERROR,
+	DMCU_OUTPUT_PSR_LT_ERROR,
+	DMCU_OUTPUT_PSR_FORCE_SR_ERROR,
+	DMCU_OUTPUT_PSR_SDP_SEND_TIMEOUT
+};
+
+/* PSR states, based similarly on states defined in eDP specification. */
+enum psr_state {
+	STATE0,		/* PSR is disabled */
+	STATE1,		/* PSR is enabled, but inactive */
+	STATE1A,
+	STATE2,		/* PSR is transitioning to active state */
+	STATE2A,
+	STATE3,		/* PSR is active; Display is in self refresh */
+	STATE3INIT,
+	STATE4,		/* RFB single frame update */
+	STATE4A,
+	STATE4B,
+	STATE4C,
+	STATE4D,
+	STATE5,		/* Exiting from PSR active state */
+	STATE5A,
+	STATE5B,
+	STATE5C
+};
+
+enum phy_type {
+	PHY_TYPE_UNKNOWN = 1,
+	PHY_TYPE_PCIE_PHY = 2,
+	PHY_TYPE_UNIPHY = 3,
+};
+
+struct dmcu_context {
+	enum channel_id channel;
+	enum transmitter transmitter_id;
+	enum engine_id engine_id;
+	enum controller_id controller_id;
+	enum phy_type phy_type;
+	enum physical_phy_id smu_physical_phy_id;
+
+	/* Vertical total pixels from crtc timing.
+	 * This is used for static screen detection.
+	 * ie. If we want to detect half a frame,
+	 * we use this to determine the hyst lines.*/
+	uint32_t crtc_timing_vertical_total;
+
+	/* PSR supported from panel capabilities
+	 * and current display configuration */
+	bool psr_supported_display_config;
+
+	/* Whether fast link training is supported by the panel */
+	bool psr_exit_link_training_required;
+
+	/* If RFB setup time is greater than the total VBLANK time, it is not
+	 * possible for the sink to capture the video frame in the same frame
+	 * the SDP is sent. In this case, the frame capture indication bit
+	 * should be set and an extra static frame should be transmitted to
+	 * the sink */
+	bool psr_frame_capture_indication_required;
+
+	/* Set the last possible line SDP may be transmitted without violating
+	 * the RFB setup time */
+	bool sdp_transmit_line_num_deadline;
+
+	/* The VSync rate in Hz used to calculate the step size
+	 * for smooth brightness feature */
+	uint32_t vsync_rate_hz;
+};
+
+union dmcu_psr_level {
+	struct {
+		bool SKIP_CRC:1;
+		bool SKIP_DP_VID_STREAM_DISABLE:1;
+		bool SKIP_PHY_POWER_DOWN:1;
+		bool SKIP_AUX_ACK_CHECK:1;
+		bool SKIP_CRTC_DISABLE:1;
+		bool SKIP_AUX_RFB_CAPTURE_CHECK:1;
+		bool SKIP_SMU_NOTIFICATION:1;
+		bool SKIP_AUTO_STATE_ADVANCE:1;
+		bool DISABLE_PSR_ENTRY_ABORT:1;
+	} bits;
+	uint32_t u32all;
+};
+
+struct dmcu_config_data {
+	/* Command sent to DMCU. */
+	enum dmcu_action action;
+	/* PSR Level controls which HW blocks to power down during PSR active,
+	 * and also other sequence modifications. */
+	union dmcu_psr_level psr_level;
+	/* To indicate that first changed frame from active state should not
+	 * result in exit to inactive state, but instead perform an automatic
+	 * single frame RFB update. */
+	bool rfb_update_auto_en;
+	/* Number of consecutive static frames to detect before entering PSR
+	 * active state. */
+	uint32_t hyst_frames;
+	/* Partial frames before entering PSR active. Note this parameter is in
+	 * units of 100 lines. i.e. Wait a value of 5 means wait 500 additional
+	 * lines. */
+	uint32_t hyst_lines;
+	/* Number of repeated AUX retries before indicating failure to driver.
+	 * In a working case, first attempt to write/read AUX should pass. */
+	uint32_t aux_repeat;
+	/* Additional delay after remote frame capture before continuing to
+	 * power down. This is mainly for debug purposes to identify timing
+	 * issues. */
+	uint32_t frame_delay;
+	/* Controls how long the delay of a wait loop is. It should be tuned
+	 * to 1 us, and needs to be reconfigured every time DISPCLK changes. */
+	uint32_t wait_loop_num;
+};
+
+struct dmcu_output_data {
+	/* DMCU reply */
+	enum dmcu_output output;
+	/* The current PSR state. */
+	uint32_t psr_state;
+	/* The number of frames during PSR active state. */
+	uint32_t psr_count;
+};
+
+enum varibright_command {
+	VARIBRIGHT_CMD_SET_VB_LEVEL = 0,
+	VARIBRIGHT_CMD_USER_ENABLE,
+	VARIBRIGHT_CMD_POST_DISPLAY_CONFIG,
+	VARIBRIGHT_CMD_UNKNOWN
+};
+
+struct varibright_control {
+	enum varibright_command command;
+	uint8_t level;
+	bool enable;
+	bool activate;
+};
+
+#endif /* __DAL_DMCU_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dpcd_defs.h b/drivers/gpu/drm/amd/dal/include/dpcd_defs.h
new file mode 100644
index 000000000000..bd410ccdc3a5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dpcd_defs.h
@@ -0,0 +1,873 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DPCD_DEFS_H__
+#define __DAL_DPCD_DEFS_H__
+
+enum dpcd_address {
+/* addresses marked with 1.2 are only defined since DP 1.2 spec */
+
+	/* Reciever Capability Field */
+	DPCD_ADDRESS_DPCD_REV = 0x00000,
+	DPCD_ADDRESS_MAX_LINK_RATE = 0x00001,
+	DPCD_ADDRESS_MAX_LANE_COUNT = 0x00002,
+	DPCD_ADDRESS_MAX_DOWNSPREAD = 0x00003,
+	DPCD_ADDRESS_NORP = 0x00004,
+	DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT = 0x00005,
+	DPCD_ADDRESS_MAIN_LINK_CHANNEL_CODING = 0x00006,
+	DPCD_ADDRESS_DOWNSTREAM_PORT_COUNT = 0x00007,
+	DPCD_ADDRESS_RECEIVE_PORT0_CAP0 = 0x00008,
+	DPCD_ADDRESS_RECEIVE_PORT0_CAP1 = 0x00009,
+	DPCD_ADDRESS_RECEIVE_PORT1_CAP0 = 0x0000A,
+	DPCD_ADDRESS_RECEIVE_PORT1_CAP1 = 0x0000B,
+
+	DPCD_ADDRESS_I2C_SPEED_CNTL_CAP = 0x0000C,/*1.2*/
+	DPCD_ADDRESS_EDP_CONFIG_CAP = 0x0000D,/*1.2*/
+	DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL = 0x000E,/*1.2*/
+
+	DPCD_ADDRESS_MSTM_CAP = 0x00021,/*1.2*/
+
+	/* Audio Video Sync Data Feild */
+	DPCD_ADDRESS_AV_GRANULARITY = 0x0023,
+	DPCD_ADDRESS_AUDIO_DECODE_LATENCY1 = 0x0024,
+	DPCD_ADDRESS_AUDIO_DECODE_LATENCY2 = 0x0025,
+	DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY1 = 0x0026,
+	DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY2 = 0x0027,
+	DPCD_ADDRESS_VIDEO_INTERLACED_LATENCY = 0x0028,
+	DPCD_ADDRESS_VIDEO_PROGRESSIVE_LATENCY = 0x0029,
+	DPCD_ADDRESS_AUDIO_DELAY_INSERT1 = 0x0002B,
+	DPCD_ADDRESS_AUDIO_DELAY_INSERT2 = 0x0002C,
+	DPCD_ADDRESS_AUDIO_DELAY_INSERT3 = 0x0002D,
+
+	/* Audio capability */
+	DPCD_ADDRESS_NUM_OF_AUDIO_ENDPOINTS = 0x00022,
+
+	DPCD_ADDRESS_GUID_START = 0x00030,/*1.2*/
+	DPCD_ADDRESS_GUID_END = 0x0003f,/*1.2*/
+
+	DPCD_ADDRESS_PSR_SUPPORT_VER = 0x00070,
+	DPCD_ADDRESS_PSR_CAPABILITY = 0x00071,
+
+	DPCD_ADDRESS_DWN_STRM_PORT0_CAPS = 0x00080,/*1.2a*/
+
+	/* Link Configuration Field */
+	DPCD_ADDRESS_LINK_BW_SET = 0x00100,
+	DPCD_ADDRESS_LANE_COUNT_SET = 0x00101,
+	DPCD_ADDRESS_TRAINING_PATTERN_SET = 0x00102,
+	DPCD_ADDRESS_LANE0_SET = 0x00103,
+	DPCD_ADDRESS_LANE1_SET = 0x00104,
+	DPCD_ADDRESS_LANE2_SET = 0x00105,
+	DPCD_ADDRESS_LANE3_SET = 0x00106,
+	DPCD_ADDRESS_DOWNSPREAD_CNTL = 0x00107,
+	DPCD_ADDRESS_I2C_SPEED_CNTL = 0x00109,/*1.2*/
+
+	DPCD_ADDRESS_EDP_CONFIG_SET = 0x0010A,
+	DPCD_ADDRESS_LINK_QUAL_LANE0_SET = 0x0010B,
+	DPCD_ADDRESS_LINK_QUAL_LANE1_SET = 0x0010C,
+	DPCD_ADDRESS_LINK_QUAL_LANE2_SET = 0x0010D,
+	DPCD_ADDRESS_LINK_QUAL_LANE3_SET = 0x0010E,
+
+	DPCD_ADDRESS_LANE0_SET2 = 0x0010F,/*1.2*/
+	DPCD_ADDRESS_LANE2_SET2 = 0x00110,/*1.2*/
+
+	DPCD_ADDRESS_MSTM_CNTL = 0x00111,/*1.2*/
+
+	DPCD_ADDRESS_PSR_ENABLE_CFG = 0x0170,
+
+	/* Payload Table Configuration Field 1.2 */
+	DPCD_ADDRESS_PAYLOAD_ALLOCATE_SET = 0x001C0,
+	DPCD_ADDRESS_PAYLOAD_ALLOCATE_START_TIMESLOT = 0x001C1,
+	DPCD_ADDRESS_PAYLOAD_ALLOCATE_TIMESLOT_COUNT = 0x001C2,
+
+	DPCD_ADDRESS_SINK_COUNT = 0x0200,
+	DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR = 0x0201,
+
+	/* Link / Sink Status Field */
+	DPCD_ADDRESS_LANE_01_STATUS = 0x00202,
+	DPCD_ADDRESS_LANE_23_STATUS = 0x00203,
+	DPCD_ADDRESS_LANE_ALIGN_STATUS_UPDATED = 0x0204,
+	DPCD_ADDRESS_SINK_STATUS = 0x0205,
+
+	/* Adjust Request Field */
+	DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1 = 0x0206,
+	DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3 = 0x0207,
+	DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2 = 0x020C,
+
+	/* Test Request Field */
+	DPCD_ADDRESS_TEST_REQUEST = 0x0218,
+	DPCD_ADDRESS_TEST_LINK_RATE = 0x0219,
+	DPCD_ADDRESS_TEST_LANE_COUNT = 0x0220,
+	DPCD_ADDRESS_TEST_PATTERN = 0x0221,
+	DPCD_ADDRESS_TEST_MISC1 = 0x0232,
+
+	/* Phy Test Pattern Field */
+	DPCD_ADDRESS_TEST_PHY_PATTERN = 0x0248,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0 = 0x0250,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_15_8 = 0x0251,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_23_16 = 0x0252,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_31_24 = 0x0253,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_39_32 = 0x0254,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_47_40 = 0x0255,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_55_48 = 0x0256,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_63_56 = 0x0257,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_71_64 = 0x0258,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 = 0x0259,
+
+	/* Test Response Field*/
+	DPCD_ADDRESS_TEST_RESPONSE = 0x0260,
+
+	/* Audio Test Pattern Field 1.2*/
+	DPCD_ADDRESS_TEST_AUDIO_MODE = 0x0271,
+	DPCD_ADDRESS_TEST_AUDIO_PATTERN_TYPE = 0x0272,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_1 = 0x0273,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_2 = 0x0274,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_3 = 0x0275,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_4 = 0x0276,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_5 = 0x0277,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_6 = 0x0278,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_7 = 0x0279,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_8 = 0x027A,
+
+	/* Payload Table Status Field */
+	DPCD_ADDRESS_PAYLOAD_TABLE_UPDATE_STATUS = 0x002C0,/*1.2*/
+	DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT1 = 0x002C1,/*1.2*/
+	DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT63 = 0x002FF,/*1.2*/
+
+	/* Source Device Specific Field */
+	DPCD_ADDRESS_SOURCE_DEVICE_ID_START = 0x0300,
+	DPCD_ADDRESS_SOURCE_DEVICE_ID_END = 0x0301,
+	DPCD_ADDRESS_AMD_INTERNAL_DEBUG_START       = 0x030C,
+	DPCD_ADDRESS_AMD_INTERNAL_DEBUG_END         = 0x030F,
+	DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_START    = 0x0310,
+	DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_END      = 0x037F,
+	DPCD_ADDRESS_SOURCE_RESERVED_START         = 0x0380,
+	DPCD_ADDRESS_SOURCE_RESERVED_END           = 0x03FF,
+
+	/* Sink Device Specific Field */
+	DPCD_ADDRESS_SINK_DEVICE_ID_START = 0x0400,
+	DPCD_ADDRESS_SINK_DEVICE_ID_END = 0x0402,
+	DPCD_ADDRESS_SINK_DEVICE_STR_START = 0x0403,
+	DPCD_ADDRESS_SINK_DEVICE_STR_END = 0x0408,
+	DPCD_ADDRESS_SINK_REVISION_START = 0x409,
+	DPCD_ADDRESS_SINK_REVISION_END = 0x40B,
+
+	/* Branch Device Specific Field */
+	DPCD_ADDRESS_BRANCH_DEVICE_ID_START = 0x0500,
+	DPCD_ADDRESS_BRANCH_DEVICE_ID_END = 0x0502,
+	DPCD_ADDRESS_BRANCH_DEVICE_STR_START = 0x0503,
+	DPCD_ADDRESS_BRANCH_DEVICE_STR_END = 0x0508,
+
+	DPCD_ADDRESS_POWER_STATE = 0x0600,
+
+	/* EDP related */
+	DPCD_ADDRESS_EDP_REV = 0x0700,
+	DPCD_ADDRESS_EDP_CAPABILITY = 0x0701,
+	DPCD_ADDRESS_EDP_BACKLIGHT_ADJUST_CAP = 0x0702,
+	DPCD_ADDRESS_EDP_GENERAL_CAP2 = 0x0703,
+
+	DPCD_ADDRESS_EDP_DISPLAY_CONTROL = 0x0720,
+	DPCD_ADDRESS_EDP_BACKLIGHT_SET = 0x0721,
+	DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_MSB = 0x0722,
+	DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_LSB = 0x0723,
+	DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT = 0x0724,
+	DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MIN = 0x0725,
+	DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MAX = 0x0726,
+	DPCD_ADDRESS_EDP_BACKLIGHT_CONTROL_STATUS = 0x0727,
+	DPCD_ADDRESS_EDP_BACKLIGHT_FREQ_SET = 0x0728,
+	DPCD_ADDRESS_EDP_REVERVED = 0x0729,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MSB = 0x072A,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MID = 0x072B,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_LSB = 0x072C,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MSB = 0x072D,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MID = 0x072E,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_LSB = 0x072F,
+
+	DPCD_ADDRESS_EDP_DBC_MINIMUM_BRIGHTNESS_SET = 0x0732,
+	DPCD_ADDRESS_EDP_DBC_MAXIMUM_BRIGHTNESS_SET = 0x0733,
+
+	/* Sideband MSG Buffers 1.2 */
+	DPCD_ADDRESS_DOWN_REQ_START = 0x01000,
+	DPCD_ADDRESS_DOWN_REQ_END = 0x011ff,
+
+	DPCD_ADDRESS_UP_REP_START = 0x01200,
+	DPCD_ADDRESS_UP_REP_END = 0x013ff,
+
+	DPCD_ADDRESS_DOWN_REP_START = 0x01400,
+	DPCD_ADDRESS_DOWN_REP_END = 0x015ff,
+
+	DPCD_ADDRESS_UP_REQ_START = 0x01600,
+	DPCD_ADDRESS_UP_REQ_END = 0x017ff,
+
+	/* ESI (Event Status Indicator) Field 1.2 */
+	DPCD_ADDRESS_SINK_COUNT_ESI = 0x02002,
+	DPCD_ADDRESS_DEVICE_IRQ_ESI0 = 0x02003,
+	DPCD_ADDRESS_DEVICE_IRQ_ESI1 = 0x02004,
+	/*@todo move dpcd_address_Lane01Status back here*/
+
+	DPCD_ADDRESS_PSR_ERROR_STATUS = 0x2006,
+	DPCD_ADDRESS_PSR_EVENT_STATUS = 0x2007,
+	DPCD_ADDRESS_PSR_SINK_STATUS = 0x2008,
+	DPCD_ADDRESS_PSR_DBG_REGISTER0 = 0x2009,
+	DPCD_ADDRESS_PSR_DBG_REGISTER1 = 0x200A,
+
+	/* Travis specific addresses */
+	DPCD_ADDRESS_TRAVIS_SINK_DEV_SEL = 0x5f0,
+	DPCD_ADDRESS_TRAVIS_SINK_ACCESS_OFFSET	= 0x5f1,
+	DPCD_ADDRESS_TRAVIS_SINK_ACCESS_REG = 0x5f2,
+};
+
+enum dpcd_revision {
+	DPCD_REV_10 = 0x10,
+	DPCD_REV_11 = 0x11,
+	DPCD_REV_12 = 0x12
+};
+
+enum dp_pwr_state {
+	DP_PWR_STATE_D0 = 1,/* direct HW translation! */
+	DP_PWR_STATE_D3
+};
+
+/* these are the types stored at DOWNSTREAMPORT_PRESENT */
+enum dpcd_downstream_port_type {
+	DOWNSTREAM_DP = 0,
+	DOWNSTREAM_VGA,
+	DOWNSTREAM_DVI_HDMI,
+	DOWNSTREAM_NONDDC /* has no EDID (TV,CV) */
+};
+
+enum dpcd_link_test_patterns {
+	LINK_TEST_PATTERN_NONE = 0,
+	LINK_TEST_PATTERN_COLOR_RAMP,
+	LINK_TEST_PATTERN_VERTICAL_BARS,
+	LINK_TEST_PATTERN_COLOR_SQUARES
+};
+
+enum dpcd_test_color_format {
+	TEST_COLOR_FORMAT_RGB = 0,
+	TEST_COLOR_FORMAT_YCBCR422,
+	TEST_COLOR_FORMAT_YCBCR444
+};
+
+enum dpcd_test_bit_depth {
+	TEST_BIT_DEPTH_6 = 0,
+	TEST_BIT_DEPTH_8,
+	TEST_BIT_DEPTH_10,
+	TEST_BIT_DEPTH_12,
+	TEST_BIT_DEPTH_16
+};
+
+/* PHY (encoder) test patterns
+The order of test patterns follows DPCD register PHY_TEST_PATTERN (0x248) */
+enum dpcd_phy_test_patterns {
+	PHY_TEST_PATTERN_NONE = 0,
+	PHY_TEST_PATTERN_D10_2,
+	PHY_TEST_PATTERN_SYMBOL_ERROR,
+	PHY_TEST_PATTERN_PRBS7,
+	PHY_TEST_PATTERN_80BIT_CUSTOM,/* For DP1.2 only */
+	PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE/* For DP1.2 only */
+};
+
+enum dpcd_test_dyn_range {
+	TEST_DYN_RANGE_VESA = 0,
+	TEST_DYN_RANGE_CEA
+};
+
+enum dpcd_audio_test_pattern {
+	AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0,/* direct HW translation */
+	AUDIO_TEST_PATTERN_SAWTOOTH
+};
+
+enum dpcd_audio_sampling_rate {
+	AUDIO_SAMPLING_RATE_32KHZ = 0,/* direct HW translation */
+	AUDIO_SAMPLING_RATE_44_1KHZ,
+	AUDIO_SAMPLING_RATE_48KHZ,
+	AUDIO_SAMPLING_RATE_88_2KHZ,
+	AUDIO_SAMPLING_RATE_96KHZ,
+	AUDIO_SAMPLING_RATE_176_4KHZ,
+	AUDIO_SAMPLING_RATE_192KHZ
+};
+
+enum dpcd_audio_channels {
+	AUDIO_CHANNELS_1 = 0,/* direct HW translation */
+	AUDIO_CHANNELS_2,
+	AUDIO_CHANNELS_3,
+	AUDIO_CHANNELS_4,
+	AUDIO_CHANNELS_5,
+	AUDIO_CHANNELS_6,
+	AUDIO_CHANNELS_7,
+	AUDIO_CHANNELS_8,
+
+	AUDIO_CHANNELS_COUNT
+};
+
+enum dpcd_audio_test_pattern_periods {
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_NOTUSED = 0,/* direct HW translation */
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_3,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_6,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_12,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_24,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_48,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_96,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_192,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_384,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_768,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_1536
+};
+
+/* This enum is for programming DPCD TRAINING_PATTERN_SET */
+enum dpcd_training_patterns {
+	DPCD_TRAINING_PATTERN_VIDEOIDLE = 0,/* direct HW translation! */
+	DPCD_TRAINING_PATTERN_1,
+	DPCD_TRAINING_PATTERN_2,
+	DPCD_TRAINING_PATTERN_3
+};
+
+/* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus
+It defines the possible PSR states. */
+enum dpcd_psr_sink_states {
+	PSR_SINK_STATE_INACTIVE = 0,
+	PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SOURCE_TIMING = 1,
+	PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB = 2,
+	PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SINK_TIMING = 3,
+	PSR_SINK_STATE_ACTIVE_CAPTURE_TIMING_RESYNC = 4,
+	PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7,
+};
+
+/* This enum defines the Panel's eDP revision at DPCD 700h
+ * 00h = eDP v1.1 or lower
+ * 01h = eDP v1.2
+ * 02h = eDP v1.3 (PSR support starts here)
+ * 03h = eDP v1.4
+ * If unknown revision, treat as eDP v1.1, meaning least functionality set.
+ * This enum has values matched to eDP spec, thus values should not change.
+ */
+enum dpcd_edp_revision {
+	DPCD_EDP_REVISION_EDP_V1_1 = 0,
+	DPCD_EDP_REVISION_EDP_V1_2 = 1,
+	DPCD_EDP_REVISION_EDP_V1_3 = 2,
+	DPCD_EDP_REVISION_EDP_V1_4 = 3,
+	DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1,
+};
+
+union dpcd_rev {
+	struct {
+		uint8_t MINOR:4;
+		uint8_t MAJOR:4;
+	} bits;
+	uint8_t raw;
+};
+
+union max_lane_count {
+	struct {
+		uint8_t MAX_LANE_COUNT:5;
+		uint8_t POST_LT_ADJ_REQ_SUPPORTED:1;
+		uint8_t TPS3_SUPPORTED:1;
+		uint8_t ENHANCED_FRAME_CAP:1;
+	} bits;
+	uint8_t raw;
+};
+
+union max_down_spread {
+	struct {
+		uint8_t MAX_DOWN_SPREAD:1;
+		uint8_t RESERVED:5;
+		uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1;
+		uint8_t RESERVED1:1;
+	} bits;
+	uint8_t raw;
+};
+
+union mstm_cap {
+	struct {
+		uint8_t MST_CAP:1;
+		uint8_t RESERVED:7;
+	} bits;
+	uint8_t raw;
+};
+
+union mstm_cntl {
+	struct {
+		uint8_t MST_EN:1;
+		uint8_t UP_REQ_EN:1;
+		uint8_t UPSTREAM_IS_SRC:1;
+		uint8_t RESERVED:5;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_count_set {
+	struct {
+		uint8_t LANE_COUNT_SET:5;
+		uint8_t POST_LT_ADJ_REQ_GRANTED:1;
+		uint8_t RESERVED:1;
+		uint8_t ENHANCED_FRAMING:1;
+	} bits;
+	uint8_t raw;
+};
+
+/* for DPCD_ADDRESS_I2C_SPEED_CNTL_CAP
+ * and DPCD_ADDRESS_I2C_SPEED_CNTL
+ */
+union i2c_speed {
+	struct {
+		uint8_t _1KBPS:1;
+		uint8_t _5KBPS:1;
+		uint8_t _10KBPS:1;
+		uint8_t _100KBPS:1;
+		uint8_t _400KBPS:1;
+		uint8_t _1MBPS:1;
+		uint8_t reserved:2;
+	} bits;
+	uint8_t raw;
+};
+
+union payload_table_update_status {
+	struct {
+		uint8_t VC_PAYLOAD_TABLE_UPDATED:1;
+		uint8_t ACT_HANDLED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union device_irq_esi_0 {
+	struct {
+		uint8_t REMOTE_CONTROL_CMD_PENDING:1;
+		uint8_t AUTOMATED_TEST_REQUEST:1;
+		uint8_t CP_IRQ:1;
+		uint8_t MCCS_IRQ:1;
+		uint8_t DOWN_REP_MSG_RDY:1;
+		uint8_t UP_REQ_MSG_RDY:1;
+		uint8_t SINK_SPECIFIC_IRQ:1;
+		uint8_t RESERVED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_status {
+	struct {
+		uint8_t CR_DONE_0:1;
+		uint8_t CHANNEL_EQ_DONE_0:1;
+		uint8_t SYMBOL_LOCKED_0:1;
+		uint8_t RESERVED0:1;
+		uint8_t CR_DONE_1:1;
+		uint8_t CHANNEL_EQ_DONE_1:1;
+		uint8_t SYMBOL_LOCKED_1:1;
+		uint8_t RESERVED_1:1;
+	} bits;
+	uint8_t raw;
+};
+
+union device_service_irq {
+	struct {
+		uint8_t REMOTE_CONTROL_CMD_PENDING:1;
+		uint8_t AUTOMATED_TEST:1;
+		uint8_t CP_IRQ:1;
+		uint8_t MCCS_IRQ:1;
+		uint8_t DOWN_REP_MSG_RDY:1;
+		uint8_t UP_REQ_MSG_RDY:1;
+		uint8_t SINK_SPECIFIC:1;
+		uint8_t reserved:1;
+	} bits;
+	uint8_t raw;
+};
+
+union downstream_port {
+	struct {
+		uint8_t PRESENT:1;
+		uint8_t TYPE:2;
+		uint8_t FORMAT_CONV:1;
+		uint8_t DETAILED_CAPS:1;
+		uint8_t RESERVED:3;
+	} bits;
+	uint8_t raw;
+};
+
+union sink_count {
+	struct {
+		uint8_t SINK_COUNT:6;
+		uint8_t CPREADY:1;
+		uint8_t RESERVED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_align_status_updated {
+	struct {
+		uint8_t INTERLANE_ALIGN_DONE:1;
+		uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1;
+		uint8_t RESERVED:4;
+		uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1;
+		uint8_t LINK_STATUS_UPDATED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_adjust {
+	struct {
+		uint8_t VOLTAGE_SWING_LANE:2;
+		uint8_t PRE_EMPHASIS_LANE:2;
+		uint8_t RESERVED:4;
+	} bits;
+	uint8_t raw;
+};
+
+/* Automated test structures */
+union test_request {
+	struct {
+		uint8_t LINK_TRAINING:1;
+		uint8_t LINK_TEST_PATTERN:1;
+		uint8_t EDID_READ:1;
+		uint8_t PHY_TEST_PATTERN:1;
+		uint8_t AUDIO_TEST_PATTERN:1;
+		uint8_t AUDIO_TEST_NO_VIDEO:1;
+		uint8_t RESERVED:1;
+		uint8_t TEST_STEREO_3D:1;
+	} bits;
+	uint8_t raw;
+};
+
+union test_response {
+	struct {
+		uint8_t ACK:1;
+		uint8_t NO_ACK:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union link_test_pattern {
+	struct {
+		uint8_t PATTERN:2;/*DpcdLinkTestPatterns*/
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union test_misc {
+	struct dpcd_test_misc_bits {
+		uint8_t SYNC_CLOCK:1;
+		uint8_t CLR_FORMAT:2;/*DpcdTestColorFormat*/
+		uint8_t DYN_RANGE:1;/*DpcdTestDynRange*/
+		uint8_t YCBCR:1;/*DpcdTestYCbCrStandard*/
+		uint8_t BPC:3;/*DpcdTestBitDepth*/
+	} bits;
+	uint8_t raw;
+};
+
+union phy_test_pattern {
+	struct {
+		/* This field is 2 bits for DP1.1 and 3 bits for DP1.2.*/
+		uint8_t PATTERN:3;
+		uint8_t RESERVED:5;/* BY spec, bit7:2 is 0 for DP1.1.*/
+	} bits;
+	uint8_t raw;
+};
+
+union audio_test_mode {
+	struct {
+		uint8_t SAMPLING_RATE:4;
+		uint8_t CHANNEL_COUNT:4;
+	} bits;
+	uint8_t raw;
+};
+
+union audio_tes_tpattern_period {
+	struct {
+		uint8_t PATTERN_PERIOD:4;
+		uint8_t RESERVED:4;
+	} bits;
+	uint8_t raw;
+};
+
+struct audio_test_pattern_type {
+	uint8_t value;
+};
+
+union dpcd_training_pattern {
+	struct {
+		uint8_t TRAINING_PATTERN_SET:2;
+		uint8_t LINK_QUAL_PATTERN_SET:2;
+		uint8_t RECOVERED_CLOCK_OUT_EN:1;
+		uint8_t SCRAMBLING_DISABLE:1;
+		uint8_t RESERVED:2;
+	} bits;
+	uint8_t raw;
+};
+
+/* Training Lane is used to configure downstream DP device's voltage swing
+and pre-emphasis levels*/
+/* The DPCD addresses are from 0x103 to 0x106*/
+union dpcd_training_lane {
+	struct {
+		uint8_t VOLTAGE_SWING_SET:2;
+		uint8_t MAX_SWING_REACHED:1;
+		uint8_t PRE_EMPHASIS_SET:2;
+		uint8_t MAX_PRE_EMPHASIS_REACHED:1;
+		uint8_t RESERVED:2;
+	} bits;
+	uint8_t raw;
+};
+
+/*Training Lane Set 2 is used to configure downstream DP device's
+post cursor 2 level of Training Pattern 2 or 3*/
+/* The DPCD addresses are 0x10F (TRAINING_LANE0_1_SET2)
+and 0x110 (TRAINING_LANE2_3_SET2)*/
+union dpcd_training_lane_set2 {
+	struct {
+		uint8_t POST_CURSOR2_SET:2;
+		uint8_t MAX_POST_CURSOR2_REACHED:1;
+		uint8_t RESERVED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union dpcd_psr_configuration {
+	struct {
+		uint8_t ENABLE:1;
+		uint8_t TRANSMITTER_ACTIVE_IN_PSR:1;
+		uint8_t CRC_VERIFICATION:1;
+		uint8_t FRAME_CAPTURE_INDICATION:1;
+		uint8_t LINE_CAPTURE_INDICATION:1;
+		uint8_t IRQ_HPD_WITH_CRC_ERROR:1;
+		uint8_t RESERVED:2;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_error_status {
+	struct {
+		uint8_t LINK_CRC_ERROR:1;
+		uint8_t RFB_STORAGE_ERROR:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_event_status_ind {
+	struct {
+		uint8_t SINK_PSR_CAP_CHANGE:1;
+		uint8_t RESERVED:7;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_sink_psr_status {
+	struct {
+		uint8_t SINK_SELF_REFRESH_STATUS:3;
+		uint8_t RESERVED:5;
+	} bits;
+	uint8_t raw;
+};
+
+/* EDP related 0x701 */
+union edp_generial_cap1 {
+	struct {
+		uint8_t TCON_BACKLIGHT_ADJUSTMENT_CAPABLE:1;
+		uint8_t BACKLIGHT_PIN_ENABLE_CAPABLE:1;
+		uint8_t BACKLIGHT_AUX_ENABLE_CAPABLE:1;
+		uint8_t PANEL_SELFTEST_PIN_ENABLE_CAPABLE:1;
+		uint8_t BACKLIGHT_SELFTEST_AUX_ENABLE_CAPABLE:1;
+		uint8_t FRC_ENABLE_CAPABLE:1;
+		uint8_t COLOR_ENGINE_CAPABLE:1;
+		/*bit 7, pane can be controlled by 0x600*/
+		uint8_t SET_POWER_CAPABLE:1;
+	} bits;
+	uint8_t raw;
+};
+
+/* TMDS-converter related */
+union dwnstream_port_caps_byte0 {
+	struct {
+		uint8_t DWN_STRM_PORTX_TYPE:3;
+		uint8_t DWN_STRM_PORTX_HPD:1;
+		uint8_t RESERVERD:4;
+	} bits;
+	uint8_t raw;
+};
+
+/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/
+enum dpcd_downstream_port_detailed_type {
+	DOWN_STREAM_DETAILED_DP = 0,
+	DOWN_STREAM_DETAILED_VGA,
+	DOWN_STREAM_DETAILED_DVI,
+	DOWN_STREAM_DETAILED_HDMI,
+	DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/
+	DOWN_STREAM_DETAILED_DP_PLUS_PLUS
+};
+
+union dwnstream_port_caps_byte2 {
+	struct {
+		uint8_t MAX_BITS_PER_COLOR_COMPONENT:2;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union dp_downstream_port_present {
+	uint8_t byte;
+	struct {
+		uint8_t PORT_PRESENT:1;
+		uint8_t PORT_TYPE:2;
+		uint8_t FMT_CONVERSION:1;
+		uint8_t DETAILED_CAPS:1;
+		uint8_t RESERVED:3;
+	} fields;
+};
+
+
+union dwnstream_port_caps_byte3_dvi {
+	struct {
+		uint8_t RESERVED1:1;
+		uint8_t DUAL_LINK:1;
+		uint8_t HIGH_COLOR_DEPTH:1;
+		uint8_t RESERVED2:5;
+	} bits;
+	uint8_t raw;
+};
+
+union dwnstream_port_caps_byte3_hdmi {
+	struct {
+		uint8_t FRAME_SEQ_TO_FRAME_PACK:1;
+		uint8_t RESERVED:7;
+	} bits;
+	uint8_t raw;
+};
+
+/*4-byte structure for detailed capabilities of a down-stream port
+(DP-to-TMDS converter).*/
+union dwnstream_portx_caps {
+	struct {
+		union dwnstream_port_caps_byte0 byte0;
+		uint8_t max_tmds_clk;/* byte1 */
+		union dwnstream_port_caps_byte2 byte2;
+
+		union {
+			union dwnstream_port_caps_byte3_dvi byte_dvi;
+			union dwnstream_port_caps_byte3_hdmi byte_hdmi;
+		} byte3;
+	} bytes;
+	uint8_t raw[4];
+};
+
+union sink_status {
+	struct {
+		uint8_t RX_PORT0_STATUS:1;
+		uint8_t RX_PORT1_STATUS:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+/*6-byte structure corresponding to 6 registers (200h-205h)
+read during handling of HPD-IRQ*/
+union hpd_irq_data {
+	struct {
+		union sink_count sink_cnt;/* 200h */
+		union device_service_irq device_service_irq;/* 201h */
+		union lane_status lane01_status;/* 202h */
+		union lane_status lane23_status;/* 203h */
+		union lane_align_status_updated lane_status_updated;/* 204h */
+		union sink_status sink_status;
+	} bytes;
+	uint8_t raw[6];
+};
+
+union down_stream_port_count {
+	struct {
+		uint8_t DOWN_STR_PORT_COUNT:4;
+		uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/
+		/*Bit 6 = MSA_TIMING_PAR_IGNORED
+		0 = Sink device requires the MSA timing parameters
+		1 = Sink device is capable of rendering incoming video
+		 stream without MSA timing parameters*/
+		uint8_t IGNORE_MSA_TIMING_PARAM:1;
+		/*Bit 7 = OUI Support
+		0 = OUI not supported
+		1 = OUI supported
+		(OUI and Device Identification mandatory for DP 1.2)*/
+		uint8_t OUI_SUPPORT:1;
+	} bits;
+	uint8_t raw;
+};
+
+union down_spread_ctrl {
+	struct {
+		uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/
+	/* Bits 4 = SPREAD_AMP. Spreading amplitude
+	0 = Main link signal is not downspread
+	1 = Main link signal is downspread <= 0.5%
+	with frequency in the range of 30kHz ~ 33kHz*/
+		uint8_t SPREAD_AMP:1;
+		uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/
+	/*Bit 7 = MSA_TIMING_PAR_IGNORE_EN
+	0 = Source device will send valid data for the MSA Timing Params
+	1 = Source device may send invalid data for these MSA Timing Params*/
+		uint8_t IGNORE_MSA_TIMING_PARAM:1;
+	} bits;
+	uint8_t raw;
+};
+
+union dpcd_edp_config {
+	struct {
+		uint8_t PANEL_MODE_EDP:1;
+		uint8_t FRAMING_CHANGE_ENABLE:1;
+		uint8_t RESERVED:5;
+		uint8_t PANEL_SELF_TEST_ENABLE:1;
+	} bits;
+	uint8_t raw;
+};
+
+struct dp_device_vendor_id {
+	uint8_t ieee_oui[3];/*24-bit IEEE OUI*/
+	uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/
+};
+
+struct dp_sink_hw_fw_revision {
+	uint8_t ieee_hw_rev;
+	uint8_t ieee_fw_rev[2];
+};
+
+/*DPCD register of DP receiver capability field bits-*/
+union edp_configuration_cap {
+	struct {
+		uint8_t ALT_SCRAMBLER_RESET:1;
+		uint8_t FRAMING_CHANGE:1;
+		uint8_t RESERVED:1;
+		uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1;
+		uint8_t RESERVED2:4;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_capabilities {
+	struct {
+		uint8_t EXIT_LT_NOT_REQ:1;
+		uint8_t RFB_SETUP_TIME:3;
+		uint8_t RESERVED:4;
+	} bits;
+	uint8_t raw;
+};
+
+#endif /* __DAL_DPCD_DEFS_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/encoder_interface.h b/drivers/gpu/drm/amd/dal/include/encoder_interface.h
new file mode 100644
index 000000000000..5fbf816cf96e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/encoder_interface.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of enc software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and enc permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ENCODER_INTERFACE_H__
+#define __DAL_ENCODER_INTERFACE_H__
+
+#include "encoder_types.h"
+#include "adapter_service_interface.h"
+#include "fixed31_32.h"
+
+enum encoder_result {
+	ENCODER_RESULT_OK,
+	ENCODER_RESULT_ERROR,
+	ENCODER_RESULT_NOBANDWIDTH,
+	ENCODER_RESULT_SINKCONNECTIVITYCHANGED,
+};
+
+struct encoder_init_data {
+	struct adapter_service *adapter_service;
+	enum channel_id channel;
+	struct graphics_object_id connector;
+	enum hpd_source_id hpd_source;
+	/* TODO: in DAL2, here was pointer to EventManagerInterface */
+	struct graphics_object_id encoder;
+	struct dc_context *ctx;
+};
+
+/* forward declaration */
+struct encoder;
+
+struct encoder *dal_encoder_create(
+	const struct encoder_init_data *init_data);
+
+/* access graphics object base */
+const struct graphics_object_id dal_encoder_get_graphics_object_id(
+	const struct encoder *enc);
+
+/*
+ * Signal types support
+ */
+uint32_t dal_encoder_enumerate_input_signals(
+	const struct encoder *enc);
+uint32_t dal_encoder_enumerate_output_signals(
+	const struct encoder *enc);
+bool dal_encoder_is_input_signal_supported(
+	const struct encoder *enc,
+	enum signal_type signal);
+bool dal_encoder_is_output_signal_supported(
+	const struct encoder *enc,
+	enum signal_type signal);
+void dal_encoder_set_input_signals(
+	struct encoder *enc,
+	uint32_t signals);
+void dal_encoder_set_output_signals(
+	struct encoder *enc,
+	uint32_t signals);
+
+/*
+ * Programming interface
+ */
+/* perform power-up sequence (boot up, resume, recovery) */
+enum encoder_result dal_encoder_power_up(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* perform power-down (shut down, stand-by */
+enum encoder_result dal_encoder_power_down(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* setup encoder block (DIG, DVO, DAC), does not enables encoder */
+enum encoder_result dal_encoder_setup(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* activate transmitter,
+ * do preparation before enables the actual stream output */
+enum encoder_result dal_encoder_pre_enable_output(
+	struct encoder *enc,
+	const struct encoder_pre_enable_output_param *param);
+/* activate transmitter, enables actual stream output */
+enum encoder_result dal_encoder_enable_output(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* deactivate transmitter, disables stream output */
+enum encoder_result dal_encoder_disable_output(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* output blank data,
+ *prevents output of the actual surface data on active transmitter */
+enum encoder_result dal_encoder_blank(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* stop sending blank data,
+ * output the actual surface data on active transmitter */
+enum encoder_result dal_encoder_unblank(
+	struct encoder *enc,
+	const struct encoder_unblank_param *param);
+/* setup stereo signal from given controller */
+enum encoder_result dal_encoder_setup_stereo(
+	struct encoder *enc,
+	const struct encoder_3d_setup *setup);
+/* enable HSync/VSync output from given controller */
+enum encoder_result dal_encoder_enable_sync_output(
+	struct encoder *enc,
+	enum sync_source src);
+/* disable HSync/VSync output */
+enum encoder_result dal_encoder_disable_sync_output(
+	struct encoder *enc);
+/* action of encoder before DDC transaction */
+enum encoder_result dal_encoder_pre_ddc(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* action of encoder after DDC transaction */
+enum encoder_result dal_encoder_post_ddc(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* CRT DDC EDID polling interrupt interface */
+enum encoder_result dal_encoder_update_implementation(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* set test pattern signal */
+enum encoder_result dal_encoder_set_dp_phy_pattern(
+	struct encoder *enc,
+	const struct encoder_set_dp_phy_pattern_param *param);
+
+void dal_encoder_release_hw(struct encoder *enc);
+/*
+ * Information interface
+ */
+/* check whether sink is present based on SENSE detection,
+ * analog encoders will return true */
+bool dal_encoder_is_sink_present(
+	struct encoder *enc,
+	struct graphics_object_id downstream);
+/* detect load on the sink,
+ * for analog signal,
+ * load detection will be called for the specified signal */
+enum signal_type dal_encoder_detect_load(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* detect output sink type,
+ * for digital perform sense detection,
+ * for analog return encoder's signal type */
+enum signal_type dal_encoder_detect_sink(
+	struct encoder *enc,
+	struct graphics_object_id downstream);
+/* get transmitter id */
+enum transmitter dal_encoder_get_transmitter(
+	const struct encoder *enc);
+/*  */
+enum transmitter dal_encoder_get_paired_transmitter(
+	const struct encoder *enc);
+/*  */
+enum physical_phy_id dal_encoder_get_phy(
+	const struct encoder *enc);
+/*  */
+enum physical_phy_id dal_encoder_get_paired_phy(
+	const struct encoder *enc);
+/* reports if the encoder supports given link settings */
+bool dal_encoder_is_link_settings_supported(
+	struct encoder *enc,
+	const struct link_settings *link_settings);
+/* options and features supported by encoder */
+struct encoder_feature_support dal_encoder_get_supported_features(
+	const struct encoder *enc);
+/* reports list of supported stream engines */
+union supported_stream_engines dal_encoder_get_supported_stream_engines(
+	const struct encoder *enc);
+/* reports preferred stream engine */
+enum engine_id dal_encoder_get_preferred_stream_engine(
+	const struct encoder *enc);
+/* reports whether clock source can be used with enc encoder */
+bool dal_encoder_is_clock_source_supported(
+	const struct encoder *enc,
+	enum clock_source_id clock_source);
+/* check encoder capabilities to confirm
+ * specified timing is in the encoder limits
+ * when outputting certain signal */
+enum encoder_result dal_encoder_validate_output(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* retrieves sync source which outputs VSync signal from encoder */
+enum sync_source dal_encoder_get_vsync_output_source(
+	const struct encoder *enc);
+/*
+ * Adjustments
+ */
+/* update AVI info frame */
+void dal_encoder_update_info_frame(
+	struct encoder *enc,
+	const struct encoder_info_frame_param *param);
+/*  */
+void dal_encoder_stop_info_frame(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/*  */
+enum encoder_result dal_encoder_set_lcd_backlight_level(
+	struct encoder *enc,
+	uint32_t level);
+/* backlight control interface */
+enum encoder_result dal_encoder_backlight_control(
+	struct encoder *enc,
+	bool enable);
+/*
+ * DP MST programming
+ */
+/* update payload slot allocation for each DP MST stream */
+enum encoder_result dal_encoder_update_mst_alloc_table(
+	struct encoder *enc,
+	const struct dp_mst_stream_allocation_table *table,
+	bool is_removal);
+/* enable virtual channel stream with throttled value X.Y */
+enum encoder_result dal_encoder_enable_stream(
+	struct encoder *enc,
+	enum engine_id engine,
+	struct fixed31_32 throttled_vcp_size);
+/* disable virtual channel stream */
+enum encoder_result dal_encoder_disable_stream(
+	struct encoder *enc,
+	enum engine_id engine);
+void dal_encoder_set_multi_path(struct encoder *enc, bool is_multi_path);
+/*
+ * Test harness
+ */
+/* check whether Test Pattern enabled */
+bool dal_encoder_is_test_pattern_enabled(
+	struct encoder *enc,
+	enum engine_id engine);
+/* set lane parameters */
+enum encoder_result dal_encoder_set_lane_settings(
+	struct encoder *enc,
+	const struct encoder_context *ctx,
+	const struct link_training_settings *link_settings);
+/* get lane parameters */
+enum encoder_result dal_encoder_get_lane_settings(
+	struct encoder *enc,
+	const struct encoder_context *ctx,
+	struct link_training_settings *link_settings);
+/* enable master clock of HPD interrupt */
+void dal_encoder_enable_hpd(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* disable all HPD interrupts */
+void dal_encoder_disable_hpd(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+
+/* get current HW state - used for optimization code path only */
+enum clock_source_id dal_encoder_get_active_clock_source(
+	const struct encoder *enc);
+enum engine_id dal_encoder_get_active_engine(
+	const struct encoder *enc);
+
+/* destroy encoder instance */
+void dal_encoder_destroy(
+	struct encoder **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/fixed31_32.h b/drivers/gpu/drm/amd/dal/include/fixed31_32.h
new file mode 100644
index 000000000000..507f9f639099
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/fixed31_32.h
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_FIXED31_32_H__
+#define __DAL_FIXED31_32_H__
+
+/*
+ * @brief
+ * Arithmetic operations on real numbers
+ * represented as fixed-point numbers.
+ * There are: 1 bit for sign,
+ * 31 bit for integer part,
+ * 32 bits for fractional part.
+ *
+ * @note
+ * Currently, overflows and underflows are asserted;
+ * no special result returned.
+ */
+
+struct fixed31_32 {
+	int64_t value;
+};
+
+/*
+ * @brief
+ * Useful constants
+ */
+
+static const struct fixed31_32 dal_fixed31_32_zero = { 0 };
+static const struct fixed31_32 dal_fixed31_32_epsilon = { 1LL };
+static const struct fixed31_32 dal_fixed31_32_half = { 0x80000000LL };
+static const struct fixed31_32 dal_fixed31_32_one = { 0x100000000LL };
+
+static const struct fixed31_32 dal_fixed31_32_pi = { 13493037705LL };
+static const struct fixed31_32 dal_fixed31_32_two_pi = { 26986075409LL };
+static const struct fixed31_32 dal_fixed31_32_e = { 11674931555LL };
+static const struct fixed31_32 dal_fixed31_32_ln2 = { 2977044471LL };
+static const struct fixed31_32 dal_fixed31_32_ln2_div_2 = { 1488522236LL };
+
+/*
+ * @brief
+ * Initialization routines
+ */
+
+/*
+ * @brief
+ * result = numerator / denominator
+ */
+struct fixed31_32 dal_fixed31_32_from_fraction(
+	int64_t numerator,
+	int64_t denominator);
+
+/*
+ * @brief
+ * result = arg
+ */
+struct fixed31_32 dal_fixed31_32_from_int(
+	int64_t arg);
+
+/*
+ * @brief
+ * Unary operators
+ */
+
+/*
+ * @brief
+ * result = -arg
+ */
+struct fixed31_32 dal_fixed31_32_neg(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = abs(arg) := (arg >= 0) ? arg : -arg
+ */
+struct fixed31_32 dal_fixed31_32_abs(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Binary relational operators
+ */
+
+/*
+ * @brief
+ * result = arg1 < arg2
+ */
+bool dal_fixed31_32_lt(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = arg1 <= arg2
+ */
+bool dal_fixed31_32_le(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = arg1 == arg2
+ */
+bool dal_fixed31_32_eq(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2
+ */
+struct fixed31_32 dal_fixed31_32_min(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1
+ */
+struct fixed31_32 dal_fixed31_32_max(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ *          | min_value, when arg <= min_value
+ * result = | arg, when min_value < arg < max_value
+ *          | max_value, when arg >= max_value
+ */
+struct fixed31_32 dal_fixed31_32_clamp(
+	struct fixed31_32 arg,
+	struct fixed31_32 min_value,
+	struct fixed31_32 max_value);
+
+/*
+ * @brief
+ * Binary shift operators
+ */
+
+/*
+ * @brief
+ * result = arg << shift
+ */
+struct fixed31_32 dal_fixed31_32_shl(
+	struct fixed31_32 arg,
+	uint8_t shift);
+
+/*
+ * @brief
+ * result = arg >> shift
+ */
+struct fixed31_32 dal_fixed31_32_shr(
+	struct fixed31_32 arg,
+	uint8_t shift);
+
+/*
+ * @brief
+ * Binary additive operators
+ */
+
+/*
+ * @brief
+ * result = arg1 + arg2
+ */
+struct fixed31_32 dal_fixed31_32_add(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = arg1 - arg2
+ */
+struct fixed31_32 dal_fixed31_32_sub_int(
+	struct fixed31_32 arg1,
+	int32_t arg2);
+
+/*
+ * @brief
+ * result = arg1 - arg2
+ */
+struct fixed31_32 dal_fixed31_32_sub(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * Binary multiplicative operators
+ */
+
+/*
+ * @brief
+ * result = arg1 * arg2
+ */
+struct fixed31_32 dal_fixed31_32_mul_int(
+	struct fixed31_32 arg1,
+	int32_t arg2);
+
+/*
+ * @brief
+ * result = arg1 * arg2
+ */
+struct fixed31_32 dal_fixed31_32_mul(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = square(arg) := arg * arg
+ */
+struct fixed31_32 dal_fixed31_32_sqr(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = arg1 / arg2
+ */
+struct fixed31_32 dal_fixed31_32_div_int(
+	struct fixed31_32 arg1,
+	int64_t arg2);
+
+/*
+ * @brief
+ * result = arg1 / arg2
+ */
+struct fixed31_32 dal_fixed31_32_div(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * Reciprocal function
+ */
+
+/*
+ * @brief
+ * result = reciprocal(arg) := 1 / arg
+ *
+ * @note
+ * No special actions taken in case argument is zero.
+ */
+struct fixed31_32 dal_fixed31_32_recip(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Trigonometric functions
+ */
+
+/*
+ * @brief
+ * result = sinc(arg) := sin(arg) / arg
+ *
+ * @note
+ * Argument specified in radians,
+ * internally it's normalized to [-2pi...2pi] range.
+ */
+struct fixed31_32 dal_fixed31_32_sinc(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = sin(arg)
+ *
+ * @note
+ * Argument specified in radians,
+ * internally it's normalized to [-2pi...2pi] range.
+ */
+struct fixed31_32 dal_fixed31_32_sin(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = cos(arg)
+ *
+ * @note
+ * Argument specified in radians
+ * and should be in [-2pi...2pi] range -
+ * passing arguments outside that range
+ * will cause incorrect result!
+ */
+struct fixed31_32 dal_fixed31_32_cos(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Transcendent functions
+ */
+
+/*
+ * @brief
+ * result = exp(arg)
+ *
+ * @note
+ * Currently, function is verified for abs(arg) <= 1.
+ */
+struct fixed31_32 dal_fixed31_32_exp(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = log(arg)
+ *
+ * @note
+ * Currently, abs(arg) should be less than 1.
+ * No normalization is done.
+ * Currently, no special actions taken
+ * in case of invalid argument(s). Take care!
+ */
+struct fixed31_32 dal_fixed31_32_log(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Power function
+ */
+
+/*
+ * @brief
+ * result = pow(arg1, arg2)
+ *
+ * @note
+ * Currently, abs(arg1) should be less than 1. Take care!
+ */
+struct fixed31_32 dal_fixed31_32_pow(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * Rounding functions
+ */
+
+/*
+ * @brief
+ * result = floor(arg) := greatest integer lower than or equal to arg
+ */
+int32_t dal_fixed31_32_floor(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = round(arg) := integer nearest to arg
+ */
+int32_t dal_fixed31_32_round(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = ceil(arg) := lowest integer greater than or equal to arg
+ */
+int32_t dal_fixed31_32_ceil(
+	struct fixed31_32 arg);
+
+/* the following two function are used in scaler hw programming to convert fixed
+ * point value to format 2 bits from integer part and 19 bits from fractional
+ * part. The same applies for u0d19, 0 bits from integer part and 19 bits from
+ * fractional
+ */
+
+uint32_t dal_fixed31_32_u2d19(
+	struct fixed31_32 arg);
+
+uint32_t dal_fixed31_32_u0d19(
+	struct fixed31_32 arg);
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/fixed32_32.h b/drivers/gpu/drm/amd/dal/include/fixed32_32.h
new file mode 100644
index 000000000000..f393e953e91a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/fixed32_32.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_FIXED32_32_H__
+#define __DAL_FIXED32_32_H__
+
+#include "dm_services_types.h"
+
+struct fixed32_32 {
+	uint64_t value;
+};
+
+static const struct fixed32_32 dal_fixed32_32_zero = { 0 };
+static const struct fixed32_32 dal_fixed32_32_one = { 0x100000000LL };
+static const struct fixed32_32 dal_fixed32_32_half = { 0x80000000LL };
+
+struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d);
+struct fixed32_32 dal_fixed32_32_from_int(uint32_t value);
+struct fixed32_32 dal_fixed32_32_add(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_add_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_sub(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_sub_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_mul(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_mul_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_div(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_div_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_min(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_max(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs);
+bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs);
+bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs);
+bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs);
+bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs);
+bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs);
+bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs);
+uint32_t dal_fixed32_32_ceil(struct fixed32_32 value);
+uint32_t dal_fixed32_32_floor(struct fixed32_32 value);
+uint32_t dal_fixed32_32_round(struct fixed32_32 value);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/gpio_interface.h b/drivers/gpu/drm/amd/dal/include/gpio_interface.h
new file mode 100644
index 000000000000..a084d7923e2f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/gpio_interface.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_INTERFACE_H__
+#define __DAL_GPIO_INTERFACE_H__
+
+#include "gpio_types.h"
+#include "grph_object_defs.h"
+
+struct gpio;
+
+/* Open the handle for future use */
+enum gpio_result dal_gpio_open(
+	struct gpio *gpio,
+	enum gpio_mode mode);
+
+enum gpio_result dal_gpio_open_ex(
+	struct gpio *gpio,
+	enum gpio_mode mode,
+	void *options);
+
+/* Get high or low from the pin */
+enum gpio_result dal_gpio_get_value(
+	const struct gpio *gpio,
+	uint32_t *value);
+
+/* Set pin high or low */
+enum gpio_result dal_gpio_set_value(
+	const struct gpio *gpio,
+	uint32_t value);
+
+/* Get current mode */
+enum gpio_mode dal_gpio_get_mode(
+	const struct gpio *gpio);
+
+/* Change mode of the handle */
+enum gpio_result dal_gpio_change_mode(
+	struct gpio *gpio,
+	enum gpio_mode mode);
+
+/* Get the GPIO id */
+enum gpio_id dal_gpio_get_id(
+	const struct gpio *gpio);
+
+/* Get the GPIO enum */
+uint32_t dal_gpio_get_enum(
+	const struct gpio *gpio);
+
+/* Set the GPIO pin configuration */
+enum gpio_result dal_gpio_set_config(
+	struct gpio *gpio,
+	const struct gpio_config_data *config_data);
+
+/* Obtain GPIO pin info */
+enum gpio_result dal_gpio_get_pin_info(
+	const struct gpio *gpio,
+	struct gpio_pin_info *pin_info);
+
+/* Obtain GPIO sync source */
+enum sync_source dal_gpio_get_sync_source(
+	const struct gpio *gpio);
+
+/* Obtain GPIO pin output state (active low or active high) */
+enum gpio_pin_output_state dal_gpio_get_output_state(
+	const struct gpio *gpio);
+
+/* Close the handle */
+void dal_gpio_close(
+	struct gpio *gpio);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h b/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
new file mode 100644
index 000000000000..3f1b923c1885
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_SERVICE_INTERFACE_H__
+#define __DAL_GPIO_SERVICE_INTERFACE_H__
+
+#include "gpio_types.h"
+#include "gpio_interface.h"
+#include "ddc_interface.h"
+#include "irq_interface.h"
+
+struct gpio_service;
+
+struct gpio_service *dal_gpio_service_create(
+	enum dce_version dce_version_major,
+	enum dce_version dce_version_minor,
+	struct dc_context *ctx);
+
+struct gpio *dal_gpio_service_create_gpio(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	enum gpio_pin_output_state output_state);
+
+struct gpio *dal_gpio_service_create_gpio_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state);
+
+void dal_gpio_service_destroy_gpio(
+	struct gpio **gpio);
+
+struct ddc *dal_gpio_service_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info);
+
+void dal_gpio_service_destroy_ddc(
+	struct ddc **ddc);
+
+struct irq *dal_gpio_service_create_irq(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask);
+
+struct irq *dal_gpio_service_create_irq_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en);
+
+void dal_gpio_service_destroy_irq(
+	struct irq **ptr);
+
+void dal_gpio_service_destroy(
+	struct gpio_service **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/gpio_types.h b/drivers/gpu/drm/amd/dal/include/gpio_types.h
new file mode 100644
index 000000000000..6d3214b36cf4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/gpio_types.h
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_TYPES_H__
+#define __DAL_GPIO_TYPES_H__
+
+#define BUNDLE_A_MASK 0x00FFF000L
+#define BUNDLE_B_MASK 0x00000FFFL
+
+/*
+ * gpio_result
+ *
+ * @brief
+ * The possible return codes that the GPIO object can return.
+ * These return codes can be generated
+ * directly by the GPIO object or from the GPIOPin object.
+ */
+enum gpio_result {
+	GPIO_RESULT_OK,
+	GPIO_RESULT_NULL_HANDLE,
+	GPIO_RESULT_INVALID_DATA,
+	GPIO_RESULT_DEVICE_BUSY,
+	GPIO_RESULT_OPEN_FAILED,
+	GPIO_RESULT_ALREADY_OPENED,
+	GPIO_RESULT_NON_SPECIFIC_ERROR
+};
+
+/*
+ * @brief
+ * Used to identify the specific GPIO device
+ *
+ * @notes
+ * These constants are used as indices in a vector.
+ * Thus they should start from zero and be contiguous.
+ */
+enum gpio_id {
+	GPIO_ID_UNKNOWN = (-1),
+	GPIO_ID_DDC_DATA,
+	GPIO_ID_DDC_CLOCK,
+	GPIO_ID_GENERIC,
+	GPIO_ID_HPD,
+	GPIO_ID_GPIO_PAD,
+	GPIO_ID_VIP_PAD,
+	GPIO_ID_SYNC,
+	GPIO_ID_GSL, /* global swap lock */
+	GPIO_ID_COUNT,
+	GPIO_ID_MIN = GPIO_ID_DDC_DATA,
+	GPIO_ID_MAX = GPIO_ID_GSL
+};
+
+#define GPIO_ENUM_UNKNOWN \
+	32
+
+struct gpio_pin_info {
+	uint32_t offset;
+	uint32_t offset_y;
+	uint32_t offset_en;
+	uint32_t offset_mask;
+
+	uint32_t mask;
+	uint32_t mask_y;
+	uint32_t mask_en;
+	uint32_t mask_mask;
+};
+
+enum gpio_pin_output_state {
+	GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW,
+	GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH,
+	GPIO_PIN_OUTPUT_STATE_DEFAULT = GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW
+};
+
+enum gpio_generic {
+	GPIO_GENERIC_UNKNOWN = (-1),
+	GPIO_GENERIC_A,
+	GPIO_GENERIC_B,
+	GPIO_GENERIC_C,
+	GPIO_GENERIC_D,
+	GPIO_GENERIC_E,
+	GPIO_GENERIC_F,
+	GPIO_GENERIC_G,
+	GPIO_GENERIC_COUNT,
+	GPIO_GENERIC_MIN = GPIO_GENERIC_A,
+	GPIO_GENERIC_MAX = GPIO_GENERIC_B
+};
+
+enum gpio_hpd {
+	GPIO_HPD_UNKNOWN = (-1),
+	GPIO_HPD_1,
+	GPIO_HPD_2,
+	GPIO_HPD_3,
+	GPIO_HPD_4,
+	GPIO_HPD_5,
+	GPIO_HPD_6,
+	GPIO_HPD_COUNT,
+	GPIO_HPD_MIN = GPIO_HPD_1,
+	GPIO_HPD_MAX = GPIO_HPD_6
+};
+
+enum gpio_gpio_pad {
+	GPIO_GPIO_PAD_UNKNOWN = (-1),
+	GPIO_GPIO_PAD_0,
+	GPIO_GPIO_PAD_1,
+	GPIO_GPIO_PAD_2,
+	GPIO_GPIO_PAD_3,
+	GPIO_GPIO_PAD_4,
+	GPIO_GPIO_PAD_5,
+	GPIO_GPIO_PAD_6,
+	GPIO_GPIO_PAD_7,
+	GPIO_GPIO_PAD_8,
+	GPIO_GPIO_PAD_9,
+	GPIO_GPIO_PAD_10,
+	GPIO_GPIO_PAD_11,
+	GPIO_GPIO_PAD_12,
+	GPIO_GPIO_PAD_13,
+	GPIO_GPIO_PAD_14,
+	GPIO_GPIO_PAD_15,
+	GPIO_GPIO_PAD_16,
+	GPIO_GPIO_PAD_17,
+	GPIO_GPIO_PAD_18,
+	GPIO_GPIO_PAD_19,
+	GPIO_GPIO_PAD_20,
+	GPIO_GPIO_PAD_21,
+	GPIO_GPIO_PAD_22,
+	GPIO_GPIO_PAD_23,
+	GPIO_GPIO_PAD_24,
+	GPIO_GPIO_PAD_25,
+	GPIO_GPIO_PAD_26,
+	GPIO_GPIO_PAD_27,
+	GPIO_GPIO_PAD_28,
+	GPIO_GPIO_PAD_29,
+	GPIO_GPIO_PAD_30,
+	GPIO_GPIO_PAD_COUNT,
+	GPIO_GPIO_PAD_MIN = GPIO_GPIO_PAD_0,
+	GPIO_GPIO_PAD_MAX = GPIO_GPIO_PAD_30
+};
+
+enum gpio_vip_pad {
+	GPIO_VIP_PAD_UNKNOWN = (-1),
+	/* following never used -
+	 * GPIO_ID_DDC_CLOCK::GPIO_DDC_LINE_VIP_PAD defined instead */
+	GPIO_VIP_PAD_SCL,
+	/* following never used -
+	 * GPIO_ID_DDC_DATA::GPIO_DDC_LINE_VIP_PAD defined instead */
+	GPIO_VIP_PAD_SDA,
+	GPIO_VIP_PAD_VHAD,
+	GPIO_VIP_PAD_VPHCTL,
+	GPIO_VIP_PAD_VIPCLK,
+	GPIO_VIP_PAD_VID,
+	GPIO_VIP_PAD_VPCLK0,
+	GPIO_VIP_PAD_DVALID,
+	GPIO_VIP_PAD_PSYNC,
+	GPIO_VIP_PAD_COUNT,
+	GPIO_VIP_PAD_MIN = GPIO_VIP_PAD_SCL,
+	GPIO_VIP_PAD_MAX = GPIO_VIP_PAD_PSYNC
+};
+
+enum gpio_sync {
+	GPIO_SYNC_UNKNOWN = (-1),
+	GPIO_SYNC_HSYNC_A,
+	GPIO_SYNC_VSYNC_A,
+	GPIO_SYNC_HSYNC_B,
+	GPIO_SYNC_VSYNC_B,
+	GPIO_SYNC_COUNT,
+	GPIO_SYNC_MIN = GPIO_SYNC_HSYNC_A,
+	GPIO_SYNC_MAX = GPIO_SYNC_VSYNC_B
+};
+
+enum gpio_gsl {
+	GPIO_GSL_UNKNOWN = (-1),
+	GPIO_GSL_GENLOCK_CLOCK,
+	GPIO_GSL_GENLOCK_VSYNC,
+	GPIO_GSL_SWAPLOCK_A,
+	GPIO_GSL_SWAPLOCK_B,
+	GPIO_GSL_COUNT,
+	GPIO_GSL_MIN = GPIO_GSL_GENLOCK_CLOCK,
+	GPIO_GSL_MAX = GPIO_GSL_SWAPLOCK_B
+};
+
+/*
+ * @brief
+ * Unique Id for DDC handle.
+ * Values are meaningful (used as indexes to array)
+ */
+enum gpio_ddc_line {
+	GPIO_DDC_LINE_UNKNOWN = (-1),
+	GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_DDC2,
+	GPIO_DDC_LINE_DDC3,
+	GPIO_DDC_LINE_DDC4,
+	GPIO_DDC_LINE_DDC5,
+	GPIO_DDC_LINE_DDC6,
+	GPIO_DDC_LINE_DDC_VGA,
+	GPIO_DDC_LINE_VIP_PAD,
+	GPIO_DDC_LINE_I2C_PAD = GPIO_DDC_LINE_VIP_PAD,
+	GPIO_DDC_LINE_COUNT,
+	GPIO_DDC_LINE_MIN = GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_MAX = GPIO_DDC_LINE_I2C_PAD
+};
+
+/*
+ * @brief
+ * Identifies the mode of operation to open a GPIO device.
+ * A GPIO device (pin) can be programmed in only one of these modes at a time.
+ */
+enum gpio_mode {
+	GPIO_MODE_UNKNOWN = (-1),
+	GPIO_MODE_INPUT,
+	GPIO_MODE_OUTPUT,
+	GPIO_MODE_FAST_OUTPUT,
+	GPIO_MODE_HARDWARE,
+	GPIO_MODE_INTERRUPT
+};
+
+/*
+ * @brief
+ * Identifies the source of the signal when GPIO is in HW mode.
+ * get_signal_source() will return GPIO_SYGNAL_SOURCE__UNKNOWN
+ * when one of the following holds:
+ *    1. GPIO is input GPIO
+ *    2. GPIO is not opened in HW mode
+ *    3. GPIO does not have fixed signal source
+ *    (like DC_GenericA have mux instead fixed)
+ */
+enum gpio_signal_source {
+	GPIO_SIGNAL_SOURCE_UNKNOWN = (-1),
+	GPIO_SIGNAL_SOURCE_DACA_STEREO_SYNC,
+	GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC,
+	GPIO_SIGNAL_SOURCE_DACB_STEREO_SYNC,
+	GPIO_SIGNAL_SOURCE_DACA_HSYNC,
+	GPIO_SIGNAL_SOURCE_DACB_HSYNC,
+	GPIO_SIGNAL_SOURCE_DACA_VSYNC,
+	GPIO_SIGNAL_SOURCE_DACB_VSYNC,
+};
+
+enum gpio_stereo_source {
+	GPIO_STEREO_SOURCE_UNKNOWN = (-1),
+	GPIO_STEREO_SOURCE_D1,
+	GPIO_STEREO_SOURCE_D2,
+	GPIO_STEREO_SOURCE_D3,
+	GPIO_STEREO_SOURCE_D4,
+	GPIO_STEREO_SOURCE_D5,
+	GPIO_STEREO_SOURCE_D6
+};
+
+/*
+ * GPIO config
+ */
+
+enum gpio_config_type {
+	GPIO_CONFIG_TYPE_NONE,
+	GPIO_CONFIG_TYPE_DDC,
+	GPIO_CONFIG_TYPE_HPD,
+	GPIO_CONFIG_TYPE_GENERIC_MUX,
+	GPIO_CONFIG_TYPE_GSL_MUX,
+	GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE
+};
+
+/* DDC configuration */
+
+enum gpio_ddc_config_type {
+	GPIO_DDC_CONFIG_TYPE_MODE_AUX,
+	GPIO_DDC_CONFIG_TYPE_MODE_I2C,
+	GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT,
+	GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT,
+	GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING
+};
+
+struct gpio_ddc_config {
+	enum gpio_ddc_config_type type;
+	bool data_en_bit_present;
+	bool clock_en_bit_present;
+};
+
+/* HPD configuration */
+
+struct gpio_hpd_config {
+	uint32_t delay_on_connect; /* milliseconds */
+	uint32_t delay_on_disconnect; /* milliseconds */
+};
+
+struct gpio_generic_mux_config {
+	bool enable_output_from_mux;
+	enum gpio_signal_source mux_select;
+	enum gpio_stereo_source stereo_select;
+};
+
+enum gpio_gsl_mux_config_type {
+	GPIO_GSL_MUX_CONFIG_TYPE_DISABLE,
+	GPIO_GSL_MUX_CONFIG_TYPE_TIMING_SYNC,
+	GPIO_GSL_MUX_CONFIG_TYPE_FLIP_SYNC
+};
+
+struct gpio_gsl_mux_config {
+	enum gpio_gsl_mux_config_type type;
+	/* Actually sync_source type,
+	 * however we want to avoid inter-component includes here */
+	uint32_t gsl_group;
+};
+
+struct gpio_config_data {
+	enum gpio_config_type type;
+	union {
+		struct gpio_ddc_config ddc;
+		struct gpio_hpd_config hpd;
+		struct gpio_generic_mux_config generic_mux;
+		struct gpio_gsl_mux_config gsl_mux;
+	} config;
+};
+
+struct gpio_ddc_hw_info {
+	bool hw_supported;
+	uint32_t ddc_channel;
+};
+
+struct gpio_ddc_open_options {
+	bool en_bit_present;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_csc_types.h b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h
new file mode 100644
index 000000000000..711b458ff564
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_CSC_TYPES_H__
+#define __DAL_GRPH_CSC_TYPES_H__
+
+#include "set_mode_types.h"
+
+enum color_space {
+	COLOR_SPACE_UNKNOWN,
+	COLOR_SPACE_SRGB_FULL_RANGE,
+	COLOR_SPACE_SRGB_LIMITED_RANGE,
+	COLOR_SPACE_YPBPR601,
+	COLOR_SPACE_YPBPR709,
+	COLOR_SPACE_YCBCR601,
+	COLOR_SPACE_YCBCR709,
+	COLOR_SPACE_YCBCR601_YONLY,
+	COLOR_SPACE_YCBCR709_YONLY,
+	COLOR_SPACE_N_MVPU_SUPER_AA,
+};
+
+enum grph_color_adjust_option {
+	GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
+	GRPH_COLOR_MATRIX_SW
+};
+
+enum grph_csc_adjust_item {
+	GRPH_ADJUSTMENT_CONTRAST = 1,
+	GRPH_ADJUSTMENT_SATURATION,
+	GRPH_ADJUSTMENT_BRIGHTNESS,
+	GRPH_ADJUSTMENT_HUE,
+	GRPH_ADJUSTMENT_COLOR_TEMPERATURE
+};
+
+#define CSC_TEMPERATURE_MATRIX_SIZE 9
+
+enum graphics_csc_adjust_type {
+	GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0,
+	GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */
+	GRAPHICS_CSC_ADJUST_TYPE_SW  /*use adjustments */
+};
+
+enum graphics_gamut_adjust_type {
+	GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS = 0,
+	GRAPHICS_GAMUT_ADJUST_TYPE_HW, /* without adjustments */
+	GRAPHICS_GAMUT_ADJUST_TYPE_SW  /* use adjustments */
+};
+
+struct grph_csc_adjustment {
+	enum grph_color_adjust_option color_adjust_option;
+	enum color_space c_space;
+	int32_t grph_cont;
+	int32_t grph_sat;
+	int32_t grph_bright;
+	int32_t grph_hue;
+	int32_t adjust_divider;
+	int32_t temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE];
+	int32_t temperature_divider;
+	uint32_t lb_color_depth;
+	uint8_t gamma; /* gamma from Edid */
+	enum dc_color_depth color_depth; /* clean up to uint32_t */
+	enum pixel_format surface_pixel_format;
+	enum graphics_csc_adjust_type   csc_adjust_type;
+	enum graphics_gamut_adjust_type gamut_adjust_type;
+};
+
+struct default_adjustment {
+	uint32_t lb_color_depth;
+	enum color_space color_space;
+	enum dc_color_depth color_depth;
+	enum pixel_format surface_pixel_format;
+	enum graphics_csc_adjust_type csc_adjust_type;
+	bool force_hw_default;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
new file mode 100644
index 000000000000..2ed01bd43c37
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
@@ -0,0 +1,593 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_OBJECT_CTRL_DEFS_H__
+#define __DAL_GRPH_OBJECT_CTRL_DEFS_H__
+
+#include "grph_object_defs.h"
+
+/*
+ * #####################################################
+ * #####################################################
+ *
+ * These defines shared between asic_control/bios_parser and other
+ * DAL components
+ *
+ * #####################################################
+ * #####################################################
+ */
+
+enum tv_standard {
+	TV_STANDARD_UNKNOWN = 0, /* direct HW (mmBIOS_SCRATCH_2) translation! */
+	TV_STANDARD_NTSC,
+	TV_STANDARD_NTSCJ,
+	TV_STANDARD_PAL,
+	TV_STANDARD_PALM,
+	TV_STANDARD_PALCN,
+	TV_STANDARD_PALN,
+	TV_STANDARD_PAL60,
+	TV_STANDARD_SECAM
+};
+
+enum cv_standard {
+	CV_STANDARD_UNKNOWN = 0x0000,
+	CV_STANDARD_HD_MASK = 0x0800,		/* Flag mask HDTV output */
+	CV_STANDARD_SD_NTSC_MASK = 0x1000,	/* Flag mask NTSC output */
+	CV_STANDARD_SD_NTSC_M,		/* NTSC (North America) output 1001 */
+	CV_STANDARD_SD_NTSC_J,		/* NTSC (Japan) output 1002 */
+	CV_STANDARD_SD_480I,		/* SDTV 480i output 1003 */
+	CV_STANDARD_SD_480P,		/* SDTV 480p output 1004 */
+	CV_STANDARD_HD_720_60P = 0x1800,/* HDTV 720/60p output 1800 */
+	CV_STANDARD_HD_1080_60I,	/* HDTV 1080/60i output 1801 */
+	CV_STANDARD_SD_PAL_MASK = 0x2000,/* Flag mask PAL output */
+	CV_STANDARD_SD_PAL_B,			/* PAL B output 2001 */
+	CV_STANDARD_SD_PAL_D,			/* PAL D output 2002 */
+	CV_STANDARD_SD_PAL_G,			/* PAL G output 2003 */
+	CV_STANDARD_SD_PAL_H,			/* PAL H output 2004 */
+	CV_STANDARD_SD_PAL_I,			/* PAL I output 2005 */
+	CV_STANDARD_SD_PAL_M,			/* PAL M output 2006 */
+	CV_STANDARD_SD_PAL_N,			/* PAL N output 2007 */
+	CV_STANDARD_SD_PAL_N_COMB,	/* PAL Combination N output 2008 */
+	CV_STANDARD_SD_PAL_60,		/* PAL 60 output (test mode) 2009 */
+	CV_STANDARD_SD_576I,		/* SDTV 576i output 2010 */
+	CV_STANDARD_SD_576P,		/* SDTV 576p output 2011 */
+	CV_STANDARD_HD_720_50P = 0x2800,/* HDTV 720/50p output 2800 */
+	CV_STANDARD_HD_1080_50I,	/* HDTV 1080/50i output 2801 */
+	CV_STANDARD_SD_SECAM_MASK = 0x4000, /* Flag mask SECAM output */
+	CV_STANDARD_SD_SECAM_B,		/* SECAM B output 4001 */
+	CV_STANDARD_SD_SECAM_D,		/* SECAM D output 4002 */
+	CV_STANDARD_SD_SECAM_G,		/* SECAM G output 4003 */
+	CV_STANDARD_SD_SECAM_H,		/* SECAM H output 4004 */
+	CV_STANDARD_SD_SECAM_K,		/* SECAM K output 4005 */
+	CV_STANDARD_SD_SECAM_K1,	/* SECAM K1 output 4006 */
+	CV_STANDARD_SD_SECAM_L,		/* SECAM L output 4007 */
+	CV_STANDARD_SD_SECAM_L1		/* SECAM L1 output 4009 */
+};
+
+enum display_output_bit_depth {
+	PANEL_UNDEFINE = 0,
+	PANEL_6BIT_COLOR = 1,
+	PANEL_8BIT_COLOR = 2,
+	PANEL_10BIT_COLOR = 3,
+	PANEL_12BIT_COLOR = 4,
+	PANEL_16BIT_COLOR = 5,
+};
+
+enum lcd_scale {
+	/* No request to turn on LCD SCALER (Centering or Replication) */
+	LCD_SCALE_NONE = 0,
+	/* Request LCD SCALER in full panel mode */
+	LCD_SCALE_FULLPANEL,
+	/* Request LCD SCALER in aspect-ratio mode */
+	LCD_SCALE_ASPECTRATIO,
+
+	LCD_SCALE_UNKNOWN = (-1L),
+};
+
+/* Device type as abstracted by ATOM BIOS */
+enum dal_device_type {
+	DEVICE_TYPE_UNKNOWN = 0,
+	DEVICE_TYPE_LCD,
+	DEVICE_TYPE_CRT,
+	DEVICE_TYPE_DFP,
+	DEVICE_TYPE_CV,
+	DEVICE_TYPE_TV,
+	DEVICE_TYPE_CF,
+	DEVICE_TYPE_WIRELESS
+};
+
+/* Device ID as abstracted by ATOM BIOS */
+struct device_id {
+	enum dal_device_type device_type:16;
+	uint32_t enum_id:16;	/* 1 based enum */
+};
+
+struct graphics_object_i2c_info {
+	struct gpio_info {
+		uint32_t clk_mask_register_index;
+		uint32_t clk_en_register_index;
+		uint32_t clk_y_register_index;
+		uint32_t clk_a_register_index;
+		uint32_t data_mask_register_index;
+		uint32_t data_en_register_index;
+		uint32_t data_y_register_index;
+		uint32_t data_a_register_index;
+
+		uint32_t clk_mask_shift;
+		uint32_t clk_en_shift;
+		uint32_t clk_y_shift;
+		uint32_t clk_a_shift;
+		uint32_t data_mask_shift;
+		uint32_t data_en_shift;
+		uint32_t data_y_shift;
+		uint32_t data_a_shift;
+	} gpio_info;
+
+	bool i2c_hw_assist;
+	uint32_t i2c_line;
+	uint32_t i2c_engine_id;
+	uint32_t i2c_slave_address;
+};
+
+
+struct graphics_object_hpd_info {
+	uint8_t hpd_int_gpio_uid;
+	uint8_t hpd_active;
+};
+
+struct connector_device_tag_info {
+	uint32_t acpi_device;
+	struct device_id dev_id;
+};
+
+struct device_timing {
+	struct misc_info {
+		uint32_t HORIZONTAL_CUT_OFF:1;
+		/* 0=Active High, 1=Active Low */
+		uint32_t H_SYNC_POLARITY:1;
+		/* 0=Active High, 1=Active Low */
+		uint32_t V_SYNC_POLARITY:1;
+		uint32_t VERTICAL_CUT_OFF:1;
+		uint32_t H_REPLICATION_BY2:1;
+		uint32_t V_REPLICATION_BY2:1;
+		uint32_t COMPOSITE_SYNC:1;
+		uint32_t INTERLACE:1;
+		uint32_t DOUBLE_CLOCK:1;
+		uint32_t RGB888:1;
+		uint32_t GREY_LEVEL:2;
+		uint32_t SPATIAL:1;
+		uint32_t TEMPORAL:1;
+		uint32_t API_ENABLED:1;
+	} misc_info;
+
+	uint32_t pixel_clk; /* in KHz */
+	uint32_t horizontal_addressable;
+	uint32_t horizontal_blanking_time;
+	uint32_t vertical_addressable;
+	uint32_t vertical_blanking_time;
+	uint32_t horizontal_sync_offset;
+	uint32_t horizontal_sync_width;
+	uint32_t vertical_sync_offset;
+	uint32_t vertical_sync_width;
+	uint32_t horizontal_border;
+	uint32_t vertical_border;
+};
+
+struct supported_refresh_rate {
+	uint32_t REFRESH_RATE_30HZ:1;
+	uint32_t REFRESH_RATE_40HZ:1;
+	uint32_t REFRESH_RATE_48HZ:1;
+	uint32_t REFRESH_RATE_50HZ:1;
+	uint32_t REFRESH_RATE_60HZ:1;
+};
+
+struct embedded_panel_info {
+	struct device_timing lcd_timing;
+	uint32_t ss_id;
+	struct supported_refresh_rate supported_rr;
+	uint32_t drr_enabled;
+	uint32_t min_drr_refresh_rate;
+};
+
+struct embedded_panel_patch_mode {
+	uint32_t width;
+	uint32_t height;
+};
+
+struct firmware_info {
+	struct pll_info {
+		uint32_t crystal_frequency; /* in KHz */
+		uint32_t min_input_pxl_clk_pll_frequency; /* in KHz */
+		uint32_t max_input_pxl_clk_pll_frequency; /* in KHz */
+		uint32_t min_output_pxl_clk_pll_frequency; /* in KHz */
+		uint32_t max_output_pxl_clk_pll_frequency; /* in KHz */
+	} pll_info;
+
+	struct firmware_feature {
+		uint32_t memory_clk_ss_percentage;
+		uint32_t engine_clk_ss_percentage;
+	} feature;
+
+	uint32_t default_display_engine_pll_frequency; /* in KHz */
+	uint32_t external_clock_source_frequency_for_dp; /* in KHz */
+	uint32_t smu_gpu_pll_output_freq; /* in KHz */
+	uint8_t min_allowed_bl_level;
+	uint8_t remote_display_config;
+};
+
+/* direct HW (mmBIOS_SCRATCH_2) translation! */
+union tv_standard_support {
+	uint8_t u_all;
+	struct {
+		bool TV_SUPPORT_NTSC:1;
+		bool TV_SUPPORT_NTSCJ:1;
+
+		bool TV_SUPPORT_PAL:1;
+		bool TV_SUPPORT_PALM:1;
+		bool TV_SUPPORT_PALCN:1;
+		bool TV_SUPPORT_PALN:1;
+		bool TV_SUPPORT_PAL60:1;
+
+		bool TV_SUPPORT_SECAM:1;
+	} bits;
+};
+
+struct analog_tv_info {
+	union tv_standard_support tv_suppported;
+	union tv_standard_support tv_boot_up_default;
+};
+
+struct step_and_delay_info {
+    uint32_t step;
+    uint32_t delay;
+    uint32_t recommended_ref_div;
+};
+
+struct spread_spectrum_info {
+	struct spread_spectrum_type {
+		bool CENTER_MODE:1;
+		bool EXTERNAL:1;
+		bool STEP_AND_DELAY_INFO:1;
+	} type;
+
+	/* in unit of 0.01% (spreadPercentageDivider = 100),
+	otherwise in 0.001% units (spreadPercentageDivider = 1000); */
+	uint32_t spread_spectrum_percentage;
+	uint32_t spread_percentage_divider; /* 100 or 1000 */
+	uint32_t spread_spectrum_range; /* modulation freq (HZ)*/
+
+	union {
+		struct step_and_delay_info step_and_delay_info;
+		/* For mem/engine/uvd, Clock Out frequence (VCO ),
+		in unit of kHz. For TMDS/HDMI/LVDS, it is pixel clock,
+		for DP, it is link clock ( 270000 or 162000 ) */
+		uint32_t target_clock_range; /* in KHz */
+	};
+
+};
+
+struct graphics_object_encoder_cap_info {
+	uint32_t dp_hbr2_cap:1;
+	uint32_t dp_hbr2_validated:1;
+	uint32_t reserved:15;
+};
+
+struct din_connector_info {
+	uint32_t gpio_id;
+	bool gpio_tv_active_state;
+};
+
+/* Invalid channel mapping */
+enum { INVALID_DDI_CHANNEL_MAPPING = 0x0 };
+
+/**
+ * DDI PHY channel mapping reflecting XBAR setting
+ */
+union ddi_channel_mapping {
+	struct mapping {
+		uint8_t lane0:2;	/* Mapping for lane 0 */
+		uint8_t lane1:2;	/* Mapping for lane 1 */
+		uint8_t lane2:2;	/* Mapping for lane 2 */
+		uint8_t lane3:2;	/* Mapping for lane 3 */
+	} mapping;
+	uint8_t raw;
+};
+
+/**
+* Transmitter output configuration description
+*/
+struct transmitter_configuration_info {
+	/* DDI PHY ID for the transmitter */
+	enum transmitter transmitter_phy_id;
+	/* DDI PHY channel mapping reflecting crossbar setting */
+	union ddi_channel_mapping output_channel_mapping;
+};
+
+struct transmitter_configuration {
+	/* Configuration for the primary transmitter */
+	struct transmitter_configuration_info primary_transmitter_config;
+	/* Secondary transmitter configuration for Dual-link DVI */
+	struct transmitter_configuration_info secondary_transmitter_config;
+};
+
+
+/* These size should be sufficient to store info coming from BIOS */
+#define NUMBER_OF_UCHAR_FOR_GUID 16
+#define MAX_NUMBER_OF_EXT_DISPLAY_PATH 7
+#define NUMBER_OF_CSR_M3_ARB 10
+#define NUMBER_OF_DISP_CLK_VOLTAGE 4
+#define NUMBER_OF_AVAILABLE_SCLK 5
+
+/* V6 */
+struct integrated_info {
+	struct clock_voltage_caps {
+		/* The Voltage Index indicated by FUSE, same voltage index
+		shared with SCLK DPM fuse table */
+		uint32_t voltage_index;
+		/* Maximum clock supported with specified voltage index */
+		uint32_t max_supported_clk; /* in KHz */
+	} disp_clk_voltage[NUMBER_OF_DISP_CLK_VOLTAGE];
+
+	struct display_connection_info {
+		struct external_display_path {
+			/* A bit vector to show what devices are supported */
+			uint32_t device_tag;
+			/* 16bit device ACPI id. */
+			uint32_t device_acpi_enum;
+			/* A physical connector for displays to plug in,
+			using object connector definitions */
+			struct graphics_object_id device_connector_id;
+			/* An index into external AUX/DDC channel LUT */
+			uint8_t ext_aux_ddc_lut_index;
+			/* An index into external HPD pin LUT */
+			uint8_t ext_hpd_pin_lut_index;
+			/* external encoder object id */
+			struct graphics_object_id ext_encoder_obj_id;
+			/* XBAR mapping of the PHY channels */
+			union ddi_channel_mapping channel_mapping;
+		} path[MAX_NUMBER_OF_EXT_DISPLAY_PATH];
+
+		uint8_t gu_id[NUMBER_OF_UCHAR_FOR_GUID];
+		uint8_t checksum;
+	} ext_disp_conn_info; /* exiting long long time */
+
+	struct available_s_clk_list {
+		/* Maximum clock supported with specified voltage index */
+		uint32_t supported_s_clk; /* in KHz */
+		/* The Voltage Index indicated by FUSE for specified SCLK */
+		uint32_t voltage_index;
+		/* The Voltage ID indicated by FUSE for specified SCLK */
+		uint32_t voltage_id;
+	} avail_s_clk[NUMBER_OF_AVAILABLE_SCLK];
+
+	uint8_t memory_type;
+	uint8_t ma_channel_number;
+	uint32_t boot_up_engine_clock; /* in KHz */
+	uint32_t dentist_vco_freq; /* in KHz */
+	uint32_t boot_up_uma_clock; /* in KHz */
+	uint32_t boot_up_req_display_vector;
+	uint32_t other_display_misc;
+	uint32_t gpu_cap_info;
+	uint32_t sb_mmio_base_addr;
+	uint32_t system_config;
+	uint32_t cpu_cap_info;
+	uint32_t max_nb_voltage;
+	uint32_t min_nb_voltage;
+	uint32_t boot_up_nb_voltage;
+	uint32_t ext_disp_conn_info_offset;
+	uint32_t csr_m3_arb_cntl_default[NUMBER_OF_CSR_M3_ARB];
+	uint32_t csr_m3_arb_cntl_uvd[NUMBER_OF_CSR_M3_ARB];
+	uint32_t csr_m3_arb_cntl_fs3d[NUMBER_OF_CSR_M3_ARB];
+	uint32_t gmc_restore_reset_time;
+	uint32_t minimum_n_clk;
+	uint32_t idle_n_clk;
+	uint32_t ddr_dll_power_up_time;
+	uint32_t ddr_pll_power_up_time;
+	/* start for V6 */
+	uint32_t pcie_clk_ss_type;
+	uint32_t lvds_ss_percentage;
+	uint32_t lvds_sspread_rate_in_10hz;
+	uint32_t hdmi_ss_percentage;
+	uint32_t hdmi_sspread_rate_in_10hz;
+	uint32_t dvi_ss_percentage;
+	uint32_t dvi_sspread_rate_in_10_hz;
+	uint32_t sclk_dpm_boost_margin;
+	uint32_t sclk_dpm_throttle_margin;
+	uint32_t sclk_dpm_tdp_limit_pg;
+	uint32_t sclk_dpm_tdp_limit_boost;
+	uint32_t boost_engine_clock;
+	uint32_t boost_vid_2bit;
+	uint32_t enable_boost;
+	uint32_t gnb_tdp_limit;
+	/* Start from V7 */
+	uint32_t max_lvds_pclk_freq_in_single_link;
+	uint32_t lvds_misc;
+	uint32_t lvds_pwr_on_seq_dig_on_to_de_in_4ms;
+	uint32_t lvds_pwr_on_seq_de_to_vary_bl_in_4ms;
+	uint32_t lvds_pwr_off_seq_vary_bl_to_de_in4ms;
+	uint32_t lvds_pwr_off_seq_de_to_dig_on_in4ms;
+	uint32_t lvds_off_to_on_delay_in_4ms;
+	uint32_t lvds_pwr_on_seq_vary_bl_to_blon_in_4ms;
+	uint32_t lvds_pwr_off_seq_blon_to_vary_bl_in_4ms;
+	uint32_t lvds_reserved1;
+	uint32_t lvds_bit_depth_control_val;
+};
+
+/**
+* Power source ids.
+*/
+enum power_source {
+	POWER_SOURCE_AC = 0,
+	POWER_SOURCE_DC,
+	POWER_SOURCE_LIMITED_POWER,
+	POWER_SOURCE_LIMITED_POWER_2,
+	POWER_SOURCE_MAX
+};
+
+struct bios_event_info {
+	uint32_t thermal_state;
+	uint32_t backlight_level;
+	enum power_source powerSource;
+	bool has_thermal_state_changed;
+	bool has_power_source_changed;
+	bool has_forced_mode_changed;
+	bool forced_mode;
+	bool backlight_changed;
+};
+
+union stereo_3d_support {
+	struct {
+		/* HW can alter left and right image sequentially */
+		uint32_t FRAME_ALTERNATE:1;
+		/* Frame Alternate + HW can integrate stereosync
+		signal into TMDS stream */
+		uint32_t DVI_FRAME_ALT:1;
+		/* Frame Alternate + HW can integrate stereosync
+		signal into DP stream */
+		uint32_t DISPLAY_PORT_FRAME_ALT:1;
+		/* Frame Alternate + HW can drive stereosync signal
+		on separate line */
+		uint32_t SIDEBAND_FRAME_ALT:1;
+		/* SW allowed to pack left and right image into single frame.
+		Used for HDMI only, DP has it's own flags. */
+		uint32_t SW_FRAME_PACK:1;
+		/* HW can pack left and right image into single HDMI frame */
+		uint32_t PROGRESSIVE_FRAME_PACK:1;
+		/* HW can pack left and right interlaced images into
+		single HDMI frame */
+		uint32_t INTERLACE_FRAME_PACK:1;
+		/* HW can pack left and right images into single DP frame */
+		uint32_t DISPLAY_PORT_FRAME_PACK:1;
+		/* SW can pack left and right images into single DP frame */
+		uint32_t DISPLAY_PORT_SW_FRAME_PACK:1;
+		/* HW can mix left and right images into single image */
+		uint32_t INTERLEAVE:1;
+		/* HW can mix left and right interlaced images
+		into single image */
+		uint32_t INTERLACE_INTERLEAVE:1;
+		/* Allow display-based formats (whatever supported)
+		in WS stereo mode */
+		uint32_t DISPLAY_3DIN_WS_MODE:1;
+		/* Side-by-side, packed by application/driver into 2D frame */
+		uint32_t SIDE_BY_SIDE_SW_PACKED:1;
+		/* Top-and-bottom, packed by application/driver into 2D frame */
+		uint32_t TOP_AND_BOTTOM_SW_PACKED:1;
+	} bits;
+	uint32_t u_all;
+};
+
+/* Bitvector and bitfields of possible optimizations
+ #IMPORTANT# Keep bitfields match bitvector! */
+enum optimization_feature {
+	/* Don't do HW programming on panels that were enabled by VBIOS */
+	OF_SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY = 0x1,
+	OF_SKIP_RESET_OF_ALL_HW_ON_S3RESUME = 0x2,
+	OF_SKIP_HW_RESET_OF_EMBEDDED_DISPLAY_ON_S3RESUME = 0x4,
+	OF_SKIP_POWER_UP_VBIOS_ENABLED_ENCODER = 0x8,
+	/* Do not turn off VCC while powering down on boot or resume */
+	OF_KEEP_VCC_DURING_POWER_DOWN_ON_BOOT_OR_RESUME = 0x10,
+	/* Do not turn off VCC while performing SetMode */
+	OF_KEEP_VCC_DURING_SET_MODE = 0x20,
+	OF_DO_NOT_WAIT_FOR_HPD_LOW = 0x40,
+	OF_SKIP_POWER_DOWN_INACTIVE_ENCODER = 0x80
+};
+
+union optimization_flags {
+	struct {
+		/* Don't do HW programming if panels were enabled by VBIOS */
+		uint32_t SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY:1;
+		uint32_t SKIP_RESET_OF_ALL_HW_ON_S3RESUME:1;
+		uint32_t SKIP_HW_RESET_OF_EMBEDDED_DISPLAY_ON_S3RESUME:1;
+		uint32_t SKIP_POWER_UP_VBIOS_ENABLED_ENCODER:1;
+		/* Do not turn off VCC while powering down on boot or resume */
+		uint32_t KEEP_VCC_DURING_POWER_DOWN_ON_BOOT_OR_RESUME:1;
+		/* Do not turn off VCC while performing SetMode */
+		uint32_t KEEP_VCC_DURING_SET_MODE:1;
+		uint32_t DO_NOT_WAIT_FOR_HPD_LOW:1;
+	} bits;
+	uint32_t u_all;
+};
+
+/* Bitvector and bitfields of performance measurements
+ #IMPORTANT# Keep bitfields match bitvector! */
+enum perf_measure {
+	PERF_MEASURE_ADAPTER_POWER_STATE = 0x1,
+	PERF_MEASURE_DISPLAY_POWER_STATE = 0x2,
+	PERF_MEASURE_SET_MODE_SEQ = 0x4,
+	PERF_MEASURE_DETECT_AT_RESUME = 0x8,
+	PERF_MEASURE_MEMORY_READ_CONTROL = 0x10,
+};
+
+union perf_measure_flags {
+	struct {
+		uint32_t ADAPTER_POWER_STATE:1;
+		uint32_t DISPLAY_POWER_STATE:1;
+		uint32_t SET_MODE_SEQ:1;
+		uint32_t DETECT_AT_RESUME:1;
+		uint32_t MEMORY_READ_CONTROL:1;
+
+	} bits;
+	uint32_t u_all;
+};
+
+enum {
+	PERF_MEASURE_POWERCODE_OFFSET = 0x0,
+	PERF_MEASURE_POWER_CODE_MASK = 0xFF,
+	PERF_MEASURE_POWER_STATE_OFFSET = 8,
+	PERF_MEASURE_POWER_STATE_MASK = 0x000FF00,
+	PERF_MEASURE_PREV_POWER_STATE_OFFSET = 16,
+	PERF_MEASURE_PREV_POWER_STATE_MASK = 0x00FF0000,
+	PERF_MEASURE_DISPLAY_INDEX_OFFSET = 24,
+	PERF_MEASURE_DISPLAY_INDEX_MASK = 0xFF000000
+};
+
+enum {
+	HDMI_PIXEL_CLOCK_IN_KHZ_297 = 297000,
+	TMDS_PIXEL_CLOCK_IN_KHZ_165 = 165000
+};
+
+/*
+ * DFS-bypass flag
+ */
+/* Copy of SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS from atombios.h */
+enum {
+	DFS_BYPASS_ENABLE = 0x10
+};
+
+enum {
+	INVALID_BACKLIGHT = -1
+};
+
+struct panel_backlight_boundaries {
+	uint32_t min_signal_level;
+	uint32_t max_signal_level;
+};
+
+struct panel_backlight_default_levels {
+	uint32_t ac_level_percentage;
+	uint32_t dc_level_percentage;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_defs.h b/drivers/gpu/drm/amd/dal/include/grph_object_defs.h
new file mode 100644
index 000000000000..a1e468fbbb2b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_object_defs.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_OBJECT_DEFS_H__
+#define __DAL_GRPH_OBJECT_DEFS_H__
+
+#include "grph_object_id.h"
+
+/* ********************************************************************
+ * ********************************************************************
+ *
+ *  These defines shared between All Graphics Objects
+ *
+ * ********************************************************************
+ * ********************************************************************
+ */
+
+/* HPD unit id - HW direct translation */
+enum hpd_source_id {
+	HPD_SOURCEID1 = 0,
+	HPD_SOURCEID2,
+	HPD_SOURCEID3,
+	HPD_SOURCEID4,
+	HPD_SOURCEID5,
+	HPD_SOURCEID6,
+
+	HPD_SOURCEID_COUNT,
+	HPD_SOURCEID_UNKNOWN
+};
+
+/* DDC unit id - HW direct translation */
+enum channel_id {
+	CHANNEL_ID_UNKNOWN = 0,
+	CHANNEL_ID_DDC1,
+	CHANNEL_ID_DDC2,
+	CHANNEL_ID_DDC3,
+	CHANNEL_ID_DDC4,
+	CHANNEL_ID_DDC5,
+	CHANNEL_ID_DDC6,
+	CHANNEL_ID_DDC_VGA,
+	CHANNEL_ID_I2C_PAD,
+	CHANNEL_ID_COUNT
+};
+
+#define DECODE_CHANNEL_ID(ch_id) \
+	(ch_id) == CHANNEL_ID_DDC1 ? "CHANNEL_ID_DDC1" : \
+	(ch_id) == CHANNEL_ID_DDC2 ? "CHANNEL_ID_DDC2" : \
+	(ch_id) == CHANNEL_ID_DDC3 ? "CHANNEL_ID_DDC3" : \
+	(ch_id) == CHANNEL_ID_DDC4 ? "CHANNEL_ID_DDC4" : \
+	(ch_id) == CHANNEL_ID_DDC5 ? "CHANNEL_ID_DDC5" : \
+	(ch_id) == CHANNEL_ID_DDC6 ? "CHANNEL_ID_DDC6" : \
+	(ch_id) == CHANNEL_ID_DDC_VGA ? "CHANNEL_ID_DDC_VGA" : \
+	(ch_id) == CHANNEL_ID_I2C_PAD ? "CHANNEL_ID_I2C_PAD" : "Invalid"
+
+enum transmitter {
+	TRANSMITTER_UNKNOWN = (-1L),
+	TRANSMITTER_UNIPHY_A,
+	TRANSMITTER_UNIPHY_B,
+	TRANSMITTER_UNIPHY_C,
+	TRANSMITTER_UNIPHY_D,
+	TRANSMITTER_UNIPHY_E,
+	TRANSMITTER_UNIPHY_F,
+	TRANSMITTER_NUTMEG_CRT,
+	TRANSMITTER_TRAVIS_CRT,
+	TRANSMITTER_TRAVIS_LCD,
+	TRANSMITTER_UNIPHY_G,
+	TRANSMITTER_COUNT
+};
+
+enum physical_phy_id {
+	PHY_ID_UNKNOWN = (-1L),
+	PHY_ID_0,
+	PHY_ID_1,
+	PHY_ID_2,
+	PHY_ID_3,
+	PHY_ID_4,
+	PHY_ID_5,
+	PHY_ID_6,
+	PHY_ID_7,
+	PHY_ID_8,
+	PHY_ID_9,
+	PHY_ID_COUNT
+};
+
+/* Generic source of the synchronisation input/output signal */
+/* Can be used for flow control, stereo sync, timing sync, frame sync, etc */
+enum sync_source {
+	SYNC_SOURCE_NONE = 0,
+
+	/* Source based on controllers */
+	SYNC_SOURCE_CONTROLLER0,
+	SYNC_SOURCE_CONTROLLER1,
+	SYNC_SOURCE_CONTROLLER2,
+	SYNC_SOURCE_CONTROLLER3,
+	SYNC_SOURCE_CONTROLLER4,
+	SYNC_SOURCE_CONTROLLER5,
+
+	/* Source based on GSL group */
+	SYNC_SOURCE_GSL_GROUP0,
+	SYNC_SOURCE_GSL_GROUP1,
+	SYNC_SOURCE_GSL_GROUP2,
+
+	/* Source based on GSL IOs */
+	/* These IOs normally used as GSL input/output */
+	SYNC_SOURCE_GSL_IO_FIRST,
+	SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK = SYNC_SOURCE_GSL_IO_FIRST,
+	SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC,
+	SYNC_SOURCE_GSL_IO_SWAPLOCK_A,
+	SYNC_SOURCE_GSL_IO_SWAPLOCK_B,
+	SYNC_SOURCE_GSL_IO_LAST = SYNC_SOURCE_GSL_IO_SWAPLOCK_B,
+
+	/* Source based on regular IOs */
+	SYNC_SOURCE_IO_FIRST,
+	SYNC_SOURCE_IO_GENERIC_A = SYNC_SOURCE_IO_FIRST,
+	SYNC_SOURCE_IO_GENERIC_B,
+	SYNC_SOURCE_IO_GENERIC_C,
+	SYNC_SOURCE_IO_GENERIC_D,
+	SYNC_SOURCE_IO_GENERIC_E,
+	SYNC_SOURCE_IO_GENERIC_F,
+	SYNC_SOURCE_IO_HPD1,
+	SYNC_SOURCE_IO_HPD2,
+	SYNC_SOURCE_IO_HSYNC_A,
+	SYNC_SOURCE_IO_VSYNC_A,
+	SYNC_SOURCE_IO_HSYNC_B,
+	SYNC_SOURCE_IO_VSYNC_B,
+	SYNC_SOURCE_IO_LAST = SYNC_SOURCE_IO_VSYNC_B,
+
+	/* Misc. flow control sources */
+	SYNC_SOURCE_DUAL_GPU_PIN
+};
+
+enum trigger_edge {
+	TRIGGER_EDGE_RISING = 0,
+	TRIGGER_EDGE_FALLING,
+	TRIGGER_EDGE_BOTH,
+	TRIGGER_EDGE_DEFAULT
+};
+
+/* Parameters to enable CRTC trigger */
+struct trigger_params {
+	enum sync_source source;
+	enum trigger_edge edge;
+};
+
+/* CRTC Static Screen event triggers */
+struct static_screen_events {
+	union {
+		/* event mask to enable/disable various
+		   trigger sources for static screen detection */
+		struct {
+			/* Force event high */
+			uint32_t FRAME_START:1;
+			/* Cursor register change */
+			uint32_t CURSOR_MOVE:1;
+			/* Memory write to any client other than MCIF */
+			uint32_t MEM_WRITE:1;
+			/* Memory write to hit memory region 0 */
+			uint32_t MEM_REGION0_WRITE:1;
+			/* Memory write to hit memory region 1 */
+			uint32_t MEM_REGION1_WRITE:1;
+			/* Memory write to hit memory region 2 */
+			uint32_t MEM_REGION2_WRITE:1;
+			/* Memory write to hit memory region 3 */
+			uint32_t MEM_REGION3_WRITE:1;
+			/* Graphics Surface Update Pending */
+			uint32_t GFX_UPDATE:1;
+			/* Overlay Surface Update Pending */
+			uint32_t OVL_UPDATE:1;
+			/* Compressed surface invalidated in FBC */
+			uint32_t INVALIDATE_FBC_SURFACE:1;
+			/* Register pending update in any double buffered
+			register group in the display pipe
+			(i.e. Blender, DCP, or SCL) */
+			uint32_t REG_PENDING_UPDATE:1;
+			/* Crtc_trig_a: Based on signal from any other CRTC */
+			uint32_t CRTC_TRIG_A:1;
+			/* Crtc_trig_b: Based on signal from any other CRTC */
+			uint32_t CRTC_TRIG_B:1;
+			/* Readback of CRTC nominal vertical count register
+			by driver  indicates that OS may be trying to change
+			mode or contents of the display therefore need to
+			switch to higher refresh rate */
+			uint32_t READBACK_NOMINAL_VERTICAL:1;
+			/* Readback of CRTC dynamic vertical count register
+			by driver  indicates that OS may be trying to change
+			mode or contents of the display therefore need to
+			switch to higher refresh rate */
+			uint32_t READBACK_DYNAMIC_VERTICAL:1;
+			/* Reserved */
+			uint32_t RESERVED:1;
+		} bits;
+		uint32_t u_all;
+	};
+};
+
+
+/*
+ * ***************************************************************
+ * ********************* Register programming sequences ********
+ * ***************************************************************
+ */
+
+/* GPIO/Register access sequences */
+enum io_register_sequence {
+	/* GLSync sequences to access SwapReady & SwapRequest
+	GPIOs - GLSync Connector parameter */
+	IO_REG_SEQUENCE_SWAPREADY_SET = 0,
+	IO_REG_SEQUENCE_SWAPREADY_RESET,
+	IO_REG_SEQUENCE_SWAPREADY_READ,
+	IO_REG_SEQUENCE_SWAPREQUEST_SET,
+	IO_REG_SEQUENCE_SWAPREQUEST_RESET,
+	IO_REG_SEQUENCE_SWAPREQUEST_READ,
+
+	/* Frame synchronization start/stop - display index parameter */
+	IO_REG_SEQUENCE_FRAMELOCK_STOP,
+	IO_REG_SEQUENCE_FRAMELOCK_START,
+
+	/* Flip lock/unlock - GLSync Connector parameter */
+	IO_REG_SEQUENCE_GLOBALSWAP_LOCK,
+	IO_REG_SEQUENCE_GLOBALSWAP_UNLOCK,
+
+	IO_REG_SEQUENCEENUM_MAX
+};
+
+#define IO_REGISTER_SEQUENCE_MAX_LENGTH 5
+
+/*
+ *****************************************************************************
+ *                             struct io_register
+ *****************************************************************************
+ * Generic struct for read/write register or GPIO.
+ * It allows controlling only some bit section of register, rather then the
+ * whole one.
+ * For write operation should be used as following:
+ *   1. data  = READ(Base + RegisterOffset)
+ *   2. data &= ANDMask
+ *   3. data |= ORMask
+ *   4. WRITE(Base + RegisterOffset, data)
+ *
+ * Note: In case of regular register, ANDMask will be typically 0.
+ *	In case of GPIO, ANDMask will have typically all bits set
+ *	except the specific GPIO bit.
+ *
+ * For read operation should be used as following:
+ *   1. data   = READ(Base + RegisterOffset)
+ *   2. data  &= ANDMask
+ *   3. data >>= BitShift
+ *
+ * Note: In case of regular register, ANDMask will be typically 0xFFFFFFFF.
+ *	In case of GPIO, ANDMask will have typically only specific GPIO bit set
+ *
+ * Note: Base Address is not exposed in this structure due to
+ *	security consideration.
+ */
+
+/*
+ * The generic sequence to program/access registers or GPIOs.
+ * There could be 2 types of sequences - read and write.
+ * Read sequence may have 0 or more writes and in the end one read
+ * Write sequence may have 1 or more writes.
+ */
+struct io_reg_sequence {
+	/* Ordered array of register to program */
+	struct {
+		/* Offset of memory mapped register or GPIO */
+		uint32_t register_offset;
+		/* Mask to use at AND operation (Mandatory, comes
+		before OR operation) */
+		uint32_t and_mask;
+		union {
+			/* Mask to use at OR operation (For write
+			sequence only, comes after AND operation) */
+			uint32_t or_mask;
+			/* Number of bits to shift to get the actual value
+			(For read  sequence only, comes after AND operation) */
+			uint32_t bit_shift;
+		};
+	} io_registers[IO_REGISTER_SEQUENCE_MAX_LENGTH];
+
+	uint32_t steps_num; /* Total number of r/w steps in the sequence */
+};
+
+/* Sequence ID - uniqly defines sequence on single adapter */
+struct io_reg_sequence_id {
+	enum io_register_sequence sequence; /* Sequence enumeration Index/ID */
+	union {
+		/* Refers to object to which the sequence applies.*/
+		uint32_t index;
+		uint32_t display_index;
+		uint32_t controller_index;
+		uint32_t glsync_connector_index;
+	};
+};
+
+struct fbc_info {
+	bool fbc_enable;
+	bool lpt_enable;
+};
+
+/* Event to request TM change IRQ registration state */
+struct hotplug_irq_data {
+	bool disable;
+	struct graphics_object_id connector;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_id.h b/drivers/gpu/drm/amd/dal/include/grph_object_id.h
new file mode 100644
index 000000000000..372e46c9f0dd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_object_id.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_OBJECT_ID_H__
+#define __DAL_GRPH_OBJECT_ID_H__
+
+/* Types of graphics objects */
+enum object_type {
+	OBJECT_TYPE_UNKNOWN  = 0,
+
+	/* Direct ATOM BIOS translation */
+	OBJECT_TYPE_GPU,
+	OBJECT_TYPE_ENCODER,
+	OBJECT_TYPE_CONNECTOR,
+	OBJECT_TYPE_ROUTER,
+	OBJECT_TYPE_GENERIC,
+
+	/* Driver specific */
+	OBJECT_TYPE_AUDIO,
+	OBJECT_TYPE_CONTROLLER,
+	OBJECT_TYPE_CLOCK_SOURCE,
+	OBJECT_TYPE_ENGINE,
+
+	OBJECT_TYPE_COUNT
+};
+
+/* Enumeration inside one type of graphics objects */
+enum object_enum_id {
+	ENUM_ID_UNKNOWN = 0,
+	ENUM_ID_1,
+	ENUM_ID_2,
+	ENUM_ID_3,
+	ENUM_ID_4,
+	ENUM_ID_5,
+	ENUM_ID_6,
+	ENUM_ID_7,
+
+	ENUM_ID_COUNT
+};
+
+/* Generic object ids */
+enum generic_id {
+	GENERIC_ID_UNKNOWN = 0,
+	GENERIC_ID_MXM_OPM,
+	GENERIC_ID_GLSYNC,
+	GENERIC_ID_STEREO,
+
+	GENERIC_ID_COUNT
+};
+
+/* Controller object ids */
+enum controller_id {
+	CONTROLLER_ID_UNDEFINED = 0,
+	CONTROLLER_ID_D0,
+	CONTROLLER_ID_D1,
+	CONTROLLER_ID_D2,
+	CONTROLLER_ID_D3,
+	CONTROLLER_ID_D4,
+	CONTROLLER_ID_D5,
+	CONTROLLER_ID_UNDERLAY0,
+	CONTROLLER_ID_MAX = CONTROLLER_ID_UNDERLAY0
+};
+
+#define IS_UNDERLAY_CONTROLLER(ctrlr_id) (ctrlr_id >= CONTROLLER_ID_UNDERLAY0)
+
+/*
+ * ClockSource object ids.
+ * We maintain the order matching (more or less) ATOM BIOS
+ * to improve optimized acquire
+ */
+enum clock_source_id {
+	CLOCK_SOURCE_ID_UNDEFINED = 0,
+	CLOCK_SOURCE_ID_PLL0,
+	CLOCK_SOURCE_ID_PLL1,
+	CLOCK_SOURCE_ID_PLL2,
+	CLOCK_SOURCE_ID_EXTERNAL, /* ID (Phy) ref. clk. for DP */
+	CLOCK_SOURCE_ID_DCPLL,
+	CLOCK_SOURCE_ID_DFS,	/* DENTIST */
+	CLOCK_SOURCE_ID_VCE,	/* VCE does not need a real PLL */
+	/* Used to distinguish between programming pixel clock and ID (Phy) clock */
+	CLOCK_SOURCE_ID_DP_DTO,
+
+	CLOCK_SOURCE_COMBO_PHY_PLL0,
+	CLOCK_SOURCE_COMBO_PHY_PLL1,
+	CLOCK_SOURCE_COMBO_PHY_PLL2,
+	CLOCK_SOURCE_COMBO_PHY_PLL3,
+	CLOCK_SOURCE_COMBO_PHY_PLL4,
+	CLOCK_SOURCE_COMBO_PHY_PLL5,
+	CLOCK_SOURCE_COMBO_DISPLAY_PLL0
+};
+
+
+/* Encoder object ids */
+enum encoder_id {
+	ENCODER_ID_UNKNOWN = 0,
+
+	/* Radeon Class Display Hardware */
+	ENCODER_ID_INTERNAL_LVDS,
+	ENCODER_ID_INTERNAL_TMDS1,
+	ENCODER_ID_INTERNAL_TMDS2,
+	ENCODER_ID_INTERNAL_DAC1,
+	ENCODER_ID_INTERNAL_DAC2,	/* TV/CV DAC */
+
+	/* External Third Party Encoders */
+	ENCODER_ID_INTERNAL_LVTM1,	/* not used for Radeon */
+	ENCODER_ID_INTERNAL_HDMI,
+
+	/* Kaledisope (KLDSCP) Class Display Hardware */
+	ENCODER_ID_INTERNAL_KLDSCP_TMDS1,
+	ENCODER_ID_INTERNAL_KLDSCP_DAC1,
+	ENCODER_ID_INTERNAL_KLDSCP_DAC2,	/* Shared with CV/TV and CRT */
+	/* External TMDS (dual link) */
+	ENCODER_ID_EXTERNAL_MVPU_FPGA,	/* MVPU FPGA chip */
+	ENCODER_ID_INTERNAL_DDI,
+	ENCODER_ID_INTERNAL_UNIPHY,
+	ENCODER_ID_INTERNAL_KLDSCP_LVTMA,
+	ENCODER_ID_INTERNAL_UNIPHY1,
+	ENCODER_ID_INTERNAL_UNIPHY2,
+	ENCODER_ID_EXTERNAL_NUTMEG,
+	ENCODER_ID_EXTERNAL_TRAVIS,
+
+	ENCODER_ID_INTERNAL_WIRELESS,	/* Internal wireless display encoder */
+	ENCODER_ID_INTERNAL_UNIPHY3,
+	ENCODER_ID_INTERNAL_VIRTUAL,
+};
+
+
+/* Connector object ids */
+enum connector_id {
+	CONNECTOR_ID_UNKNOWN = 0,
+	CONNECTOR_ID_SINGLE_LINK_DVII = 1,
+	CONNECTOR_ID_DUAL_LINK_DVII = 2,
+	CONNECTOR_ID_SINGLE_LINK_DVID = 3,
+	CONNECTOR_ID_DUAL_LINK_DVID = 4,
+	CONNECTOR_ID_VGA = 5,
+	CONNECTOR_ID_HDMI_TYPE_A = 12,
+	CONNECTOR_ID_LVDS = 14,
+	CONNECTOR_ID_PCIE = 16,
+	CONNECTOR_ID_HARDCODE_DVI = 18,
+	CONNECTOR_ID_DISPLAY_PORT = 19,
+	CONNECTOR_ID_EDP = 20,
+	CONNECTOR_ID_MXM = 21,
+	CONNECTOR_ID_WIRELESS = 22,
+	CONNECTOR_ID_MIRACAST = 23,
+
+	CONNECTOR_ID_VIRTUAL = 100
+};
+
+
+/* Audio object ids */
+enum audio_id {
+	AUDIO_ID_UNKNOWN = 0,
+	AUDIO_ID_INTERNAL_AZALIA
+};
+
+
+/* Engine object ids */
+enum engine_id {
+	ENGINE_ID_DIGA,
+	ENGINE_ID_DIGB,
+	ENGINE_ID_DIGC,
+	ENGINE_ID_DIGD,
+	ENGINE_ID_DIGE,
+	ENGINE_ID_DIGF,
+	ENGINE_ID_DIGG,
+	ENGINE_ID_DACA,
+	ENGINE_ID_DACB,
+	ENGINE_ID_VCE,	/* wireless display pseudo-encoder */
+	ENGINE_ID_VIRTUAL,
+
+	ENGINE_ID_COUNT,
+	ENGINE_ID_UNKNOWN = (-1L)
+};
+
+union supported_stream_engines {
+	struct {
+		uint32_t ENGINE_ID_DIGA:1;
+		uint32_t ENGINE_ID_DIGB:1;
+		uint32_t ENGINE_ID_DIGC:1;
+		uint32_t ENGINE_ID_DIGD:1;
+		uint32_t ENGINE_ID_DIGE:1;
+		uint32_t ENGINE_ID_DIGF:1;
+		uint32_t ENGINE_ID_DIGG:1;
+		uint32_t ENGINE_ID_DACA:1;
+		uint32_t ENGINE_ID_DACB:1;
+		uint32_t ENGINE_ID_VCE:1;
+	} engine;
+	uint32_t u_all;
+};
+
+enum transmitter_color_depth {
+	TRANSMITTER_COLOR_DEPTH_24 = 0,  /* 8  bits */
+	TRANSMITTER_COLOR_DEPTH_30,      /* 10 bits */
+	TRANSMITTER_COLOR_DEPTH_36,      /* 12 bits */
+	TRANSMITTER_COLOR_DEPTH_48       /* 16 bits */
+};
+
+/*
+ *****************************************************************************
+ * graphics_object_id struct
+ *
+ * graphics_object_id is a very simple struct wrapping 32bit Graphics
+ * Object identication
+ *
+ * This struct should stay very simple
+ *  No dependencies at all (no includes)
+ *  No debug messages or asserts
+ *  No #ifndef and preprocessor directives
+ *  No grow in space (no more data member)
+ *****************************************************************************
+ */
+
+struct graphics_object_id {
+	uint32_t  id:8;
+	uint32_t  enum_id:4;
+	uint32_t  type:4;
+	uint32_t  reserved:16; /* for padding. total size should be u32 */
+};
+
+/* some simple functions for convenient graphics_object_id handle */
+
+static inline struct graphics_object_id dal_graphics_object_id_init(
+	uint32_t id,
+	enum object_enum_id enum_id,
+	enum object_type type)
+{
+	struct graphics_object_id result = {
+		id, enum_id, type, 0
+	};
+
+	return result;
+}
+
+bool dal_graphics_object_id_is_valid(
+	struct graphics_object_id id);
+bool dal_graphics_object_id_is_equal(
+	struct graphics_object_id id1,
+	struct graphics_object_id id2);
+uint32_t dal_graphics_object_id_to_uint(
+	struct graphics_object_id id);
+
+
+enum controller_id dal_graphics_object_id_get_controller_id(
+	struct graphics_object_id id);
+enum clock_source_id dal_graphics_object_id_get_clock_source_id(
+	struct graphics_object_id id);
+enum encoder_id dal_graphics_object_id_get_encoder_id(
+	struct graphics_object_id id);
+enum connector_id dal_graphics_object_id_get_connector_id(
+	struct graphics_object_id id);
+enum audio_id dal_graphics_object_id_get_audio_id(
+	struct graphics_object_id id);
+enum engine_id dal_graphics_object_id_get_engine_id(
+	struct graphics_object_id id);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h b/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
new file mode 100644
index 000000000000..ddd78d6c97e3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_SEQUENCER_INTERFACE_H__
+#define __DAL_HW_SEQUENCER_INTERFACE_H__
+
+#include "hw_sequencer_types.h"
+#include "hw_adjustment_types.h"
+#include "include/display_clock_interface.h"
+#include "include/scaler_types.h"
+#include "include/grph_csc_types.h"
+#include "plane_types.h"
+
+#include "adapter_service_interface.h"
+
+enum hwss_result {
+	HWSS_RESULT_OK,
+	HWSS_RESULT_ERROR,
+	HWSS_RESULT_NO_BANDWIDTH,
+	HWSS_RESULT_OUT_OF_RANGE,
+	HWSS_RESULT_NOT_SUPPORTED,
+	HWSS_RESULT_UNKNOWN
+};
+
+struct hws_init_data {
+	struct adapter_service *as;
+	struct dal_context *dal_context;
+};
+
+/* TODO: below is three almost equal structures.
+ * We should decide what to do with them */
+struct blank_stream_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	struct hw_crtc_timing timing;
+	struct link_settings link_settings;
+};
+
+struct enable_stream_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	struct hw_crtc_timing timing;
+	struct link_settings link_settings;
+
+	const struct hw_path_mode *path_mode;
+};
+
+struct enable_link_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	struct hw_crtc_timing timing;
+	struct link_settings link_settings;
+
+	bool optimized_programming;
+	const struct hw_path_mode *path_mode;
+};
+
+struct validate_link_param {
+	const struct display_path *display_path;
+	uint32_t link_idx;
+	struct link_settings link_settings;
+};
+
+struct set_dp_phy_pattern_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	enum dp_test_pattern test_pattern;
+	const uint8_t *custom_pattern;
+	uint32_t cust_pattern_size;
+};
+
+struct hw_global_objects;
+struct hw_sequencer;
+struct hw_adjustment;
+struct hw_path_mode_set;
+struct hw_path_mode;
+struct hwss_build_params;
+struct controller;
+
+void dal_hw_sequencer_mute_audio_endpoint(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	bool mute);
+
+void dal_hw_sequencer_enable_audio_endpoint(
+	struct hw_sequencer *hws,
+	struct link_settings *ls,
+	struct display_path *display_path,
+	bool enable);
+
+enum hwss_result dal_hw_sequencer_reset_audio_device(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum hwss_result dal_hw_sequencer_validate_link(
+	struct hw_sequencer *hws,
+	const struct validate_link_param *param);
+
+bool dal_hw_sequencer_is_supported_dp_training_pattern3(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	uint32_t link_idx);
+
+enum hwss_result dal_hw_sequencer_set_dp_phy_pattern(
+	struct hw_sequencer *hws,
+	const struct set_dp_phy_pattern_param *param);
+
+enum hwss_result dal_hw_sequencer_set_lane_settings(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	const struct link_training_settings *link_settings);
+
+void dal_hw_sequencer_set_test_pattern(
+	struct hw_sequencer *hws,
+	struct hw_path_mode *path_mode,
+	enum dp_test_pattern test_pattern,
+	const struct link_training_settings *link_settings,
+	const uint8_t *custom_pattern,
+	uint8_t cust_pattern_size);
+
+bool dal_hw_sequencer_has_audio_bandwidth_changed(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *old,
+	const struct hw_path_mode *new);
+
+void dal_hw_sequencer_enable_azalia_audio_jack_presence(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_disable_azalia_audio_jack_presence(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_enable_memory_requests(
+	struct hw_sequencer *hws,
+	struct hw_path_mode *path_mode);
+
+void dal_hw_sequencer_update_info_packets(
+	struct hw_sequencer *hws,
+	struct hw_path_mode *path_mode);
+
+/* Static validation for a SINGLE path mode.
+ * Already "active" paths (if any) are NOT taken into account. */
+enum hwss_result dal_hw_sequencer_validate_display_path_mode(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *path_mode);
+
+/* Validation for a SET of path modes, including Video Memory Bandwidth
+ * validation. */
+enum hwss_result dal_hw_sequencer_validate_display_hwpms(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set);
+
+struct hw_adjustment_gamma_ramp;
+
+enum hwss_result dal_hw_sequencer_set_gamma_ramp_adjustment(
+	struct hw_sequencer *hws,
+	const struct display_path *display_path,
+	struct hw_adjustment_gamma_ramp *adjusment);
+
+enum hwss_result dal_hw_sequencer_set_color_control_adjustment(
+	struct hw_sequencer *hws,
+	struct controller *crtc,
+	struct hw_adjustment_color_control *adjustment);
+
+enum hwss_result dal_hw_sequencer_set_vertical_sync_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+enum hwss_result dal_hw_sequencer_set_horizontal_sync_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+enum hwss_result dal_hw_sequencer_set_composite_sync_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+enum hwss_result dal_hw_sequencer_enable_sync_output(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum hwss_result dal_hw_sequencer_disable_sync_output(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum hwss_result dal_hw_sequencer_set_backlight_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+void dal_hw_sequencer_disable_memory_requests(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *path_mode);
+
+enum hwss_result dal_hw_sequencer_enable_link(
+	struct hw_sequencer *hws,
+	const struct enable_link_param *in);
+
+void dal_hw_sequencer_disable_link(
+	struct hw_sequencer *hws,
+	const struct enable_link_param *in);
+
+void dal_hw_sequencer_enable_stream(
+	struct hw_sequencer *hws,
+	const struct enable_stream_param *in);
+
+void dal_hw_sequencer_disable_stream(
+	struct hw_sequencer *hws,
+	const struct enable_stream_param *in);
+
+void dal_hw_sequencer_blank_stream(
+	struct hw_sequencer *hws,
+	const struct blank_stream_param *in);
+
+void dal_hw_sequencer_unblank_stream(
+	struct hw_sequencer *hws,
+	const struct blank_stream_param *in);
+
+enum hwss_result dal_hw_sequencer_set_clocks_and_clock_state(
+		struct hw_sequencer *hws,
+		struct hw_global_objects *g_obj,
+		const struct minimum_clocks_calculation_result *min_clk_in,
+		enum clocks_state required_clocks_state);
+
+enum hwss_result dal_hw_sequencer_set_mode(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set);
+
+enum signal_type dal_hw_sequencer_detect_sink(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum signal_type dal_hw_sequencer_detect_load(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+bool dal_hw_sequencer_is_sink_present(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_psr_setup(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *path_mode,
+	const struct psr_caps *psr_caps);
+
+void dal_hw_sequencer_psr_enable(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_psr_disable(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_program_drr(
+		struct hw_sequencer *hws,
+		const struct hw_path_mode *path_mode);
+
+enum hwss_result dal_hw_sequencer_set_safe_displaymark(
+		struct hw_sequencer *hws,
+		struct hw_path_mode_set *path_set);
+
+enum hwss_result dal_hw_sequencer_set_displaymark(
+		struct hw_sequencer *hws,
+		struct hw_path_mode_set *path_set);
+
+void dal_hw_sequencer_destroy(struct hw_sequencer **hws);
+
+struct hw_sequencer *dal_hw_sequencer_create(
+		struct hws_init_data *hws_init_data);
+
+enum hwss_result dal_hw_sequencer_set_overscan_adj(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *set,
+	struct hw_underscan_adjustment_data *hw_underscan);
+
+bool dal_hw_sequencer_enable_line_buffer_power_gating(
+	struct line_buffer *lb,
+	enum controller_id id,
+	enum pixel_type pixel_type,
+	uint32_t src_pixel_width,
+	uint32_t dst_pixel_width,
+	struct scaling_taps *taps,
+	enum lb_pixel_depth lb_depth,
+	uint32_t src_height,
+	uint32_t dst_height,
+	bool interlaced);
+
+void dal_hw_sequencer_build_scaler_parameter(
+	const struct hw_path_mode *path_mode,
+	const struct scaling_taps *taps,
+	bool build_timing_required,
+	struct scaler_data *scaler_data);
+
+void dal_hw_sequencer_update_info_frame(
+	const struct hw_path_mode *hw_path_mode);
+
+enum hwss_result dal_hw_sequencer_set_bit_depth_reduction_adj(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	union hw_adjustment_bit_depth_reduction *bit_depth);
+
+bool dal_hw_sequencer_is_support_custom_gamut_adj(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	enum hw_surface_type surface_type);
+
+enum hwss_result dal_hw_sequencer_get_hw_color_adj_range(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	struct hw_color_control_range *hw_color_range);
+
+bool dal_hw_sequencer_is_support_custom_gamma_coefficients(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	enum hw_surface_type surface_type);
+
+enum hwss_result dal_hw_sequencer_build_csc_adjust(
+	struct hw_sequencer *hws,
+	struct hw_adjustment_color_control *color_control,
+	struct grph_csc_adjustment *adjust);
+
+void dal_hw_sequencer_build_gamma_ramp_adj_params(
+		const struct hw_adjustment_gamma_ramp *adjusment,
+		struct gamma_parameters *gamma_param,
+		struct gamma_ramp *ramp);
+
+void translate_from_hw_to_controller_regamma(
+		const struct hw_regamma_lut *hw_regamma,
+		struct regamma_lut *regamma);
+
+void dal_hw_sequencer_enable_wireless_idle_detection(
+		struct hw_sequencer *hws,
+		bool enable);
+
+/* Cursor interface */
+enum hwss_result dal_hw_sequencer_set_cursor_position(
+		struct hw_sequencer *hws,
+		struct display_path *dp,
+		const struct dc_cursor_position *position);
+
+enum hwss_result dal_hw_sequencer_set_cursor_attributes(
+		struct hw_sequencer *hws,
+		struct display_path *dp,
+		const struct dc_cursor_attributes *attributes);
+
+/* Underlay/MPO interface */
+enum hwss_result dal_hw_sequencer_set_plane_config(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set,
+	uint32_t display_index);
+
+bool dal_hw_sequencer_update_plane_address(
+	struct hw_sequencer *hws,
+	struct display_path *dp,
+	uint32_t num_planes,
+	struct plane_addr_flip_info *info);
+
+void dal_hw_sequencer_prepare_to_release_planes(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set,
+	uint32_t display_index);
+
+#endif /* __DAL_HW_SEQUENCER_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
new file mode 100644
index 000000000000..ad7b90605d75
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_SEQUENCER_TYPES_H__
+#define __DAL_HW_SEQUENCER_TYPES_H__
+
+#include "signal_types.h"
+#include "grph_object_defs.h"
+#include "link_service_types.h"
+
+struct color_quality {
+	uint32_t bpp_graphics;
+	uint32_t bpp_backend_video;
+};
+
+enum {
+	HW_MAX_NUM_VIEWPORTS = 2,
+	HW_CURRENT_PIPE_INDEX = 0,
+	HW_OTHER_PIPE_INDEX = 1
+};
+
+struct hw_view_port_adjustment {
+	int32_t start_adjustment;
+	int32_t width;
+
+	enum controller_id controller_id;
+};
+
+struct hw_view_port_adjustments {
+	uint32_t view_ports_num;
+	struct hw_view_port_adjustment adjustments[HW_MAX_NUM_VIEWPORTS];
+};
+
+/* Timing standard */
+enum hw_timing_standard {
+	HW_TIMING_STANDARD_UNDEFINED,
+	HW_TIMING_STANDARD_DMT,
+	HW_TIMING_STANDARD_GTF,
+	HW_TIMING_STANDARD_CVT,
+	HW_TIMING_STANDARD_CVT_RB,
+	HW_TIMING_STANDARD_CEA770,
+	HW_TIMING_STANDARD_CEA861,
+	HW_TIMING_STANDARD_HDMI,
+	HW_TIMING_STANDARD_TV_NTSC,
+	HW_TIMING_STANDARD_TV_NTSC_J,
+	HW_TIMING_STANDARD_TV_PAL,
+	HW_TIMING_STANDARD_TV_PAL_M,
+	HW_TIMING_STANDARD_TV_PAL_CN,
+	HW_TIMING_STANDARD_TV_SECAM,
+	/* for explicit timings from VBIOS, EDID etc. */
+	HW_TIMING_STANDARD_EXPLICIT
+};
+
+/* TODO: identical to struct crtc_ranged_timing_control
+ * defined in inc\timing_generator_types.h */
+struct hw_ranged_timing_control {
+	/* set to 1 to force dynamic counter V_COUNT
+	 * to lock to constant rate counter V_COUNT_NOM
+	 * on page flip event in dynamic refresh mode
+	 * when switching from a low refresh rate to nominal refresh rate */
+	bool force_lock_on_event;
+	/* set to 1 to force CRTC2 (slave) to lock to CRTC1 (master) VSync
+	 * in order to overlap their blank regions for MC clock changes */
+	bool lock_to_master_vsync;
+
+	/* set to 1 to program Static Screen Detection Masks
+	 * without enabling dynamic refresh rate */
+	bool program_static_screen_mask;
+	/* set to 1 to program Dynamic Refresh Rate */
+	bool program_dynamic_refresh_rate;
+	/* set to 1 to force disable Dynamic Refresh Rate */
+	bool force_disable_drr;
+
+	/* event mask to enable/disable various trigger sources
+	 * for static screen detection */
+	struct static_screen_events event_mask;
+
+	/* Number of consecutive static screen frames before static state is
+	 * asserted. */
+	uint32_t static_frame_count;
+};
+
+/* define the structure of Dynamic Refresh Mode */
+struct hw_ranged_timing {
+	/* defines the minimum possible vertical dimension of display timing
+	 * for CRTC as supported by the panel */
+	uint32_t vertical_total_min;
+	/* defines the maximum possible vertical dimension of display timing
+	 * for CRTC as supported by the panel */
+	uint32_t vertical_total_max;
+
+	struct hw_ranged_timing_control control;
+};
+
+/* CRTC timing structure */
+struct hw_crtc_timing {
+	uint32_t h_total;
+	uint32_t h_addressable;
+	uint32_t h_overscan_left;
+	uint32_t h_overscan_right;
+	uint32_t h_sync_start;
+	uint32_t h_sync_width;
+
+	uint32_t v_total;
+	uint32_t v_addressable;
+	uint32_t v_overscan_top;
+	uint32_t v_overscan_bottom;
+	uint32_t v_sync_start;
+	uint32_t v_sync_width;
+
+	struct hw_ranged_timing ranged_timing;
+
+	/* in KHz */
+	uint32_t pixel_clock;
+
+	enum hw_timing_standard timing_standard;
+	enum dc_color_depth color_depth;
+	enum dc_pixel_encoding pixel_encoding;
+
+	struct {
+		uint32_t INTERLACED:1;
+		uint32_t DOUBLESCAN:1;
+		uint32_t PIXEL_REPETITION:4; /* 1...10 */
+		uint32_t HSYNC_POSITIVE_POLARITY:1;
+		uint32_t VSYNC_POSITIVE_POLARITY:1;
+		/* frame should be packed for 3D
+		 * (currently this refers to HDMI 1.4a FramePacking format */
+		uint32_t HORZ_COUNT_BY_TWO:1;
+		uint32_t PACK_3D_FRAME:1;
+		/* 0 - left eye polarity, 1 - right eye polarity */
+		uint32_t RIGHT_EYE_3D_POLARITY:1;
+		/* DVI-DL High-Color mode */
+		uint32_t HIGH_COLOR_DL_MODE:1;
+		uint32_t Y_ONLY:1;
+		/* HDMI 2.0 - Support scrambling for TMDS character
+		 * rates less than or equal to 340Mcsc */
+		uint32_t LTE_340MCSC_SCRAMBLE:1;
+	} flags;
+};
+
+struct hw_scaling_info {
+	struct view src;
+	struct view dst;
+	enum signal_type signal;
+};
+
+enum hw_color_space {
+	HW_COLOR_SPACE_UNKNOWN = 0,
+	HW_COLOR_SPACE_SRGB_FULL_RANGE,
+	HW_COLOR_SPACE_SRGB_LIMITED_RANGE,
+	HW_COLOR_SPACE_YPBPR601,
+	HW_COLOR_SPACE_YPBPR709,
+	HW_COLOR_SPACE_YCBCR601,
+	HW_COLOR_SPACE_YCBCR709,
+	HW_COLOR_SPACE_YCBCR601_YONLY,
+	HW_COLOR_SPACE_YCBCR709_YONLY,
+	HW_COLOR_SPACE_NMVPU_SUPERAA,
+};
+
+enum hw_overlay_color_space {
+	HW_OVERLAY_COLOR_SPACE_UNKNOWN,
+	HW_OVERLAY_COLOR_SPACE_BT709,
+	HW_OVERLAY_COLOR_SPACE_BT601,
+	HW_OVERLAY_COLOR_SPACE_SMPTE240,
+	HW_OVERLAY_COLOR_SPACE_RGB
+};
+
+enum hw_overlay_backend_bpp {
+	HW_OVERLAY_BACKEND_BPP_UNKNOWN,
+	HW_OVERLAY_BACKEND_BPP32_FULL_BANDWIDTH,
+	HW_OVERLAY_BACKEND_BPP16_FULL_BANDWIDTH,
+	HW_OVERLAY_BACKEND_BPP32_HALF_BANDWIDTH,
+};
+enum hw_overlay_format {
+	HW_OVERLAY_FORMAT_UNKNOWN,
+	HW_OVERLAY_FORMAT_YUY2,
+	HW_OVERLAY_FORMAT_UYVY,
+	HW_OVERLAY_FORMAT_RGB565,
+	HW_OVERLAY_FORMAT_RGB555,
+	HW_OVERLAY_FORMAT_RGB32,
+	HW_OVERLAY_FORMAT_YUV444,
+	HW_OVERLAY_FORMAT_RGB32_2101010
+};
+
+enum hw_scale_options {
+	HW_SCALE_OPTION_UNKNOWN,
+	HW_SCALE_OPTION_OVERSCAN, /* multimedia pass through mode */
+	HW_SCALE_OPTION_UNDERSCAN
+};
+
+enum hw_stereo_format {
+	HW_STEREO_FORMAT_NONE = 0,
+	HW_STEREO_FORMAT_SIDE_BY_SIDE = 1,
+	HW_STEREO_FORMAT_TOP_AND_BOTTOM = 2,
+	HW_STEREO_FORMAT_FRAME_ALTERNATE = 3,
+	HW_STEREO_FORMAT_ROW_INTERLEAVED = 5,
+	HW_STEREO_FORMAT_COLUMN_INTERLEAVED = 6,
+	HW_STEREO_FORMAT_CHECKER_BOARD = 7 /* the same as pixel interleave */
+};
+
+enum hw_dithering_options {
+	HW_DITHERING_OPTION_UNKNOWN,
+	HW_DITHERING_OPTION_SKIP_PROGRAMMING,
+	HW_DITHERING_OPTION_ENABLE,
+	HW_DITHERING_OPTION_DISABLE
+};
+
+struct hw_stereo_mixer_params {
+	bool sub_sampling;
+	bool single_pipe;
+};
+
+
+
+struct hw_action_flags {
+	uint32_t RESYNC_PATH:1;
+	uint32_t TIMING_CHANGED:1;
+	uint32_t PIXEL_ENCODING_CHANGED:1;
+	uint32_t GAMUT_CHANGED:1;
+	uint32_t TURN_OFF_VCC:1;
+};
+
+enum hw_sync_request {
+	HW_SYNC_REQUEST_NONE = 0,
+	HW_SYNC_REQUEST_SET_INTERPATH,
+	HW_SYNC_REQUEST_SET_GL_SYNC_GENLOCK,
+	HW_SYNC_REQUEST_SET_GL_SYNC_FREE_RUN,
+	HW_SYNC_REQUEST_SET_GL_SYNC_SHADOW,
+	HW_SYNC_REQUEST_RESET_GLSYNC,
+	HW_SYNC_REQUEST_RESYNC_GLSYNC,
+	HW_SYNC_REQUEST_SET_STEREO3D
+};
+
+struct hw_sync_info {
+	enum hw_sync_request sync_request;
+	uint32_t target_pixel_clock; /* in KHz */
+	enum sync_source sync_source;
+};
+
+/* TODO hw_info_frame and hw_info_packet structures are same as in encoder
+ * merge it*/
+struct hw_info_packet {
+	bool valid;
+	uint8_t hb0;
+	uint8_t hb1;
+	uint8_t hb2;
+	uint8_t hb3;
+	uint8_t sb[28];
+};
+
+struct hw_info_frame {
+	/* Auxiliary Video Information */
+	struct hw_info_packet avi_info_packet;
+	struct hw_info_packet gamut_packet;
+	struct hw_info_packet vendor_info_packet;
+	/* Source Product Description */
+	struct hw_info_packet spd_packet;
+	/* Video Stream Configuration */
+	struct hw_info_packet vsc_packet;
+};
+
+
+enum channel_command_type {
+	CHANNEL_COMMAND_I2C,
+	CHANNEL_COMMAND_I2C_OVER_AUX,
+	CHANNEL_COMMAND_AUX
+};
+
+
+/* maximum TMDS transmitter pixel clock is 165 MHz. So it is KHz */
+#define	TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
+#define	NATIVE_HDMI_MAX_PIXEL_CLOCK_IN_KHZ 297000
+
+struct hw_adjustment_range {
+	int32_t hw_default;
+	int32_t min;
+	int32_t max;
+	int32_t step;
+	uint32_t divider; /* (actually HW range is min/divider; divider !=0) */
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/i2caux_interface.h b/drivers/gpu/drm/amd/dal/include/i2caux_interface.h
new file mode 100644
index 000000000000..b961d24d0e70
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/i2caux_interface.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2CAUX_INTERFACE_H__
+#define __DAL_I2CAUX_INTERFACE_H__
+
+#include "ddc_interface.h"
+#include "adapter_service_interface.h"
+
+struct i2c_payload {
+	bool write;
+	uint8_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum i2c_command_engine {
+	I2C_COMMAND_ENGINE_DEFAULT,
+	I2C_COMMAND_ENGINE_SW,
+	I2C_COMMAND_ENGINE_HW
+};
+
+struct i2c_command {
+	struct i2c_payload *payloads;
+	uint8_t number_of_payloads;
+
+	enum i2c_command_engine engine;
+
+	/* expressed in KHz
+	 * zero means "use default value" */
+	uint32_t speed;
+};
+
+#define DEFAULT_AUX_MAX_DATA_SIZE 16
+#define AUX_MAX_DEFER_WRITE_RETRY 20
+
+struct aux_payload {
+	/* set following flag to read/write I2C data,
+	 * reset it to read/write DPCD data */
+	bool i2c_over_aux;
+	/* set following flag to write data,
+	 * reset it to read data */
+	bool write;
+	uint32_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+struct aux_command {
+	struct aux_payload *payloads;
+	uint8_t number_of_payloads;
+
+	/* expressed in milliseconds
+	 * zero means "use default value" */
+	uint32_t defer_delay;
+
+	/* zero means "use default value" */
+	uint32_t max_defer_write_retry;
+};
+
+union aux_config {
+	struct {
+		uint32_t ALLOW_AUX_WHEN_HPD_LOW:1;
+	} bits;
+	uint32_t raw;
+};
+
+struct i2caux;
+
+struct i2caux *dal_i2caux_create(
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+bool dal_i2caux_submit_i2c_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct i2c_command *cmd);
+
+bool dal_i2caux_submit_aux_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct aux_command *cmd);
+
+void dal_i2caux_keep_engine_power_up(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	bool keep_power_up);
+
+bool dal_i2caux_start_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+bool dal_i2caux_stop_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+void dal_i2caux_configure_aux(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	union aux_config cfg);
+
+void dal_i2caux_destroy(
+	struct i2caux **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/irq_interface.h b/drivers/gpu/drm/amd/dal/include/irq_interface.h
new file mode 100644
index 000000000000..0faa48fabf95
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/irq_interface.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_INTERFACE_H__
+#define __DAL_IRQ_INTERFACE_H__
+
+#include "gpio_types.h"
+
+struct irq;
+
+enum gpio_result dal_irq_open(
+	struct irq *irq);
+
+enum gpio_result dal_irq_get_value(
+	const struct irq *irq,
+	uint32_t *value);
+
+enum dc_irq_source dal_irq_get_source(
+	const struct irq *irq);
+
+enum dc_irq_source dal_irq_get_rx_source(
+	const struct irq *irq);
+
+enum gpio_result dal_irq_setup_hpd_filter(
+	struct irq *irq,
+	struct gpio_hpd_config *config);
+
+void dal_irq_close(
+	struct irq *irq);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/irq_service_interface.h b/drivers/gpu/drm/amd/dal/include/irq_service_interface.h
new file mode 100644
index 000000000000..7ae4aebb738d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/irq_service_interface.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_SERVICE_INTERFACE_H__
+#define __DAL_IRQ_SERVICE_INTERFACE_H__
+
+#include "include/adapter_service_types.h"
+
+struct irq_service_init_data {
+	struct dc_context *ctx;
+};
+
+struct irq_service *dal_irq_service_create(
+	enum dce_version version,
+	struct irq_service_init_data *init_data);
+
+void dal_irq_service_destroy(struct irq_service **irq_service);
+
+bool dal_irq_service_set(
+	struct irq_service *irq_service,
+	enum dc_irq_source source,
+	bool enable);
+
+bool dal_irq_service_ack(
+	struct irq_service *irq_service,
+	enum dc_irq_source source);
+
+enum dc_irq_source dal_irq_service_to_irq_source(
+		struct irq_service *irq_service,
+		uint32_t src_id,
+		uint32_t ext_id);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/link_service_interface.h b/drivers/gpu/drm/amd/dal/include/link_service_interface.h
new file mode 100644
index 000000000000..2ac93119cc02
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/link_service_interface.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LINK_SERVICE_INTERFACE_H__
+#define __DAL_LINK_SERVICE_INTERFACE_H__
+
+#include "include/link_service_types.h"
+
+/* forward declaration */
+struct link_service;
+struct hw_crtc_timing;
+struct hw_path_mode;
+struct display_path;
+struct hw_path_mode_set;
+struct link_training_preference;
+enum ddc_result;
+
+struct link_service *dal_link_service_create(
+	struct link_service_init_data *init_data);
+
+void dal_link_service_destroy(
+	struct link_service **ls);
+
+enum link_service_type dal_ls_get_link_service_type(
+	struct link_service *link_service);
+
+bool dal_ls_validate_mode_timing(
+	struct link_service *ls,
+	uint32_t display_index,
+	const struct hw_crtc_timing *timing,
+	struct link_validation_flags flags);
+
+bool dal_ls_get_mst_sink_info(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct mst_sink_info *sink_info);
+
+bool dal_ls_get_gtc_sync_status(
+	struct link_service *ls);
+
+bool dal_ls_enable_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_disable_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *poath_mode);
+
+bool dal_ls_optimized_enable_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct display_path *display_path);
+
+void dal_ls_update_stream_features(
+	struct link_service *ls,
+	const struct hw_path_mode *path_mode);
+
+bool dal_ls_blank_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_unblank_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_pre_mode_change(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_post_mode_change(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_power_on_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_power_off_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+void dal_ls_retrain_link(
+	struct link_service *ls,
+	struct hw_path_mode_set *path_set);
+
+bool dal_ls_get_current_link_setting(
+	struct link_service *ls,
+	struct link_settings *link_settings);
+
+void dal_ls_connect_link(
+	struct link_service *ls,
+	const struct display_path *display_path,
+	bool initial_detection);
+
+void dal_ls_disconnect_link(
+	struct link_service *ls);
+
+bool dal_ls_is_mst_network_present(
+	struct link_service *ls);
+
+void dal_ls_invalidate_down_stream_devices(
+	struct link_service *ls);
+
+bool dal_ls_are_mst_displays_cofunctional(
+	struct link_service *ls,
+	const uint32_t *array_display_index,
+	uint32_t len);
+
+bool dal_ls_is_sink_present_at_display_index(
+	struct link_service *ls,
+	uint32_t display_index);
+
+struct ddc_service *dal_ls_obtain_mst_ddc_service(
+	struct link_service *ls,
+	uint32_t display_index);
+
+void dal_ls_release_mst_ddc_service(
+	struct link_service *ls,
+	struct ddc_service *ddc_service);
+
+void dal_ls_release_hw(
+	struct link_service *ls);
+
+bool dal_ls_associate_link(
+	struct link_service *ls,
+	uint32_t display_index,
+	uint32_t link_index,
+	bool is_internal_link);
+
+bool dal_dpsst_ls_set_overridden_trained_link_settings(
+	struct link_service *ls,
+	const struct link_settings *link_settings);
+
+void dal_dpsst_ls_set_link_training_preference(
+	struct link_service *ls,
+	const struct link_training_preference *ltp);
+
+struct link_training_preference
+	dal_dpsst_ls_get_link_training_preference(
+	struct link_service *ls);
+
+bool dal_ls_should_send_notification(
+	struct link_service *ls);
+
+uint32_t dal_ls_get_notification_display_index(
+	struct link_service *ls);
+
+enum ddc_result dal_dpsst_ls_read_dpcd_data(
+	struct link_service *ls,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t size);
+
+enum ddc_result dal_dpsst_ls_write_dpcd_data(
+	struct link_service *ls,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t size);
+
+bool dal_ls_is_link_psr_supported(struct link_service *ls);
+
+bool dal_ls_is_stream_drr_supported(struct link_service *ls);
+
+void dal_ls_set_link_psr_capabilities(
+		struct link_service *ls,
+		struct psr_caps *psr_caps);
+
+void dal_ls_get_link_psr_capabilities(
+		struct link_service *ls,
+		struct psr_caps *psr_caps);
+
+#endif /* __DAL_LINK_SERVICE_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/link_service_types.h b/drivers/gpu/drm/amd/dal/include/link_service_types.h
new file mode 100644
index 000000000000..d2e6256695fb
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/link_service_types.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LINK_SERVICE_TYPES_H__
+#define __DAL_LINK_SERVICE_TYPES_H__
+
+#include "grph_object_id.h"
+#include "dpcd_defs.h"
+#include "dal_types.h"
+#include "irq_types.h"
+
+/*struct mst_mgr_callback_object;*/
+struct ddc;
+struct irq_manager;
+
+enum {
+	MAX_CONTROLLER_NUM = 6
+};
+
+enum link_service_type {
+	LINK_SERVICE_TYPE_LEGACY = 0,
+	LINK_SERVICE_TYPE_DP_SST,
+	LINK_SERVICE_TYPE_DP_MST,
+	LINK_SERVICE_TYPE_MAX
+};
+
+struct link_validation_flags {
+	uint32_t DYNAMIC_VALIDATION:1;
+	uint32_t CANDIDATE_TIMING:1;
+	uint32_t START_OF_VALIDATION:1;
+};
+
+/* Post Cursor 2 is optional for transmitter
+ * and it applies only to the main link operating at HBR2
+ */
+enum post_cursor2 {
+	POST_CURSOR2_DISABLED = 0,	/* direct HW translation! */
+	POST_CURSOR2_LEVEL1,
+	POST_CURSOR2_LEVEL2,
+	POST_CURSOR2_LEVEL3,
+	POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3,
+};
+
+enum voltage_swing {
+	VOLTAGE_SWING_LEVEL0 = 0,	/* direct HW translation! */
+	VOLTAGE_SWING_LEVEL1,
+	VOLTAGE_SWING_LEVEL2,
+	VOLTAGE_SWING_LEVEL3,
+	VOLTAGE_SWING_MAX_LEVEL = VOLTAGE_SWING_LEVEL3
+};
+
+enum pre_emphasis {
+	PRE_EMPHASIS_DISABLED = 0,	/* direct HW translation! */
+	PRE_EMPHASIS_LEVEL1,
+	PRE_EMPHASIS_LEVEL2,
+	PRE_EMPHASIS_LEVEL3,
+	PRE_EMPHASIS_MAX_LEVEL = PRE_EMPHASIS_LEVEL3
+};
+
+enum dpcd_value_mask {
+	DPCD_VALUE_MASK_MAX_LANE_COUNT_LANE_COUNT = 0x1F,
+	DPCD_VALUE_MASK_MAX_LANE_COUNT_TPS3_SUPPORTED = 0x40,
+	DPCD_VALUE_MASK_MAX_LANE_COUNT_ENHANCED_FRAME_EN = 0x80,
+	DPCD_VALUE_MASK_MAX_DOWNSPREAD = 0x01,
+	DPCD_VALUE_MASK_LANE_ALIGN_STATUS_INTERLANE_ALIGN_DONE = 0x01
+};
+
+enum dp_power_state {
+	DP_POWER_STATE_D0 = 1,
+	DP_POWER_STATE_D3
+};
+
+enum dpcd_downstream_port_types {
+	DPCD_DOWNSTREAM_DP,
+	DPCD_DOWNSTREAM_VGA,
+	DPCD_DOWNSTREAM_DVI_HDMI,
+	/* has no EDID (TV, CV) */
+	DPCD_DOWNSTREAM_NON_DDC
+};
+
+enum edp_revision {
+	/* eDP version 1.1 or lower */
+	EDP_REVISION_11 = 0x00,
+	/* eDP version 1.2 */
+	EDP_REVISION_12 = 0x01,
+	/* eDP version 1.3 */
+	EDP_REVISION_13 = 0x02
+};
+
+enum lane_count {
+	LANE_COUNT_UNKNOWN = 0,
+	LANE_COUNT_ONE = 1,
+	LANE_COUNT_TWO = 2,
+	LANE_COUNT_FOUR = 4,
+	LANE_COUNT_EIGHT = 8,
+	LANE_COUNT_DP_MAX = LANE_COUNT_FOUR
+};
+
+/* This is actually a reference clock (27MHz) multiplier
+ * 162MBps bandwidth for 1.62GHz like rate,
+ * 270MBps for 2.70GHz,
+ * 324MBps for 3.24Ghz,
+ * 540MBps for 5.40GHz
+ */
+enum link_rate {
+	LINK_RATE_UNKNOWN = 0,
+	LINK_RATE_LOW = 0x06,
+	LINK_RATE_HIGH = 0x0A,
+	LINK_RATE_RBR2 = 0x0C,
+	LINK_RATE_HIGH2 = 0x14
+};
+
+enum {
+	LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/
+};
+
+enum link_spread {
+	LINK_SPREAD_DISABLED = 0x00,
+	/* 0.5 % downspread 30 kHz */
+	LINK_SPREAD_05_DOWNSPREAD_30KHZ = 0x10,
+	/* 0.5 % downspread 33 kHz */
+	LINK_SPREAD_05_DOWNSPREAD_33KHZ = 0x11
+};
+
+/* DPCD_ADDR_DOWNSTREAM_PORT_PRESENT register value */
+union dpcd_downstream_port {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t PRESENT:1;
+		uint8_t TYPE:2;
+		uint8_t FORMAT_CONV:1;
+		uint8_t RESERVED:4;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t RESERVED:4;
+		uint8_t FORMAT_CONV:1;
+		uint8_t TYPE:2;
+		uint8_t PRESENT:1;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+/* DPCD_ADDR_SINK_COUNT register value */
+union dpcd_sink_count {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t SINK_COUNT:6;
+		uint8_t CP_READY:1;
+		uint8_t RESERVED:1;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t RESERVED:1;
+		uint8_t CP_READY:1;
+		uint8_t SINK_COUNT:6;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+struct link_settings {
+	enum lane_count lane_count;
+	enum link_rate link_rate;
+	enum link_spread link_spread;
+};
+
+struct lane_settings {
+	enum voltage_swing VOLTAGE_SWING;
+	enum pre_emphasis PRE_EMPHASIS;
+	enum post_cursor2 POST_CURSOR2;
+};
+
+struct link_training_settings {
+	struct link_settings link_settings;
+	struct lane_settings lane_settings[LANE_COUNT_DP_MAX];
+	bool allow_invalid_msa_timing_param;
+};
+
+enum hw_dp_training_pattern {
+	HW_DP_TRAINING_PATTERN_1 = 0,
+	HW_DP_TRAINING_PATTERN_2,
+	HW_DP_TRAINING_PATTERN_3
+};
+
+/*TODO: Move this enum test harness*/
+/* Test patterns*/
+enum dp_test_pattern {
+	/* Input data is pass through Scrambler
+	 * and 8b10b Encoder straight to output*/
+	DP_TEST_PATTERN_VIDEO_MODE = 0,
+	/* phy test patterns*/
+	DP_TEST_PATTERN_D102,
+	DP_TEST_PATTERN_SYMBOL_ERROR,
+	DP_TEST_PATTERN_PRBS7,
+
+	DP_TEST_PATTERN_80BIT_CUSTOM,
+	DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE,
+
+	/* Link Training Patterns */
+	DP_TEST_PATTERN_TRAINING_PATTERN1,
+	DP_TEST_PATTERN_TRAINING_PATTERN2,
+	DP_TEST_PATTERN_TRAINING_PATTERN3,
+
+	/* link test patterns*/
+	DP_TEST_PATTERN_COLOR_SQUARES,
+	DP_TEST_PATTERN_COLOR_SQUARES_CEA,
+	DP_TEST_PATTERN_VERTICAL_BARS,
+	DP_TEST_PATTERN_HORIZONTAL_BARS,
+	DP_TEST_PATTERN_COLOR_RAMP,
+
+	/* audio test patterns*/
+	DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED,
+	DP_TEST_PATTERN_AUDIO_SAWTOOTH,
+
+	DP_TEST_PATTERN_UNSUPPORTED
+};
+
+enum dp_panel_mode {
+	/* not required */
+	DP_PANEL_MODE_DEFAULT,
+	/* standard mode for eDP */
+	DP_PANEL_MODE_EDP,
+	/* external chips specific settings */
+	DP_PANEL_MODE_SPECIAL
+};
+
+/**
+ * @brief LinkServiceInitOptions to set certain bits
+ */
+struct link_service_init_options {
+	uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1;
+};
+
+/**
+ * @brief data required to initialize LinkService
+ */
+struct link_service_init_data {
+	/* number of displays indices which the MST Mgr would manange*/
+	uint32_t num_of_displays;
+	enum link_service_type link_type;
+	/*struct mst_mgr_callback_object*topology_change_callback;*/
+	/* native aux access */
+	struct ddc_service *dpcd_access_srv;
+	/* for calling HWSS to program HW */
+	struct hw_sequencer *hwss;
+	/* the source which to register IRQ on */
+	enum dc_irq_source irq_src_hpd_rx;
+	enum dc_irq_source irq_src_dp_sink;
+	/* other init options such as SW Workarounds */
+	struct link_service_init_options init_options;
+	uint32_t connector_enum_id;
+	struct graphics_object_id connector_id;
+	struct adapter_service *adapter_service;
+	struct dc_context *ctx;
+	struct topology_mgr *tm;
+};
+
+/**
+ * @brief LinkServiceInitOptions to set certain bits
+ */
+struct LinkServiceInitOptions {
+	uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1;
+};
+
+/* DPCD_ADDR_TRAINING_LANEx_SET registers value */
+union dpcd_training_lane_set {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t VOLTAGE_SWING_SET:2;
+		uint8_t MAX_SWING_REACHED:1;
+		uint8_t PRE_EMPHASIS_SET:2;
+		uint8_t MAX_PRE_EMPHASIS_REACHED:1;
+		/* following is reserved in DP 1.1 */
+		uint8_t POST_CURSOR2_SET:2;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t POST_CURSOR2_SET:2;
+		uint8_t MAX_PRE_EMPHASIS_REACHED:1;
+		uint8_t PRE_EMPHASIS_SET:2;
+		uint8_t MAX_SWING_REACHED:1;
+		uint8_t VOLTAGE_SWING_SET:2;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+/* DPCD_ADDR_TRAINING_LANEx_SET2 registers value - since DP 1.2 */
+union dpcd_training_lanes_set2 {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t LANE0_POST_CURSOR2_SET:2;
+		uint8_t LANE0_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE0_RESERVED:1;
+		uint8_t LANE1_POST_CURSOR2_SET:2;
+		uint8_t LANE1_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE1_RESERVED:1;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t LANE1_RESERVED:1;
+		uint8_t LANE1_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE1_POST_CURSOR2_SET:2;
+		uint8_t LANE0_RESERVED:1;
+		uint8_t LANE0_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE0_POST_CURSOR2_SET:2;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+/**
+ * @brief represent the 16 byte
+ *  global unique identifier
+ */
+struct mst_guid {
+	uint8_t ids[16];
+};
+
+/**
+ * @brief represents the relative address used
+ * to identify a node in MST topology network
+ */
+struct mst_rad {
+	/* number of links. rad[0] up to
+	 * rad [linkCount - 1] are valid. */
+	uint32_t rad_link_count;
+	/* relative address. rad[0] is the
+	 * first device connected to the source.	*/
+	uint8_t rad[15];
+	/* extra 10 bytes for underscores; for e.g.:2_1_8*/
+	int8_t rad_str[25];
+};
+
+/**
+ * @brief this structure is used to report
+ * properties associated to a sink device
+ */
+struct mst_sink_info {
+	/* global unique identifier */
+	struct mst_guid guid;
+	/* relative address */
+	struct mst_rad  rad;
+	/* total bandwidth available on the DP connector */
+	uint32_t total_available_bandwidth_in_mbps;
+	/* bandwidth allocated to the sink device. */
+	uint32_t allocated_bandwidth_in_mbps;
+	/* bandwidth consumed to support for the current mode. */
+	uint32_t consumed_bandwidth_in_mbps;
+};
+
+/**
+ * @brief represent device information in MST topology
+ */
+struct mst_device_info {
+	/* global unique identifier*/
+	struct mst_guid guid;
+	/* relative address*/
+	struct mst_rad  rad;
+};
+
+/* DP MST stream allocation (payload bandwidth number) */
+struct dp_mst_stream_allocation {
+	uint8_t vcp_id;
+	/* number of slots required for the DP stream in
+	 * transport packet */
+	uint8_t slot_count;
+};
+
+/* DP MST stream allocation table */
+struct dp_mst_stream_allocation_table {
+	/* number of DP video streams */
+	int stream_count;
+	/* array of stream allocations */
+	struct dp_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM];
+};
+
+struct dp_test_event_data {
+	/*size of parameters (starting from params) in bytes*/
+	uint32_t size;
+	/*parameters block*/
+	uint32_t params[1];
+};
+
+struct psr_caps {
+	/* These parameters are from PSR capabilities reported by Sink DPCD. */
+	uint8_t psr_version;
+	uint32_t psr_rfb_setup_time;
+	bool psr_exit_link_training_req;
+
+	/* These parameters are calculated in Driver, based on display timing
+	 * and Sink capabilities.
+	 * If VBLANK region is too small and Sink takes a long time to power up
+	 * Remote Frame Buffer, it may take an extra frame to enter PSR */
+	bool psr_frame_capture_indication_req;
+	uint32_t psr_sdp_transmit_line_num_deadline;
+};
+
+#endif /*__DAL_LINK_SERVICE_TYPES_H__*/
diff --git a/drivers/gpu/drm/amd/dal/include/logger_interface.h b/drivers/gpu/drm/amd/dal/include/logger_interface.h
new file mode 100644
index 000000000000..4d945eabb07f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/logger_interface.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LOGGER_INTERFACE_H__
+#define __DAL_LOGGER_INTERFACE_H__
+
+#include "logger_types.h"
+
+struct dal_logger;
+struct dc_context;
+union logger_flags;
+
+/*
+ * TODO: This logger functionality needs to be implemented and reworked.
+ */
+
+
+/*
+ *
+ * DAL logger functionality
+ *
+ */
+
+struct dal_logger *dal_logger_create(struct dc_context *ctx);
+
+uint32_t dal_logger_destroy(struct dal_logger **logger);
+
+uint32_t dal_logger_get_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor);
+
+uint32_t dal_logger_set_mask(
+		struct dal_logger *logger,
+		enum log_major lvl_major, enum log_minor lvl_minor);
+
+uint32_t dal_logger_get_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major);
+
+void dal_logger_set_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major, uint32_t log_mask);
+
+uint32_t dal_logger_unset_mask(
+		struct dal_logger *logger,
+		enum log_major lvl_major, enum log_minor lvl_minor);
+
+bool dal_logger_should_log(
+		struct dal_logger *logger,
+		enum log_major major,
+		enum log_minor minor);
+
+uint32_t dal_logger_get_flags(
+		struct dal_logger *logger);
+
+void dal_logger_set_flags(
+		struct dal_logger *logger,
+		union logger_flags flags);
+
+void dal_logger_write(
+		struct dal_logger *logger,
+		enum log_major major,
+		enum log_minor minor,
+		const char *msg,
+		...);
+
+void dal_logger_append(
+		struct log_entry *entry,
+		const char *msg,
+		...);
+
+uint32_t dal_logger_read(
+		struct dal_logger *logger,
+		uint32_t output_buffer_size,
+		char *output_buffer,
+		uint32_t *bytes_read,
+		bool single_line);
+
+void dal_logger_open(
+		struct dal_logger *logger,
+		struct log_entry *entry,
+		enum log_major major,
+		enum log_minor minor);
+
+void dal_logger_close(struct log_entry *entry);
+
+uint32_t dal_logger_get_buffer_size(struct dal_logger *logger);
+
+uint32_t dal_logger_set_buffer_size(
+		struct dal_logger *logger,
+		uint32_t new_size);
+
+const struct log_major_info *dal_logger_enum_log_major_info(
+		struct dal_logger *logger,
+		unsigned int enum_index);
+
+const struct log_minor_info *dal_logger_enum_log_minor_info(
+		struct dal_logger *logger,
+		enum log_major major,
+		unsigned int enum_index);
+
+/* Any function which is empty or have incomplete implementation should be
+ * marked by this macro.
+ * Note that the message will be printed exactly once for every function
+ * it is used in order to avoid repeating of the same message. */
+#define DAL_LOGGER_NOT_IMPL(log_minor, fmt, ...) \
+{ \
+	static bool print_not_impl = true; \
+\
+	if (print_not_impl == true) { \
+		print_not_impl = false; \
+		dal_logger_write(ctx->logger, LOG_MAJOR_WARNING, \
+		log_minor, "DAL_NOT_IMPL: " fmt, ##__VA_ARGS__); \
+	} \
+}
+
+/******************************************************************************
+ * Convenience macros to save on typing.
+ *****************************************************************************/
+
+#define DC_ERROR(...) \
+	dal_logger_write(dc_ctx->logger, \
+		LOG_MAJOR_ERROR, LOG_MINOR_COMPONENT_DC, \
+		__VA_ARGS__);
+
+#define DC_SYNC_INFO(...) \
+	dal_logger_write(dc_ctx->logger, \
+		LOG_MAJOR_SYNC, LOG_MINOR_SYNC_TIMING, \
+		__VA_ARGS__);
+
+#endif /* __DAL_LOGGER_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/logger_types.h b/drivers/gpu/drm/amd/dal/include/logger_types.h
new file mode 100644
index 000000000000..614799907e19
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/logger_types.h
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LOGGER_TYPES_H__
+#define __DAL_LOGGER_TYPES_H__
+
+
+/*
+ * TODO: This logger functionality needs to be implemented and reworked.
+ */
+
+
+struct dal_logger;
+
+enum log_major {
+/*00*/
+	LOG_MAJOR_ERROR = 0,	/*< DAL subcomponent error MSG*/
+/*01*/  LOG_MAJOR_WARNING,	/*< DAL subcomponent warning MSG*/
+/*02*/  LOG_MAJOR_INTERFACE_TRACE,/*< DAL subcomponent interface tracing*/
+/*03*/  LOG_MAJOR_HW_TRACE,	/*< Log ASIC register read/write,
+				* ATOMBIOS exec table call and delays*/
+
+/*04*/  LOG_MAJOR_MST,		/*< related to multi-stream*/
+/*05*/  LOG_MAJOR_DCS,		/*< related to Dcs*/
+/*06*/  LOG_MAJOR_DCP,		/*< related to Dcp grph and ovl,gamam and csc*/
+/*07*/  LOG_MAJOR_BIOS,		/*< related to BiosParser*/
+/*08*/  LOG_MAJOR_REGISTER,	/*< register access*/
+/*09*/  LOG_MAJOR_INFO_PACKETS,	/*< info packets*/
+/*10*/  LOG_MAJOR_DSAT,		/*< related
+				*	to Display System Analysis Tool*/
+/*11*/  LOG_MAJOR_EC,		/*< External Components - MCIL Events/queries,
+				*	PPLib notifications/queries*/
+/*12*/  LOG_MAJOR_BWM,		/*< related to Bandwidth Manager*/
+/*13*/  LOG_MAJOR_MODE_ENUM,	/*< related to mode enumeration*/
+/*14*/  LOG_MAJOR_I2C_AUX,	/*< i2c and aux channel log*/
+/*15*/  LOG_MAJOR_LINE_BUFFER,	/*< Line Buffer object logging activity*/
+/*16*/  LOG_MAJOR_HWSS,		/*< HWSS object logging activity*/
+/*17*/  LOG_MAJOR_OPTIMIZATION,	/*< Optimization code path*/
+/*18*/  LOG_MAJOR_PERF_MEASURE,	/*< Performance measurement dumps*/
+/*19*/  LOG_MAJOR_SYNC,		/*< related to HW and SW Synchronization*/
+/*20*/  LOG_MAJOR_BACKLIGHT,	/*< related to backlight */
+/*21*/  LOG_MAJOR_INTERRUPTS,	/*< logging for all interrupts */
+
+/*22*/  LOG_MAJOR_TM,		/*< related to Topology Manager*/
+/*23*/  LOG_MAJOR_DISPLAY_SERVICE, /*< related to Display Service*/
+/*24*/	LOG_MAJOR_FEATURE_OVERRIDE,	/*< related to features*/
+/*25*/	LOG_MAJOR_DETECTION,	/*< related to detection*/
+	LOG_MAJOR_COUNT,	/*< count of the Major categories*/
+};
+
+/**
+* @brief defines minor switch for logging.  each of these define sub category
+*        of log message per LogMajor
+*/
+
+
+enum log_minor {
+
+	/* Special case for 'all' checkbox */
+	LOG_MINOR_MASK_ALL = (uint32_t)-1, /* 0xFFFFFFFF */
+/**
+* @brief defines minor category for
+*         LOG_MAJOR_ERROR,
+*         LOG_MAJOR_WARNING,
+*         LOG_MAJOR_INTERFACE_TRACE
+*
+* @note  each DAL subcomponent should have a corresponding enum
+*/
+	LOG_MINOR_COMPONENT_LINK_SERVICE = 0,
+	LOG_MINOR_COMPONENT_DAL_INTERFACE,
+	LOG_MINOR_COMPONENT_HWSS,
+	LOG_MINOR_COMPONENT_ADAPTER_SERVICE,
+	LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+	LOG_MINOR_COMPONENT_TOPOLOGY_MANAGER,
+	LOG_MINOR_COMPONENT_ENCODER,
+	LOG_MINOR_COMPONENT_I2C_AUX,
+	LOG_MINOR_COMPONENT_AUDIO,
+	LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE,
+	LOG_MINOR_COMPONENT_DMCU,
+	LOG_MINOR_COMPONENT_GPU,
+	LOG_MINOR_COMPONENT_CONTROLLER,
+	LOG_MINOR_COMPONENT_ISR,
+	LOG_MINOR_COMPONENT_BIOS,
+	LOG_MINOR_COMPONENT_DC,
+	LOG_MINOR_COMPONENT_IRQ_SERVICE,
+
+/**
+* @brief define minor category for LogMajor_HardwareTrace
+*
+* @note  defines functionality based HW programming trace
+*/
+	LOG_MINOR_HW_TRACE_MST = 0,
+	LOG_MINOR_HW_TRACE_TRAVIS,
+	LOG_MINOR_HW_TRACE_HOTPLUG,
+	LOG_MINOR_HW_TRACE_LINK_TRAINING,
+	LOG_MINOR_HW_TRACE_SET_MODE,
+	LOG_MINOR_HW_TRACE_RESUME_S3,
+	LOG_MINOR_HW_TRACE_RESUME_S4,
+	LOG_MINOR_HW_TRACE_BOOTUP,
+	LOG_MINOR_HW_TRACE_AUDIO,
+	LOG_MINOR_HW_TRACE_HPD_IRQ,
+	LOG_MINOR_HW_TRACE_INTERRUPT,
+	LOG_MINOR_HW_TRACE_MPO,
+
+/**
+* @brief defines minor category for LogMajor_Mst
+*
+* @note  define sub functionality related to MST
+*/
+	LOG_MINOR_MST_IRQ_HPD_RX = 0,
+	LOG_MINOR_MST_IRQ_TIMER,
+	LOG_MINOR_MST_NATIVE_AUX,
+	LOG_MINOR_MST_SIDEBAND_MSG,
+	LOG_MINOR_MST_MSG_TRANSACTION,
+	LOG_MINOR_MST_SIDEBAND_MSG_PARSED,
+	LOG_MINOR_MST_MSG_TRANSACTION_PARSED,
+	LOG_MINOR_MST_AUX_MSG_DPCD_ACCESS,
+	LOG_MINOR_MST_PROGRAMMING,
+	LOG_MINOR_MST_TOPOLOGY_DISCOVERY,
+	LOG_MINOR_MST_CONVERTER_CAPS,
+
+/**
+* @brief defines minor category for LogMajor_DCS
+*
+* @note  should define sub functionality related to Dcs
+*/
+	LOG_MINOR_DCS_EDID_EMULATOR = 0,
+	LOG_MINOR_DCS_DONGLE_DETECTION,
+
+/**
+* @brief defines minor category for DCP
+*
+* @note  should define sub functionality related to Dcp
+*/
+	LOG_MINOR_DCP_GAMMA_GRPH = 0,
+	LOG_MINOR_DCP_GAMMA_OVL,
+	LOG_MINOR_DCP_CSC_GRPH,
+	LOG_MINOR_DCP_CSC_OVL,
+	LOG_MINOR_DCP_SCALER,
+	LOG_MINOR_DCP_SCALER_TABLES,
+/**
+* @brief defines minor category for LogMajor_Bios
+*
+* @note define sub functionality related to BiosParser
+*/
+	LOG_MINOR_BIOS_CMD_TABLE = 0,
+/**
+* @brief defines minor category for LogMajor_Bios
+*
+* @note define sub functionality related to BiosParser
+*/
+	LOG_MINOR_REGISTER_INDEX = 0,
+/**
+* @brief defines minor category for info packets
+*
+*/
+	LOG_MINOR_INFO_PACKETS_HDMI = 0,
+
+/**
+* @brief defines minor category for LOG_MAJOR_DSAT
+*
+* @note define sub functionality related to Display System Analysis Tool
+*/
+	LOG_MINOR_DSAT_LOGGER = 0,
+	LOG_MINOR_DSAT_GET_EDID,
+	LOG_MINOR_DSAT_EDID_OVERRIDE,
+	LOG_MINOR_DSAT_SET_ADJUSTMENTS,
+	LOG_MINOR_DSAT_GET_ADJUSTMENTS,
+
+/**
+* @brief defines minor category for LOG_MAJOR_EC
+*
+* @note define sub functionality related to External components notifications
+*/
+	LOG_MINOR_EC_PPLIB_NOTIFY = 0,
+	LOG_MINOR_EC_PPLIB_QUERY,
+
+/**
+* @brief defines minor category for LOG_MAJOR_BWM
+*
+* @note define sub functionality related to Bandwidth Manager
+*/
+	LOG_MINOR_BWM_MODE_VALIDATION = 0,
+	LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS,
+
+/**
+* @brief define minor category for LogMajor_ModeEnum
+*
+* @note  defines functionality mode enumeration trace
+*/
+	LOG_MINOR_MODE_ENUM_BEST_VIEW_CANDIDATES = 0,
+	LOG_MINOR_MODE_ENUM_VIEW_SOLUTION,
+	LOG_MINOR_MODE_ENUM_TS_LIST_BUILD,
+	LOG_MINOR_MODE_ENUM_TS_LIST,
+	LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST,
+	LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST_UPDATE,
+
+/**
+* @brief defines minor category for LogMajor_I2C_AUX
+*
+* @note define sub functionality related to I2c and Aux Channel Log
+*/
+	LOG_MINOR_I2C_AUX_LOG = 0,
+	LOG_MINOR_I2C_AUX_AUX_TIMESTAMP,
+	LOG_MINOR_I2C_AUX_CFG,
+
+/**
+* @brief defines minor category for LogMajor_LineBuffer
+*
+* @note define sub functionality related to LineBuffer
+*/
+	LOG_MINOR_LINE_BUFFER_POWERGATING = 0,
+
+/**
+* @brief defines minor category for LogMajor_HWSS
+*
+* @note define sub functionality related to HWSS
+*/
+	LOG_MINOR_HWSS_TAPS_VALIDATION = 0,
+
+/**
+* @brief defines minor category for LogMajor_Optimization
+*
+* @note define sub functionality related to Optimization
+*/
+	LOG_MINOR_OPTMZ_GENERAL = 0,
+	LOG_MINOR_OPTMZ_DO_NOT_TURN_OFF_VCC_DURING_SET_MODE,
+
+/**
+* @brief defines minor category for LogMajor_PerfMeasure
+*
+* @note define sub functionality related to Performance measurement dumps
+*/
+	LOG_MINOR_PERF_MEASURE_GENERAL = 0,
+	LOG_MINOR_PERF_MEASURE_HEAP_MEMORY,
+
+/**
+* @brief defines minor category for LogMajor_Sync
+*
+* @note define sub functionality related to HW and SW Synchronization
+*/
+	LOG_MINOR_SYNC_HW_CLOCK_ADJUST = 0,
+	LOG_MINOR_SYNC_TIMING,
+
+/**
+* @brief defines minor category for LogMajor_Backlight
+*
+* @note define sub functionality related to backlight (including VariBright)
+*/
+	LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS = 0,
+	LOG_MINOR_BACKLIGHT_DMCU_DELTALUT,
+	LOG_MINOR_BACKLIGHT_DMCU_BUILD_DELTALUT,
+	LOG_MINOR_BACKLIGHT_INTERFACE,
+	LOG_MINOR_BACKLIGHT_LID,
+
+/**
+* @brief defines minor category for LOG_MAJOR_TM
+*
+* @note define sub functionality related to Topology Manager
+*/
+	LOG_MINOR_TM_INFO = 0,
+	LOG_MINOR_TM_IFACE_TRACE,
+	LOG_MINOR_TM_RESOURCES,
+	LOG_MINOR_TM_ENCODER_CTL,
+	LOG_MINOR_TM_ENG_ASN,
+	LOG_MINOR_TM_CONTROLLER_ASN,
+	LOG_MINOR_TM_PWR_GATING,
+	LOG_MINOR_TM_BUILD_DSP_PATH,
+	LOG_MINOR_TM_DISPLAY_DETECT,
+	LOG_MINOR_TM_LINK_SRV,
+	LOG_MINOR_TM_NOT_IMPLEMENTED,
+	LOG_MINOR_TM_COFUNC_PATH,
+
+/**
+* @brief defines minor category for LOG_MAJOR_DISPLAY_SERVICE
+*
+* @note define sub functionality related to Display Service
+*/
+	LOG_MINOR_DS_MODE_SETTING = 0,
+
+/**
+* @brief defines minor category for LOG_MAJOR_FEATURE_OVERRIDE
+*
+* @note define sub functionality related to features in adapter service
+*/
+	LOG_MINOR_FEATURE_OVERRIDE = 0,
+
+/**
+* @brief defines minor category for LOG_MAJOR_DETECTION
+*
+* @note define sub functionality related to detection
+*/
+	LOG_MINOR_DETECTION_EDID_PARSER = 0,
+	LOG_MINOR_DETECTION_DP_CAPS,
+};
+
+union logger_flags {
+	struct {
+		uint32_t ENABLE_CONSOLE:1; /* Print to console */
+		uint32_t ENABLE_BUFFER:1; /* Print to buffer */
+		uint32_t RESERVED:30;
+	} bits;
+	uint32_t value;
+};
+
+struct log_entry {
+
+	struct dal_logger *logger;
+	enum log_major major;
+	enum log_minor minor;
+
+	char *buf;
+	uint32_t buf_offset;
+	uint32_t max_buf_bytes;
+};
+
+/**
+* Structure for enumerating LogMajors and LogMinors
+*/
+
+#define MAX_MAJOR_NAME_LEN 32
+#define MAX_MINOR_NAME_LEN 32
+
+struct log_major_info {
+	enum log_major major;
+	char major_name[MAX_MAJOR_NAME_LEN];
+};
+
+struct log_minor_info {
+	enum log_minor minor;
+	char minor_name[MAX_MINOR_NAME_LEN];
+};
+
+#endif /* __DAL_LOGGER_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/scaler_types.h b/drivers/gpu/drm/amd/dal/include/scaler_types.h
new file mode 100644
index 000000000000..db52dbc72383
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/scaler_types.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SCALER_TYPES_H__
+#define __DAL_SCALER_TYPES_H__
+
+#include "signal_types.h"
+#include "fixed31_32.h"
+#include "dc_types.h"
+
+enum pixel_type {
+	PIXEL_TYPE_30BPP = 1,
+	PIXEL_TYPE_20BPP
+};
+
+/*overscan or window*/
+struct overscan_info {
+	uint32_t left;
+	uint32_t right;
+	uint32_t top;
+	uint32_t bottom;
+};
+
+struct mp_scaling_data {
+	struct rect viewport;
+	struct view dst_res;
+	struct overscan_info overscan;
+	struct scaling_taps taps;
+	struct scaling_ratios ratios;
+};
+
+struct scaler_validation_params {
+	uint32_t INTERLACED:1;
+	uint32_t CHROMA_SUB_SAMPLING:1;
+
+	uint32_t line_buffer_size;
+	uint32_t display_clock; /* in KHz */
+	uint32_t actual_pixel_clock; /* in KHz */
+	struct view source_view;
+	struct view dest_view;
+	enum signal_type signal_type;
+
+	struct scaling_taps taps_requested;
+	enum pixel_format pixel_format;
+	enum dc_rotation_angle rotation;
+};
+
+struct adjustment_factor {
+	int32_t adjust;	 /* Actual adjustment value * lDivider */
+	uint32_t divider;
+};
+
+struct sharpness_adjustment {
+	int32_t sharpness;
+	bool enable_sharpening;
+};
+
+enum scaling_options {
+	SCALING_BYPASS = 0,
+	SCALING_ENABLE
+};
+
+/* same as Hw register */
+enum filter_type {
+	FILTER_TYPE_V_LOW_PASS = 0x0,
+	FILTER_TYPE_V_HIGH_PASS = 0x1,
+	FILTER_TYPE_H_LUMA = 0x2,
+	FILTER_TYPE_H_CHROMA = 0x3
+};
+
+/* Validation Result enumeration */
+enum scaler_validation_code {
+	SCALER_VALIDATION_OK = 0,
+	SCALER_VALIDATION_INVALID_INPUT_PARAMETERS,
+	SCALER_VALIDATION_SCALING_RATIO_NOT_SUPPORTED,
+	SCALER_VALIDATION_SOURCE_VIEW_WIDTH_EXCEEDING_LIMIT,
+	SCALER_VALIDATION_DISPLAY_CLOCK_BELOW_PIXEL_CLOCK,
+	SCALER_VALIDATION_FAILURE_PREDEFINED_TAPS_NUMBER
+};
+
+
+#define FILTER_TYPE_MASK 0x0000000FL
+#define TWO_TAPS 2
+
+struct init_int_and_frac {
+	uint32_t integer;
+	uint32_t fraction;
+};
+
+struct scl_ratios_inits {
+	uint32_t bottom_enable;
+	uint32_t h_int_scale_ratio;
+	uint32_t v_int_scale_ratio;
+	struct init_int_and_frac h_init;
+	struct init_int_and_frac v_init;
+	struct init_int_and_frac v_init_bottom;
+};
+
+union scaler_flags {
+	uint32_t raw;
+	struct {
+		uint32_t INTERLACED:1;
+		uint32_t DOUBLE_SCAN_MODE:1;
+		/* this one is legacy flag only used in DCE80 */
+		uint32_t RGB_COLOR_SPACE:1;
+		uint32_t PIPE_LOCK_REQ:1;
+		/* 4 */
+		uint32_t WIDE_DISPLAY:1;
+		uint32_t OTHER_PIPE:1;
+		uint32_t SHOULD_PROGRAM_VIEWPORT:1;
+		uint32_t SHOULD_UNLOCK:1;
+		/* 8 */
+		uint32_t SHOULD_PROGRAM_ALPHA:1;
+		uint32_t SHOW_COLOURED_BORDER:1;
+
+		uint32_t  RESERVED:22;
+	} bits;
+};
+
+struct scaler_data {
+	struct view src_res;
+	struct view dst_res;
+	struct overscan_info overscan;
+	struct scaling_taps taps;
+	struct adjustment_factor scale_ratio_hp_factor;
+	struct adjustment_factor scale_ratio_lp_factor;
+	enum pixel_type pixel_type; /*legacy*/
+	struct sharpness_adjustment sharp_gain;
+
+	union scaler_flags flags;
+	int32_t h_sharpness;
+	int32_t v_sharpness;
+
+	struct view src_res_wide_display;
+	struct view dst_res_wide_display;
+
+	/* it is here because of the HW bug in NI (UBTS #269539)
+	causes glitches in this VBI signal. It shouldn't change after
+	initialization, kind of a const */
+	const struct hw_crtc_timing *hw_crtc_timing;
+
+	struct rect viewport;
+
+	enum pixel_format dal_pixel_format;/*plane concept*/
+	/*stereoformat TODO*/
+	/*hwtotation TODO*/
+
+	const struct scaling_ratios *ratios;
+};
+
+enum bypass_type {
+	/* 00 - 00 - Manual Centering, Manual Replication */
+	BYPASS_TYPE_MANUAL = 0,
+	/* 01 - 01 - Auto-Centering, No Replication */
+	BYPASS_TYPE_AUTO_CENTER = 1,
+	/* 02 - 10 - Auto-Centering, Auto-Replication */
+	BYPASS_TYPE_AUTO_REPLICATION = 3
+};
+
+struct replication_factor {
+	uint32_t h_manual;
+	uint32_t v_manual;
+};
+
+enum ram_filter_type {
+	FILTER_TYPE_RGB_Y_VERTICAL = 0,	/* 0 - RGB/Y Vertical filter */
+	FILTER_TYPE_CBCR_VERTICAL = 1,	/* 1 - CbCr  Vertical filter */
+	FILTER_TYPE_RGB_Y_HORIZONTAL   = 2, /* 1 - RGB/Y Horizontal filter */
+	FILTER_TYPE_CBCR_HORIZONTAL   = 3, /* 3 - CbCr  Horizontal filter */
+	FILTER_TYPE_ALPHA_VERTICAL    = 4, /* 4 - Alpha Vertical filter. */
+	FILTER_TYPE_ALPHA_HORIZONTAL  = 5, /* 5 - Alpha Horizontal filter. */
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/set_mode_types.h b/drivers/gpu/drm/amd/dal/include/set_mode_types.h
new file mode 100644
index 000000000000..97160fe7484c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/set_mode_types.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SET_MODE_TYPES_H__
+#define __DAL_SET_MODE_TYPES_H__
+
+#include "dc_types.h"
+
+
+/* GTC group number */
+enum gtc_group {
+	GTC_GROUP_DISABLED,
+	GTC_GROUP_1,
+	GTC_GROUP_2,
+	GTC_GROUP_3,
+	GTC_GROUP_4,
+	GTC_GROUP_5,
+	GTC_GROUP_6,
+	GTC_GROUP_MAX
+};
+
+/* Info frame packet status */
+enum info_frame_flag {
+	INFO_PACKET_PACKET_INVALID = 0,
+	INFO_PACKET_PACKET_VALID = 1,
+	INFO_PACKET_PACKET_RESET = 2,
+	INFO_PACKET_PACKET_UPDATE_SCAN_TYPE = 8
+};
+
+/* Info frame types */
+enum info_frame_type {
+	INFO_FRAME_GAMUT = 0x0A,
+	INFO_FRAME_VENDOR_INFO = 0x81,
+	INFO_FRAME_AVI = 0x82
+};
+
+/* Info frame versions */
+enum info_frame_version {
+	INFO_FRAME_VERSION_1 = 1,
+	INFO_FRAME_VERSION_2 = 2,
+	INFO_FRAME_VERSION_3 = 3
+};
+
+/* Info frame size */
+enum info_frame_size {
+	INFO_FRAME_SIZE_AVI = 13,
+	INFO_FRAME_SIZE_VENDOR = 25,
+	INFO_FRAME_SIZE_AUDIO = 10
+};
+
+struct hdmi_info_frame_header {
+	uint8_t info_frame_type;
+	uint8_t version;
+	uint8_t length;
+};
+
+#pragma pack(push)
+#pragma pack(1)
+
+struct info_packet_raw_data {
+	uint8_t hb0;
+	uint8_t hb1;
+	uint8_t hb2;
+	uint8_t sb[28]; /* sb0~sb27 */
+};
+
+union hdmi_info_packet {
+	struct avi_info_frame {
+		struct hdmi_info_frame_header header;
+
+		uint8_t CHECK_SUM:8;
+
+		uint8_t S0_S1:2;
+		uint8_t B0_B1:2;
+		uint8_t A0:1;
+		uint8_t Y0_Y1_Y2:3;
+
+		uint8_t R0_R3:4;
+		uint8_t M0_M1:2;
+		uint8_t C0_C1:2;
+
+		uint8_t SC0_SC1:2;
+		uint8_t Q0_Q1:2;
+		uint8_t EC0_EC2:3;
+		uint8_t ITC:1;
+
+		uint8_t VIC0_VIC7:8;
+
+		uint8_t PR0_PR3:4;
+		uint8_t CN0_CN1:2;
+		uint8_t YQ0_YQ1:2;
+
+		uint16_t bar_top;
+		uint16_t bar_bottom;
+		uint16_t bar_left;
+		uint16_t bar_right;
+
+		uint8_t reserved[14];
+	} bits;
+
+	struct info_packet_raw_data packet_raw_data;
+};
+
+struct info_packet {
+	enum info_frame_flag flags;
+	union hdmi_info_packet info_packet_hdmi;
+};
+
+struct info_frame {
+	struct info_packet avi_info_packet;
+	struct info_packet gamut_packet;
+	struct info_packet vendor_info_packet;
+	struct info_packet spd_info_packet;
+};
+
+
+
+#pragma pack(pop)
+
+#endif /* __DAL_SET_MODE_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/signal_types.h b/drivers/gpu/drm/amd/dal/include/signal_types.h
new file mode 100644
index 000000000000..a50f7ed74a33
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/signal_types.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_SIGNAL_TYPES_H__
+#define __DC_SIGNAL_TYPES_H__
+
+enum signal_type {
+	SIGNAL_TYPE_NONE		= 0L,		/* no signal */
+	SIGNAL_TYPE_DVI_SINGLE_LINK	= (1 << 0),
+	SIGNAL_TYPE_DVI_DUAL_LINK	= (1 << 1),
+	SIGNAL_TYPE_HDMI_TYPE_A		= (1 << 2),
+	SIGNAL_TYPE_LVDS		= (1 << 3),
+	SIGNAL_TYPE_RGB			= (1 << 4),
+	SIGNAL_TYPE_DISPLAY_PORT	= (1 << 5),
+	SIGNAL_TYPE_DISPLAY_PORT_MST	= (1 << 6),
+	SIGNAL_TYPE_EDP			= (1 << 7),
+	SIGNAL_TYPE_WIRELESS		= (1 << 8),	/* Wireless Display */
+	SIGNAL_TYPE_VIRTUAL		= (1 << 9),	/* Virtual Display */
+
+	SIGNAL_TYPE_COUNT		= 10,
+	SIGNAL_TYPE_ALL			= (1 << SIGNAL_TYPE_COUNT) - 1
+};
+
+/* help functions for signal types manipulation */
+bool dc_is_hdmi_signal(enum signal_type signal);
+bool dc_is_dp_sst_signal(enum signal_type signal);
+bool dc_is_dp_signal(enum signal_type signal);
+bool dc_is_dp_external_signal(enum signal_type signal);
+bool dc_is_analog_signal(enum signal_type signal);
+bool dc_is_embedded_signal(enum signal_type signal);
+bool dc_is_dvi_signal(enum signal_type signal);
+bool dc_is_dvi_single_link_signal(enum signal_type signal);
+bool dc_is_dual_link_signal(enum signal_type signal);
+bool dc_is_audio_capable_signal(enum signal_type signal);
+bool dc_is_digital_encoder_compatible_signal(enum signal_type signal);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/vector.h b/drivers/gpu/drm/amd/dal/include/vector.h
new file mode 100644
index 000000000000..8233b7c22a07
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/vector.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_VECTOR_H__
+#define __DAL_VECTOR_H__
+
+struct vector {
+	uint8_t *container;
+	uint32_t struct_size;
+	uint32_t count;
+	uint32_t capacity;
+	struct dc_context *ctx;
+};
+
+bool dal_vector_construct(
+	struct vector *vector,
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size);
+
+struct vector *dal_vector_create(
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size);
+
+/* 'initial_value' is optional. If initial_value not supplied,
+ * each "structure" in the vector will contain zeros by default. */
+struct vector *dal_vector_presized_create(
+	struct dc_context *ctx,
+	uint32_t size,
+	void *initial_value,
+	uint32_t struct_size);
+
+void dal_vector_destruct(
+	struct vector *vector);
+
+void dal_vector_destroy(
+	struct vector **vector);
+
+uint32_t dal_vector_get_count(
+	const struct vector *vector);
+
+/* dal_vector_insert_at
+ * reallocate container if necessary
+ * then shell items at right and insert
+ * return if the container modified
+ * do not check that index belongs to container
+ * since the function is private and index is going to be calculated
+ * either with by function or as get_count+1 */
+bool dal_vector_insert_at(
+	struct vector *vector,
+	const void *what,
+	uint32_t position);
+
+bool dal_vector_append(
+	struct vector *vector,
+	const void *item);
+
+/* operator[] */
+void *dal_vector_at_index(
+	const struct vector *vector,
+	uint32_t index);
+
+void dal_vector_set_at_index(
+	const struct vector *vector,
+	const void *what,
+	uint32_t index);
+
+/* create a clone (copy) of a vector */
+struct vector *dal_vector_clone(
+	const struct vector *vector_other);
+
+/* dal_vector_remove_at_index
+ * Shifts elements on the right from remove position to the left,
+ * removing an element at position by overwrite means*/
+bool dal_vector_remove_at_index(
+	struct vector *vector,
+	uint32_t index);
+
+uint32_t dal_vector_capacity(const struct vector *vector);
+
+bool dal_vector_reserve(struct vector *vector, uint32_t capacity);
+
+void dal_vector_clear(struct vector *vector);
+
+/***************************************************************************
+ * Macro definitions of TYPE-SAFE versions of vector set/get functions.
+ ***************************************************************************/
+
+#define DAL_VECTOR_INSERT_AT(vector_type, type_t) \
+	static bool vector_type##_vector_insert_at( \
+		struct vector *vector, \
+		type_t what, \
+		uint32_t position) \
+{ \
+	return dal_vector_insert_at(vector, what, position); \
+}
+
+#define DAL_VECTOR_APPEND(vector_type, type_t) \
+	static bool vector_type##_vector_append( \
+		struct vector *vector, \
+		type_t item) \
+{ \
+	return dal_vector_append(vector, item); \
+}
+
+/* Note: "type_t" is the ONLY token accepted by "checkpatch.pl" and by
+ * "checkcommit" as *return type*.
+ * For uniformity reasons "type_t" is used for all type-safe macro
+ * definitions here. */
+#define DAL_VECTOR_AT_INDEX(vector_type, type_t) \
+	static type_t vector_type##_vector_at_index( \
+		const struct vector *vector, \
+		uint32_t index) \
+{ \
+	return dal_vector_at_index(vector, index); \
+}
+
+#define DAL_VECTOR_SET_AT_INDEX(vector_type, type_t) \
+	static void vector_type##_vector_set_at_index( \
+		const struct vector *vector, \
+		type_t what, \
+		uint32_t index) \
+{ \
+	dal_vector_set_at_index(vector, what, index); \
+}
+
+#endif /* __DAL_VECTOR_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/video_csc_types.h b/drivers/gpu/drm/amd/dal/include/video_csc_types.h
new file mode 100644
index 000000000000..c229f5a7a325
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/video_csc_types.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_VIDEO_CSC_TYPES_H__
+#define __DAL_VIDEO_CSC_TYPES_H__
+
+#include "video_gamma_types.h"
+
+enum ovl_alpha_blending_mode {
+	OVL_ALPHA_PER_PIXEL_GRPH_ALPHA_MODE = 0,
+	OVL_ALPHA_PER_PIXEL_OVL_ALPHA_MODE
+};
+
+enum ovl_color_space {
+	OVL_COLOR_SPACE_UNKNOWN = 0,
+	OVL_COLOR_SPACE_RGB,
+	OVL_COLOR_SPACE_YUV601,
+	OVL_COLOR_SPACE_YUV709
+};
+
+enum ovl_surface_format {
+	OVL_SURFACE_FORMAT_UNKNOWN = 0,
+	OVL_SURFACE_FORMAT_YUY2,
+	OVL_SURFACE_FORMAT_UYVY,
+	OVL_SURFACE_FORMAT_RGB565,
+	OVL_SURFACE_FORMAT_RGB555,
+	OVL_SURFACE_FORMAT_RGB32,
+	OVL_SURFACE_FORMAT_YUV444,
+	OVL_SURFACE_FORMAT_RGB32_2101010
+};
+
+struct ovl_color_adjust_option {
+	uint32_t ALLOW_OVL_RGB_ADJUST:1;
+	uint32_t ALLOW_OVL_TEMPERATURE:1;
+	uint32_t FULL_RANGE:1; /* 0 for limited range it'is default for YUV */
+	uint32_t OVL_MATRIX:1;
+	uint32_t RESERVED:28;
+};
+
+struct overlay_adjust_item {
+	int32_t adjust; /* InInteger */
+	int32_t adjust_divider;
+};
+
+enum overlay_csc_adjust_type {
+	OVERLAY_CSC_ADJUST_TYPE_BYPASS = 0,
+	OVERLAY_CSC_ADJUST_TYPE_HW, /* without adjustments */
+	OVERLAY_CSC_ADJUST_TYPE_SW  /* use adjustments */
+};
+
+enum overlay_gamut_adjust_type {
+	OVERLAY_GAMUT_ADJUST_TYPE_BYPASS = 0,
+	OVERLAY_GAMUT_ADJUST_TYPE_SW /* use adjustments */
+};
+
+#define TEMPERATURE_MATRIX_SIZE 9
+#define MAXTRIX_SIZE TEMPERATURE_MAXTRIX_SIZE
+#define MAXTRIX_SIZE_WITH_OFFSET 12
+
+/* overlay adjustment input */
+union ovl_csc_flag {
+	uint32_t u_all;
+	struct {
+		uint32_t CONFIG_IS_CHANGED:1;
+		uint32_t RESERVED:31;
+	} bits;
+};
+
+struct ovl_csc_adjustment {
+	enum ovl_color_space ovl_cs;
+	struct ovl_color_adjust_option ovl_option;
+	enum dc_color_depth display_color_depth;
+	uint32_t lb_color_depth;
+	enum pixel_format desktop_surface_pixel_format;
+	enum ovl_surface_format ovl_sf;
+	/* API adjustment */
+	struct overlay_adjust_item overlay_brightness;
+	struct overlay_adjust_item overlay_gamma;
+	struct overlay_adjust_item overlay_contrast;
+	struct overlay_adjust_item overlay_saturation;
+	struct overlay_adjust_item overlay_hue; /* unit in degree from API. */
+	int32_t f_temperature[TEMPERATURE_MATRIX_SIZE];
+	uint32_t temperature_divider;
+	/* OEM/Application matrix related. */
+	int32_t matrix[MAXTRIX_SIZE_WITH_OFFSET];
+	uint32_t matrix_divider;
+
+	/* DCE50 parameters */
+	struct regamma_lut regamma;
+	enum overlay_gamma_adjust adjust_gamma_type;
+	enum overlay_csc_adjust_type adjust_csc_type;
+	enum overlay_gamut_adjust_type adjust_gamut_type;
+	union ovl_csc_flag flag;
+
+};
+
+enum ovl_csc_adjust_item {
+	OVERLAY_BRIGHTNESS = 0,
+	OVERLAY_GAMMA,
+	OVERLAY_CONTRAST,
+	OVERLAY_SATURATION,
+	OVERLAY_HUE,
+	OVERLAY_ALPHA,
+	OVERLAY_ALPHA_PER_PIX,
+	OVERLAY_COLOR_TEMPERATURE
+};
+
+struct input_csc_matrix {
+	enum color_space color_space;
+	uint16_t regval[12];
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/video_gamma_types.h b/drivers/gpu/drm/amd/dal/include/video_gamma_types.h
new file mode 100644
index 000000000000..6f9cd3fda21d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/video_gamma_types.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_VIDEO_GAMMA_TYPES_H__
+#define __DAL_VIDEO_GAMMA_TYPES_H__
+
+#include "set_mode_types.h"
+#include "gamma_types.h"
+
+enum overlay_gamma_adjust {
+	OVERLAY_GAMMA_ADJUST_BYPASS,
+	OVERLAY_GAMMA_ADJUST_HW, /* without adjustments */
+	OVERLAY_GAMMA_ADJUST_SW /* use adjustments */
+
+};
+
+union video_gamma_flag {
+	struct {
+		uint32_t CONFIG_IS_CHANGED:1;
+		uint32_t RESERVED:31;
+	} bits;
+	uint32_t u_all;
+};
+
+struct overlay_gamma_parameters {
+	union video_gamma_flag flag;
+	int32_t ovl_gamma_cont;
+	enum overlay_gamma_adjust adjust_type;
+	enum pixel_format desktop_surface;
+	struct regamma_lut regamma;
+
+	/* here we grow with parameters if necessary */
+};
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 02/26] drm/amd/dal: Add DAL Basic Types and Logger
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 01/26] drm/amd/dal: Add dal headers Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 03/26] drm/amd/dal: Fixed point arithmetic Harry Wentland
                     ` (23 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Laying the groundwork for the AMD DAL display driver.
This patch includes the basic services and defines basic
types required by the display driver, such as:
- ASIC register access
- VBIOS access
- Vector and flat_set data structures
- Display signal types
- ASIC versions and IDs
- HW IDs
- Logging functionality

This patch adds Kconfig options to enable the DAL
display driver.
- DRM_AMD_DAL
- DRM_AMD_DAL_VBIOS_PRESENT
- DRM_AMD_DAL_DCE11_0
- DRM_AMD_DAL_DCE10_0
- DEBUG_KERNEL_DAL

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/Kconfig                    |  48 ++
 drivers/gpu/drm/amd/dal/Makefile                   |  21 +
 drivers/gpu/drm/amd/dal/dc/basics/Makefile         |  10 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.c     | 224 +++++
 drivers/gpu/drm/amd/dal/dc/basics/conversion.h     |  49 ++
 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c | 134 +++
 drivers/gpu/drm/amd/dal/dc/basics/logger.c         | 954 +++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/basics/logger.h         |  64 ++
 .../gpu/drm/amd/dal/dc/basics/register_logger.c    | 197 +++++
 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c   | 116 +++
 drivers/gpu/drm/amd/dal/dc/basics/vector.c         | 309 +++++++
 11 files changed, 2126 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/Kconfig
 create mode 100644 drivers/gpu/drm/amd/dal/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c

diff --git a/drivers/gpu/drm/amd/dal/Kconfig b/drivers/gpu/drm/amd/dal/Kconfig
new file mode 100644
index 000000000000..2289c0b10dae
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/Kconfig
@@ -0,0 +1,48 @@
+menu "Display Engine Configuration"
+	depends on DRM && (DRM_AMDSOC || DRM_AMDGPU)
+
+config DRM_AMD_DAL
+        bool "AMD DAL - Enable new display engine
+        help
+          Choose this option if you want to use the new display engine
+          support for AMD SOC.
+
+          Will be deprecated when the DAL component becomes stable and
+          AMDSOC will fully switch to it.
+
+config DRM_AMD_DAL_VBIOS_PRESENT
+        bool "Video Bios available on board"
+        depends on DRM_AMD_DAL
+        help
+         This option is needed to allow a full range of feature
+	 support when working on
+	 x86 platforms and there is a VBIOS
+	 present in the system
+
+config DRM_AMD_DAL_DCE11_0
+        bool "Carrizo family"
+        depends on DRM_AMD_DAL
+        help
+         Choose this option
+	 if you want to have
+	 CZ family
+	 for display engine
+
+config DRM_AMD_DAL_DCE10_0
+        bool "VI family"
+        depends on DRM_AMD_DAL
+        help
+         Choose this option
+	 if you want to have
+	 VI family for display
+	 engine.
+
+config DEBUG_KERNEL_DAL
+        bool "Enable kgdb break in DAL"
+        depends on DRM_AMD_DAL
+        help
+         Choose this option
+         if you want to hit
+         kdgb_break in assert.
+
+endmenu
diff --git a/drivers/gpu/drm/amd/dal/Makefile b/drivers/gpu/drm/amd/dal/Makefile
new file mode 100644
index 000000000000..25ae4646c4d3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the DAL (Display Abstract Layer), which is a  sub-component
+# of the AMDGPU drm driver.
+# It provides the HW control for display related functionalities.
+
+AMDDALPATH = $(RELATIVE_AMD_DAL_PATH)
+
+subdir-ccflags-y += -Werror
+
+subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include
+
+subdir-ccflags-y += -I$(FULL_AMD_DAL_PATH)/dc/inc/
+
+#TODO: remove when Timing Sync feature is complete
+subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
+
+DAL_LIBS = amdgpu_dm dc
+
+AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/,$(DAL_LIBS)))
+
+include $(AMD_DAL)
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/Makefile b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
new file mode 100644
index 000000000000..6f382812fae3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the 'utils' sub-component of DAL.
+# It provides the general basic services required by other DAL
+# subcomponents.
+
+BASICS = conversion.o grph_object_id.o logger.o register_logger.o signal_types.o vector.o
+
+AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS))
+
+AMD_DAL_FILES += $(AMD_DAL_BASICS)
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.c b/drivers/gpu/drm/amd/dal/dc/basics/conversion.c
new file mode 100644
index 000000000000..2f1f3d4ff96b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/conversion.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#include "dm_services.h"
+
+#define DIVIDER 10000
+
+/* S2D13 value in [-3.00...0.9999] */
+#define S2D13_MIN (-3 * DIVIDER)
+#define S2D13_MAX (3 * DIVIDER)
+
+uint16_t fixed_point_to_int_frac(
+	struct fixed31_32 arg,
+	uint8_t integer_bits,
+	uint8_t fractional_bits)
+{
+	int32_t numerator;
+	int32_t divisor = 1 << fractional_bits;
+
+	uint16_t result;
+
+	uint16_t d = (uint16_t)dal_fixed31_32_floor(
+		dal_fixed31_32_abs(
+			arg));
+
+	if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
+		numerator = (uint16_t)dal_fixed31_32_floor(
+			dal_fixed31_32_mul_int(
+				arg,
+				divisor));
+	else {
+		numerator = dal_fixed31_32_floor(
+			dal_fixed31_32_sub(
+				dal_fixed31_32_from_int(
+					1LL << integer_bits),
+				dal_fixed31_32_recip(
+					dal_fixed31_32_from_int(
+						divisor))));
+	}
+
+	if (numerator >= 0)
+		result = (uint16_t)numerator;
+	else
+		result = (uint16_t)(
+		(1 << (integer_bits + fractional_bits + 1)) + numerator);
+
+	if ((result != 0) && dal_fixed31_32_lt(
+		arg, dal_fixed31_32_zero))
+		result |= 1 << (integer_bits + fractional_bits);
+
+	return result;
+}
+/**
+* convert_float_matrix
+* This converts a double into HW register spec defined format S2D13.
+* @param :
+* @return None
+*/
+void convert_float_matrix(
+	uint16_t *matrix,
+	struct fixed31_32 *flt,
+	uint32_t buffer_size)
+{
+	const struct fixed31_32 min_2_13 =
+		dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER);
+	const struct fixed31_32 max_2_13 =
+		dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER);
+	uint32_t i;
+
+	for (i = 0; i < buffer_size; ++i) {
+		uint32_t reg_value =
+				fixed_point_to_int_frac(
+					dal_fixed31_32_clamp(
+						flt[i],
+						min_2_13,
+						max_2_13),
+						2,
+						13);
+
+		matrix[i] = (uint16_t)reg_value;
+	}
+}
+
+static void calculate_adjustments_common(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix)
+{
+	const struct fixed31_32 sin_hue =
+		dal_fixed31_32_sin(adjustments->hue);
+	const struct fixed31_32 cos_hue =
+		dal_fixed31_32_cos(adjustments->hue);
+
+	const struct fixed31_32 multiplier =
+		dal_fixed31_32_mul(
+			adjustments->contrast,
+			adjustments->saturation);
+
+	matrix[0] = dal_fixed31_32_mul(
+		ideal_matrix[0],
+		adjustments->contrast);
+
+	matrix[1] = dal_fixed31_32_mul(
+		ideal_matrix[1],
+		adjustments->contrast);
+
+	matrix[2] = dal_fixed31_32_mul(
+		ideal_matrix[2],
+		adjustments->contrast);
+
+	matrix[4] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(
+				ideal_matrix[8],
+				sin_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[4],
+				cos_hue)));
+
+	matrix[5] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(
+				ideal_matrix[9],
+				sin_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[5],
+				cos_hue)));
+
+	matrix[6] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(
+				ideal_matrix[10],
+				sin_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[6],
+				cos_hue)));
+
+	matrix[7] = ideal_matrix[7];
+
+	matrix[8] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				ideal_matrix[8],
+				cos_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[4],
+				sin_hue)));
+
+	matrix[9] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				ideal_matrix[9],
+				cos_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[5],
+				sin_hue)));
+
+	matrix[10] = dal_fixed31_32_mul(
+		multiplier,
+		dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				ideal_matrix[10],
+				cos_hue),
+			dal_fixed31_32_mul(
+				ideal_matrix[6],
+				sin_hue)));
+
+	matrix[11] = ideal_matrix[11];
+}
+
+void calculate_adjustments(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix)
+{
+	calculate_adjustments_common(ideal_matrix, adjustments, matrix);
+
+	matrix[3] = dal_fixed31_32_add(
+		ideal_matrix[3],
+		dal_fixed31_32_mul(
+			adjustments->brightness,
+			dal_fixed31_32_from_fraction(86, 100)));
+}
+
+void calculate_adjustments_y_only(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix)
+{
+	calculate_adjustments_common(ideal_matrix, adjustments, matrix);
+
+	matrix[3] = dal_fixed31_32_add(
+		ideal_matrix[3],
+		adjustments->brightness);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/conversion.h b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h
new file mode 100644
index 000000000000..24ff47352688
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/conversion.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_CONVERSION_H__
+#define __DAL_CONVERSION_H__
+
+uint16_t fixed_point_to_int_frac(
+	struct fixed31_32 arg,
+	uint8_t integer_bits,
+	uint8_t fractional_bits);
+
+void convert_float_matrix(
+	uint16_t *matrix,
+	struct fixed31_32 *flt,
+	uint32_t buffer_size);
+
+void calculate_adjustments(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix);
+
+void calculate_adjustments_y_only(
+	const struct fixed31_32 *ideal_matrix,
+	const struct dc_csc_adjustments *adjustments,
+	struct fixed31_32 *matrix);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
new file mode 100644
index 000000000000..9c80847d03a9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/grph_object_id.h"
+
+bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
+{
+	bool rc = true;
+
+	switch (id.type) {
+	case OBJECT_TYPE_UNKNOWN:
+		rc = false;
+		break;
+	case OBJECT_TYPE_GPU:
+	case OBJECT_TYPE_ENGINE:
+		/* do NOT check for id.id == 0 */
+		if (id.enum_id == ENUM_ID_UNKNOWN)
+			rc = false;
+		break;
+	default:
+		if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
+			rc = false;
+		break;
+	}
+
+	return rc;
+}
+
+bool dal_graphics_object_id_is_equal(
+	struct graphics_object_id id1,
+	struct graphics_object_id id2)
+{
+	if (false == dal_graphics_object_id_is_valid(id1)) {
+		dm_output_to_console(
+		"%s: Warning: comparing invalid object 'id1'!\n", __func__);
+		return false;
+	}
+
+	if (false == dal_graphics_object_id_is_valid(id2)) {
+		dm_output_to_console(
+		"%s: Warning: comparing invalid object 'id2'!\n", __func__);
+		return false;
+	}
+
+	if (id1.id == id2.id && id1.enum_id == id2.enum_id
+		&& id1.type == id2.type)
+		return true;
+
+	return false;
+}
+
+/* Based on internal data members memory layout */
+uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id)
+{
+	uint32_t object_id = 0;
+
+	object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc);
+	return object_id;
+}
+
+/*
+ * ******* get specific ID - internal safe cast into specific type *******
+ */
+
+enum controller_id dal_graphics_object_id_get_controller_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_CONTROLLER)
+		return id.id;
+	return CONTROLLER_ID_UNDEFINED;
+}
+
+enum clock_source_id dal_graphics_object_id_get_clock_source_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_CLOCK_SOURCE)
+		return id.id;
+	return CLOCK_SOURCE_ID_UNDEFINED;
+}
+
+enum encoder_id dal_graphics_object_id_get_encoder_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_ENCODER)
+		return id.id;
+	return ENCODER_ID_UNKNOWN;
+}
+
+enum connector_id dal_graphics_object_id_get_connector_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_CONNECTOR)
+		return id.id;
+	return CONNECTOR_ID_UNKNOWN;
+}
+
+enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_AUDIO)
+		return id.id;
+	return AUDIO_ID_UNKNOWN;
+}
+
+enum engine_id dal_graphics_object_id_get_engine_id(
+	struct graphics_object_id id)
+{
+	if (id.type == OBJECT_TYPE_ENGINE)
+		return id.id;
+	return ENGINE_ID_UNKNOWN;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.c b/drivers/gpu/drm/amd/dal/dc/basics/logger.c
new file mode 100644
index 000000000000..e7938ec9bb7c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.c
@@ -0,0 +1,954 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include <stdarg.h>
+#include "dm_services.h"
+#include "include/dal_types.h"
+#include "include/logger_interface.h"
+#include "logger.h"
+
+/* TODO: for now - empty, use DRM defines from dal services.
+		Need to define appropriate levels of prints, and implement
+		this component
+void dal_log(const char *format, ...)
+{
+}
+*/
+
+/* ----------- Logging Major/Minor names ------------ */
+
+#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
+
+static const struct log_minor_info component_minor_info_tbl[] = {
+	{LOG_MINOR_COMPONENT_LINK_SERVICE, "LS"},
+	{LOG_MINOR_COMPONENT_DAL_INTERFACE, "DalIf"},
+	{LOG_MINOR_COMPONENT_HWSS, "HWSS"},
+	{LOG_MINOR_COMPONENT_ADAPTER_SERVICE, "AS"},
+	{LOG_MINOR_COMPONENT_DISPLAY_SERVICE, "DS"},
+	{LOG_MINOR_COMPONENT_TOPOLOGY_MANAGER, "TM"},
+	{LOG_MINOR_COMPONENT_ENCODER, "Encoder"},
+	{LOG_MINOR_COMPONENT_I2C_AUX, "I2cAux"},
+	{LOG_MINOR_COMPONENT_AUDIO, "Audio"},
+	{LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE, "Dcs"},
+	{LOG_MINOR_COMPONENT_DMCU, "Dmcu"},
+	{LOG_MINOR_COMPONENT_GPU, "GPU"},
+	{LOG_MINOR_COMPONENT_CONTROLLER, "Cntrlr"},
+	{LOG_MINOR_COMPONENT_ISR, "ISR"},
+	{LOG_MINOR_COMPONENT_BIOS, "BIOS"},
+	{LOG_MINOR_COMPONENT_DC, "DC"},
+	{LOG_MINOR_COMPONENT_IRQ_SERVICE, "IRQ SERVICE"},
+
+};
+
+static const struct log_minor_info hw_trace_minor_info_tbl[] = {
+	{LOG_MINOR_HW_TRACE_MST, "Mst" },
+	{LOG_MINOR_HW_TRACE_TRAVIS, "Travis" },
+	{LOG_MINOR_HW_TRACE_HOTPLUG, "Hotplug" },
+	{LOG_MINOR_HW_TRACE_LINK_TRAINING, "LinkTraining" },
+	{LOG_MINOR_HW_TRACE_SET_MODE, "SetMode" },
+	{LOG_MINOR_HW_TRACE_RESUME_S3, "ResumeS3" },
+	{LOG_MINOR_HW_TRACE_RESUME_S4, "ResumeS4" },
+	{LOG_MINOR_HW_TRACE_BOOTUP, "BootUp" },
+	{LOG_MINOR_HW_TRACE_AUDIO, "Audio"},
+	{LOG_MINOR_HW_TRACE_HPD_IRQ, "HpdIrq" },
+	{LOG_MINOR_HW_TRACE_INTERRUPT, "Interrupt" },
+	{LOG_MINOR_HW_TRACE_MPO, "Planes" },
+};
+
+static const struct log_minor_info mst_minor_info_tbl[] = {
+	{LOG_MINOR_MST_IRQ_HPD_RX, "IrqHpdRx"},
+	{LOG_MINOR_MST_IRQ_TIMER, "IrqTimer"},
+	{LOG_MINOR_MST_NATIVE_AUX, "NativeAux"},
+	{LOG_MINOR_MST_SIDEBAND_MSG, "SB"},
+	{LOG_MINOR_MST_MSG_TRANSACTION, "MT"},
+	{LOG_MINOR_MST_SIDEBAND_MSG_PARSED, "SB Parsed"},
+	{LOG_MINOR_MST_MSG_TRANSACTION_PARSED, "MT Parsed"},
+	{LOG_MINOR_MST_AUX_MSG_DPCD_ACCESS, "AuxMsgDpcdAccess"},
+	{LOG_MINOR_MST_PROGRAMMING, "Programming"},
+	{LOG_MINOR_MST_TOPOLOGY_DISCOVERY, "TopologyDiscovery"},
+	{LOG_MINOR_MST_CONVERTER_CAPS, "ConverterCaps"},
+};
+
+static const struct log_minor_info dcs_minor_info_tbl[] = {
+	{LOG_MINOR_DCS_EDID_EMULATOR, "EdidEmul"},
+	{LOG_MINOR_DCS_DONGLE_DETECTION, "DongleDetect"},
+};
+
+static const struct log_minor_info dcp_minor_info_tbl[] = {
+	{ LOG_MINOR_DCP_GAMMA_GRPH, "GammaGrph"},
+	{ LOG_MINOR_DCP_GAMMA_OVL, "GammaOvl"},
+	{ LOG_MINOR_DCP_CSC_GRPH, "CscGrph"},
+	{ LOG_MINOR_DCP_CSC_OVL, "CscOvl"},
+	{ LOG_MINOR_DCP_SCALER, "Scaler"},
+	{ LOG_MINOR_DCP_SCALER_TABLES, "ScalerTables"},
+};
+
+static const struct log_minor_info bios_minor_info_tbl[] = {
+	{LOG_MINOR_BIOS_CMD_TABLE, "CmdTbl"},
+};
+
+static const struct log_minor_info reg_minor_info_tbl[] = {
+	{LOG_MINOR_REGISTER_INDEX, "Index"},
+};
+
+static const struct log_minor_info info_packet_minor_info_tbl[] = {
+	{LOG_MINOR_INFO_PACKETS_HDMI, "Hdmi"},
+};
+
+
+static const struct log_minor_info dsat_minor_info_tbl[] = {
+	{LOG_MINOR_DSAT_LOGGER, "Logger"},
+	{LOG_MINOR_DSAT_EDID_OVERRIDE, "EDID_Override"},
+};
+
+static const struct log_minor_info ec_minor_info_tbl[] = {
+	{LOG_MINOR_EC_PPLIB_NOTIFY, "PPLib_Notify" }, /* PPLib notifies DAL */
+	{LOG_MINOR_EC_PPLIB_QUERY, "PPLib_Query" } /* DAL requested info from
+							PPLib */
+};
+
+static const struct log_minor_info bwm_minor_info_tbl[] = {
+	{LOG_MINOR_BWM_MODE_VALIDATION, "ModeValidation"},
+	{LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS, "Req_Bandw_Calcs"}
+};
+
+static const struct log_minor_info mode_enum_minor_info_tbl[] = {
+	{LOG_MINOR_MODE_ENUM_BEST_VIEW_CANDIDATES, "BestviewCandidates"},
+	{LOG_MINOR_MODE_ENUM_VIEW_SOLUTION, "ViewSolution"},
+	{LOG_MINOR_MODE_ENUM_TS_LIST_BUILD, "TsListBuild"},
+	{LOG_MINOR_MODE_ENUM_TS_LIST, "TsList"},
+	{LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST, "MasterViewList"},
+	{LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST_UPDATE, "MasterViewListUpdate"},
+};
+
+static const struct log_minor_info i2caux_minor_info_tbl[] = {
+	{LOG_MINOR_I2C_AUX_LOG, "Log"},
+	{LOG_MINOR_I2C_AUX_AUX_TIMESTAMP, "Timestamp"},
+	{LOG_MINOR_I2C_AUX_CFG, "Config"}
+};
+
+static const struct log_minor_info line_buffer_minor_info_tbl[] = {
+	{LOG_MINOR_LINE_BUFFER_POWERGATING, "PowerGating"}
+};
+
+static const struct log_minor_info hwss_minor_info_tbl[] = {
+	{LOG_MINOR_HWSS_TAPS_VALIDATION, "HWSS Taps"}
+};
+
+static const struct log_minor_info optimization_minor_info_tbl[] = {
+	{LOG_MINOR_OPTMZ_GENERAL, "General Optimizations"},
+	{LOG_MINOR_OPTMZ_DO_NOT_TURN_OFF_VCC_DURING_SET_MODE,
+		"Skip Vcc Off During Set Mode"}
+};
+
+static const struct log_minor_info perf_measure_minor_info_tbl[] = {
+	{LOG_MINOR_PERF_MEASURE_GENERAL, "General Performance Measurement"},
+	{LOG_MINOR_PERF_MEASURE_HEAP_MEMORY, "Heap Memory Management"}
+};
+
+static const struct log_minor_info sync_minor_info_tbl[] = {
+	{LOG_MINOR_SYNC_HW_CLOCK_ADJUST, "Pixel Rate Tune-up"},
+	{LOG_MINOR_SYNC_TIMING, "Timing"}
+};
+
+static const struct log_minor_info backlight_minor_info_tbl[] = {
+	{LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS, "Caps"},
+	{LOG_MINOR_BACKLIGHT_DMCU_DELTALUT, "DMCU Delta LUT"},
+	{LOG_MINOR_BACKLIGHT_DMCU_BUILD_DELTALUT, "Build DMCU Delta LUT"},
+	{LOG_MINOR_BACKLIGHT_INTERFACE, "Interface"},
+	{LOG_MINOR_BACKLIGHT_LID, "Lid Status"}
+};
+
+
+static const struct log_minor_info override_feature_minor_info_tbl[] = {
+	{LOG_MINOR_FEATURE_OVERRIDE, "overriden feature"},
+};
+
+static const struct log_minor_info detection_minor_info_tbl[] = {
+	{LOG_MINOR_DETECTION_EDID_PARSER, "EDID Parser"},
+	{LOG_MINOR_DETECTION_DP_CAPS, "DP caps"},
+};
+
+static const struct log_minor_info tm_minor_info_tbl[] = {
+	{LOG_MINOR_TM_INFO, "INFO"},
+	{LOG_MINOR_TM_IFACE_TRACE, "IFACE_TRACE"},
+	{LOG_MINOR_TM_RESOURCES, "RESOURCES"},
+	{LOG_MINOR_TM_ENCODER_CTL, "ENCODER_CTL"},
+	{LOG_MINOR_TM_ENG_ASN, "ENG_ASN"},
+	{LOG_MINOR_TM_CONTROLLER_ASN, "CONTROLLER_ASN"},
+	{LOG_MINOR_TM_PWR_GATING, "PWR_GATING"},
+	{LOG_MINOR_TM_BUILD_DSP_PATH, "BUILD_PATH"},
+	{LOG_MINOR_TM_DISPLAY_DETECT, "DISPLAY_DETECT"},
+	{LOG_MINOR_TM_LINK_SRV,	"LINK_SRV"},
+	{LOG_MINOR_TM_NOT_IMPLEMENTED, "NOT_IMPL"},
+	{LOG_MINOR_TM_COFUNC_PATH, "COFUNC_PATH"}
+};
+
+static const struct log_minor_info ds_minor_info_tbl[] = {
+	{LOG_MINOR_DS_MODE_SETTING, "Mode_Setting"},
+};
+
+
+struct log_major_mask_info {
+	struct log_major_info major_info;
+	uint32_t default_mask;
+	const struct log_minor_info *minor_tbl;
+	uint32_t tbl_element_cnt;
+};
+
+/* A mask for each Major.
+ * Use a mask or zero. */
+#define LG_ERR_MSK 0xffffffff
+#define LG_WRN_MSK 0xffffffff
+#define LG_TM_MSK (1 << LOG_MINOR_TM_INFO)
+#define LG_FO_MSK (1 << LOG_MINOR_FEATURE_OVERRIDE)
+#define LG_EC_MSK ((1 << LOG_MINOR_EC_PPLIB_NOTIFY) | \
+			(1 << LOG_MINOR_EC_PPLIB_QUERY))
+#define LG_DSAT_MSK (1 << LOG_MINOR_DSAT_EDID_OVERRIDE)
+#define LG_DT_MSK (1 << LOG_MINOR_DETECTION_EDID_PARSER)
+
+/* IFT - InterFaceTrace */
+#define LG_IFT_MSK (1 << LOG_MINOR_COMPONENT_DC)
+
+
+#define LG_HW_TR_AUD_MSK (1 << LOG_MINOR_HW_TRACE_AUDIO)
+#define LG_HW_TR_INTERRUPT_MSK (1 << LOG_MINOR_HW_TRACE_INTERRUPT) | \
+		(1 << LOG_MINOR_HW_TRACE_HPD_IRQ)
+#define LG_HW_TR_PLANES_MSK (1 << LOG_MINOR_HW_TRACE_MPO)
+#define LG_ALL_MSK 0xffffffff
+#define LG_DCP_MSK ~(1 << LOG_MINOR_DCP_SCALER)
+
+#define LG_SYNC_MSK (1 << LOG_MINOR_SYNC_TIMING)
+
+#define LG_BWM_MSK (1 << LOG_MINOR_BWM_MODE_VALIDATION)
+
+static const struct log_major_mask_info log_major_mask_info_tbl[] = {
+	/* LogMajor                  major name       default     MinorTble                    tblElementCnt */
+	{{LOG_MAJOR_ERROR,           "Error"       }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_WARNING,         "Warning"     }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_INTERFACE_TRACE, "IfTrace"     }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_HW_TRACE,        "HwTrace"     }, (LG_ALL_MSK &
+			~((1 << LOG_MINOR_HW_TRACE_LINK_TRAINING) |
+			(1 << LOG_MINOR_HW_TRACE_AUDIO))),
+								hw_trace_minor_info_tbl,     NUM_ELEMENTS(hw_trace_minor_info_tbl)},
+	{{LOG_MAJOR_MST,             "MST"         }, LG_ALL_MSK, mst_minor_info_tbl,          NUM_ELEMENTS(mst_minor_info_tbl)},
+	{{LOG_MAJOR_DCS,             "DCS"         }, LG_ALL_MSK, dcs_minor_info_tbl,          NUM_ELEMENTS(dcs_minor_info_tbl)},
+	{{LOG_MAJOR_DCP,             "DCP"         }, LG_DCP_MSK, dcp_minor_info_tbl,          NUM_ELEMENTS(dcp_minor_info_tbl)},
+	{{LOG_MAJOR_BIOS,            "Bios"        }, LG_ALL_MSK, bios_minor_info_tbl,         NUM_ELEMENTS(bios_minor_info_tbl)},
+	{{LOG_MAJOR_REGISTER,        "Register"    }, LG_ALL_MSK, reg_minor_info_tbl,          NUM_ELEMENTS(reg_minor_info_tbl)},
+	{{LOG_MAJOR_INFO_PACKETS,    "InfoPacket"  }, LG_ALL_MSK, info_packet_minor_info_tbl,  NUM_ELEMENTS(info_packet_minor_info_tbl)},
+	{{LOG_MAJOR_DSAT,            "DSAT"        }, LG_ALL_MSK, dsat_minor_info_tbl,         NUM_ELEMENTS(dsat_minor_info_tbl)},
+	{{LOG_MAJOR_EC,              "EC"          }, LG_ALL_MSK, ec_minor_info_tbl,           NUM_ELEMENTS(ec_minor_info_tbl)},
+	{{LOG_MAJOR_BWM,             "BWM"         }, LG_BWM_MSK, bwm_minor_info_tbl,          NUM_ELEMENTS(bwm_minor_info_tbl)},
+	{{LOG_MAJOR_MODE_ENUM,       "ModeEnum"    }, LG_ALL_MSK, mode_enum_minor_info_tbl,    NUM_ELEMENTS(mode_enum_minor_info_tbl)},
+	{{LOG_MAJOR_I2C_AUX,         "I2cAux"      }, LG_ALL_MSK, i2caux_minor_info_tbl,       NUM_ELEMENTS(i2caux_minor_info_tbl)},
+	{{LOG_MAJOR_LINE_BUFFER,     "LineBuffer"  }, LG_ALL_MSK, line_buffer_minor_info_tbl,  NUM_ELEMENTS(line_buffer_minor_info_tbl)},
+	{{LOG_MAJOR_HWSS,            "HWSS"        }, LG_ALL_MSK, hwss_minor_info_tbl,         NUM_ELEMENTS(hwss_minor_info_tbl)},
+	{{LOG_MAJOR_OPTIMIZATION,    "Optimization"}, LG_ALL_MSK, optimization_minor_info_tbl, NUM_ELEMENTS(optimization_minor_info_tbl)},
+	{{LOG_MAJOR_PERF_MEASURE,    "PerfMeasure" }, LG_ALL_MSK, perf_measure_minor_info_tbl, NUM_ELEMENTS(perf_measure_minor_info_tbl)},
+	{{LOG_MAJOR_SYNC,            "Sync"        }, LG_SYNC_MSK,sync_minor_info_tbl,         NUM_ELEMENTS(sync_minor_info_tbl)},
+	{{LOG_MAJOR_BACKLIGHT,       "Backlight"   }, LG_ALL_MSK, backlight_minor_info_tbl,    NUM_ELEMENTS(backlight_minor_info_tbl)},
+	{{LOG_MAJOR_INTERRUPTS,      "Interrupts"  }, LG_ALL_MSK, component_minor_info_tbl,    NUM_ELEMENTS(component_minor_info_tbl)},
+	{{LOG_MAJOR_TM,              "TM"          }, 0,          tm_minor_info_tbl,           NUM_ELEMENTS(tm_minor_info_tbl)},
+	{{LOG_MAJOR_DISPLAY_SERVICE, "DS"          }, LG_ALL_MSK, ds_minor_info_tbl,           NUM_ELEMENTS(ds_minor_info_tbl)},
+	{{LOG_MAJOR_FEATURE_OVERRIDE, "FeatureOverride" }, LG_ALL_MSK, override_feature_minor_info_tbl, NUM_ELEMENTS(override_feature_minor_info_tbl)},
+	{{LOG_MAJOR_DETECTION,       "Detection"   }, LG_ALL_MSK,  detection_minor_info_tbl,    NUM_ELEMENTS(detection_minor_info_tbl)},
+};
+
+/* ----------- Object init and destruction ----------- */
+static bool construct(struct dc_context *ctx, struct dal_logger *logger)
+{
+	uint32_t i;
+	/* malloc buffer and init offsets */
+
+	logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE;
+	logger->log_buffer = (char *)dm_alloc(ctx,
+		logger->log_buffer_size *
+		sizeof(char));
+
+	if (!logger->log_buffer)
+		return false;
+
+	/* todo: Fill buffer with \0 if not done by dal_alloc */
+
+	/* Initialize both offsets to start of buffer (empty) */
+	logger->buffer_read_offset = 0;
+	logger->buffer_write_offset = 0;
+
+	logger->write_wrap_count = 0;
+	logger->read_wrap_count = 0;
+	logger->open_count = 0;
+
+	logger->flags.bits.ENABLE_CONSOLE = 1;
+	logger->flags.bits.ENABLE_BUFFER = 0;
+
+	logger->ctx = ctx;
+
+	/* malloc and init minor mask array */
+	logger->log_enable_mask_minors =
+			(uint32_t *)dm_alloc(
+				ctx,
+				NUM_ELEMENTS(log_major_mask_info_tbl)
+				* sizeof(uint32_t));
+	if (!logger->log_enable_mask_minors)
+		return false;
+
+
+	/* Set default values for mask */
+	for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) {
+
+		uint32_t dflt_mask = log_major_mask_info_tbl[i].default_mask;
+
+		logger->log_enable_mask_minors[i] = dflt_mask;
+	}
+
+	return true;
+}
+
+static void destruct(struct dal_logger *logger)
+{
+	if (logger->log_buffer) {
+		dm_free(logger->ctx, logger->log_buffer);
+		logger->log_buffer = NULL;
+	}
+
+	if (logger->log_enable_mask_minors) {
+		dm_free(logger->ctx, logger->log_enable_mask_minors);
+		logger->log_enable_mask_minors = NULL;
+	}
+}
+
+struct dal_logger *dal_logger_create(struct dc_context *ctx)
+{
+	/* malloc struct */
+	struct dal_logger *logger = dm_alloc(ctx, sizeof(struct dal_logger));
+
+	if (!logger)
+		return NULL;
+	if (!construct(ctx, logger)) {
+		dm_free(ctx, logger);
+		return NULL;
+	}
+
+	return logger;
+}
+
+uint32_t dal_logger_destroy(struct dal_logger **logger)
+{
+	if (logger == NULL || *logger == NULL)
+		return 1;
+	destruct(*logger);
+	dm_free((*logger)->ctx, *logger);
+	*logger = NULL;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void lock(struct dal_logger *logger)
+{
+	/* Todo: lock mutex? */
+}
+
+static void unlock(struct dal_logger *logger)
+{
+	/* Todo: unlock mutex */
+}
+
+bool dal_logger_should_log(
+	struct dal_logger *logger,
+	enum log_major major,
+	enum log_minor minor)
+{
+	if (major < LOG_MAJOR_COUNT) {
+
+		uint32_t minor_mask = logger->log_enable_mask_minors[major];
+
+		if ((minor_mask & (1 << minor)) != 0)
+			return true;
+	}
+
+	return false;
+}
+
+static void log_to_debug_console(struct log_entry *entry)
+{
+	struct dal_logger *logger = entry->logger;
+
+	if (logger->flags.bits.ENABLE_CONSOLE == 0)
+		return;
+
+	if (entry->buf_offset) {
+		switch (entry->major) {
+		case LOG_MAJOR_ERROR:
+			dm_error("%s", entry->buf);
+			break;
+		default:
+			dm_output_to_console("%s", entry->buf);
+			break;
+		}
+	}
+}
+
+/* Print everything unread existing in log_buffer to debug console*/
+static void flush_to_debug_console(struct dal_logger *logger)
+{
+	int i = logger->buffer_read_offset;
+	char *string_start = &logger->log_buffer[i];
+
+	dm_output_to_console(
+		"---------------- FLUSHING LOG BUFFER ----------------\n");
+	while (i < logger->buffer_write_offset)	{
+
+		if (logger->log_buffer[i] == '\0') {
+			dm_output_to_console("%s", string_start);
+			string_start = (char *)logger->log_buffer + i + 1;
+		}
+		i++;
+	}
+	dm_output_to_console(
+		"-------------- END FLUSHING LOG BUFFER --------------\n\n");
+}
+
+static void log_to_internal_buffer(struct log_entry *entry)
+{
+
+	uint32_t size = entry->buf_offset;
+	struct dal_logger *logger = entry->logger;
+
+	if (logger->flags.bits.ENABLE_BUFFER == 0)
+		return;
+
+	if (logger->log_buffer == NULL)
+		return;
+
+	if (size > 0 && size < logger->log_buffer_size) {
+
+		int total_free_space = 0;
+		int space_before_wrap = 0;
+
+		if (logger->buffer_write_offset > logger->buffer_read_offset) {
+			total_free_space = logger->log_buffer_size -
+					logger->buffer_write_offset +
+					logger->buffer_read_offset;
+			space_before_wrap = logger->log_buffer_size -
+					logger->buffer_write_offset;
+		} else if (logger->buffer_write_offset <
+				logger->buffer_read_offset) {
+			total_free_space = logger->log_buffer_size -
+					logger->buffer_read_offset +
+					logger->buffer_write_offset;
+			space_before_wrap = total_free_space;
+		} else if (logger->write_wrap_count !=
+				logger->read_wrap_count) {
+			/* Buffer is completely full already */
+			total_free_space = 0;
+			space_before_wrap = 0;
+		} else {
+			/* Buffer is empty, start writing at beginning */
+			total_free_space = logger->log_buffer_size;
+			space_before_wrap = logger->log_buffer_size;
+			logger->buffer_write_offset = 0;
+			logger->buffer_read_offset = 0;
+		}
+
+
+
+
+		if (space_before_wrap > size) {
+			/* No wrap around, copy 'size' bytes
+			 * from 'entry->buf' to 'log_buffer'
+			 */
+			dm_memmove(logger->log_buffer +
+					logger->buffer_write_offset,
+					entry->buf, size);
+			logger->buffer_write_offset += size;
+
+		} else if (total_free_space > size) {
+			/* We have enough room without flushing,
+			 * but need to wrap around */
+
+			int space_after_wrap = total_free_space -
+					space_before_wrap;
+
+			dm_memmove(logger->log_buffer +
+					logger->buffer_write_offset,
+					entry->buf, space_before_wrap);
+			dm_memmove(logger->log_buffer, entry->buf +
+					space_before_wrap, space_after_wrap);
+
+			logger->buffer_write_offset = space_after_wrap;
+			logger->write_wrap_count++;
+
+		} else {
+			/* Not enough room remaining, we should flush
+			 * existing logs */
+
+			/* Flush existing unread logs to console */
+			flush_to_debug_console(logger);
+
+			/* Start writing to beginning of buffer */
+			dm_memmove(logger->log_buffer, entry->buf, size);
+			logger->buffer_write_offset = size;
+			logger->buffer_read_offset = 0;
+		}
+
+	}
+
+	unlock(logger);
+}
+
+
+static void log_timestamp(struct log_entry *entry)
+{
+	dal_logger_append(entry, "00:00:00 ");
+}
+
+static void log_major_minor(struct log_entry *entry)
+{
+	uint32_t i;
+	enum log_major major = entry->major;
+	enum log_minor minor = entry->minor;
+
+	for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) {
+
+		const struct log_major_mask_info *maj_mask_info =
+				&log_major_mask_info_tbl[i];
+
+		if (maj_mask_info->major_info.major == major) {
+
+			dal_logger_append(entry, "[%s_",
+					maj_mask_info->major_info.major_name);
+
+			if (maj_mask_info->minor_tbl != NULL) {
+				uint32_t j;
+
+				for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) {
+
+					const struct log_minor_info *min_info = &maj_mask_info->minor_tbl[j];
+
+					if (min_info->minor == minor)
+						dal_logger_append(entry, "%s]\t", min_info->minor_name);
+				}
+			}
+
+			break;
+		}
+	}
+}
+
+static void log_heading(struct log_entry *entry,
+			enum log_major major,
+			enum log_minor minor)
+{
+	log_timestamp(entry);
+	log_major_minor(entry);
+}
+
+
+static void append_entry(
+		struct log_entry *entry,
+		char *buffer,
+		uint32_t buf_size)
+{
+	if (!entry->buf ||
+		entry->buf_offset + buf_size > entry->max_buf_bytes
+	) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	/* Todo: check if off by 1 byte due to \0 anywhere */
+	dm_memmove(entry->buf + entry->buf_offset, buffer, buf_size);
+	entry->buf_offset += buf_size;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Warning: Be careful that 'msg' is null terminated and the total size is
+ * less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0'
+ */
+void dal_logger_write(
+	struct dal_logger *logger,
+	enum log_major major,
+	enum log_minor minor,
+	const char *msg,
+	...)
+{
+
+	if (logger && dal_logger_should_log(logger, major, minor)) {
+
+		uint32_t size;
+		va_list args;
+		char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE];
+		struct log_entry entry;
+
+		va_start(args, msg);
+		dal_logger_open(logger, &entry, major, minor);
+
+
+		size = dm_log_to_buffer(
+			buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args);
+
+		if (size > 0 && size <
+				DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) {
+
+			if (buffer[size] == '\0')
+				size++; /* Add one for null terminator */
+
+			/* Concatenate onto end of entry buffer */
+			append_entry(&entry, buffer, size);
+		} else {
+			append_entry(&entry,
+				"LOG_ERROR, line too long or null\n", 35);
+		}
+
+		dal_logger_close(&entry);
+		va_end(args);
+
+	}
+}
+
+
+/* Same as dal_logger_write, except without open() and close(), which must
+ * be done separately.
+ */
+void dal_logger_append(
+	struct log_entry *entry,
+	const char *msg,
+	...)
+{
+	struct dal_logger *logger;
+
+	if (!entry) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	logger = entry->logger;
+
+	if (logger && logger->open_count > 0 &&
+		dal_logger_should_log(logger, entry->major, entry->minor)) {
+
+		uint32_t size;
+		va_list args;
+		char buffer[DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE];
+
+		va_start(args, msg);
+
+		size = dm_log_to_buffer(
+			buffer, DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE, msg, args);
+
+		if (size < DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE - 1) {
+			append_entry(entry, buffer, size);
+		} else {
+			append_entry(entry, "LOG_ERROR, line too long\n", 27);
+		}
+
+		va_end(args);
+	}
+}
+
+
+uint32_t dal_logger_read(
+	struct dal_logger *logger, /* <[in] */
+	uint32_t output_buffer_size, /* <[in] */
+	char *output_buffer, /* >[out] */
+	uint32_t *bytes_read, /* >[out] */
+	bool single_line)
+{
+	uint32_t bytes_remaining = 0;
+	uint32_t bytes_read_count = 0;
+	bool keep_reading = true;
+
+	if (!logger || output_buffer == NULL || output_buffer_size == 0) {
+		BREAK_TO_DEBUGGER();
+		*bytes_read = 0;
+		return 0;
+	}
+
+	lock(logger);
+
+	/* Read until null terminator (if single_line==true,
+	 *  max buffer size, or until we've read everything new
+	 */
+
+	do {
+		char cur;
+
+		/* Stop when we've read everything */
+		if (logger->buffer_read_offset ==
+			logger->buffer_write_offset) {
+
+			break;
+		}
+
+		cur = logger->log_buffer[logger->buffer_read_offset];
+		logger->buffer_read_offset++;
+
+		/* Wrap read pointer if at end */
+		if (logger->buffer_read_offset == logger->log_buffer_size) {
+
+			logger->buffer_read_offset = 0;
+			logger->read_wrap_count++;
+		}
+
+		/* Don't send null terminators to buffer */
+		if (cur != '\0') {
+			output_buffer[bytes_read_count] = cur;
+			bytes_read_count++;
+		} else if (single_line) {
+			keep_reading = false;
+		}
+
+	} while (bytes_read_count <= output_buffer_size && keep_reading);
+
+	/* We assume that reading can never be ahead of writing */
+	if (logger->write_wrap_count > logger->read_wrap_count) {
+		bytes_remaining = logger->log_buffer_size -
+			logger->buffer_read_offset +
+			logger->buffer_write_offset;
+	} else {
+		bytes_remaining = logger->buffer_write_offset -
+				logger->buffer_read_offset;
+	}
+
+	/* reset write/read wrap count to 0 if we've read everything */
+	if (bytes_remaining == 0) {
+
+		logger->write_wrap_count = 0;
+		logger->read_wrap_count = 0;
+	}
+
+	*bytes_read = bytes_read_count;
+	unlock(logger);
+
+	return bytes_remaining;
+}
+
+void dal_logger_open(
+		struct dal_logger *logger,
+		struct log_entry *entry, /* out */
+		enum log_major major,
+		enum log_minor minor)
+{
+	if (!entry) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	entry->major = LOG_MAJOR_COUNT;
+	entry->minor = 0;
+	entry->logger = logger;
+
+	entry->buf = dm_alloc(
+		logger->ctx,
+		DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char));
+
+	entry->buf_offset = 0;
+	entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char);
+
+	logger->open_count++;
+	entry->major = major;
+	entry->minor = minor;
+
+	log_heading(entry, major, minor);
+}
+
+void dal_logger_close(struct log_entry *entry)
+{
+	struct dal_logger *logger = entry->logger;
+
+
+	if (logger && logger->open_count > 0) {
+		logger->open_count--;
+	} else {
+		BREAK_TO_DEBUGGER();
+		goto cleanup;
+	}
+
+	/* --Flush log_entry buffer-- */
+	/* print to kernel console */
+	log_to_debug_console(entry);
+	/* log internally for dsat */
+	log_to_internal_buffer(entry);
+
+	/* TODO: Write end heading */
+
+cleanup:
+	if (entry->buf) {
+		dm_free(entry->logger->ctx, entry->buf);
+		entry->buf = NULL;
+		entry->buf_offset = 0;
+		entry->max_buf_bytes = 0;
+	}
+}
+
+uint32_t dal_logger_get_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor)
+{
+	uint32_t log_mask = 0;
+
+	if (logger && lvl_major < LOG_MAJOR_COUNT)
+		log_mask = logger->log_enable_mask_minors[lvl_major];
+
+	log_mask &= 1 << lvl_minor;
+	return log_mask;
+}
+
+uint32_t dal_logger_set_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor)
+{
+
+	if (logger && lvl_major < LOG_MAJOR_COUNT) {
+		if (lvl_minor == LOG_MINOR_MASK_ALL) {
+			logger->log_enable_mask_minors[lvl_major] = 0xFFFFFFFF;
+		} else {
+			logger->log_enable_mask_minors[lvl_major] |=
+				(1 << lvl_minor);
+		}
+		return 0;
+	}
+	return 1;
+}
+
+uint32_t dal_logger_get_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major)
+{
+	uint32_t log_mask = 0;
+
+	if (logger && lvl_major < LOG_MAJOR_COUNT)
+		log_mask = logger->log_enable_mask_minors[lvl_major];
+
+	return log_mask;
+}
+
+void dal_logger_set_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major, uint32_t log_mask)
+{
+	if (logger && lvl_major < LOG_MAJOR_COUNT)
+		logger->log_enable_mask_minors[lvl_major] = log_mask;
+}
+
+uint32_t dal_logger_unset_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor)
+{
+
+	if (lvl_major < LOG_MAJOR_COUNT) {
+		if (lvl_minor == LOG_MINOR_MASK_ALL) {
+			logger->log_enable_mask_minors[lvl_major] = 0;
+		} else {
+			logger->log_enable_mask_minors[lvl_major] &=
+				~(1 << lvl_minor);
+		}
+		return 0;
+	}
+	return 1;
+}
+
+uint32_t dal_logger_get_flags(
+		struct dal_logger *logger)
+{
+
+	return logger->flags.value;
+}
+
+void dal_logger_set_flags(
+		struct dal_logger *logger,
+		union logger_flags flags)
+{
+
+	logger->flags = flags;
+}
+
+
+uint32_t dal_logger_get_buffer_size(struct dal_logger *logger)
+{
+	return DAL_LOGGER_BUFFER_MAX_SIZE;
+}
+
+uint32_t dal_logger_set_buffer_size(
+		struct dal_logger *logger,
+		uint32_t new_size)
+{
+	/* ToDo: implement dynamic size */
+
+	/* return new size */
+	return DAL_LOGGER_BUFFER_MAX_SIZE;
+}
+
+
+const struct log_major_info *dal_logger_enum_log_major_info(
+		struct dal_logger *logger,
+		unsigned int enum_index)
+{
+	const struct log_major_info *major_info;
+
+	if (enum_index >= NUM_ELEMENTS(log_major_mask_info_tbl))
+		return NULL;
+
+	major_info = &log_major_mask_info_tbl[enum_index].major_info;
+	return major_info;
+}
+
+const struct log_minor_info *dal_logger_enum_log_minor_info(
+		struct dal_logger *logger,
+		enum log_major major,
+		unsigned int enum_index)
+{
+	const struct log_minor_info *minor_info = NULL;
+	uint32_t i;
+
+	for (i = 0; i < NUM_ELEMENTS(log_major_mask_info_tbl); i++) {
+
+		const struct log_major_mask_info *maj_mask_info =
+				&log_major_mask_info_tbl[i];
+
+		if (maj_mask_info->major_info.major == major) {
+
+			if (maj_mask_info->minor_tbl != NULL) {
+				uint32_t j;
+
+				for (j = 0; j < maj_mask_info->tbl_element_cnt; j++) {
+
+					minor_info = &maj_mask_info->minor_tbl[j];
+
+					if (minor_info->minor == enum_index)
+						return minor_info;
+				}
+			}
+
+			break;
+		}
+	}
+	return NULL;
+
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/logger.h b/drivers/gpu/drm/amd/dal/dc/basics/logger.h
new file mode 100644
index 000000000000..fba5ec3264b6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/logger.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LOGGER_H__
+#define __DAL_LOGGER_H__
+
+/* Structure for keeping track of offsets, buffer, etc */
+
+#define DAL_LOGGER_BUFFER_MAX_SIZE 2048
+#define DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE 256
+
+
+#include "include/logger_types.h"
+
+struct dal_logger {
+
+	/* How far into the circular buffer has been read by dsat
+	 * Read offset should never cross write offset. Write \0's to
+	 * read data just to be sure?
+	 */
+	uint32_t buffer_read_offset;
+
+	/* How far into the circular buffer we have written
+	 * Write offset should never cross read offset
+	 */
+	uint32_t buffer_write_offset;
+
+	uint32_t write_wrap_count;
+	uint32_t read_wrap_count;
+
+	uint32_t open_count;
+
+	char *log_buffer;	/* Pointer to malloc'ed buffer */
+	uint32_t log_buffer_size; /* Size of circular buffer */
+
+	uint32_t *log_enable_mask_minors; /*array of masks for major elements*/
+
+	union logger_flags flags;
+	struct dc_context *ctx;
+};
+
+#endif /* __DAL_LOGGER_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
new file mode 100644
index 000000000000..6d32b1bdf35c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/dal_types.h"
+#include "include/logger_interface.h"
+#include "logger.h"
+
+/******************************************************************************
+ * Register Logger.
+ * A facility to create register R/W logs.
+ * Currently used for DAL Test.
+ *****************************************************************************/
+
+/******************************************************************************
+ * Private structures
+ *****************************************************************************/
+struct dal_reg_dump_stack_location {
+	const char *current_caller_func;
+	long current_pid;
+	long current_tgid;
+	uint32_t rw_count;/* register access counter for current function. */
+};
+
+/* This the maximum number of nested calls to the 'reg_dump' facility. */
+#define DAL_REG_DUMP_STACK_MAX_SIZE 32
+
+struct dal_reg_dump_stack {
+	int32_t stack_pointer;
+	struct dal_reg_dump_stack_location
+		stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE];
+	uint32_t total_rw_count; /* Total count for *all* functions. */
+};
+
+static struct dal_reg_dump_stack reg_dump_stack = {0};
+
+/******************************************************************************
+ * Private functions
+ *****************************************************************************/
+
+/* Check if current process is the one which requested register dump.
+ * The reason for the check:
+ * mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter().
+ * Which runs all the time when at least one display is connected.
+ * (Triggered by drm_mode_page_flip_ioctl()). */
+static bool is_reg_dump_process(void)
+{
+	uint32_t i;
+
+	/* walk the list of our processes */
+	for (i = 0; i < reg_dump_stack.stack_pointer; i++) {
+		struct dal_reg_dump_stack_location *stack_location
+					= &reg_dump_stack.stack_locations[i];
+
+		if (stack_location->current_pid == dm_get_pid()
+			&& stack_location->current_tgid == dm_get_tgid())
+			return true;
+	}
+
+	return false;
+}
+
+static bool dal_reg_dump_stack_is_empty(void)
+{
+	if (reg_dump_stack.stack_pointer <= 0)
+		return true;
+	else
+		return false;
+}
+
+static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void)
+{
+	struct dal_reg_dump_stack_location *current_location = NULL;
+
+	if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) {
+		/* stack is full */
+		dm_output_to_console("[REG_DUMP]: %s: stack is full!\n",
+				__func__);
+	} else {
+		current_location =
+		&reg_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
+		++reg_dump_stack.stack_pointer;
+	}
+
+	return current_location;
+}
+
+static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void)
+{
+	struct dal_reg_dump_stack_location *current_location = NULL;
+
+	if (dal_reg_dump_stack_is_empty()) {
+		/* stack is empty */
+		dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n",
+				__func__);
+	} else {
+		--reg_dump_stack.stack_pointer;
+		current_location =
+		&reg_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
+	}
+
+	return current_location;
+}
+
+/******************************************************************************
+ * Public functions
+ *****************************************************************************/
+
+void dal_reg_logger_push(const char *caller_func)
+{
+	struct dal_reg_dump_stack_location *free_stack_location;
+
+	free_stack_location = dal_reg_dump_stack_push();
+
+	if (NULL == free_stack_location)
+		return;
+
+	dm_memset(free_stack_location, 0, sizeof(*free_stack_location));
+
+	free_stack_location->current_caller_func = caller_func;
+	free_stack_location->current_pid = dm_get_pid();
+	free_stack_location->current_tgid = dm_get_tgid();
+
+	dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n",
+		caller_func,
+		free_stack_location->current_pid,
+		free_stack_location->current_tgid);
+}
+
+void dal_reg_logger_pop(void)
+{
+	struct dal_reg_dump_stack_location *top_stack_location;
+
+	top_stack_location = dal_reg_dump_stack_pop();
+
+	if (NULL == top_stack_location) {
+		dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n",
+				__func__);
+		return;
+	}
+
+	dm_output_to_console(
+	"[REG_DUMP]:%s - end."\
+	" Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n",
+			top_stack_location->current_caller_func,
+			reg_dump_stack.total_rw_count,
+			top_stack_location->rw_count,
+			dm_get_pid(),
+			dm_get_tgid());
+
+	dm_memset(top_stack_location, 0, sizeof(*top_stack_location));
+}
+
+void dal_reg_logger_rw_count_increment(void)
+{
+	++reg_dump_stack.total_rw_count;
+
+	++reg_dump_stack.stack_locations
+		[reg_dump_stack.stack_pointer - 1].rw_count;
+}
+
+bool dal_reg_logger_should_dump_register(void)
+{
+	if (true == dal_reg_dump_stack_is_empty())
+		return false;
+
+	if (false == is_reg_dump_process())
+		return false;
+
+	return true;
+}
+
+/******************************************************************************
+ * End of File.
+ *****************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
new file mode 100644
index 000000000000..44447e07803a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/signal_types.h"
+
+bool dc_is_hdmi_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_HDMI_TYPE_A);
+}
+
+bool dc_is_dp_sst_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_EDP);
+}
+
+bool dc_is_dp_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_EDP ||
+		signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
+}
+
+bool dc_is_dp_external_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
+}
+
+bool dc_is_analog_signal(enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_RGB:
+		return true;
+	break;
+	default:
+		return false;
+	}
+}
+
+bool dc_is_embedded_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS);
+}
+
+bool dc_is_dvi_signal(enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		return true;
+	break;
+	default:
+		return false;
+	}
+}
+
+bool dc_is_dvi_single_link_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK);
+}
+
+bool dc_is_dual_link_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DVI_DUAL_LINK);
+}
+
+bool dc_is_audio_capable_signal(enum signal_type signal)
+{
+	return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
+		signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
+		dc_is_hdmi_signal(signal) ||
+		signal == SIGNAL_TYPE_WIRELESS);
+}
+
+/*
+ * @brief
+ * Returns whether the signal is compatible
+ * with other digital encoder signal types.
+ * This is true for DVI, LVDS, and HDMI signal types.
+ */
+bool dc_is_digital_encoder_compatible_signal(enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_LVDS:
+		return true;
+	default:
+		return false;
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/vector.c b/drivers/gpu/drm/amd/dal/dc/basics/vector.c
new file mode 100644
index 000000000000..32ca6b13a3bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/vector.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/vector.h"
+
+bool dal_vector_construct(
+	struct vector *vector,
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size)
+{
+	vector->container = NULL;
+
+	if (!struct_size || !capacity) {
+		/* Container must be non-zero size*/
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	vector->container = dm_alloc(ctx, struct_size * capacity);
+	if (vector->container == NULL)
+		return false;
+	vector->capacity = capacity;
+	vector->struct_size = struct_size;
+	vector->count = 0;
+	vector->ctx = ctx;
+	return true;
+}
+
+bool dal_vector_presized_costruct(
+	struct vector *vector,
+	struct dc_context *ctx,
+	uint32_t count,
+	void *initial_value,
+	uint32_t struct_size)
+{
+	uint32_t i;
+
+	vector->container = NULL;
+
+	if (!struct_size || !count) {
+		/* Container must be non-zero size*/
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	vector->container = dm_alloc(ctx, struct_size * count);
+
+	if (vector->container == NULL)
+		return false;
+
+	/* If caller didn't supply initial value then the default
+	 * of all zeros is expected, which is exactly what dal_alloc()
+	 * initialises the memory to. */
+	if (NULL != initial_value) {
+		for (i = 0; i < count; ++i)
+			dm_memmove(
+				vector->container + i * struct_size,
+				initial_value,
+				struct_size);
+	}
+
+	vector->capacity = count;
+	vector->struct_size = struct_size;
+	vector->count = count;
+	return true;
+}
+
+struct vector *dal_vector_presized_create(
+	struct dc_context *ctx,
+	uint32_t size,
+	void *initial_value,
+	uint32_t struct_size)
+{
+	struct vector *vector = dm_alloc(ctx, sizeof(struct vector));
+
+	if (vector == NULL)
+		return NULL;
+
+	if (dal_vector_presized_costruct(
+		vector, ctx, size, initial_value, struct_size))
+		return vector;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, vector);
+	return NULL;
+}
+
+struct vector *dal_vector_create(
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size)
+{
+	struct vector *vector = dm_alloc(ctx, sizeof(struct vector));
+
+	if (vector == NULL)
+		return NULL;
+
+	if (dal_vector_construct(vector, ctx, capacity, struct_size))
+		return vector;
+
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, vector);
+	return NULL;
+}
+
+void dal_vector_destruct(
+	struct vector *vector)
+{
+	if (vector->container != NULL)
+		dm_free(vector->ctx, vector->container);
+	vector->count = 0;
+	vector->capacity = 0;
+}
+
+void dal_vector_destroy(
+	struct vector **vector)
+{
+	if (vector == NULL || *vector == NULL)
+		return;
+	dal_vector_destruct(*vector);
+	dm_free((*vector)->ctx, *vector);
+	*vector = NULL;
+}
+
+uint32_t dal_vector_get_count(
+	const struct vector *vector)
+{
+	return vector->count;
+}
+
+void *dal_vector_at_index(
+	const struct vector *vector,
+	uint32_t index)
+{
+	if (vector->container == NULL || index >= vector->count)
+		return NULL;
+	return vector->container + (index * vector->struct_size);
+}
+
+bool dal_vector_remove_at_index(
+	struct vector *vector,
+	uint32_t index)
+{
+	if (index >= vector->count)
+		return false;
+
+	if (index != vector->count - 1)
+		dm_memmove(
+			vector->container + (index * vector->struct_size),
+			vector->container + ((index + 1) * vector->struct_size),
+			(vector->count - index - 1) * vector->struct_size);
+	vector->count -= 1;
+
+	return true;
+}
+
+void dal_vector_set_at_index(
+	const struct vector *vector,
+	const void *what,
+	uint32_t index)
+{
+	void *where = dal_vector_at_index(vector, index);
+
+	if (!where) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+	dm_memmove(
+		where,
+		what,
+		vector->struct_size);
+}
+
+static inline uint32_t calc_increased_capacity(
+	uint32_t old_capacity)
+{
+	return old_capacity * 2;
+}
+
+bool dal_vector_insert_at(
+	struct vector *vector,
+	const void *what,
+	uint32_t position)
+{
+	uint8_t *insert_address;
+
+	if (vector->count == vector->capacity) {
+		if (!dal_vector_reserve(
+			vector,
+			calc_increased_capacity(vector->capacity)))
+			return false;
+	}
+
+	insert_address = vector->container + (vector->struct_size * position);
+
+	if (vector->count && position < vector->count)
+		dm_memmove(
+			insert_address + vector->struct_size,
+			insert_address,
+			vector->struct_size * (vector->count - position));
+
+	dm_memmove(
+		insert_address,
+		what,
+		vector->struct_size);
+
+	vector->count++;
+
+	return true;
+}
+
+bool dal_vector_append(
+	struct vector *vector,
+	const void *item)
+{
+	return dal_vector_insert_at(vector, item, vector->count);
+}
+
+struct vector *dal_vector_clone(
+	const struct vector *vector)
+{
+	struct vector *vec_cloned;
+	uint32_t count;
+
+	/* create new vector */
+	count = dal_vector_get_count(vector);
+
+	if (count == 0)
+		/* when count is 0 we still want to create clone of the vector
+		 */
+		vec_cloned = dal_vector_create(
+			vector->ctx,
+			vector->capacity,
+			vector->struct_size);
+	else
+		/* Call "presized create" version, independently of how the
+		 * original vector was created.
+		 * The owner of original vector must know how to treat the new
+		 * vector - as "presized" or as "regular".
+		 * But from vector point of view it doesn't matter. */
+		vec_cloned = dal_vector_presized_create(vector->ctx, count,
+			NULL,/* no initial value */
+			vector->struct_size);
+
+	if (NULL == vec_cloned) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	/* copy vector's data */
+	dm_memmove(vec_cloned->container, vector->container,
+			vec_cloned->struct_size * vec_cloned->capacity);
+
+	return vec_cloned;
+}
+
+uint32_t dal_vector_capacity(const struct vector *vector)
+{
+	return vector->capacity;
+}
+
+bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
+{
+	void *new_container;
+
+	if (capacity <= vector->capacity)
+		return true;
+
+	new_container = dm_realloc(vector->ctx, vector->container,
+		capacity * vector->struct_size);
+
+	if (new_container) {
+		vector->container = new_container;
+		vector->capacity = capacity;
+		return true;
+	}
+
+	return false;
+}
+
+void dal_vector_clear(struct vector *vector)
+{
+	vector->count = 0;
+}
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 03/26] drm/amd/dal: Fixed point arithmetic
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 01/26] drm/amd/dal: Add dal headers Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 02/26] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 04/26] drm/amd/dal: Asic Capabilities Harry Wentland
                     ` (22 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Arithmetic operations on real numbers represented
as fixed-point numbers.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/basics/Makefile     |   2 +-
 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c | 692 +++++++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c | 223 ++++++++
 3 files changed, 916 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c

diff --git a/drivers/gpu/drm/amd/dal/dc/basics/Makefile b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
index 6f382812fae3..93e23714e411 100644
--- a/drivers/gpu/drm/amd/dal/dc/basics/Makefile
+++ b/drivers/gpu/drm/amd/dal/dc/basics/Makefile
@@ -3,7 +3,7 @@
 # It provides the general basic services required by other DAL
 # subcomponents.
 
-BASICS = conversion.o grph_object_id.o logger.o register_logger.o signal_types.o vector.o
+BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o logger.o register_logger.o signal_types.o vector.o
 
 AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS))
 
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
new file mode 100644
index 000000000000..9f93b3b20634
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
@@ -0,0 +1,692 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/fixed31_32.h"
+
+static inline uint64_t abs_i64(
+	int64_t arg)
+{
+	if (arg > 0)
+		return (uint64_t)arg;
+	else
+		return (uint64_t)(-arg);
+}
+
+/*
+ * @brief
+ * result = dividend / divisor
+ * *remainder = dividend % divisor
+ */
+static inline uint64_t complete_integer_division_u64(
+	uint64_t dividend,
+	uint64_t divisor,
+	uint64_t *remainder)
+{
+	uint64_t result;
+
+	ASSERT(divisor);
+
+	result = div64_u64_rem(dividend, divisor, remainder);
+
+	return result;
+}
+
+#define BITS_PER_FRACTIONAL_PART \
+	32
+
+#define FRACTIONAL_PART_MASK \
+	((1ULL << BITS_PER_FRACTIONAL_PART) - 1)
+
+#define GET_INTEGER_PART(x) \
+	((x) >> BITS_PER_FRACTIONAL_PART)
+
+#define GET_FRACTIONAL_PART(x) \
+	(FRACTIONAL_PART_MASK & (x))
+
+struct fixed31_32 dal_fixed31_32_from_fraction(
+	int64_t numerator,
+	int64_t denominator)
+{
+	struct fixed31_32 res;
+
+	bool arg1_negative = numerator < 0;
+	bool arg2_negative = denominator < 0;
+
+	uint64_t arg1_value = arg1_negative ? -numerator : numerator;
+	uint64_t arg2_value = arg2_negative ? -denominator : denominator;
+
+	uint64_t remainder;
+
+	/* determine integer part */
+
+	uint64_t res_value = complete_integer_division_u64(
+		arg1_value, arg2_value, &remainder);
+
+	ASSERT(res_value <= LONG_MAX);
+
+	/* determine fractional part */
+	{
+		uint32_t i = BITS_PER_FRACTIONAL_PART;
+
+		do {
+			remainder <<= 1;
+
+			res_value <<= 1;
+
+			if (remainder >= arg2_value) {
+				res_value |= 1;
+				remainder -= arg2_value;
+			}
+		} while (--i != 0);
+	}
+
+	/* round up LSB */
+	{
+		uint64_t summand = (remainder << 1) >= arg2_value;
+
+		ASSERT(res_value <= LLONG_MAX - summand);
+
+		res_value += summand;
+	}
+
+	res.value = (int64_t)res_value;
+
+	if (arg1_negative ^ arg2_negative)
+		res.value = -res.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_from_int(
+	int64_t arg)
+{
+	struct fixed31_32 res;
+
+	ASSERT((LONG_MIN <= arg) && (arg <= LONG_MAX));
+
+	res.value = arg << BITS_PER_FRACTIONAL_PART;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_neg(
+	struct fixed31_32 arg)
+{
+	struct fixed31_32 res;
+
+	res.value = -arg.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_abs(
+	struct fixed31_32 arg)
+{
+	if (arg.value < 0)
+		return dal_fixed31_32_neg(arg);
+	else
+		return arg;
+}
+
+bool dal_fixed31_32_lt(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return arg1.value < arg2.value;
+}
+
+bool dal_fixed31_32_le(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return arg1.value <= arg2.value;
+}
+
+bool dal_fixed31_32_eq(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return arg1.value == arg2.value;
+}
+
+struct fixed31_32 dal_fixed31_32_min(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	if (arg1.value <= arg2.value)
+		return arg1;
+	else
+		return arg2;
+}
+
+struct fixed31_32 dal_fixed31_32_max(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	if (arg1.value <= arg2.value)
+		return arg2;
+	else
+		return arg1;
+}
+
+struct fixed31_32 dal_fixed31_32_clamp(
+	struct fixed31_32 arg,
+	struct fixed31_32 min_value,
+	struct fixed31_32 max_value)
+{
+	if (dal_fixed31_32_le(arg, min_value))
+		return min_value;
+	else if (dal_fixed31_32_le(max_value, arg))
+		return max_value;
+	else
+		return arg;
+}
+
+struct fixed31_32 dal_fixed31_32_shl(
+	struct fixed31_32 arg,
+	uint8_t shift)
+{
+	struct fixed31_32 res;
+
+	ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) ||
+		((arg.value < 0) && (arg.value >= LLONG_MIN >> shift)));
+
+	res.value = arg.value << shift;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_shr(
+	struct fixed31_32 arg,
+	uint8_t shift)
+{
+	struct fixed31_32 res;
+
+	ASSERT(shift < 64);
+
+	res.value = arg.value >> shift;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_add(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	struct fixed31_32 res;
+
+	ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) ||
+		((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value)));
+
+	res.value = arg1.value + arg2.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_sub_int(
+	struct fixed31_32 arg1,
+	int32_t arg2)
+{
+	return dal_fixed31_32_sub(
+		arg1,
+		dal_fixed31_32_from_int(arg2));
+}
+
+struct fixed31_32 dal_fixed31_32_sub(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	struct fixed31_32 res;
+
+	ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) ||
+		((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value)));
+
+	res.value = arg1.value - arg2.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_mul_int(
+	struct fixed31_32 arg1,
+	int32_t arg2)
+{
+	return dal_fixed31_32_mul(
+		arg1,
+		dal_fixed31_32_from_int(arg2));
+}
+
+struct fixed31_32 dal_fixed31_32_mul(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	struct fixed31_32 res;
+
+	bool arg1_negative = arg1.value < 0;
+	bool arg2_negative = arg2.value < 0;
+
+	uint64_t arg1_value = arg1_negative ? -arg1.value : arg1.value;
+	uint64_t arg2_value = arg2_negative ? -arg2.value : arg2.value;
+
+	uint64_t arg1_int = GET_INTEGER_PART(arg1_value);
+	uint64_t arg2_int = GET_INTEGER_PART(arg2_value);
+
+	uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
+	uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
+
+	uint64_t tmp;
+
+	res.value = arg1_int * arg2_int;
+
+	ASSERT(res.value <= LONG_MAX);
+
+	res.value <<= BITS_PER_FRACTIONAL_PART;
+
+	tmp = arg1_int * arg2_fra;
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	tmp = arg2_int * arg1_fra;
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	tmp = arg1_fra * arg2_fra;
+
+	tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
+		(tmp >= (uint64_t)dal_fixed31_32_half.value);
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	if (arg1_negative ^ arg2_negative)
+		res.value = -res.value;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_sqr(
+	struct fixed31_32 arg)
+{
+	struct fixed31_32 res;
+
+	uint64_t arg_value = abs_i64(arg.value);
+
+	uint64_t arg_int = GET_INTEGER_PART(arg_value);
+
+	uint64_t arg_fra = GET_FRACTIONAL_PART(arg_value);
+
+	uint64_t tmp;
+
+	res.value = arg_int * arg_int;
+
+	ASSERT(res.value <= LONG_MAX);
+
+	res.value <<= BITS_PER_FRACTIONAL_PART;
+
+	tmp = arg_int * arg_fra;
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	tmp = arg_fra * arg_fra;
+
+	tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
+		(tmp >= (uint64_t)dal_fixed31_32_half.value);
+
+	ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
+
+	res.value += tmp;
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_div_int(
+	struct fixed31_32 arg1,
+	int64_t arg2)
+{
+	return dal_fixed31_32_from_fraction(
+		arg1.value,
+		dal_fixed31_32_from_int(arg2).value);
+}
+
+struct fixed31_32 dal_fixed31_32_div(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return dal_fixed31_32_from_fraction(
+		arg1.value,
+		arg2.value);
+}
+
+struct fixed31_32 dal_fixed31_32_recip(
+	struct fixed31_32 arg)
+{
+	/*
+	 * @note
+	 * Good idea to use Newton's method
+	 */
+
+	ASSERT(arg.value);
+
+	return dal_fixed31_32_from_fraction(
+		dal_fixed31_32_one.value,
+		arg.value);
+}
+
+struct fixed31_32 dal_fixed31_32_sinc(
+	struct fixed31_32 arg)
+{
+	struct fixed31_32 square;
+
+	struct fixed31_32 res = dal_fixed31_32_one;
+
+	int32_t n = 27;
+
+	struct fixed31_32 arg_norm = arg;
+
+	if (dal_fixed31_32_le(
+		dal_fixed31_32_two_pi,
+		dal_fixed31_32_abs(arg))) {
+		arg_norm = dal_fixed31_32_sub(
+			arg_norm,
+			dal_fixed31_32_mul_int(
+				dal_fixed31_32_two_pi,
+				(int32_t)div64_s64(
+					arg_norm.value,
+					dal_fixed31_32_two_pi.value)));
+	}
+
+	square = dal_fixed31_32_sqr(arg_norm);
+
+	do {
+		res = dal_fixed31_32_sub(
+			dal_fixed31_32_one,
+			dal_fixed31_32_div_int(
+				dal_fixed31_32_mul(
+					square,
+					res),
+				n * (n - 1)));
+
+		n -= 2;
+	} while (n > 2);
+
+	if (arg.value != arg_norm.value)
+		res = dal_fixed31_32_div(
+			dal_fixed31_32_mul(res, arg_norm),
+			arg);
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_sin(
+	struct fixed31_32 arg)
+{
+	return dal_fixed31_32_mul(
+		arg,
+		dal_fixed31_32_sinc(arg));
+}
+
+struct fixed31_32 dal_fixed31_32_cos(
+	struct fixed31_32 arg)
+{
+	/* TODO implement argument normalization */
+
+	const struct fixed31_32 square = dal_fixed31_32_sqr(arg);
+
+	struct fixed31_32 res = dal_fixed31_32_one;
+
+	int32_t n = 26;
+
+	do {
+		res = dal_fixed31_32_sub(
+			dal_fixed31_32_one,
+			dal_fixed31_32_div_int(
+				dal_fixed31_32_mul(
+					square,
+					res),
+				n * (n - 1)));
+
+		n -= 2;
+	} while (n != 0);
+
+	return res;
+}
+
+/*
+ * @brief
+ * result = exp(arg),
+ * where abs(arg) < 1
+ *
+ * Calculated as Taylor series.
+ */
+static struct fixed31_32 fixed31_32_exp_from_taylor_series(
+	struct fixed31_32 arg)
+{
+	uint32_t n = 9;
+
+	struct fixed31_32 res = dal_fixed31_32_from_fraction(
+		n + 2,
+		n + 1);
+	/* TODO find correct res */
+
+	ASSERT(dal_fixed31_32_lt(arg, dal_fixed31_32_one));
+
+	do
+		res = dal_fixed31_32_add(
+			dal_fixed31_32_one,
+			dal_fixed31_32_div_int(
+				dal_fixed31_32_mul(
+					arg,
+					res),
+				n));
+	while (--n != 1);
+
+	return dal_fixed31_32_add(
+		dal_fixed31_32_one,
+		dal_fixed31_32_mul(
+			arg,
+			res));
+}
+
+struct fixed31_32 dal_fixed31_32_exp(
+	struct fixed31_32 arg)
+{
+	/*
+	 * @brief
+	 * Main equation is:
+	 * exp(x) = exp(r + m * ln(2)) = (1 << m) * exp(r),
+	 * where m = round(x / ln(2)), r = x - m * ln(2)
+	 */
+
+	if (dal_fixed31_32_le(
+		dal_fixed31_32_ln2_div_2,
+		dal_fixed31_32_abs(arg))) {
+		int32_t m = dal_fixed31_32_round(
+			dal_fixed31_32_div(
+				arg,
+				dal_fixed31_32_ln2));
+
+		struct fixed31_32 r = dal_fixed31_32_sub(
+			arg,
+			dal_fixed31_32_mul_int(
+				dal_fixed31_32_ln2,
+				m));
+
+		ASSERT(m != 0);
+
+		ASSERT(dal_fixed31_32_lt(
+			dal_fixed31_32_abs(r),
+			dal_fixed31_32_one));
+
+		if (m > 0)
+			return dal_fixed31_32_shl(
+				fixed31_32_exp_from_taylor_series(r),
+				(uint8_t)m);
+		else
+			return dal_fixed31_32_div_int(
+				fixed31_32_exp_from_taylor_series(r),
+				1LL << -m);
+	} else if (arg.value != 0)
+		return fixed31_32_exp_from_taylor_series(arg);
+	else
+		return dal_fixed31_32_one;
+}
+
+struct fixed31_32 dal_fixed31_32_log(
+	struct fixed31_32 arg)
+{
+	struct fixed31_32 res = dal_fixed31_32_neg(dal_fixed31_32_one);
+	/* TODO improve 1st estimation */
+
+	struct fixed31_32 error;
+
+	ASSERT(arg.value > 0);
+	/* TODO if arg is negative, return NaN */
+	/* TODO if arg is zero, return -INF */
+
+	do {
+		struct fixed31_32 res1 = dal_fixed31_32_add(
+			dal_fixed31_32_sub(
+				res,
+				dal_fixed31_32_one),
+			dal_fixed31_32_div(
+				arg,
+				dal_fixed31_32_exp(res)));
+
+		error = dal_fixed31_32_sub(
+			res,
+			res1);
+
+		res = res1;
+		/* TODO determine max_allowed_error based on quality of exp() */
+	} while (abs_i64(error.value) > 100ULL);
+
+	return res;
+}
+
+struct fixed31_32 dal_fixed31_32_pow(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2)
+{
+	return dal_fixed31_32_exp(
+		dal_fixed31_32_mul(
+			dal_fixed31_32_log(arg1),
+			arg2));
+}
+
+int32_t dal_fixed31_32_floor(
+	struct fixed31_32 arg)
+{
+	uint64_t arg_value = abs_i64(arg.value);
+
+	if (arg.value >= 0)
+		return (int32_t)GET_INTEGER_PART(arg_value);
+	else
+		return -(int32_t)GET_INTEGER_PART(arg_value);
+}
+
+int32_t dal_fixed31_32_round(
+	struct fixed31_32 arg)
+{
+	uint64_t arg_value = abs_i64(arg.value);
+
+	const int64_t summand = dal_fixed31_32_half.value;
+
+	ASSERT(LLONG_MAX - (int64_t)arg_value >= summand);
+
+	arg_value += summand;
+
+	if (arg.value >= 0)
+		return (int32_t)GET_INTEGER_PART(arg_value);
+	else
+		return -(int32_t)GET_INTEGER_PART(arg_value);
+}
+
+int32_t dal_fixed31_32_ceil(
+	struct fixed31_32 arg)
+{
+	uint64_t arg_value = abs_i64(arg.value);
+
+	const int64_t summand = dal_fixed31_32_one.value -
+		dal_fixed31_32_epsilon.value;
+
+	ASSERT(LLONG_MAX - (int64_t)arg_value >= summand);
+
+	arg_value += summand;
+
+	if (arg.value >= 0)
+		return (int32_t)GET_INTEGER_PART(arg_value);
+	else
+		return -(int32_t)GET_INTEGER_PART(arg_value);
+}
+
+/* this function is a generic helper to translate fixed point value to
+ * specified integer format that will consist of integer_bits integer part and
+ * fractional_bits fractional part. For example it is used in
+ * dal_fixed31_32_u2d19 to receive 2 bits integer part and 19 bits fractional
+ * part in 32 bits. It is used in hw programming (scaler)
+ */
+
+static inline uint32_t ux_dy(
+	int64_t value,
+	uint32_t integer_bits,
+	uint32_t fractional_bits)
+{
+	/* 1. create mask of integer part */
+	uint32_t result =
+		(1 << integer_bits) - 1;
+	/* 2. mask out fractional part */
+	uint32_t fractional_part = FRACTIONAL_PART_MASK & value;
+	/* 3. shrink fixed point integer part to be of integer_bits width*/
+	result &= GET_INTEGER_PART(value);
+	/* 4. make space for fractional part to be filled in after integer */
+	result <<= fractional_bits;
+	/* 5. shrink fixed point fractional part to of fractional_bits width*/
+	fractional_part >>= BITS_PER_FRACTIONAL_PART - fractional_bits;
+	/* 6. merge the result */
+	return result | fractional_part;
+}
+
+uint32_t dal_fixed31_32_u2d19(
+	struct fixed31_32 arg)
+{
+	return ux_dy(arg.value, 2, 19);
+}
+
+uint32_t dal_fixed31_32_u0d19(
+	struct fixed31_32 arg)
+{
+	return ux_dy(arg.value, 0, 19);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c b/drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c
new file mode 100644
index 000000000000..74e6d756295e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/fixed32_32.h"
+
+static uint64_t u64_div(uint64_t n, uint64_t d)
+{
+	uint32_t i = 0;
+	uint64_t r;
+	uint64_t q = div64_u64_rem(n, d, &r);
+
+	for (i = 0; i < 32; ++i) {
+		uint64_t sbit = q & (1ULL<<63);
+
+		r <<= 1;
+		r |= sbit ? 1 : 0;
+		q <<= 1;
+		if (r >= d) {
+			r -= d;
+			q |= 1;
+		}
+	}
+
+	if (2*r >= d)
+		q += 1;
+	return q;
+}
+
+struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d)
+{
+	struct fixed32_32 fx;
+
+	fx.value = u64_div((uint64_t)n << 32, (uint64_t)d << 32);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_from_int(uint32_t value)
+{
+	struct fixed32_32 fx;
+
+	fx.value = (uint64_t)value<<32;
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_add(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	struct fixed32_32 fx = {lhs.value + rhs.value};
+
+	ASSERT(fx.value >= rhs.value);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_add_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	struct fixed32_32 fx = {lhs.value + ((uint64_t)rhs << 32)};
+
+	ASSERT(fx.value >= (uint64_t)rhs << 32);
+	return fx;
+
+}
+struct fixed32_32 dal_fixed32_32_sub(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	struct fixed32_32 fx;
+
+	ASSERT(lhs.value >= rhs.value);
+	fx.value = lhs.value - rhs.value;
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_sub_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	struct fixed32_32 fx;
+
+	ASSERT(lhs.value >= ((uint64_t)rhs<<32));
+	fx.value = lhs.value - ((uint64_t)rhs<<32);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_mul(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	struct fixed32_32 fx;
+	uint64_t lhs_int = lhs.value>>32;
+	uint64_t lhs_frac = (uint32_t)lhs.value;
+	uint64_t rhs_int = rhs.value>>32;
+	uint64_t rhs_frac = (uint32_t)rhs.value;
+	uint64_t ahbh = lhs_int * rhs_int;
+	uint64_t ahbl = lhs_int * rhs_frac;
+	uint64_t albh = lhs_frac * rhs_int;
+	uint64_t albl = lhs_frac * rhs_frac;
+
+	ASSERT((ahbh>>32) == 0);
+
+	fx.value = (ahbh<<32) + ahbl + albh + (albl>>32);
+	return fx;
+
+}
+
+struct fixed32_32 dal_fixed32_32_mul_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	struct fixed32_32 fx;
+	uint64_t lhsi = (lhs.value>>32) * (uint64_t)rhs;
+	uint64_t lhsf;
+
+	ASSERT((lhsi>>32) == 0);
+	lhsf = ((uint32_t)lhs.value) * (uint64_t)rhs;
+	ASSERT((lhsi<<32) + lhsf >= lhsf);
+	fx.value = (lhsi<<32) + lhsf;
+	return fx;
+}
+
+
+
+struct fixed32_32 dal_fixed32_32_div(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	struct fixed32_32 fx;
+
+	fx.value = u64_div(lhs.value, rhs.value);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_div_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	struct fixed32_32 fx;
+
+	fx.value = u64_div(lhs.value, (uint64_t)rhs << 32);
+	return fx;
+}
+
+struct fixed32_32 dal_fixed32_32_min(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	return (lhs.value < rhs.value) ? lhs : rhs;
+}
+
+struct fixed32_32 dal_fixed32_32_max(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs)
+{
+	return (lhs.value > rhs.value) ? lhs : rhs;
+}
+
+bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs)
+{
+	return lhs.value > rhs.value;
+}
+bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	return lhs.value > ((uint64_t)rhs<<32);
+}
+
+bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs)
+{
+	return lhs.value < rhs.value;
+}
+
+bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs)
+{
+	return lhs.value <= rhs.value;
+}
+
+bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	return lhs.value < ((uint64_t)rhs<<32);
+}
+
+bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs)
+{
+	return lhs.value <= ((uint64_t)rhs<<32);
+}
+
+uint32_t dal_fixed32_32_ceil(struct fixed32_32 v)
+{
+	ASSERT((uint32_t)v.value ? (v.value >> 32) + 1 >= 1 : true);
+	return (v.value>>32) + ((uint32_t)v.value ? 1 : 0);
+}
+
+uint32_t dal_fixed32_32_floor(struct fixed32_32 v)
+{
+	return v.value>>32;
+}
+
+uint32_t dal_fixed32_32_round(struct fixed32_32 v)
+{
+	ASSERT(v.value + (1ULL<<31) >= (1ULL<<31));
+	return (v.value + (1ULL<<31))>>32;
+}
+
+bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs)
+{
+	return lhs.value == rhs.value;
+}
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 04/26] drm/amd/dal: Asic Capabilities
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (2 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 03/26] drm/amd/dal: Fixed point arithmetic Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
                     ` (21 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Add a generic way to manage display HW capabilities
for different ASICs and implement it for Carrizo.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/dal/dc/asic_capability/Makefile    |  35 ++++
 .../amd/dal/dc/asic_capability/asic_capability.c   | 190 +++++++++++++++++++++
 .../dc/asic_capability/carrizo_asic_capability.c   | 147 ++++++++++++++++
 .../dc/asic_capability/carrizo_asic_capability.h   |  36 ++++
 .../dal/dc/asic_capability/tonga_asic_capability.c | 146 ++++++++++++++++
 .../dal/dc/asic_capability/tonga_asic_capability.h |  36 ++++
 6 files changed, 590 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h

diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile b/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
new file mode 100644
index 000000000000..8491b38ae726
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
@@ -0,0 +1,35 @@
+#
+# Makefile for the 'asic_capability' sub-component of DAL.
+#
+
+ASIC_CAPABILITY = asic_capability.o
+
+AMD_DAL_ASIC_CAPABILITY = \
+	$(addprefix $(AMDDALPATH)/dc/asic_capability/,$(ASIC_CAPABILITY))
+
+AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY)
+
+###############################################################################
+# DCE 10x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE10_0
+ASIC_CAPABILITY_DCE10 = tonga_asic_capability.o
+
+AMD_DAL_ASIC_CAPABILITY_DCE10 = \
+	$(addprefix $(AMDDALPATH)/dc/asic_capability/,$(ASIC_CAPABILITY_DCE10))
+
+AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY_DCE10)
+endif
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+ASIC_CAPABILITY_DCE11 = carrizo_asic_capability.o
+
+AMD_DAL_ASIC_CAPABILITY_DCE11 = \
+	$(addprefix $(AMDDALPATH)/dc/asic_capability/,$(ASIC_CAPABILITY_DCE11))
+
+AMD_DAL_FILES += $(AMD_DAL_ASIC_CAPABILITY_DCE11)
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
new file mode 100644
index 000000000000..7a905f532040
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "include/asic_capability_interface.h"
+#include "include/asic_capability_types.h"
+#include "include/dal_types.h"
+#include "include/dal_asic_id.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "tonga_asic_capability.h"
+#endif
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "carrizo_asic_capability.h"
+#endif
+
+/*
+ * Initializes asic_capability instance.
+ */
+static bool construct(
+	struct asic_capability *cap,
+	struct hw_asic_id *init,
+	struct dc_context *ctx)
+{
+	bool asic_supported = false;
+
+	cap->ctx = ctx;
+	dm_memset(cap->data, 0, sizeof(cap->data));
+
+	/* ASIC data */
+	cap->data[ASIC_DATA_VRAM_TYPE] = init->vram_type;
+	cap->data[ASIC_DATA_VRAM_BITWIDTH] = init->vram_width;
+	cap->data[ASIC_DATA_FEATURE_FLAGS] = init->feature_flags;
+	cap->runtime_flags = init->runtime_flags;
+	cap->data[ASIC_DATA_REVISION_ID] = init->hw_internal_rev;
+	cap->data[ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE] = 10;
+	cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY] = 4;
+	cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 1;
+	cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES] = 0;
+	cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ] = 25;
+
+	/* ASIC basic capability */
+	cap->caps.UNDERSCAN_FOR_HDMI_ONLY = true;
+	cap->caps.SUPPORT_CEA861E_FINAL = true;
+	cap->caps.MIRABILIS_SUPPORTED = false;
+	cap->caps.MIRABILIS_ENABLED_BY_DEFAULT = false;
+	cap->caps.WIRELESS_LIMIT_TO_720P = false;
+	cap->caps.WIRELESS_FULL_TIMING_ADJUSTMENT = false;
+	cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+	cap->caps.WIRELESS_COMPRESSED_AUDIO = false;
+	cap->caps.VCE_SUPPORTED = false;
+	cap->caps.HPD_CHECK_FOR_EDID = false;
+	cap->caps.NO_VCC_OFF_HPD_POLLING = false;
+	cap->caps.NEED_MC_TUNING = false;
+	cap->caps.SUPPORT_8BPP = true;
+
+	/* ASIC stereo 3D capability */
+	cap->stereo_3d_caps.SUPPORTED = true;
+
+	switch (init->chip_family) {
+	case FAMILY_CI:
+		break;
+
+	case FAMILY_KV:
+		if (ASIC_REV_IS_KALINDI(init->hw_internal_rev) ||
+			ASIC_REV_IS_BHAVANI(init->hw_internal_rev)) {
+		} else {
+		}
+		break;
+
+	case FAMILY_CZ:
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+		carrizo_asic_capability_create(cap, init);
+		asic_supported = true;
+#endif
+		break;
+ 	case FAMILY_VI:
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+		if (ASIC_REV_IS_TONGA_P(init->hw_internal_rev) ||
+				ASIC_REV_IS_FIJI_P(init->hw_internal_rev)) {
+			tonga_asic_capability_create(cap, init);
+			asic_supported = true;
+			break;
+		}
+#endif
+		break;
+	default:
+		/* unsupported "chip_family" */
+		break;
+	}
+
+	if (false == asic_supported) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_MASK_ALL,
+			"%s: ASIC not supported!\n", __func__);
+	}
+
+	return asic_supported;
+}
+
+static void destruct(
+	struct asic_capability *cap)
+{
+	/* nothing to do (yet?) */
+}
+
+/*
+ * dal_asic_capability_create
+ *
+ * Creates asic capability based on DCE version.
+ */
+struct asic_capability *dal_asic_capability_create(
+	struct hw_asic_id *init,
+	struct dc_context *ctx)
+{
+	struct asic_capability *cap;
+
+	if (!init) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	cap = dm_alloc(ctx, sizeof(struct asic_capability));
+
+	if (!cap) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (construct(cap, init, ctx))
+		return cap;
+
+	BREAK_TO_DEBUGGER();
+
+	dm_free(ctx, cap);
+
+	return NULL;
+}
+
+/*
+ * dal_asic_capability_destroy
+ *
+ * Destroy allocated memory.
+ */
+void dal_asic_capability_destroy(
+	struct asic_capability **cap)
+{
+	if (!cap) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if (!*cap) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct(*cap);
+
+	dm_free((*cap)->ctx, *cap);
+
+	*cap = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
new file mode 100644
index 000000000000..4aa8c305b08c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/asic_capability_interface.h"
+#include "include/asic_capability_types.h"
+
+#include "carrizo_asic_capability.h"
+
+#include "atom.h"
+#include "dce/dce_11_0_d.h"
+#include "smu/smu_8_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dal_asic_id.h"
+
+#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074
+
+/*
+ * carrizo_asic_capability_create
+ *
+ * Create and initiate Carrizo capability.
+ */
+void carrizo_asic_capability_create(struct asic_capability *cap,
+	struct hw_asic_id *init)
+{
+	uint32_t e_fuse_setting;
+	/* ASIC data */
+	cap->data[ASIC_DATA_CONTROLLERS_NUM] = 3;
+	cap->data[ASIC_DATA_DIGFE_NUM] = 3;
+	cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 3;
+	cap->data[ASIC_DATA_LINEBUFFER_NUM] = 3;
+	cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR] = 4;
+	cap->data[ASIC_DATA_DCE_VERSION] = 0x110; /* DCE 11 */
+	cap->data[ASIC_DATA_LINEBUFFER_SIZE] = 1712 * 144;
+	cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY] = 45;
+	cap->data[ASIC_DATA_CLOCKSOURCES_NUM] = 2;
+	cap->data[ASIC_DATA_MC_LATENCY] = 5000;
+	cap->data[ASIC_DATA_STUTTERMODE] = 0x200A;
+	cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY] = 2;
+	cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS] = 2;
+	cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER] = 2;
+	cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ] = 100;
+	cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES] = 1;
+	cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 3;
+
+	/* ASIC basic capability */
+	cap->caps.IS_FUSION = true;
+	cap->caps.DP_MST_SUPPORTED = true;
+	cap->caps.PANEL_SELF_REFRESH_SUPPORTED = true;
+	cap->caps.MIRABILIS_SUPPORTED = true;
+	cap->caps.NO_VCC_OFF_HPD_POLLING = true;
+	cap->caps.VCE_SUPPORTED = true;
+	cap->caps.HPD_CHECK_FOR_EDID = true;
+	cap->caps.DFSBYPASS_DYNAMIC_SUPPORT = true;
+	cap->caps.SUPPORT_8BPP = false;
+
+	/* ASIC stereo 3d capability */
+	cap->stereo_3d_caps.DISPLAY_BASED_ON_WS = true;
+	cap->stereo_3d_caps.HDMI_FRAME_PACK = true;
+	cap->stereo_3d_caps.INTERLACE_FRAME_PACK = true;
+	cap->stereo_3d_caps.DISPLAYPORT_FRAME_PACK = true;
+	cap->stereo_3d_caps.DISPLAYPORT_FRAME_ALT = true;
+	cap->stereo_3d_caps.INTERLEAVE = true;
+
+	e_fuse_setting = dm_read_index_reg(cap->ctx,CGS_IND_REG__SMC, ixVCE_HARVEST_FUSE_MACRO__ADDRESS);
+
+	/* Bits [28:27]*/
+	switch ((e_fuse_setting >> 27) & 0x3) {
+	case 0:
+		/*both VCE engine are working*/
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = false;
+		/*TODO:
+		cap->caps.wirelessLowVCEPerformance = false;
+		m_AsicCaps.vceInstance0Enabled = true;
+		m_AsicCaps.vceInstance1Enabled = true;*/
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 1:
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+		/*TODO:
+		m_AsicCaps.wirelessLowVCEPerformance = false;
+		m_AsicCaps.vceInstance1Enabled = true;*/
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 2:
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+		/*TODO:
+		m_AsicCaps.wirelessLowVCEPerformance = false;
+		m_AsicCaps.vceInstance0Enabled = true;*/
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 3:
+		/* VCE_DISABLE = 0x3  - both VCE
+		 * instances are in harvesting,
+		 * no VCE supported any more.
+		 */
+		cap->caps.VCE_SUPPORTED = false;
+		break;
+
+	default:
+		break;
+	}
+
+	if (ASIC_REV_IS_STONEY(init->hw_internal_rev))
+	{
+		/* Stoney is the same DCE11, but only two pipes, three  digs.
+		 * and HW added 64bit back for non SG */
+		cap->data[ASIC_DATA_CONTROLLERS_NUM] = 2;
+		cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 2;
+		cap->data[ASIC_DATA_LINEBUFFER_NUM] = 2;
+		/*3 DP MST per connector, limited by number of pipe and number
+		 * of Dig.*/
+		cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR] = 2;
+
+	}
+
+
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
new file mode 100644
index 000000000000..d1e9b8337d5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_CARRIZO_ASIC_CAPABILITY_H__
+#define __DAL_CARRIZO_ASIC_CAPABILITY_H__
+
+/* Forward declaration */
+struct asic_capability;
+
+/* Create and initialize Carrizo data */
+void carrizo_asic_capability_create(struct asic_capability *cap,
+	struct hw_asic_id *init);
+
+#endif /* __DAL_CARRIZO_ASIC_CAPABILITY_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c b/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
new file mode 100644
index 000000000000..af669c81085b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/asic_capability_interface.h"
+#include "include/asic_capability_types.h"
+
+#include "tonga_asic_capability.h"
+
+#include "atom.h"
+#include "dce/dce_10_0_d.h"
+#include "smu/smu_8_0_d.h"
+#include "dce/dce_10_0_sh_mask.h"
+#include "dal_asic_id.h"
+
+#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS     0xC0014074
+
+/*
+ * carrizo_asic_capability_create
+ *
+ * Create and initiate Carrizo capability.
+ */
+void tonga_asic_capability_create(struct asic_capability *cap,
+	struct hw_asic_id *init)
+{
+	uint32_t e_fuse_setting;
+	/* ASIC data */
+	cap->data[ASIC_DATA_CONTROLLERS_NUM] = 6;
+	cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM] = 6;
+	cap->data[ASIC_DATA_DIGFE_NUM] = 6;
+	cap->data[ASIC_DATA_LINEBUFFER_NUM] = 6;
+
+	cap->data[ASIC_DATA_LINEBUFFER_SIZE] = 1712 * 144;
+	cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY] = 70;
+	cap->data[ASIC_DATA_CLOCKSOURCES_NUM] = 3;
+	cap->data[ASIC_DATA_MC_LATENCY] = 5000;
+	cap->data[ASIC_DATA_STUTTERMODE] = 0x2002;
+	cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR] = 4;
+	cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY] = 2;
+	cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM] = 3;
+	cap->data[ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN] = 300000;
+
+	cap->data[ASIC_DATA_DCE_VERSION] = 0x100; /* DCE 11 */
+
+	cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS] = 2;
+	cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER] = 4;
+	cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ] = 40;
+	cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES] = 1;
+
+
+	/* ASIC basic capability */
+	cap->caps.IS_FUSION = true;
+	cap->caps.DP_MST_SUPPORTED = true;
+	cap->caps.PANEL_SELF_REFRESH_SUPPORTED = true;
+	cap->caps.MIRABILIS_SUPPORTED = true;
+	cap->caps.NO_VCC_OFF_HPD_POLLING = true;
+	cap->caps.VCE_SUPPORTED = true;
+	cap->caps.HPD_CHECK_FOR_EDID = true;
+	cap->caps.DFSBYPASS_DYNAMIC_SUPPORT = true;
+	cap->caps.SUPPORT_8BPP = false;
+
+	/* ASIC stereo 3d capability */
+	cap->stereo_3d_caps.DISPLAY_BASED_ON_WS = true;
+	cap->stereo_3d_caps.HDMI_FRAME_PACK = true;
+	cap->stereo_3d_caps.INTERLACE_FRAME_PACK = true;
+	cap->stereo_3d_caps.DISPLAYPORT_FRAME_PACK = true;
+	cap->stereo_3d_caps.DISPLAYPORT_FRAME_ALT = true;
+	cap->stereo_3d_caps.INTERLEAVE = true;
+
+	e_fuse_setting = dm_read_index_reg(cap->ctx, CGS_IND_REG__SMC, ixVCE_HARVEST_FUSE_MACRO__ADDRESS);
+
+	/* Bits [28:27]*/
+	switch ((e_fuse_setting >> 27) & 0x3) {
+	case 0:
+		/* both VCE engine are working*/
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = false;
+		/*
+		 * TODO:
+		 * cap->caps.wirelessLowVCEPerformance = false;
+		 * m_AsicCaps.vceInstance0Enabled = true;
+		 * m_AsicCaps.vceInstance1Enabled = true;
+		 */
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 1:
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+		/*
+		 * TODO:
+		 * m_AsicCaps.wirelessLowVCEPerformance = false;
+		 * m_AsicCaps.vceInstance1Enabled = true;
+		 */
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 2:
+		cap->caps.VCE_SUPPORTED = true;
+		cap->caps.WIRELESS_TIMING_ADJUSTMENT = true;
+		/*
+		 * TODO:
+		 * m_AsicCaps.wirelessLowVCEPerformance = false;
+		 * m_AsicCaps.vceInstance0Enabled = true;
+		 */
+		cap->caps.NEED_MC_TUNING = true;
+		break;
+
+	case 3:
+		/*
+		 * VCE_DISABLE = 0x3  - both VCE
+		 * instances are in harvesting,
+		 * no VCE supported any more.
+		 */
+		cap->caps.VCE_SUPPORTED = false;
+		break;
+
+	default:
+		break;
+	}
+
+
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h b/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h
new file mode 100644
index 000000000000..29d9760e6c94
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef TONGA_ASIC_CAPABILITY_H_
+#define TONGA_ASIC_CAPABILITY_H_
+
+/* Forward declaration */
+struct asic_capability;
+
+/* Create and initialize Carrizo data */
+void tonga_asic_capability_create(struct asic_capability *cap,
+	struct hw_asic_id *init);
+
+#endif /* TONGA_ASIC_CAPABILITY_H_ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 05/26] drm/amd/dal: GPIO (General Purpose IO)
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (3 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 04/26] drm/amd/dal: Asic Capabilities Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 06/26] drm/amd/dal: Adapter Service Harry Wentland
                     ` (20 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Manages all DCE GPIO pins. The pins are represented as generic IO
handles as well as handles dedicated for certain functions, such as
DDC, HPD, and DVO.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/gpio/Makefile           |  32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c | 882 +++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h |  46 ++
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c |  81 ++
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h |  32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c | 366 +++++++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h |  47 ++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.c   | 400 ++++++++++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.h   |  34 +
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c              | 290 +++++++
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h              |  45 ++
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c  |  97 +++
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h  |  34 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.c  |  65 ++
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.h  |  32 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c  | 101 +++
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h  |  35 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.c    |  41 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.h    |  34 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h             |  48 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c        | 279 +++++++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c     | 386 +++++++++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h     |  57 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c           | 104 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h           |  60 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c       |  93 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h       |  71 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c          | 407 ++++++++++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h          | 129 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c      |  92 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h      |  47 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c      |  85 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h      |  79 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c           |  87 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h           |  45 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c     |  77 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h     |  50 ++
 drivers/gpu/drm/amd/dal/dc/gpio/irq.c              | 180 +++++
 drivers/gpu/drm/amd/dal/dc/gpio/irq.h              |  42 +
 39 files changed, 5112 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.h

diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/Makefile b/drivers/gpu/drm/amd/dal/dc/gpio/Makefile
new file mode 100644
index 000000000000..2507bb564946
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/Makefile
@@ -0,0 +1,32 @@
+#
+# Makefile for the 'gpio' sub-component of DAL.
+# It provides the control and status of HW GPIO pins.
+
+GPIO = ddc.o gpio_base.o gpio_service.o hw_ddc.o hw_factory.o \
+       hw_gpio.o hw_gpio_pad.o hw_gpio_pin.o hw_hpd.o hw_translate.o irq.o
+
+AMD_DAL_GPIO = $(addprefix $(AMDDALPATH)/dc/gpio/,$(GPIO))
+
+AMD_DAL_FILES += $(AMD_DAL_GPIO)
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+GPIO_DCE110 = hw_translate_dce110.o hw_factory_dce110.o hw_hpd_dce110.o \
+	hw_ddc_dce110.o
+
+AMD_DAL_GPIO_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpio/dce110/,$(GPIO_DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_GPIO_DCE110)
+endif
+
+###############################################################################
+# Diagnostics on FPGA
+###############################################################################
+GPIO_DIAG_FPGA = hw_translate_diag.o hw_factory_diag.o hw_hpd_diag.o hw_ddc_diag.o
+
+AMD_DAL_GPIO_DIAG_FPGA = $(addprefix $(AMDDALPATH)/dc/gpio/diagnostics/,$(GPIO_DIAG_FPGA))
+
+AMD_DAL_FILES += $(AMD_DAL_GPIO_DIAG_FPGA)
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
new file mode 100644
index 000000000000..8ff899c5ad12
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
@@ -0,0 +1,882 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+
+/*
+ * Header of this unit
+ */
+#include "hw_ddc_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#define ADDR_DDC_SETUP pin->addr.dc_i2c_ddc_setup
+/*
+ * This unit
+ */
+static void destruct(
+	struct hw_ddc_dce110 *pin)
+{
+	dal_hw_ddc_destruct(&pin->base);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_ddc_dce110 *pin = DDC_DCE110_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+struct hw_ddc_dce110_init {
+	struct hw_gpio_pin_reg hw_gpio_data_reg;
+	struct hw_ddc_mask hw_ddc_mask;
+	struct hw_ddc_dce110_addr hw_ddc_dce110_addr;
+};
+
+static const struct hw_ddc_dce110_init
+	hw_ddc_dce110_init_data[GPIO_DDC_LINE_COUNT] = {
+	/* GPIO_DDC_LINE_DDC1 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC1_MASK,
+				DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_A,
+				DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_EN,
+				DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_Y,
+				DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV_MASK,
+			DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK,
+			DC_GPIO_DDC1_MASK__AUX1_POL_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC1_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC2 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC2_MASK,
+				DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_A,
+				DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_EN,
+				DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_Y,
+				DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV_MASK,
+			DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK,
+			DC_GPIO_DDC2_MASK__AUX2_POL_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC2_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC3 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC3_MASK,
+				DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_A,
+				DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_EN,
+				DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_Y,
+				DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV_MASK,
+			DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK,
+			DC_GPIO_DDC3_MASK__AUX3_POL_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC3_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC4 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC4_MASK,
+				DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_A,
+				DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_EN,
+				DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_Y,
+				DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV_MASK,
+			DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK,
+			DC_GPIO_DDC4_MASK__AUX4_POL_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC4_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC5 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC5_MASK,
+				DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_A,
+				DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_EN,
+				DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_Y,
+				DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV_MASK,
+			DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK,
+			DC_GPIO_DDC5_MASK__AUX5_POL_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC5_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC6 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC6_MASK,
+				DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_A,
+				DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_EN,
+				DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_Y,
+				DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV_MASK,
+			DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK,
+			DC_GPIO_DDC6_MASK__AUX6_POL_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC6_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC_VGA */
+	{
+		{
+			{
+				mmDC_GPIO_DDCVGA_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_A,
+				DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_EN,
+				DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_Y,
+				DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV_MASK,
+			DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK,
+			DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDCVGA_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_I2CPAD */
+	{
+		{
+			{
+				mmDC_GPIO_I2CPAD_MASK,
+				DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_A,
+				DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_EN,
+				DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_Y,
+				DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_PD_DIS_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_RECV_MASK,
+			0,
+			0,
+			0
+		},
+		{
+			0
+		}
+	}
+};
+
+static const struct hw_ddc_dce110_init
+	hw_ddc_dce110_init_clock[GPIO_DDC_LINE_COUNT] = {
+	/* GPIO_DDC_LINE_DDC1 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC1_MASK,
+				DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_A,
+				DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_EN,
+				DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_Y,
+				DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV_MASK,
+			DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK,
+			DC_GPIO_DDC1_MASK__AUX1_POL_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC1_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC2 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC2_MASK,
+				DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_A,
+				DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_EN,
+				DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_Y,
+				DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV_MASK,
+			DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK,
+			DC_GPIO_DDC2_MASK__AUX2_POL_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC2_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC3 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC3_MASK,
+				DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_A,
+				DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_EN,
+				DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_Y,
+				DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV_MASK,
+			DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK,
+			DC_GPIO_DDC3_MASK__AUX3_POL_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC3_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC4 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC4_MASK,
+				DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_A,
+				DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_EN,
+				DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_Y,
+				DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV_MASK,
+			DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK,
+			DC_GPIO_DDC4_MASK__AUX4_POL_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC4_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC5 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC5_MASK,
+				DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_A,
+				DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_EN,
+				DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_Y,
+				DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV_MASK,
+			DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK,
+			DC_GPIO_DDC5_MASK__AUX5_POL_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC5_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC6 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC6_MASK,
+				DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_A,
+				DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_EN,
+				DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_Y,
+				DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV_MASK,
+			DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK,
+			DC_GPIO_DDC6_MASK__AUX6_POL_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC6_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC_VGA */
+	{
+		{
+			{
+				mmDC_GPIO_DDCVGA_MASK,
+				DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_A,
+				DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_EN,
+				DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_Y,
+				DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV_MASK,
+			DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK,
+			DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDCVGA_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_I2CPAD */
+	{
+		{
+			{
+				mmDC_GPIO_I2CPAD_MASK,
+				DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_A,
+				DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_EN,
+				DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_Y,
+				DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_PD_DIS_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_RECV_MASK,
+			0,
+			0,
+			0
+		},
+		{
+			0
+		}
+	}
+};
+
+static void setup_i2c_polling(
+	struct dc_context *ctx,
+	const uint32_t addr,
+	bool enable_detect,
+	bool detect_mode)
+{
+	uint32_t value;
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		enable_detect,
+		DC_I2C_DDC1_SETUP,
+		DC_I2C_DDC1_ENABLE);
+
+	set_reg_field_value(
+		value,
+		enable_detect,
+		DC_I2C_DDC1_SETUP,
+		DC_I2C_DDC1_EDID_DETECT_ENABLE);
+
+	if (enable_detect)
+		set_reg_field_value(
+			value,
+			detect_mode,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_EDID_DETECT_MODE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static enum gpio_result set_config(
+	struct hw_gpio_pin *ptr,
+	const struct gpio_config_data *config_data)
+{
+	struct hw_ddc_dce110 *pin = DDC_DCE110_FROM_BASE(ptr);
+	struct hw_gpio *hw_gpio = NULL;
+	uint32_t addr;
+	uint32_t regval;
+	uint32_t ddc_data_pd_en = 0;
+	uint32_t ddc_clk_pd_en = 0;
+	uint32_t aux_pad_mode = 0;
+
+	hw_gpio = &pin->base.base;
+
+	if (hw_gpio == NULL) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	/* switch dual mode GPIO to I2C/AUX mode */
+
+	addr = hw_gpio->pin_reg.DC_GPIO_DATA_MASK.addr;
+
+	regval = dm_read_reg(ptr->ctx, addr);
+
+	ddc_data_pd_en = get_reg_field_value(
+			regval,
+			DC_GPIO_DDC1_MASK,
+			DC_GPIO_DDC1DATA_PD_EN);
+
+	ddc_clk_pd_en = get_reg_field_value(
+			regval,
+			DC_GPIO_DDC1_MASK,
+			DC_GPIO_DDC1CLK_PD_EN);
+
+	aux_pad_mode = get_reg_field_value(
+			regval,
+			DC_GPIO_DDC1_MASK,
+			AUX_PAD1_MODE);
+
+	switch (config_data->config.ddc.type) {
+	case GPIO_DDC_CONFIG_TYPE_MODE_I2C:
+		/* On plug-in, there is a transient level on the pad
+		 * which must be discharged through the internal pull-down.
+		 * Enable internal pull-down, 2.5msec discharge time
+		 * is required for detection of AUX mode */
+		if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) {
+			if (!ddc_data_pd_en || !ddc_clk_pd_en) {
+				set_reg_field_value(
+					regval,
+					1,
+					DC_GPIO_DDC1_MASK,
+					DC_GPIO_DDC1DATA_PD_EN);
+
+				set_reg_field_value(
+					regval,
+					1,
+					DC_GPIO_DDC1_MASK,
+					DC_GPIO_DDC1CLK_PD_EN);
+
+				dm_write_reg(ptr->ctx, addr, regval);
+
+				if (config_data->type ==
+					GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
+					/* should not affect normal I2C R/W */
+					/* [anaumov] in DAL2, there was
+					 * dc_service_delay_in_microseconds(2500); */
+					dm_sleep_in_milliseconds(ptr->ctx, 3);
+			}
+		} else {
+			uint32_t reg2 = regval;
+			uint32_t sda_pd_dis = 0;
+			uint32_t scl_pd_dis = 0;
+
+			sda_pd_dis = get_reg_field_value(
+					reg2,
+					DC_GPIO_I2CPAD_MASK,
+					DC_GPIO_SDA_PD_DIS);
+
+			scl_pd_dis = get_reg_field_value(
+					reg2,
+					DC_GPIO_I2CPAD_MASK,
+					DC_GPIO_SCL_PD_DIS);
+
+			if (sda_pd_dis) {
+				sda_pd_dis = 0;
+
+				dm_write_reg(ptr->ctx, addr, reg2);
+
+				if (config_data->type ==
+					GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
+					/* should not affect normal I2C R/W */
+					/* [anaumov] in DAL2, there was
+					 * dc_service_delay_in_microseconds(2500); */
+					dm_sleep_in_milliseconds(ptr->ctx, 3);
+			}
+
+			if (!scl_pd_dis) {
+				scl_pd_dis = 1;
+
+				dm_write_reg(ptr->ctx, addr, reg2);
+
+				if (config_data->type ==
+					GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
+					/* should not affect normal I2C R/W */
+					/* [anaumov] in DAL2, there was
+					 * dc_service_delay_in_microseconds(2500); */
+					dm_sleep_in_milliseconds(ptr->ctx, 3);
+			}
+		}
+
+		if (aux_pad_mode) {
+			/* let pins to get de-asserted
+			 * before setting pad to I2C mode */
+			if (config_data->config.ddc.data_en_bit_present ||
+				config_data->config.ddc.clock_en_bit_present)
+				/* [anaumov] in DAL2, there was
+				 * dc_service_delay_in_microseconds(2000); */
+				dm_sleep_in_milliseconds(ptr->ctx, 2);
+
+			/* set the I2C pad mode */
+			/* read the register again,
+			 * some bits may have been changed */
+			regval = dm_read_reg(ptr->ctx, addr);
+
+			set_reg_field_value(
+				regval,
+				0,
+				DC_GPIO_DDC1_MASK,
+				AUX_PAD1_MODE);
+
+			dm_write_reg(ptr->ctx, addr, regval);
+		}
+
+		return GPIO_RESULT_OK;
+	case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
+		/* set the AUX pad mode */
+		if (!aux_pad_mode) {
+			set_reg_field_value(
+				regval,
+				1,
+				DC_GPIO_DDC1_MASK,
+				AUX_PAD1_MODE);
+
+			dm_write_reg(ptr->ctx, addr, regval);
+		}
+
+		return GPIO_RESULT_OK;
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
+		if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
+			(hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+			setup_i2c_polling(
+				ptr->ctx, ADDR_DDC_SETUP, 1, 0);
+			return GPIO_RESULT_OK;
+		}
+	break;
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
+		if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
+			(hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+			setup_i2c_polling(
+				ptr->ctx, ADDR_DDC_SETUP, 1, 1);
+			return GPIO_RESULT_OK;
+		}
+	break;
+	case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
+		if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
+			(hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+			setup_i2c_polling(
+				ptr->ctx, ADDR_DDC_SETUP, 0, 0);
+			return GPIO_RESULT_OK;
+		}
+	break;
+	}
+
+	BREAK_TO_DEBUGGER();
+
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = dal_hw_ddc_open,
+	.get_value = dal_hw_gpio_get_value,
+	.set_value = dal_hw_gpio_set_value,
+	.set_config = set_config,
+	.change_mode = dal_hw_gpio_change_mode,
+	.close = dal_hw_gpio_close,
+};
+
+
+static bool construct(
+	struct hw_ddc_dce110 *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	const struct hw_ddc_dce110_init *init;
+
+	if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (!dal_hw_ddc_construct(&pin->base, id, en, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	pin->base.base.base.funcs = &funcs;
+
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+		init = hw_ddc_dce110_init_data + en;
+
+		pin->base.base.pin_reg = init->hw_gpio_data_reg;
+		pin->base.mask = init->hw_ddc_mask;
+		pin->addr = init->hw_ddc_dce110_addr;
+
+		return true;
+	case GPIO_ID_DDC_CLOCK:
+		init = hw_ddc_dce110_init_clock + en;
+
+		pin->base.base.pin_reg = init->hw_gpio_data_reg;
+		pin->base.mask = init->hw_ddc_mask;
+		pin->addr = init->hw_ddc_dce110_addr;
+
+		return true;
+	default:
+		ASSERT_CRITICAL(false);
+	}
+
+	return false;
+}
+
+struct hw_gpio_pin *dal_hw_ddc_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_ddc_dce110 *pin = dm_alloc(ctx, sizeof(struct hw_ddc_dce110));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
new file mode 100644
index 000000000000..683036984f6f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_DDC_DCE110_H__
+#define __DAL_HW_DDC_DCE110_H__
+
+struct hw_ddc_dce110_addr {
+	uint32_t dc_i2c_ddc_setup;
+};
+
+struct hw_ddc_dce110 {
+	struct hw_ddc base;
+	struct hw_ddc_dce110_addr addr;
+};
+
+#define DDC_DCE110_FROM_BASE(ddc_base) \
+	container_of((HW_DDC_FROM_BASE(ddc_base)), struct hw_ddc_dce110, base)
+
+struct hw_gpio_pin *dal_hw_ddc_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
new file mode 100644
index 000000000000..bdeb60173d0e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_factory.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+#include "../hw_hpd.h"
+
+#include "hw_factory_dce110.h"
+
+#include "hw_hpd_dce110.h"
+#include "hw_ddc_dce110.h"
+
+/* fucntion table */
+static const struct hw_factory_funcs funcs = {
+	.create_ddc_data = dal_hw_ddc_dce110_create,
+	.create_ddc_clock = dal_hw_ddc_dce110_create,
+	.create_generic = NULL,
+	.create_hpd = dal_hw_hpd_dce110_create,
+	.create_gpio_pad = NULL,
+	.create_sync = NULL,
+	.create_gsl = NULL,
+};
+
+/*
+ * dal_hw_factory_dce110_init
+ *
+ * @brief
+ * Initialize HW factory function pointers and pin info
+ *
+ * @param
+ * struct hw_factory *factory - [out] struct of function pointers
+ */
+void dal_hw_factory_dce110_init(struct hw_factory *factory)
+{
+	/*TODO check ASIC CAPs*/
+	factory->number_of_pins[GPIO_ID_DDC_DATA] = 8;
+	factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8;
+	factory->number_of_pins[GPIO_ID_GENERIC] = 7;
+	factory->number_of_pins[GPIO_ID_HPD] = 6;
+	factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31;
+	factory->number_of_pins[GPIO_ID_VIP_PAD] = 0;
+	factory->number_of_pins[GPIO_ID_SYNC] = 2;
+	factory->number_of_pins[GPIO_ID_GSL] = 4;
+
+	factory->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
new file mode 100644
index 000000000000..ecf06ed0d587
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_DCE110_H__
+#define __DAL_HW_FACTORY_DCE110_H__
+
+/* Initialize HW factory function pointers and pin info */
+void dal_hw_factory_dce110_init(struct hw_factory *factory);
+
+#endif /* __DAL_HW_FACTORY_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
new file mode 100644
index 000000000000..a90115cdd55d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_hpd.h"
+
+/*
+ * Header of this unit
+ */
+#include "hw_hpd_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+/*
+ * This unit
+ */
+
+static void destruct(
+	struct hw_hpd_dce110 *pin)
+{
+	dal_hw_hpd_destruct(&pin->base);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+struct hw_gpio_generic_dce110_init {
+	struct hw_gpio_pin_reg hw_gpio_data_reg;
+	struct hw_hpd_dce110_addr addr;
+};
+
+static const struct hw_gpio_generic_dce110_init
+	hw_gpio_generic_dce110_init[GPIO_HPD_COUNT] = {
+	/* GPIO_HPD_1 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y_MASK
+			}
+		},
+		{
+			mmHPD0_DC_HPD_INT_STATUS,
+			mmHPD0_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_2 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y_MASK
+			}
+		},
+		{
+			mmHPD1_DC_HPD_INT_STATUS,
+			mmHPD1_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_3 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y_MASK
+			}
+		},
+		{
+			mmHPD2_DC_HPD_INT_STATUS,
+			mmHPD2_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_4 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y_MASK
+			}
+		},
+		{
+			mmHPD3_DC_HPD_INT_STATUS,
+			mmHPD3_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_5 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y_MASK
+			}
+		},
+		{
+			mmHPD4_DC_HPD_INT_STATUS,
+			mmHPD4_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_6 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y_MASK
+			}
+		},
+		{
+			mmHPD5_DC_HPD_INT_STATUS,
+			mmHPD5_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	}
+};
+
+static enum gpio_result get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(ptr);
+
+	/* in Interrupt mode we ask for SENSE bit */
+
+	if (ptr->mode == GPIO_MODE_INTERRUPT) {
+		uint32_t regval;
+		uint32_t hpd_delayed = 0;
+		uint32_t hpd_sense = 0;
+
+		regval = dm_read_reg(
+				ptr->ctx,
+				pin->addr.DC_HPD_INT_STATUS);
+
+		hpd_delayed = get_reg_field_value(
+				regval,
+				DC_HPD_INT_STATUS,
+				DC_HPD_SENSE_DELAYED);
+
+		hpd_sense = get_reg_field_value(
+				regval,
+				DC_HPD_INT_STATUS,
+				DC_HPD_SENSE);
+
+		*value = hpd_delayed;
+		return GPIO_RESULT_OK;
+	}
+
+	/* in any other modes, operate as normal GPIO */
+
+	return dal_hw_gpio_get_value(ptr, value);
+}
+
+static enum gpio_result set_config(
+	struct hw_gpio_pin *ptr,
+	const struct gpio_config_data *config_data)
+{
+	struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(ptr);
+
+	if (!config_data)
+		return GPIO_RESULT_INVALID_DATA;
+
+	{
+		uint32_t value;
+
+		value = dm_read_reg(
+			ptr->ctx,
+			pin->addr.DC_HPD_TOGGLE_FILT_CNTL);
+
+		set_reg_field_value(
+			value,
+			config_data->config.hpd.delay_on_connect / 10,
+			DC_HPD_TOGGLE_FILT_CNTL,
+			DC_HPD_CONNECT_INT_DELAY);
+
+		set_reg_field_value(
+			value,
+			config_data->config.hpd.delay_on_disconnect / 10,
+			DC_HPD_TOGGLE_FILT_CNTL,
+			DC_HPD_DISCONNECT_INT_DELAY);
+
+		dm_write_reg(
+			ptr->ctx,
+			pin->addr.DC_HPD_TOGGLE_FILT_CNTL,
+			value);
+
+	}
+
+	return GPIO_RESULT_OK;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = dal_hw_gpio_open,
+	.get_value = get_value,
+	.set_value = dal_hw_gpio_set_value,
+	.set_config = set_config,
+	.change_mode = dal_hw_gpio_change_mode,
+	.close = dal_hw_gpio_close,
+};
+
+static bool construct(
+	struct hw_hpd_dce110 *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	const struct hw_gpio_generic_dce110_init *init;
+
+	if (id != GPIO_ID_HPD) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (!dal_hw_hpd_construct(&pin->base, id, en, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	pin->base.base.base.funcs = &funcs;
+
+	init = hw_gpio_generic_dce110_init + en;
+
+	pin->base.base.pin_reg = init->hw_gpio_data_reg;
+
+	pin->addr = init->addr;
+
+	return true;
+}
+
+struct hw_gpio_pin *dal_hw_hpd_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_hpd_dce110 *pin = dm_alloc(ctx, sizeof(struct hw_hpd_dce110));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
new file mode 100644
index 000000000000..d032f4b9c91e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_HPD_DCE110_H__
+#define __DAL_HW_HPD_DCE110_H__
+
+struct hw_hpd_dce110_addr {
+	uint32_t DC_HPD_INT_STATUS;
+	uint32_t DC_HPD_TOGGLE_FILT_CNTL;
+};
+
+struct hw_hpd_dce110 {
+	struct hw_hpd base;
+	struct hw_hpd_dce110_addr addr;
+};
+
+#define HPD_DCE110_FROM_BASE(hpd_base) \
+	container_of((HW_HPD_FROM_BASE(hpd_base)), struct hw_hpd_dce110, base)
+
+struct hw_gpio_pin *dal_hw_hpd_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif /*__DAL_HW_HPD_DCE110_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
new file mode 100644
index 000000000000..b058f4d22708
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_translate.h"
+
+/*
+ * Header of this unit
+ */
+#include "hw_translate_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#include "../hw_gpio_pin.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+static bool offset_to_id(
+	uint32_t offset,
+	uint32_t mask,
+	enum gpio_id *id,
+	uint32_t *en)
+{
+	switch (offset) {
+	/* GENERIC */
+	case mmDC_GPIO_GENERIC_A:
+		*id = GPIO_ID_GENERIC;
+		switch (mask) {
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK:
+			*en = GPIO_GENERIC_A;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK:
+			*en = GPIO_GENERIC_B;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK:
+			*en = GPIO_GENERIC_C;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK:
+			*en = GPIO_GENERIC_D;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK:
+			*en = GPIO_GENERIC_E;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK:
+			*en = GPIO_GENERIC_F;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK:
+			*en = GPIO_GENERIC_G;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* HPD */
+	case mmDC_GPIO_HPD_A:
+		*id = GPIO_ID_HPD;
+		switch (mask) {
+		case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK:
+			*en = GPIO_HPD_1;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK:
+			*en = GPIO_HPD_2;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK:
+			*en = GPIO_HPD_3;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK:
+			*en = GPIO_HPD_4;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK:
+			*en = GPIO_HPD_5;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK:
+			*en = GPIO_HPD_6;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* SYNCA */
+	case mmDC_GPIO_SYNCA_A:
+		*id = GPIO_ID_SYNC;
+		switch (mask) {
+		case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK:
+			*en = GPIO_SYNC_HSYNC_A;
+			return true;
+		case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK:
+			*en = GPIO_SYNC_VSYNC_A;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* mmDC_GPIO_GENLK_MASK */
+	case mmDC_GPIO_GENLK_A:
+		*id = GPIO_ID_GSL;
+		switch (mask) {
+		case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK:
+			*en = GPIO_GSL_GENLOCK_CLOCK;
+			return true;
+		case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK:
+			*en = GPIO_GSL_GENLOCK_VSYNC;
+			return true;
+		case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK:
+			*en = GPIO_GSL_SWAPLOCK_A;
+			return true;
+		case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK:
+			*en = GPIO_GSL_SWAPLOCK_B;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* DDC */
+	/* we don't care about the GPIO_ID for DDC
+	 * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK
+	 * directly in the create method */
+	case mmDC_GPIO_DDC1_A:
+		*en = GPIO_DDC_LINE_DDC1;
+		return true;
+	case mmDC_GPIO_DDC2_A:
+		*en = GPIO_DDC_LINE_DDC2;
+		return true;
+	case mmDC_GPIO_DDC3_A:
+		*en = GPIO_DDC_LINE_DDC3;
+		return true;
+	case mmDC_GPIO_DDC4_A:
+		*en = GPIO_DDC_LINE_DDC4;
+		return true;
+	case mmDC_GPIO_DDC5_A:
+		*en = GPIO_DDC_LINE_DDC5;
+		return true;
+	case mmDC_GPIO_DDC6_A:
+		*en = GPIO_DDC_LINE_DDC6;
+		return true;
+	case mmDC_GPIO_DDCVGA_A:
+		*en = GPIO_DDC_LINE_DDC_VGA;
+		return true;
+	/* GPIO_I2CPAD */
+	case mmDC_GPIO_I2CPAD_A:
+		*en = GPIO_DDC_LINE_I2C_PAD;
+		return true;
+	/* Not implemented */
+	case mmDC_GPIO_PWRSEQ_A:
+	case mmDC_GPIO_PAD_STRENGTH_1:
+	case mmDC_GPIO_PAD_STRENGTH_2:
+	case mmDC_GPIO_DEBUG:
+		return false;
+	/* UNEXPECTED */
+	default:
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+}
+
+static bool id_to_offset(
+	enum gpio_id id,
+	uint32_t en,
+	struct gpio_pin_info *info)
+{
+	bool result = true;
+
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+		info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK;
+		switch (en) {
+		case GPIO_DDC_LINE_DDC1:
+			info->offset = mmDC_GPIO_DDC1_A;
+		break;
+		case GPIO_DDC_LINE_DDC2:
+			info->offset = mmDC_GPIO_DDC2_A;
+		break;
+		case GPIO_DDC_LINE_DDC3:
+			info->offset = mmDC_GPIO_DDC3_A;
+		break;
+		case GPIO_DDC_LINE_DDC4:
+			info->offset = mmDC_GPIO_DDC4_A;
+		break;
+		case GPIO_DDC_LINE_DDC5:
+			info->offset = mmDC_GPIO_DDC5_A;
+		break;
+		case GPIO_DDC_LINE_DDC6:
+			info->offset = mmDC_GPIO_DDC6_A;
+		break;
+		case GPIO_DDC_LINE_DDC_VGA:
+			info->offset = mmDC_GPIO_DDCVGA_A;
+		break;
+		case GPIO_DDC_LINE_I2C_PAD:
+			info->offset = mmDC_GPIO_I2CPAD_A;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_DDC_CLOCK:
+		info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK;
+		switch (en) {
+		case GPIO_DDC_LINE_DDC1:
+			info->offset = mmDC_GPIO_DDC1_A;
+		break;
+		case GPIO_DDC_LINE_DDC2:
+			info->offset = mmDC_GPIO_DDC2_A;
+		break;
+		case GPIO_DDC_LINE_DDC3:
+			info->offset = mmDC_GPIO_DDC3_A;
+		break;
+		case GPIO_DDC_LINE_DDC4:
+			info->offset = mmDC_GPIO_DDC4_A;
+		break;
+		case GPIO_DDC_LINE_DDC5:
+			info->offset = mmDC_GPIO_DDC5_A;
+		break;
+		case GPIO_DDC_LINE_DDC6:
+			info->offset = mmDC_GPIO_DDC6_A;
+		break;
+		case GPIO_DDC_LINE_DDC_VGA:
+			info->offset = mmDC_GPIO_DDCVGA_A;
+		break;
+		case GPIO_DDC_LINE_I2C_PAD:
+			info->offset = mmDC_GPIO_I2CPAD_A;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_GENERIC:
+		info->offset = mmDC_GPIO_GENERIC_A;
+		switch (en) {
+		case GPIO_GENERIC_A:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK;
+		break;
+		case GPIO_GENERIC_B:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK;
+		break;
+		case GPIO_GENERIC_C:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK;
+		break;
+		case GPIO_GENERIC_D:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK;
+		break;
+		case GPIO_GENERIC_E:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK;
+		break;
+		case GPIO_GENERIC_F:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK;
+		break;
+		case GPIO_GENERIC_G:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_HPD:
+		info->offset = mmDC_GPIO_HPD_A;
+		switch (en) {
+		case GPIO_HPD_1:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK;
+		break;
+		case GPIO_HPD_2:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK;
+		break;
+		case GPIO_HPD_3:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK;
+		break;
+		case GPIO_HPD_4:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK;
+		break;
+		case GPIO_HPD_5:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK;
+		break;
+		case GPIO_HPD_6:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_SYNC:
+		switch (en) {
+		case GPIO_SYNC_HSYNC_A:
+			info->offset = mmDC_GPIO_SYNCA_A;
+			info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK;
+		break;
+		case GPIO_SYNC_VSYNC_A:
+			info->offset = mmDC_GPIO_SYNCA_A;
+			info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK;
+		break;
+		case GPIO_SYNC_HSYNC_B:
+		case GPIO_SYNC_VSYNC_B:
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_GSL:
+		switch (en) {
+		case GPIO_GSL_GENLOCK_CLOCK:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK;
+		break;
+		case GPIO_GSL_GENLOCK_VSYNC:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask =
+				DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK;
+		break;
+		case GPIO_GSL_SWAPLOCK_A:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK;
+		break;
+		case GPIO_GSL_SWAPLOCK_B:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_VIP_PAD:
+	default:
+		ASSERT_CRITICAL(false);
+		result = false;
+	}
+
+	if (result) {
+		info->offset_y = info->offset + 2;
+		info->offset_en = info->offset + 1;
+		info->offset_mask = info->offset - 1;
+
+		info->mask_y = info->mask;
+		info->mask_en = info->mask;
+		info->mask_mask = info->mask;
+	}
+
+	return result;
+}
+
+/* function table */
+static const struct hw_translate_funcs funcs = {
+	.offset_to_id = offset_to_id,
+	.id_to_offset = id_to_offset,
+};
+
+/*
+ * dal_hw_translate_dce110_init
+ *
+ * @brief
+ * Initialize Hw translate function pointers.
+ *
+ * @param
+ * struct hw_translate *tr - [out] struct of function pointers
+ *
+ */
+void dal_hw_translate_dce110_init(struct hw_translate *tr)
+{
+	tr->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
new file mode 100644
index 000000000000..4d16e09853c8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_DCE110_H__
+#define __DAL_HW_TRANSLATE_DCE110_H__
+
+struct hw_translate;
+
+/* Initialize Hw translate function pointers */
+void dal_hw_translate_dce110_init(struct hw_translate *tr);
+
+#endif /* __DAL_HW_TRANSLATE_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
new file mode 100644
index 000000000000..c3d8cdb44756
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+
+#include "include/gpio_interface.h"
+#include "include/ddc_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_gpio_pin.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+#include "gpio_service.h"
+#include "gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "ddc.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+enum gpio_result dal_ddc_open(
+	struct ddc *ddc,
+	enum gpio_mode mode,
+	enum gpio_ddc_config_type config_type)
+{
+	enum gpio_result result;
+
+	struct gpio_ddc_open_options data_options;
+	struct gpio_ddc_open_options clock_options;
+	struct gpio_config_data config_data;
+
+	result = dal_gpio_open_ex(ddc->pin_data, mode, &data_options);
+
+	if (result != GPIO_RESULT_OK) {
+		BREAK_TO_DEBUGGER();
+		return result;
+	}
+
+	result = dal_gpio_open_ex(ddc->pin_clock, mode, &clock_options);
+
+	if (result != GPIO_RESULT_OK) {
+		BREAK_TO_DEBUGGER();
+		goto failure;
+	}
+
+	/* DDC clock and data pins should belong
+	 * to the same DDC block id,
+	 * we use the data pin to set the pad mode. */
+
+	if (mode == GPIO_MODE_INPUT)
+		/* this is from detect_sink_type,
+		 * we need extra delay there */
+		config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
+	else
+		config_data.type = GPIO_CONFIG_TYPE_DDC;
+
+	config_data.config.ddc.type = config_type;
+	config_data.config.ddc.data_en_bit_present =
+		data_options.en_bit_present;
+	config_data.config.ddc.clock_en_bit_present =
+		clock_options.en_bit_present;
+
+	result = dal_gpio_set_config(ddc->pin_data, &config_data);
+
+	if (result == GPIO_RESULT_OK)
+		return result;
+
+	BREAK_TO_DEBUGGER();
+
+	dal_gpio_close(ddc->pin_clock);
+
+failure:
+	dal_gpio_close(ddc->pin_data);
+
+	return result;
+}
+
+enum gpio_result dal_ddc_get_clock(
+	const struct ddc *ddc,
+	uint32_t *value)
+{
+	return dal_gpio_get_value(ddc->pin_clock, value);
+}
+
+enum gpio_result dal_ddc_set_clock(
+	const struct ddc *ddc,
+	uint32_t value)
+{
+	return dal_gpio_set_value(ddc->pin_clock, value);
+}
+
+enum gpio_result dal_ddc_get_data(
+	const struct ddc *ddc,
+	uint32_t *value)
+{
+	return dal_gpio_get_value(ddc->pin_data, value);
+}
+
+enum gpio_result dal_ddc_set_data(
+	const struct ddc *ddc,
+	uint32_t value)
+{
+	return dal_gpio_set_value(ddc->pin_data, value);
+}
+
+enum gpio_result dal_ddc_change_mode(
+	struct ddc *ddc,
+	enum gpio_mode mode)
+{
+	enum gpio_result result;
+
+	enum gpio_mode original_mode =
+		dal_gpio_get_mode(ddc->pin_data);
+
+	result = dal_gpio_change_mode(ddc->pin_data, mode);
+
+	/* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
+	 * in case of failures;
+	 * set_mode() is so that, in case of failure,
+	 * we must explicitly set original mode */
+
+	if (result != GPIO_RESULT_OK)
+		goto failure;
+
+	result = dal_gpio_change_mode(ddc->pin_clock, mode);
+
+	if (result == GPIO_RESULT_OK)
+		return result;
+
+	dal_gpio_change_mode(ddc->pin_clock, original_mode);
+
+failure:
+	dal_gpio_change_mode(ddc->pin_data, original_mode);
+
+	return result;
+}
+
+bool dal_ddc_is_hw_supported(
+	const struct ddc *ddc)
+{
+	return ddc->hw_info.hw_supported;
+}
+
+enum gpio_ddc_line dal_ddc_get_line(
+	const struct ddc *ddc)
+{
+	return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
+}
+
+bool dal_ddc_check_line_aborted(
+	const struct ddc *self)
+{
+	/* No arbitration with VBIOS is performed since DCE 6.0 */
+
+	return false;
+}
+
+enum gpio_result dal_ddc_set_config(
+	struct ddc *ddc,
+	enum gpio_ddc_config_type config_type)
+{
+	struct gpio_config_data config_data;
+
+	config_data.type = GPIO_CONFIG_TYPE_DDC;
+
+	config_data.config.ddc.type = config_type;
+	config_data.config.ddc.data_en_bit_present = false;
+	config_data.config.ddc.clock_en_bit_present = false;
+
+	return dal_gpio_set_config(ddc->pin_data, &config_data);
+}
+
+void dal_ddc_close(
+	struct ddc *ddc)
+{
+	dal_gpio_close(ddc->pin_clock);
+	dal_gpio_close(ddc->pin_data);
+}
+
+/*
+ * @brief
+ * Creation and destruction
+ */
+
+struct ddc *dal_gpio_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info)
+{
+	enum gpio_id id;
+	uint32_t en;
+	struct ddc *ddc;
+
+	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
+		return NULL;
+
+	ddc = dm_alloc(service->ctx, sizeof(struct ddc));
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	ddc->pin_data = dal_gpio_service_create_gpio_ex(
+		service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+
+	if (!ddc->pin_data) {
+		BREAK_TO_DEBUGGER();
+		goto failure_1;
+	}
+
+	ddc->pin_clock = dal_gpio_service_create_gpio_ex(
+		service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+
+	if (!ddc->pin_clock) {
+		BREAK_TO_DEBUGGER();
+		goto failure_2;
+	}
+
+	ddc->hw_info = *info;
+
+	ddc->ctx = service->ctx;
+
+	return ddc;
+
+failure_2:
+	dal_gpio_service_destroy_gpio(&ddc->pin_data);
+
+failure_1:
+	dm_free(service->ctx, ddc);
+
+	return NULL;
+}
+
+static void destruct(struct ddc *ddc)
+{
+	dal_ddc_close(ddc);
+	dal_gpio_service_destroy_gpio(&ddc->pin_data);
+	dal_gpio_service_destroy_gpio(&ddc->pin_clock);
+
+}
+
+void dal_gpio_destroy_ddc(
+	struct ddc **ddc)
+{
+	if (!ddc || !*ddc) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct(*ddc);
+	dm_free((*ddc)->ctx, *ddc);
+
+	*ddc = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
new file mode 100644
index 000000000000..2631571f09c0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DDC_H__
+#define __DAL_DDC_H__
+
+struct ddc {
+	struct gpio *pin_data;
+	struct gpio *pin_clock;
+	struct gpio_ddc_hw_info hw_info;
+	struct dc_context *ctx;
+};
+
+struct ddc *dal_gpio_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info);
+
+void dal_gpio_destroy_ddc(
+	struct ddc **ddc);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
new file mode 100644
index 000000000000..1dd31d86031c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+
+/*
+ * This unit
+ */
+static void destruct(
+	struct hw_ddc *pin)
+{
+	dal_hw_ddc_destruct(pin);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_ddc *pin = HW_DDC_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = NULL,
+	.get_value = NULL,
+	.set_value = NULL,
+	.set_config = NULL,
+	.change_mode = NULL,
+	.close = NULL,
+};
+
+static bool construct(
+	struct hw_ddc *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	pin->base.base.funcs = &funcs;
+	return true;
+}
+
+struct hw_gpio_pin *dal_hw_ddc_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_ddc *pin = dm_alloc(ctx, sizeof(struct hw_ddc));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
new file mode 100644
index 000000000000..7515aaf33ee3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_DDC_DIAG_FPGA_H__
+#define __DAL_HW_DDC_DIAG_FPGA_H__
+
+struct hw_gpio_pin *dal_hw_ddc_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
new file mode 100644
index 000000000000..0690b4266002
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_factory.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+#include "../hw_hpd.h"
+
+/* function table */
+static const struct hw_factory_funcs funcs = {
+	.create_ddc_data = NULL,
+	.create_ddc_clock = NULL,
+	.create_generic = NULL,
+	.create_hpd = NULL,
+	.create_gpio_pad = NULL,
+	.create_sync = NULL,
+	.create_gsl = NULL,
+};
+
+void dal_hw_factory_diag_fpga_init(struct hw_factory *factory)
+{
+	factory->number_of_pins[GPIO_ID_DDC_DATA] = 8;
+	factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8;
+	factory->number_of_pins[GPIO_ID_GENERIC] = 7;
+	factory->number_of_pins[GPIO_ID_HPD] = 6;
+	factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31;
+	factory->number_of_pins[GPIO_ID_VIP_PAD] = 0;
+	factory->number_of_pins[GPIO_ID_SYNC] = 2;
+	factory->number_of_pins[GPIO_ID_GSL] = 4;
+	factory->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
new file mode 100644
index 000000000000..8a74f6adb8ee
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_DIAG_FPGA_H__
+#define __DAL_HW_FACTORY_DIAG_FPGA_H__
+
+/* Initialize HW factory function pointers and pin info */
+void dal_hw_factory_diag_fpga_init(struct hw_factory *factory);
+
+#endif /* __DAL_HW_FACTORY_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
new file mode 100644
index 000000000000..019e810ec31e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_hpd.h"
+
+
+static void destruct(
+	struct hw_hpd *pin)
+{
+	dal_hw_hpd_destruct(pin);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_hpd *pin = HW_HPD_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = NULL,
+	.get_value = NULL,
+	.set_value = NULL,
+	.set_config = NULL,
+	.change_mode = NULL,
+	.close = NULL,
+};
+
+static bool construct(
+	struct hw_hpd *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_hpd_construct(pin, id, en, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	pin->base.base.funcs = &funcs;
+
+	return true;
+}
+
+struct hw_gpio_pin *dal_hw_hpd_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_hpd *pin = dm_alloc(ctx, sizeof(struct hw_hpd));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
new file mode 100644
index 000000000000..bfa2c24a987a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_HPD_DIAG_FPGA_H__
+#define __DAL_HW_HPD_DIAG_FPGA_H__
+
+
+struct hw_gpio_pin *dal_hw_hpd_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif /*__DAL_HW_HPD_DIAG_FPGA_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
new file mode 100644
index 000000000000..177330ab157c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+
+#include "../hw_translate.h"
+
+
+/* function table */
+static const struct hw_translate_funcs funcs = {
+	.offset_to_id = NULL,
+	.id_to_offset = NULL,
+};
+
+void dal_hw_translate_diag_fpga_init(struct hw_translate *tr)
+{
+	tr->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
new file mode 100644
index 000000000000..4f053241fe96
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_DIAG_FPGA_H__
+#define __DAL_HW_TRANSLATE_DIAG_FPGA_H__
+
+struct hw_translate;
+
+/* Initialize Hw translate function pointers */
+void dal_hw_translate_diag_fpga_init(struct hw_translate *tr);
+
+#endif /* __DAL_HW_TRANSLATE_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h b/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
new file mode 100644
index 000000000000..7fcbb6972895
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_H__
+#define __DAL_GPIO_H__
+
+struct gpio {
+	struct gpio_service *service;
+	struct hw_gpio_pin *pin;
+	enum gpio_id id;
+	uint32_t en;
+	enum gpio_mode mode;
+	/* when GPIO comes from VBIOS, it has defined output state */
+	enum gpio_pin_output_state output_state;
+};
+
+struct gpio *dal_gpio_create(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state);
+
+void dal_gpio_destroy(
+	struct gpio **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
new file mode 100644
index 000000000000..7e16d631e671
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+
+#include "include/gpio_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_gpio_pin.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+#include "gpio_service.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "gpio.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Public API
+ */
+
+enum gpio_result dal_gpio_open(
+	struct gpio *gpio,
+	enum gpio_mode mode)
+{
+	return dal_gpio_open_ex(gpio, mode, NULL);
+}
+
+enum gpio_result dal_gpio_open_ex(
+	struct gpio *gpio,
+	enum gpio_mode mode,
+	void *options)
+{
+	if (gpio->pin) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_ALREADY_OPENED;
+	}
+
+	gpio->mode = mode;
+
+	return dal_gpio_service_open(
+		gpio->service, gpio->id, gpio->en, mode, options, &gpio->pin);
+}
+
+enum gpio_result dal_gpio_get_value(
+	const struct gpio *gpio,
+	uint32_t *value)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->get_value(gpio->pin, value);
+}
+
+enum gpio_result dal_gpio_set_value(
+	const struct gpio *gpio,
+	uint32_t value)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->set_value(gpio->pin, value);
+}
+
+enum gpio_mode dal_gpio_get_mode(
+	const struct gpio *gpio)
+{
+	return gpio->mode;
+}
+
+enum gpio_result dal_gpio_change_mode(
+	struct gpio *gpio,
+	enum gpio_mode mode)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->change_mode(gpio->pin, mode);
+}
+
+enum gpio_id dal_gpio_get_id(
+	const struct gpio *gpio)
+{
+	return gpio->id;
+}
+
+uint32_t dal_gpio_get_enum(
+	const struct gpio *gpio)
+{
+	return gpio->en;
+}
+
+enum gpio_result dal_gpio_set_config(
+	struct gpio *gpio,
+	const struct gpio_config_data *config_data)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->set_config(gpio->pin, config_data);
+}
+
+enum gpio_result dal_gpio_get_pin_info(
+	const struct gpio *gpio,
+	struct gpio_pin_info *pin_info)
+{
+	return gpio->service->translate.funcs->id_to_offset(
+		gpio->id, gpio->en, pin_info) ?
+		GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA;
+}
+
+enum sync_source dal_gpio_get_sync_source(
+	const struct gpio *gpio)
+{
+	switch (gpio->id) {
+	case GPIO_ID_GENERIC:
+		switch (gpio->en) {
+		case GPIO_GENERIC_A:
+			return SYNC_SOURCE_IO_GENERIC_A;
+		case GPIO_GENERIC_B:
+			return SYNC_SOURCE_IO_GENERIC_B;
+		case GPIO_GENERIC_C:
+			return SYNC_SOURCE_IO_GENERIC_C;
+		case GPIO_GENERIC_D:
+			return SYNC_SOURCE_IO_GENERIC_D;
+		case GPIO_GENERIC_E:
+			return SYNC_SOURCE_IO_GENERIC_E;
+		case GPIO_GENERIC_F:
+			return SYNC_SOURCE_IO_GENERIC_F;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	case GPIO_ID_SYNC:
+		switch (gpio->en) {
+		case GPIO_SYNC_HSYNC_A:
+			return SYNC_SOURCE_IO_HSYNC_A;
+		case GPIO_SYNC_VSYNC_A:
+			return SYNC_SOURCE_IO_VSYNC_A;
+		case GPIO_SYNC_HSYNC_B:
+			return SYNC_SOURCE_IO_HSYNC_B;
+		case GPIO_SYNC_VSYNC_B:
+			return SYNC_SOURCE_IO_VSYNC_B;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	case GPIO_ID_HPD:
+		switch (gpio->en) {
+		case GPIO_HPD_1:
+			return SYNC_SOURCE_IO_HPD1;
+		case GPIO_HPD_2:
+			return SYNC_SOURCE_IO_HPD2;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	case GPIO_ID_GSL:
+		switch (gpio->en) {
+		case GPIO_GSL_GENLOCK_CLOCK:
+			return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK;
+		case GPIO_GSL_GENLOCK_VSYNC:
+			return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC;
+		case GPIO_GSL_SWAPLOCK_A:
+			return SYNC_SOURCE_GSL_IO_SWAPLOCK_A;
+		case GPIO_GSL_SWAPLOCK_B:
+			return SYNC_SOURCE_GSL_IO_SWAPLOCK_B;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	default:
+		return SYNC_SOURCE_NONE;
+	}
+}
+
+enum gpio_pin_output_state dal_gpio_get_output_state(
+	const struct gpio *gpio)
+{
+	return gpio->output_state;
+}
+
+void dal_gpio_close(
+	struct gpio *gpio)
+{
+	if (!gpio)
+		return;
+
+	dal_gpio_service_close(gpio->service, &gpio->pin);
+
+	gpio->mode = GPIO_MODE_UNKNOWN;
+}
+
+/*
+ * @brief
+ * Creation and destruction
+ */
+
+struct gpio *dal_gpio_create(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state)
+{
+	struct gpio *gpio = dm_alloc(service->ctx, sizeof(struct gpio));
+
+	if (!gpio) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	gpio->service = service;
+	gpio->pin = NULL;
+	gpio->id = id;
+	gpio->en = en;
+	gpio->mode = GPIO_MODE_UNKNOWN;
+	gpio->output_state = output_state;
+
+	return gpio;
+}
+
+void dal_gpio_destroy(
+	struct gpio **gpio)
+{
+	if (!gpio || !*gpio) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	dal_gpio_close(*gpio);
+
+	dm_free((*gpio)->service->ctx, *gpio);
+
+	*gpio = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
new file mode 100644
index 000000000000..6837898b3bfe
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_interface.h"
+#include "include/ddc_interface.h"
+#include "include/irq_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "gpio_service.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "hw_gpio_pin.h"
+#include "gpio.h"
+#include "ddc.h"
+#include "irq.h"
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Public API.
+ */
+
+struct gpio_service *dal_gpio_service_create(
+	enum dce_version dce_version_major,
+	enum dce_version dce_version_minor,
+	struct dc_context *ctx)
+{
+	struct gpio_service *service;
+
+	uint32_t index_of_id;
+
+	service = dm_alloc(ctx, sizeof(struct gpio_service));
+
+	if (!service) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (!dal_hw_translate_init(&service->translate, dce_version_major,
+			dce_version_minor)) {
+		BREAK_TO_DEBUGGER();
+		goto failure_1;
+	}
+
+	if (!dal_hw_factory_init(&service->factory, dce_version_major,
+			dce_version_minor)) {
+		BREAK_TO_DEBUGGER();
+		goto failure_1;
+	}
+
+	/* allocate and initialize business storage */
+	{
+		const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+		index_of_id = 0;
+		service->ctx = ctx;
+
+		do {
+			uint32_t number_of_bits =
+				service->factory.number_of_pins[index_of_id];
+
+			uint32_t number_of_uints =
+				(number_of_bits + bits_per_uint - 1) /
+				bits_per_uint;
+
+			uint32_t *slot;
+
+			if (number_of_bits) {
+				uint32_t index_of_uint = 0;
+
+				slot = dm_alloc(
+					ctx,
+					number_of_uints * sizeof(uint32_t));
+
+				if (!slot) {
+					BREAK_TO_DEBUGGER();
+					goto failure_2;
+				}
+
+				do {
+					slot[index_of_uint] = 0;
+
+					++index_of_uint;
+				} while (index_of_uint < number_of_uints);
+			} else
+				slot = NULL;
+
+			service->busyness[index_of_id] = slot;
+
+			++index_of_id;
+		} while (index_of_id < GPIO_ID_COUNT);
+	}
+
+	return service;
+
+failure_2:
+	while (index_of_id) {
+		uint32_t *slot;
+
+		--index_of_id;
+
+		slot = service->busyness[index_of_id];
+
+		if (slot)
+			dm_free(ctx, slot);
+	};
+
+failure_1:
+	dm_free(ctx, service);
+
+	return NULL;
+}
+
+struct gpio *dal_gpio_service_create_gpio(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	enum gpio_pin_output_state output_state)
+{
+	enum gpio_id id;
+	uint32_t en;
+
+	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	return dal_gpio_create(service, id, en, output_state);
+}
+
+struct gpio *dal_gpio_service_create_gpio_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state)
+{
+	return dal_gpio_create(service, id, en, output_state);
+}
+
+void dal_gpio_service_destroy_gpio(
+	struct gpio **gpio)
+{
+	dal_gpio_destroy(gpio);
+}
+
+struct ddc *dal_gpio_service_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info)
+{
+	return dal_gpio_create_ddc(service, offset, mask, info);
+}
+
+void dal_gpio_service_destroy_ddc(
+	struct ddc **ddc)
+{
+	dal_gpio_destroy_ddc(ddc);
+}
+
+struct irq *dal_gpio_service_create_irq(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask)
+{
+	enum gpio_id id;
+	uint32_t en;
+
+	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	return dal_gpio_create_irq(service, id, en);
+}
+
+struct irq *dal_gpio_service_create_irq_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	return dal_gpio_create_irq(service, id, en);
+}
+
+void dal_gpio_service_destroy_irq(
+	struct irq **irq)
+{
+	dal_gpio_destroy_irq(irq);
+}
+
+void dal_gpio_service_destroy(
+	struct gpio_service **ptr)
+{
+	if (!ptr || !*ptr) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	/* free business storage */
+	{
+		uint32_t index_of_id = 0;
+
+		do {
+			uint32_t *slot = (*ptr)->busyness[index_of_id];
+
+			if (slot)
+				dm_free((*ptr)->ctx, slot);
+
+			++index_of_id;
+		} while (index_of_id < GPIO_ID_COUNT);
+	}
+
+	dm_free((*ptr)->ctx, *ptr);
+
+	*ptr = NULL;
+}
+
+/*
+ * @brief
+ * Private API.
+ */
+
+static bool is_pin_busy(
+	const struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+	const uint32_t *slot = service->busyness[id] + (en / bits_per_uint);
+
+	return 0 != (*slot & (1 << (en % bits_per_uint)));
+}
+
+static void set_pin_busy(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+	service->busyness[id][en / bits_per_uint] |=
+		(1 << (en % bits_per_uint));
+}
+
+static void set_pin_free(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+	service->busyness[id][en / bits_per_uint] &=
+		~(1 << (en % bits_per_uint));
+}
+
+enum gpio_result dal_gpio_service_open(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_mode mode,
+	void *options,
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_gpio_pin *pin;
+
+	if (!service->busyness[id]) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_OPEN_FAILED;
+	}
+
+	if (is_pin_busy(service, id, en)) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_DEVICE_BUSY;
+	}
+
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+		pin = service->factory.funcs->create_ddc_data(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_DDC_CLOCK:
+		pin = service->factory.funcs->create_ddc_clock(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_GENERIC:
+		pin = service->factory.funcs->create_generic(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_HPD:
+		pin = service->factory.funcs->create_hpd(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_GPIO_PAD:
+		pin = service->factory.funcs->create_gpio_pad(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_SYNC:
+		pin = service->factory.funcs->create_sync(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_GSL:
+		pin = service->factory.funcs->create_gsl(
+			service->ctx, id, en);
+	break;
+	default:
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+
+	if (!pin->funcs->open(pin, mode, options)) {
+		ASSERT_CRITICAL(false);
+		dal_gpio_service_close(service, &pin);
+		return GPIO_RESULT_OPEN_FAILED;
+	}
+
+	set_pin_busy(service, id, en);
+	*ptr = pin;
+	return GPIO_RESULT_OK;
+}
+
+void dal_gpio_service_close(
+	struct gpio_service *service,
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_gpio_pin *pin;
+
+	if (!ptr) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	pin = *ptr;
+
+	if (pin) {
+		set_pin_free(service, pin->id, pin->en);
+
+		pin->funcs->close(pin);
+
+		pin->funcs->destroy(ptr);
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
new file mode 100644
index 000000000000..a17c4386668d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_SERVICE_H__
+#define __DAL_GPIO_SERVICE_H__
+
+struct hw_translate;
+struct hw_factory;
+
+struct gpio_service {
+	struct dc_context *ctx;
+	struct hw_translate translate;
+	struct hw_factory factory;
+	/*
+	 * @brief
+	 * Business storage.
+	 * For each member of 'enum gpio_id',
+	 * store array of bits (packed into uint32_t slots),
+	 * index individual bit by 'en' value */
+	uint32_t *busyness[GPIO_ID_COUNT];
+};
+
+enum gpio_result dal_gpio_service_open(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_mode mode,
+	void *options,
+	struct hw_gpio_pin **ptr);
+
+void dal_gpio_service_close(
+	struct gpio_service *service,
+	struct hw_gpio_pin **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
new file mode 100644
index 000000000000..41e46a7dc001
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+#include "hw_gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_ddc.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define FROM_HW_GPIO(ptr) \
+	container_of((ptr), struct hw_ddc, base)
+
+#define FROM_HW_GPIO_PIN(ptr) \
+	FROM_HW_GPIO(container_of((ptr), struct hw_gpio, base))
+
+bool dal_hw_ddc_open(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode,
+	void *options)
+{
+	struct hw_ddc *pin = FROM_HW_GPIO_PIN(ptr);
+
+	uint32_t en;
+
+	if (!options) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	/* get the EN bit before overwriting it */
+
+	dal_hw_gpio_get_reg_value(
+		ptr->ctx,
+		&pin->base.pin_reg.DC_GPIO_DATA_EN,
+		&en);
+
+	((struct gpio_ddc_open_options *)options)->en_bit_present = (en != 0);
+
+	return dal_hw_gpio_open(ptr, mode, options);
+}
+
+bool dal_hw_ddc_construct(
+	struct hw_ddc *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_gpio_construct(&pin->base, id, en, ctx))
+		return false;
+
+	pin->mask.DC_GPIO_DDC_MASK_MASK = 0;
+	pin->mask.DC_GPIO_DDC_PD_EN_MASK = 0;
+	pin->mask.DC_GPIO_DDC_RECV_MASK = 0;
+	pin->mask.AUX_PAD_MODE_MASK = 0;
+	pin->mask.AUX_POL_MASK = 0;
+	pin->mask.DC_GPIO_DDCCLK_STR_MASK = 0;
+
+	return true;
+}
+
+void dal_hw_ddc_destruct(
+	struct hw_ddc *pin)
+{
+	dal_hw_gpio_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
new file mode 100644
index 000000000000..a3a727c58b83
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_DDC_H__
+#define __DAL_HW_DDC_H__
+
+struct hw_ddc_mask {
+	uint32_t DC_GPIO_DDC_MASK_MASK;
+	uint32_t DC_GPIO_DDC_PD_EN_MASK;
+	uint32_t DC_GPIO_DDC_RECV_MASK;
+	uint32_t AUX_PAD_MODE_MASK;
+	uint32_t AUX_POL_MASK;
+	uint32_t DC_GPIO_DDCCLK_STR_MASK;
+};
+
+struct hw_ddc {
+	struct hw_gpio base;
+	struct hw_ddc_mask mask;
+};
+
+#define HW_DDC_FROM_BASE(hw_gpio) \
+	container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_ddc, base)
+
+bool dal_hw_ddc_construct(
+	struct hw_ddc *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_ddc_destruct(
+	struct hw_ddc *pin);
+
+bool dal_hw_ddc_open(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode,
+	void *options);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
new file mode 100644
index 000000000000..e0f6ecfaf4a7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_factory.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/hw_factory_dce110.h"
+#endif
+
+#include "diagnostics/hw_factory_diag.h"
+
+/*
+ * This unit
+ */
+
+bool dal_hw_factory_init(
+	struct hw_factory *factory,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment)
+{
+	if (IS_FPGA_MAXIMUS_DC(dce_environment)) {
+		dal_hw_factory_diag_fpga_init(factory);
+		return true;
+	}
+
+	switch (dce_version) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		dal_hw_factory_dce110_init(factory);
+		return true;
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		dal_hw_factory_dce110_init(factory);
+		return true;
+#endif
+	default:
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+}
+
+void dal_hw_factory_destroy(
+	struct dc_context *ctx,
+	struct hw_factory **factory)
+{
+	if (!factory || !*factory) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	dm_free(ctx, *factory);
+
+	*factory = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
new file mode 100644
index 000000000000..1fa8b6d85f35
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_H__
+#define __DAL_HW_FACTORY_H__
+
+struct hw_gpio_pin;
+
+struct hw_factory {
+	uint32_t number_of_pins[GPIO_ID_COUNT];
+
+	const struct hw_factory_funcs {
+		struct hw_gpio_pin *(*create_ddc_data)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_ddc_clock)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_generic)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_hpd)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_gpio_pad)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_sync)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_gsl)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+	} *funcs;
+};
+
+bool dal_hw_factory_init(
+	struct hw_factory *factory,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
new file mode 100644
index 000000000000..2a2262c7b107
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_gpio.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+enum gpio_result dal_hw_gpio_get_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t *value)
+{
+	*value = dm_read_reg(ctx, reg->addr);
+
+	*value &= reg->mask;
+
+	return GPIO_RESULT_OK;
+}
+
+enum gpio_result dal_hw_gpio_set_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t value)
+{
+	uint32_t prev_value;
+
+	if ((value & reg->mask) != value) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_INVALID_DATA;
+	}
+
+	prev_value = dm_read_reg(ctx, reg->addr);
+
+	prev_value &= ~reg->mask;
+	prev_value |= (value & reg->mask);
+
+	dm_write_reg(ctx, reg->addr, prev_value);
+
+	return GPIO_RESULT_OK;
+}
+
+uint32_t dal_hw_gpio_get_shift_from_mask(
+	uint32_t mask)
+{
+	uint32_t result = 0;
+
+	if (!mask)
+		return 32;
+
+	do {
+		if ((1 << result) & mask)
+			break;
+
+		++result;
+	} while (result < 32);
+
+	return result;
+}
+
+#define FROM_HW_GPIO_PIN(ptr) \
+	container_of((ptr), struct hw_gpio, base)
+
+static void store_registers(
+	struct hw_gpio *pin)
+{
+	dal_hw_gpio_get_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		&pin->store.mask);
+	dal_hw_gpio_get_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_A,
+		&pin->store.a);
+	dal_hw_gpio_get_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		&pin->store.en);
+
+	if (pin->mux_supported)
+		dal_hw_gpio_get_reg_value(
+			pin->base.ctx,
+			&pin->mux_reg.GPIO_MUX_CONTROL,
+			&pin->store.mux);
+}
+
+static void restore_registers(
+	struct hw_gpio *pin)
+{
+	dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->store.mask);
+	dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_A,
+		pin->store.a);
+	dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		pin->store.en);
+
+	if (pin->mux_supported)
+		dal_hw_gpio_set_reg_value(
+			pin->base.ctx,
+			&pin->mux_reg.GPIO_MUX_CONTROL,
+			pin->store.mux);
+}
+
+bool dal_hw_gpio_open(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode,
+	void *options)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	store_registers(pin);
+
+	ptr->opened = (pin->funcs->config_mode(pin, mode) == GPIO_RESULT_OK);
+
+	return ptr->opened;
+}
+
+enum gpio_result dal_hw_gpio_get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	const struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	enum gpio_result result;
+
+	switch (ptr->mode) {
+	case GPIO_MODE_INPUT:
+	case GPIO_MODE_OUTPUT:
+	case GPIO_MODE_HARDWARE:
+	case GPIO_MODE_FAST_OUTPUT:
+		result = dal_hw_gpio_get_reg_value(
+			ptr->ctx,
+			&pin->pin_reg.DC_GPIO_DATA_Y,
+			value);
+		/* Clients does not know that the value
+		 * comes from register and is shifted. */
+		if (result == GPIO_RESULT_OK)
+			*value >>= dal_hw_gpio_get_shift_from_mask(
+				pin->pin_reg.DC_GPIO_DATA_Y.mask);
+	break;
+	default:
+		result = GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+
+	return result;
+}
+
+enum gpio_result dal_hw_gpio_set_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	/* This is the public interface
+	 * where the input comes from client, not shifted yet
+	 * (because client does not know the shifts). */
+
+	switch (ptr->mode) {
+	case GPIO_MODE_OUTPUT:
+		return dal_hw_gpio_set_reg_value(
+			ptr->ctx,
+			&pin->pin_reg.DC_GPIO_DATA_A,
+			value << dal_hw_gpio_get_shift_from_mask(
+				pin->pin_reg.DC_GPIO_DATA_A.mask));
+	case GPIO_MODE_FAST_OUTPUT:
+		/* We use (EN) to faster switch (used in DDC GPIO).
+		 * So (A) is grounded, output is driven by (EN = 0)
+		 * to pull the line down (output == 0) and (EN=1)
+		 * then output is tri-state */
+		return dal_hw_gpio_set_reg_value(
+			ptr->ctx,
+			&pin->pin_reg.DC_GPIO_DATA_EN,
+			pin->pin_reg.DC_GPIO_DATA_EN.mask &
+			~(value << dal_hw_gpio_get_shift_from_mask(
+				pin->pin_reg.DC_GPIO_DATA_EN.mask)));
+	default:
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+enum gpio_result dal_hw_gpio_change_mode(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	return pin->funcs->config_mode(pin, mode);
+}
+
+void dal_hw_gpio_close(
+	struct hw_gpio_pin *ptr)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	restore_registers(pin);
+
+	ptr->mode = GPIO_MODE_UNKNOWN;
+	ptr->opened = false;
+}
+
+static enum gpio_result config_mode_input(
+	struct hw_gpio *pin)
+{
+	enum gpio_result result;
+
+	/* turn off output enable, act as input pin;
+	 * program the pin as GPIO, mask out signal driven by HW */
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		0);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->pin_reg.DC_GPIO_DATA_MASK.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+static enum gpio_result config_mode_output(
+	struct hw_gpio *pin)
+{
+	enum gpio_result result;
+
+	/* turn on output enable, act as output pin;
+	 * program the pin as GPIO, mask out signal driven by HW */
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		pin->pin_reg.DC_GPIO_DATA_EN.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->pin_reg.DC_GPIO_DATA_MASK.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+static enum gpio_result config_mode_fast_output(
+	struct hw_gpio *pin)
+{
+	enum gpio_result result;
+
+	/* grounding the A register then use the EN register bit
+	 * will have faster effect on the rise time */
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_A, 0);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->pin_reg.DC_GPIO_DATA_MASK.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+static enum gpio_result config_mode_hardware(
+	struct hw_gpio *pin)
+{
+	/* program the pin as tri-state, pin is driven by HW */
+
+	enum gpio_result result =
+		dal_hw_gpio_set_reg_value(
+			pin->base.ctx,
+			&pin->pin_reg.DC_GPIO_DATA_MASK,
+			0);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+enum gpio_result dal_hw_gpio_config_mode(
+	struct hw_gpio *pin,
+	enum gpio_mode mode)
+{
+	pin->base.mode = mode;
+
+	switch (mode) {
+	case GPIO_MODE_INPUT:
+		return config_mode_input(pin);
+	case GPIO_MODE_OUTPUT:
+		return config_mode_output(pin);
+	case GPIO_MODE_FAST_OUTPUT:
+		return config_mode_fast_output(pin);
+	case GPIO_MODE_HARDWARE:
+		return config_mode_hardware(pin);
+	default:
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+const struct hw_gpio_funcs func = {
+	.config_mode = dal_hw_gpio_config_mode,
+};
+
+bool dal_hw_gpio_construct(
+	struct hw_gpio *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	struct hw_gpio_pin *base = &pin->base;
+
+	if (!dal_hw_gpio_pin_construct(base, id, en, ctx))
+		return false;
+
+	pin->funcs = &func;
+
+	pin->pin_reg.DC_GPIO_DATA_MASK.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_MASK.mask = 0;
+	pin->pin_reg.DC_GPIO_DATA_A.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_A.mask = 0;
+	pin->pin_reg.DC_GPIO_DATA_EN.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_EN.mask = 0;
+	pin->pin_reg.DC_GPIO_DATA_Y.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_Y.mask = 0;
+	pin->mux_reg.GPIO_MUX_CONTROL.addr = 0;
+	pin->mux_reg.GPIO_MUX_CONTROL.mask = 0;
+	pin->mux_reg.GPIO_MUX_STEREO_SEL.addr = 0;
+	pin->mux_reg.GPIO_MUX_STEREO_SEL.mask = 0;
+
+	pin->store.mask = 0;
+	pin->store.a = 0;
+	pin->store.en = 0;
+	pin->store.mux = 0;
+
+	pin->mux_supported = false;
+
+	return true;
+}
+
+void dal_hw_gpio_destruct(
+	struct hw_gpio *pin)
+{
+	dal_hw_gpio_pin_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
new file mode 100644
index 000000000000..44eb86e1cc32
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_GPIO_H__
+#define __DAL_HW_GPIO_H__
+
+struct addr_mask {
+	uint32_t addr;
+	uint32_t mask;
+};
+
+enum gpio_result dal_hw_gpio_get_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t *value);
+
+enum gpio_result dal_hw_gpio_set_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t value);
+
+uint32_t dal_hw_gpio_get_shift_from_mask(
+	uint32_t mask);
+
+struct hw_gpio;
+
+struct hw_gpio_funcs {
+	enum gpio_result (*config_mode)(
+		struct hw_gpio *pin,
+		enum gpio_mode mode);
+};
+
+/* Register indices are represented by member variables
+ * and are to be filled in by constructors of derived classes.
+ * These members permit the use of common code
+ * for programming registers, where the sequence is the same
+ * but register sets are different.
+ * Some GPIOs have HW mux which allows to choose
+ * what is the source of the signal in HW mode */
+
+struct hw_gpio_pin_reg {
+	struct addr_mask DC_GPIO_DATA_MASK;
+	struct addr_mask DC_GPIO_DATA_A;
+	struct addr_mask DC_GPIO_DATA_EN;
+	struct addr_mask DC_GPIO_DATA_Y;
+};
+
+struct hw_gpio_mux_reg {
+	struct addr_mask GPIO_MUX_CONTROL;
+	struct addr_mask GPIO_MUX_STEREO_SEL;
+};
+
+struct hw_gpio {
+	struct hw_gpio_pin base;
+	const struct hw_gpio_funcs *funcs;
+	struct hw_gpio_pin_reg pin_reg;
+	struct hw_gpio_mux_reg mux_reg;
+
+	/* variables to save register value */
+	struct {
+		uint32_t mask;
+		uint32_t a;
+		uint32_t en;
+		uint32_t mux;
+	} store;
+
+	/* GPIO MUX support */
+	bool mux_supported;
+};
+
+#define HW_GPIO_FROM_BASE(hw_gpio_pin) \
+	container_of((hw_gpio_pin), struct hw_gpio, base)
+
+bool dal_hw_gpio_construct(
+	struct hw_gpio *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+bool dal_hw_gpio_open(
+	struct hw_gpio_pin *pin,
+	enum gpio_mode mode,
+	void *options);
+
+enum gpio_result dal_hw_gpio_get_value(
+	const struct hw_gpio_pin *pin,
+	uint32_t *value);
+
+enum gpio_result dal_hw_gpio_config_mode(
+	struct hw_gpio *pin,
+	enum gpio_mode mode);
+
+void dal_hw_gpio_destruct(
+	struct hw_gpio *pin);
+
+enum gpio_result dal_hw_gpio_set_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value);
+
+enum gpio_result dal_hw_gpio_change_mode(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode);
+
+void dal_hw_gpio_close(
+	struct hw_gpio_pin *ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
new file mode 100644
index 000000000000..2392f2ce353b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+#include "hw_gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_gpio_pad.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define FROM_HW_GPIO(ptr) \
+	container_of((ptr), struct hw_gpio_pad, base)
+
+#define FROM_HW_GPIO_PIN(ptr) \
+	FROM_HW_GPIO(container_of((ptr), struct hw_gpio, base))
+
+enum gpio_result dal_hw_gpio_pad_get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	const struct hw_gpio_pad *pin = FROM_HW_GPIO_PIN(ptr);
+
+	if (ptr->mode == GPIO_MODE_INTERRUPT)
+		/* in Interrupt mode, ask for interrupt status bit */
+		return dal_hw_gpio_get_reg_value(
+			ptr->ctx,
+			&pin->gpiopad_int_status,
+			value);
+	else
+		/* for any mode other than Interrupt,
+		 * gpio_pad operates as normal GPIO */
+		return dal_hw_gpio_get_value(ptr, value);
+}
+
+bool dal_hw_gpio_pad_construct(
+	struct hw_gpio_pad *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_gpio_construct(&pin->base, id, en, ctx))
+		return false;
+
+	pin->gpiopad_int_status.addr = 0;
+	pin->gpiopad_int_status.mask = 0;
+
+	return true;
+}
+
+void dal_hw_gpio_pad_destruct(
+	struct hw_gpio_pad *pin)
+{
+	dal_hw_gpio_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
new file mode 100644
index 000000000000..34b470a11464
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_GPIO_PAD_H__
+#define __DAL_HW_GPIO_PAD_H__
+
+struct hw_gpio_pad {
+	struct hw_gpio base;
+	struct addr_mask gpiopad_int_status;
+};
+
+bool dal_hw_gpio_pad_construct(
+	struct hw_gpio_pad *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_gpio_pad_destruct(
+	struct hw_gpio_pad *pin);
+
+enum gpio_result dal_hw_gpio_pad_get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
new file mode 100644
index 000000000000..411ad89645e0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_gpio_pin.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+enum gpio_result dal_hw_gpio_pin_set_config(
+	struct hw_gpio_pin *pin,
+	const struct gpio_config_data *config_data)
+{
+	/* Attention!
+	 * You must override this method in derived class */
+
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+enum gpio_result dal_hw_gpio_pin_change_mode(
+	struct hw_gpio_pin *pin,
+	enum gpio_mode mode)
+{
+	/* Attention!
+	 * You must override this method in derived class */
+
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+bool dal_hw_gpio_pin_construct(
+	struct hw_gpio_pin *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	pin->ctx = ctx;
+	pin->id = id;
+	pin->en = en;
+	pin->mode = GPIO_MODE_UNKNOWN;
+	pin->opened = false;
+
+	return true;
+}
+
+void dal_hw_gpio_pin_destruct(
+	struct hw_gpio_pin *pin)
+{
+	ASSERT(!pin->opened);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
new file mode 100644
index 000000000000..d1f2f2712fe2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_GPIO_PIN_H__
+#define __DAL_HW_GPIO_PIN_H__
+
+struct hw_gpio_pin;
+
+struct hw_gpio_pin_funcs {
+	void (*destroy)(
+		struct hw_gpio_pin **ptr);
+	bool (*open)(
+		struct hw_gpio_pin *pin,
+		enum gpio_mode mode,
+		void *options);
+	enum gpio_result (*get_value)(
+		const struct hw_gpio_pin *pin,
+		uint32_t *value);
+	enum gpio_result (*set_value)(
+		const struct hw_gpio_pin *pin,
+		uint32_t value);
+	enum gpio_result (*set_config)(
+		struct hw_gpio_pin *pin,
+		const struct gpio_config_data *config_data);
+	enum gpio_result (*change_mode)(
+		struct hw_gpio_pin *pin,
+		enum gpio_mode mode);
+	void (*close)(
+		struct hw_gpio_pin *pin);
+};
+
+struct hw_gpio_pin {
+	const struct hw_gpio_pin_funcs *funcs;
+	enum gpio_id id;
+	uint32_t en;
+	enum gpio_mode mode;
+	bool opened;
+	struct dc_context *ctx;
+};
+
+bool dal_hw_gpio_pin_construct(
+	struct hw_gpio_pin *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_gpio_pin_destruct(
+	struct hw_gpio_pin *pin);
+
+enum gpio_result dal_hw_gpio_pin_change_mode(
+	struct hw_gpio_pin *pin,
+	enum gpio_mode mode);
+
+enum gpio_result dal_hw_gpio_pin_set_config(
+	struct hw_gpio_pin *pin,
+	const struct gpio_config_data *config_data);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
new file mode 100644
index 000000000000..f072fd551b4a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+#include "hw_gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_hpd.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+static enum gpio_result config_mode(
+	struct hw_gpio *pin,
+	enum gpio_mode mode)
+{
+	if (mode == GPIO_MODE_INTERRUPT) {
+		/* Interrupt mode supported only by HPD (IrqGpio) pins. */
+		pin->base.mode = mode;
+
+		return dal_hw_gpio_set_reg_value(
+			pin->base.ctx,
+			&pin->pin_reg.DC_GPIO_DATA_MASK,
+			0);
+	} else
+		/* For any mode other than Interrupt,
+		 * act as normal GPIO. */
+		return dal_hw_gpio_config_mode(pin, mode);
+}
+
+const struct hw_gpio_funcs hw_hpd_func = {
+	.config_mode = config_mode,
+};
+
+bool dal_hw_hpd_construct(
+	struct hw_hpd *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_gpio_construct(&pin->base, id, en, ctx))
+		return false;
+	pin->base.funcs = &hw_hpd_func;
+	return true;
+}
+
+void dal_hw_hpd_destruct(
+	struct hw_hpd *pin)
+{
+	dal_hw_gpio_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
new file mode 100644
index 000000000000..3fb82df88802
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_HPD_H__
+#define __DAL_HW_HPD_H__
+
+struct hw_hpd {
+	struct hw_gpio base;
+};
+
+#define HW_HPD_FROM_BASE(hw_gpio) \
+	container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_hpd, base)
+
+bool dal_hw_hpd_construct(
+	struct hw_hpd *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_hpd_destruct(
+	struct hw_hpd *pin);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
new file mode 100644
index 000000000000..215322e9d7e9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_translate.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/hw_translate_dce110.h"
+#endif
+
+#include "diagnostics/hw_translate_diag.h"
+
+/*
+ * This unit
+ */
+
+bool dal_hw_translate_init(
+	struct hw_translate *translate,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment)
+{
+	if (IS_FPGA_MAXIMUS_DC(dce_environment)) {
+		dal_hw_translate_diag_fpga_init(translate);
+		return true;
+	}
+
+	switch (dce_version) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+#endif
+	case DCE_VERSION_11_0:
+		dal_hw_translate_dce110_init(translate);
+		return true;
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
new file mode 100644
index 000000000000..3a7d89ca1605
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_H__
+#define __DAL_HW_TRANSLATE_H__
+
+struct hw_translate_funcs {
+	bool (*offset_to_id)(
+		uint32_t offset,
+		uint32_t mask,
+		enum gpio_id *id,
+		uint32_t *en);
+	bool (*id_to_offset)(
+		enum gpio_id id,
+		uint32_t en,
+		struct gpio_pin_info *info);
+};
+
+struct hw_translate {
+	const struct hw_translate_funcs *funcs;
+};
+
+bool dal_hw_translate_init(
+	struct hw_translate *translate,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/irq.c b/drivers/gpu/drm/amd/dal/dc/gpio/irq.c
new file mode 100644
index 000000000000..debc2ea48ca1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/irq.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_interface.h"
+#include "include/irq_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_gpio_pin.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+#include "gpio_service.h"
+#include "gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "irq.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+enum gpio_result dal_irq_open(
+	struct irq *irq)
+{
+	return dal_gpio_open(irq->pin, GPIO_MODE_INTERRUPT);
+}
+
+enum gpio_result dal_irq_get_value(
+	const struct irq *irq,
+	uint32_t *value)
+{
+	return dal_gpio_get_value(irq->pin, value);
+}
+
+enum dc_irq_source dal_irq_get_source(
+	const struct irq *irq)
+{
+	enum gpio_id id = dal_gpio_get_id(irq->pin);
+
+	switch (id) {
+	case GPIO_ID_HPD:
+		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
+			dal_gpio_get_enum(irq->pin));
+	case GPIO_ID_GPIO_PAD:
+		return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
+			dal_gpio_get_enum(irq->pin));
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+enum dc_irq_source dal_irq_get_rx_source(
+	const struct irq *irq)
+{
+	enum gpio_id id = dal_gpio_get_id(irq->pin);
+
+	switch (id) {
+	case GPIO_ID_HPD:
+		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
+			dal_gpio_get_enum(irq->pin));
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+enum gpio_result dal_irq_setup_hpd_filter(
+	struct irq *irq,
+	struct gpio_hpd_config *config)
+{
+	struct gpio_config_data config_data;
+
+	if (!config)
+		return GPIO_RESULT_INVALID_DATA;
+
+	config_data.type = GPIO_CONFIG_TYPE_HPD;
+	config_data.config.hpd = *config;
+
+	return dal_gpio_set_config(irq->pin, &config_data);
+}
+
+void dal_irq_close(
+	struct irq *irq)
+{
+	dal_gpio_close(irq->pin);
+}
+
+/*
+ * @brief
+ * Creation and destruction
+ */
+
+struct irq *dal_gpio_create_irq(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct irq *irq;
+
+	switch (id) {
+	case GPIO_ID_HPD:
+	case GPIO_ID_GPIO_PAD:
+	break;
+	default:
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	irq = dm_alloc(service->ctx, sizeof(struct irq));
+
+	if (!irq) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	irq->pin = dal_gpio_service_create_gpio_ex(
+		service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+	irq->ctx = service->ctx;
+
+	if (irq->pin)
+		return irq;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(service->ctx, irq);
+
+	return NULL;
+}
+
+static void destruct(struct irq *irq)
+{
+	dal_irq_close(irq);
+	dal_gpio_service_destroy_gpio(&irq->pin);
+
+}
+
+void dal_gpio_destroy_irq(
+	struct irq **irq)
+{
+	if (!irq || !*irq) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	destruct(*irq);
+	dm_free((*irq)->ctx, *irq);
+
+	*irq = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/irq.h b/drivers/gpu/drm/amd/dal/dc/gpio/irq.h
new file mode 100644
index 000000000000..b69375cd8dc2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/irq.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_H__
+#define __DAL_IRQ_H__
+
+struct irq {
+	struct gpio *pin;
+	struct dc_context *ctx;
+};
+
+struct irq *dal_gpio_create_irq(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en);
+
+void dal_gpio_destroy_irq(
+	struct irq **ptr);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 06/26] drm/amd/dal: Adapter Service
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (4 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 07/26] drm/amd/dal: BIOS Parser Harry Wentland
                     ` (19 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Provides information about ASIC features and capabilities. Also provides
access to ASIC resources such as VBIOS, GPIO and I2cAux Manager

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/adapter/Makefile        |   24 +
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.c   | 2089 ++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.h   |   71 +
 .../adapter/dce110/hw_ctx_adapter_service_dce110.c |  304 +++
 .../adapter/dce110/hw_ctx_adapter_service_dce110.h |   40 +
 .../diagnostics/hw_ctx_adapter_service_diag.c      |  133 ++
 .../diagnostics/hw_ctx_adapter_service_diag.h      |   33 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.c    |  164 ++
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.h    |   86 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.c  |  208 ++
 .../drm/amd/dal/dc/adapter/wireless_data_source.h  |   80 +
 11 files changed, 3232 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h

diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/Makefile b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile
new file mode 100644
index 000000000000..2c6ca7a513bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile for the 'adapter' sub-component of DAL.
+# It provides the control and status of HW adapter.
+
+ADAPTER = adapter_service.o hw_ctx_adapter_service.o wireless_data_source.o
+
+AMD_DAL_ADAPTER = $(addprefix $(AMDDALPATH)/dc/adapter/,$(ADAPTER))
+
+AMD_DAL_FILES += $(AMD_DAL_ADAPTER)
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+AMD_DAL_FILES += $(AMDDALPATH)/dc/adapter/dce110/hw_ctx_adapter_service_dce110.o
+endif
+
+###############################################################################
+# FPGA Diagnositcs
+###############################################################################
+
+AMD_DAL_FILES += $(AMDDALPATH)/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.o
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
new file mode 100644
index 000000000000..dd2f931fe9a1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
@@ -0,0 +1,2089 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dc_bios_types.h"
+
+#include "include/adapter_service_interface.h"
+#include "include/i2caux_interface.h"
+#include "include/asic_capability_types.h"
+#include "include/gpio_service_interface.h"
+#include "include/asic_capability_interface.h"
+#include "include/logger_interface.h"
+
+#include "adapter_service.h"
+
+#include "hw_ctx_adapter_service.h"
+#include "wireless_data_source.h"
+
+#include "atom.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/hw_ctx_adapter_service_dce110.h"
+#endif
+
+#include "diagnostics/hw_ctx_adapter_service_diag.h"
+
+/*
+ * Adapter service feature entry table.
+ *
+ * This is an array of features that is used to generate feature set. Each
+ * entry consists three element:
+ *
+ * Feature name, default value, and if this feature is a boolean type. A
+ * feature can only be a boolean or int type.
+ *
+ * Example 1: a boolean type feature
+ * FEATURE_ENABLE_HW_EDID_POLLING, false, true
+ *
+ * First element is feature name: EATURE_ENABLE_HW_EDID_POLLING, it has a
+ * default value 0, and it is a boolean feature.
+ *
+ * Example 2: an int type feature
+ * FEATURE_DCP_PROGRAMMING_WA, 0x1FF7, false
+ *
+ * In this case, the default value is 0x1FF7 and not a boolean type, which
+ * makes it an int type.
+ */
+
+static struct feature_source_entry feature_entry_table[] = {
+	/* Feature name | default value | is boolean type */
+	{FEATURE_ENABLE_HW_EDID_POLLING, false, true},
+	{FEATURE_DP_SINK_DETECT_POLL_DATA_PIN, false, true},
+	{FEATURE_UNDERFLOW_INTERRUPT, false, true},
+	{FEATURE_ALLOW_WATERMARK_ADJUSTMENT, false, true},
+	{FEATURE_LIGHT_SLEEP, false, true},
+	{FEATURE_DCP_DITHER_FRAME_RANDOM_ENABLE, false, true},
+	{FEATURE_DCP_DITHER_RGB_RANDOM_ENABLE, false, true},
+	{FEATURE_DCP_DITHER_HIGH_PASS_RANDOM_ENABLE, false, true},
+	{FEATURE_LINE_BUFFER_ENHANCED_PIXEL_DEPTH, false, true},
+	{FEATURE_MAXIMIZE_URGENCY_WATERMARKS, false, true},
+	{FEATURE_MAXIMIZE_STUTTER_MARKS, false, true},
+	{FEATURE_MAXIMIZE_NBP_MARKS, false, true},
+	/*
+	 * We meet HW I2C issue when test S3 resume on KB.
+	 * An EPR is created for debug the issue.
+	 * Make Test has already been implemented
+	 * with HW I2C. The work load for revert back to SW I2C in make test
+	 * is big. Below is workaround for this issue.
+	 * Driver uses SW I2C.
+	 * Make Test uses HW I2C.
+	 */
+	{FEATURE_RESTORE_USAGE_I2C_SW_ENGINE, false, true},
+	{FEATURE_USE_MAX_DISPLAY_CLK, false, true},
+	{FEATURE_ALLOW_EDP_RESOURCE_SHARING, false, true},
+	{FEATURE_SUPPORT_DP_YUV, false, true},
+	{FEATURE_SUPPORT_DP_Y_ONLY, false, true},
+	{FEATURE_DISABLE_DP_GTC_SYNC, true, true},
+	{FEATURE_MODIFY_TIMINGS_FOR_WIRELESS, false, true},
+	{FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE, 0, false},
+	{FEATURE_DCP_DITHER_MODE, 0, false},
+	{FEATURE_DCP_PROGRAMMING_WA, 0, false},
+	{FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, false, true},
+	{FEATURE_ENABLE_DFS_BYPASS, false, true},
+	{FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT, false, true},
+	{FEATURE_MAX_COFUNC_NON_DP_DISPLAYS, 2, false},
+	{FEATURE_WIRELESS_LIMIT_720P, false, true},
+	{FEATURE_MODIFY_TIMINGS_FOR_WIRELESS, false, true},
+	{FEATURE_SUPPORTED_HDMI_CONNECTION_NUM, 0, false},
+	{FEATURE_DETECT_REQUIRE_HPD_HIGH, false, true},
+	{FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, false, true},
+	{FEATURE_LB_HIGH_RESOLUTION, false, true},
+	{FEATURE_MAX_CONTROLLER_NUM, 0, false},
+	{FEATURE_DRR_SUPPORT, AS_DRR_SUPPORT_ENABLED, false},
+	{FEATURE_STUTTER_MODE, 15, false},
+	{FEATURE_DP_DISPLAY_FORCE_SS_ENABLE, false, true},
+	{FEATURE_REPORT_CE_MODE_ONLY, false, true},
+	{FEATURE_ALLOW_OPTIMIZED_MODE_AS_DEFAULT, false, true},
+	{FEATURE_DDC_READ_FORCE_REPEATED_START, false, true},
+	{FEATURE_FORCE_TIMING_RESYNC, false, true},
+	{FEATURE_TMDS_DISABLE_DITHERING, false, true},
+	{FEATURE_HDMI_DISABLE_DITHERING, false, true},
+	{FEATURE_DP_DISABLE_DITHERING, false, true},
+	{FEATURE_EMBEDDED_DISABLE_DITHERING, true, true},
+	{FEATURE_ALLOW_SELF_REFRESH, false, true},
+	{FEATURE_ALLOW_DYNAMIC_PIXEL_ENCODING_CHANGE, false, true},
+	{FEATURE_ALLOW_HSYNC_VSYNC_ADJUSTMENT, false, true},
+	{FEATURE_FORCE_PSR, false, true},
+	{FEATURE_PSR_SETUP_TIME_TEST, 0, false},
+	{FEATURE_POWER_GATING_PIPE_IN_TILE, true, true},
+	{FEATURE_POWER_GATING_LB_PORTION, true, true},
+	{FEATURE_PREFER_3D_TIMING, false, true},
+	{FEATURE_VARI_BRIGHT_ENABLE, true, true},
+	{FEATURE_PSR_ENABLE, false, true},
+	{FEATURE_WIRELESS_ENABLE_COMPRESSED_AUDIO, false, true},
+	{FEATURE_WIRELESS_INCLUDE_UNVERIFIED_TIMINGS, true, true},
+	{FEATURE_EDID_STRESS_READ, false, true},
+	{FEATURE_DP_FRAME_PACK_STEREO3D, false, true},
+	{FEATURE_DISPLAY_PREFERRED_VIEW, 0, false},
+	{FEATURE_ALLOW_HDMI_WITHOUT_AUDIO, false, true},
+	{FEATURE_ABM_2_0, false, true},
+	{FEATURE_SUPPORT_MIRABILIS, false, true},
+	{FEATURE_OPTIMIZATION, 0xFFFF, false},
+	{FEATURE_PERF_MEASURE, 0, false},
+	{FEATURE_MIN_BACKLIGHT_LEVEL, 0, false},
+	{FEATURE_MAX_BACKLIGHT_LEVEL, 255, false},
+	{FEATURE_LOAD_DMCU_FIRMWARE, true, true},
+	{FEATURE_DISABLE_AZ_CLOCK_GATING, false, true},
+	{FEATURE_ENABLE_GPU_SCALING, false, true},
+	{FEATURE_DONGLE_SINK_COUNT_CHECK, true, true},
+	{FEATURE_INSTANT_UP_SCALE_DOWN_SCALE, false, true},
+	{FEATURE_TILED_DISPLAY, false, true},
+	{FEATURE_PREFERRED_ABM_CONFIG_SET, 0, false},
+	{FEATURE_CHANGE_SW_I2C_SPEED, 50, false},
+	{FEATURE_CHANGE_HW_I2C_SPEED, 50, false},
+	{FEATURE_CHANGE_I2C_SPEED_CONTROL, false, true},
+	{FEATURE_DEFAULT_PSR_LEVEL, 0, false},
+	{FEATURE_MAX_CLOCK_SOURCE_NUM, 0, false},
+	{FEATURE_REPORT_SINGLE_SELECTED_TIMING, false, true},
+	{FEATURE_ALLOW_HDMI_HIGH_CLK_DP_DONGLE, true, true},
+	{FEATURE_SUPPORT_EXTERNAL_PANEL_DRR, false, true},
+	{FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE, 0, false},
+	{FEATURE_ABM_CONFIG, 0, false},
+	{FEATURE_WIRELESS_ENABLE, false, true},
+	{FEATURE_ALLOW_DIRECT_MEMORY_ACCESS_TRIG, false, true},
+	{FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS, 0, false},
+	{FEATURE_USE_PPLIB, true, true},
+	{FEATURE_DISABLE_LPT_SUPPORT, false, true},
+	{FEATURE_DUMMY_FBC_BACKEND, false, true},
+	{FEATURE_DPMS_AUDIO_ENDPOINT_CONTROL, true, true},
+	{FEATURE_DISABLE_FBC_COMP_CLK_GATE, false, true},
+	{FEATURE_PIXEL_PERFECT_OUTPUT, false, true},
+	{FEATURE_8BPP_SUPPORTED, false, true}
+};
+
+
+/* Stores entire ASIC features by sets */
+uint32_t adapter_feature_set[FEATURE_MAXIMUM/32];
+
+enum {
+	LEGACY_MAX_NUM_OF_CONTROLLERS = 2,
+	DEFAULT_NUM_COFUNC_NON_DP_DISPLAYS = 2
+};
+
+/*
+ * get_feature_entries_num
+ *
+ * Get number of feature entries
+ */
+static inline uint32_t get_feature_entries_num(void)
+{
+	return ARRAY_SIZE(feature_entry_table);
+}
+
+static void get_platform_info_methods(
+		struct adapter_service *as)
+{
+	struct platform_info_params params;
+	uint32_t mask = 0;
+
+	params.data = &mask;
+	params.method = PM_GET_AVAILABLE_METHODS;
+
+	if (dm_get_platform_info(as->ctx, &params))
+		as->platform_methods_mask = mask;
+
+
+}
+
+static void initialize_backlight_caps(
+		struct adapter_service *as)
+{
+	struct firmware_info fw_info;
+	struct embedded_panel_info panel_info;
+	struct platform_info_ext_brightness_caps caps;
+	struct platform_info_params params;
+	bool custom_curve_present = false;
+	bool custom_min_max_present = false;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (!(PM_GET_EXTENDED_BRIGHNESS_CAPS & as->platform_methods_mask)) {
+			dal_logger_write(as->ctx->logger,
+					LOG_MAJOR_BACKLIGHT,
+					LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS,
+					"This method is not supported\n");
+			return;
+	}
+
+	if (dcb->funcs->get_firmware_info(dcb, &fw_info) != BP_RESULT_OK ||
+		dcb->funcs->get_embedded_panel_info(dcb, &panel_info) != BP_RESULT_OK)
+		return;
+
+	params.data = &caps;
+	params.method = PM_GET_EXTENDED_BRIGHNESS_CAPS;
+
+	if (dm_get_platform_info(as->ctx, &params)) {
+		as->ac_level_percentage = caps.basic_caps.ac_level_percentage;
+		as->dc_level_percentage = caps.basic_caps.dc_level_percentage;
+		custom_curve_present = (caps.data_points_num > 0);
+		custom_min_max_present = true;
+	} else
+		return;
+	/* Choose minimum backlight level base on priority:
+	 * extended caps,VBIOS,default */
+	if (custom_min_max_present)
+		as->backlight_8bit_lut[0] = caps.min_input_signal;
+
+	else if (fw_info.min_allowed_bl_level > 0)
+		as->backlight_8bit_lut[0] = fw_info.min_allowed_bl_level;
+
+	else
+		as->backlight_8bit_lut[0] = DEFAULT_MIN_BACKLIGHT;
+
+	/* Choose maximum backlight level base on priority:
+	 * extended caps,default */
+	if (custom_min_max_present)
+		as->backlight_8bit_lut[100] = caps.max_input_signal;
+
+	else
+		as->backlight_8bit_lut[100] = DEFAULT_MAX_BACKLIGHT;
+
+	if (as->backlight_8bit_lut[100] > ABSOLUTE_BACKLIGHT_MAX)
+		as->backlight_8bit_lut[100] = ABSOLUTE_BACKLIGHT_MAX;
+
+	if (as->backlight_8bit_lut[0] > as->backlight_8bit_lut[100])
+		as->backlight_8bit_lut[0] = as->backlight_8bit_lut[100];
+
+	if (custom_curve_present) {
+		uint16_t index = 1;
+		uint16_t i;
+		uint16_t num_of_data_points = (caps.data_points_num <= 99 ?
+				caps.data_points_num : 99);
+		/* Filling translation table from data points -
+		 * between every two provided data points we
+		 * lineary interpolate missing values
+		 */
+		for (i = 0 ; i < num_of_data_points; i++) {
+			uint16_t luminance = caps.data_points[i].luminance;
+			uint16_t signal_level =
+					caps.data_points[i].signal_level;
+
+			if (signal_level < as->backlight_8bit_lut[0])
+				signal_level = as->backlight_8bit_lut[0];
+
+			if (signal_level > as->backlight_8bit_lut[100])
+				signal_level = as->backlight_8bit_lut[100];
+
+			/* Lineary interpolate missing values */
+			if (index < luminance) {
+				uint16_t base_value =
+						as->backlight_8bit_lut[index-1];
+				uint16_t delta_signal =
+						signal_level - base_value;
+				uint16_t delta_luma = luminance - index + 1;
+				uint16_t step = delta_signal;
+
+				for (; index < luminance ; index++) {
+					as->backlight_8bit_lut[index] =
+							base_value +
+							(step / delta_luma);
+					step += delta_signal;
+				}
+			}
+			/* Now [index == luminance], so we can add
+			 * data point to the translation table */
+			as->backlight_8bit_lut[index++] = signal_level;
+		}
+		/* Complete the final segment of interpolation -
+		 * between last datapoint and maximum value */
+		if (index < 100) {
+			uint16_t base_value = as->backlight_8bit_lut[index-1];
+			uint16_t delta_signal =
+					as->backlight_8bit_lut[100]-base_value;
+			uint16_t delta_luma = 100 - index + 1;
+			uint16_t step = delta_signal;
+
+			for (; index < 100 ; index++) {
+				as->backlight_8bit_lut[index] = base_value +
+						(step / delta_luma);
+				step += delta_signal;
+			}
+		}
+	}
+	/* build backlight translation table based on default curve */
+	else {
+		/* Default backlight curve can be defined by
+		 * polinomial F(x) = A(x*x) + Bx + C.
+		 * Backlight curve should always  satisfy
+		 * F(0) = min, F(100) = max, so polinomial coefficients are:
+		 * A is 0.0255 - B/100 - min/10000 -
+		 * (255-max)/10000 = (max - min)/10000 - B/100
+		 * B is adjustable factor to modify the curve.
+		 * Bigger B results in less concave curve.
+		 * B range is [0..(max-min)/100]
+		 * C is backlight minimum
+		 */
+		uint16_t delta = as->backlight_8bit_lut[100] -
+				as->backlight_8bit_lut[0];
+		uint16_t coeffc = as->backlight_8bit_lut[0];
+		uint16_t coeffb = (BACKLIGHT_CURVE_COEFFB < delta ?
+				BACKLIGHT_CURVE_COEFFB : delta);
+		uint16_t coeffa = delta - coeffb;
+		uint16_t i;
+		uint32_t temp;
+
+		for (i = 1; i < 100 ; i++) {
+			temp = (coeffa * i * i) / BACKLIGHT_CURVE_COEFFA_FACTOR;
+			as->backlight_8bit_lut[i] = temp + (coeffb * i) /
+					BACKLIGHT_CURVE_COEFFB_FACTOR + coeffc;
+		}
+	}
+	as->backlight_caps_initialized = true;
+}
+
+static void log_overriden_features(
+	struct adapter_service *as,
+	const char *feature_name,
+	enum adapter_feature_id id,
+	bool bool_feature,
+	uint32_t value)
+{
+	if (bool_feature)
+		dal_logger_write(as->ctx->logger,
+			LOG_MAJOR_FEATURE_OVERRIDE,
+			LOG_MINOR_FEATURE_OVERRIDE,
+			"Overridden %s is %s now\n",
+			feature_name,
+			(value == 0) ? "disabled" : "enabled");
+	else
+		dal_logger_write(as->ctx->logger,
+			LOG_MAJOR_FEATURE_OVERRIDE,
+			LOG_MINOR_FEATURE_OVERRIDE,
+			"Overridden %s new value: %d\n",
+			feature_name,
+			value);
+}
+
+/*************************************
+ * Local static functions definition *
+ *************************************/
+
+#define check_bool_feature(feature) \
+case FEATURE_ ## feature: \
+	if (param->bool_param_enable_mask & \
+		(1 << DAL_PARAM_ ## feature)) { \
+		*data = param->bool_param_values & \
+		(1 << DAL_PARAM_ ## feature); \
+		ret = true; \
+		feature_name = "FEATURE_" #feature; \
+	} \
+	break
+
+#define check_int_feature(feature) \
+case FEATURE_ ## feature: \
+	if (param->int_param_values[DAL_PARAM_ ## feature] != \
+		DAL_PARAM_INVALID_INT) { \
+		*data = param->int_param_values[DAL_PARAM_ ## feature];\
+		ret = true;\
+		bool_feature = false;\
+		feature_name = "FEATURE_" #feature;\
+	} \
+	break
+
+/*
+ * override_default_parameters
+ *
+ * Override features (from runtime parameter)
+ * corresponding to Adapter Service Feature ID
+ */
+static bool override_default_parameters(
+	struct adapter_service *as,
+	const struct dal_override_parameters *param,
+	const uint32_t idx,
+	uint32_t *data)
+{
+	bool ret = false;
+	bool bool_feature = true;
+	char *feature_name;
+
+	if (idx >= get_feature_entries_num()) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	switch (feature_entry_table[idx].feature_id) {
+	check_int_feature(MAX_COFUNC_NON_DP_DISPLAYS);
+	check_int_feature(DRR_SUPPORT);
+	check_bool_feature(LIGHT_SLEEP);
+	check_bool_feature(MAXIMIZE_STUTTER_MARKS);
+	check_bool_feature(MAXIMIZE_URGENCY_WATERMARKS);
+	check_bool_feature(USE_MAX_DISPLAY_CLK);
+	check_bool_feature(ENABLE_DFS_BYPASS);
+	check_bool_feature(POWER_GATING_PIPE_IN_TILE);
+	check_bool_feature(POWER_GATING_LB_PORTION);
+	check_bool_feature(PSR_ENABLE);
+	check_bool_feature(VARI_BRIGHT_ENABLE);
+	check_bool_feature(USE_PPLIB);
+	check_bool_feature(DISABLE_LPT_SUPPORT);
+	check_bool_feature(DUMMY_FBC_BACKEND);
+	check_bool_feature(ENABLE_GPU_SCALING);
+	default:
+		return false;
+	}
+	if (ret)
+		log_overriden_features(
+			as,
+			feature_name,
+			feature_entry_table[idx].feature_id,
+			bool_feature,
+			*data);
+
+	return ret;
+}
+
+/*
+ * get_feature_value_from_data_sources
+ *
+ * For a given feature, determine its value from ASIC cap and wireless
+ * data source.
+ * idx : index of feature_entry_table for the feature id.
+ */
+static bool get_feature_value_from_data_sources(
+		const struct adapter_service *as,
+		const uint32_t idx,
+		uint32_t *data)
+{
+	if (idx >= get_feature_entries_num()) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	switch (feature_entry_table[idx].feature_id) {
+	case FEATURE_MAX_COFUNC_NON_DP_DISPLAYS:
+		*data = as->asic_cap->data[ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS];
+		break;
+
+	case FEATURE_WIRELESS_LIMIT_720P:
+		*data = as->asic_cap->caps.WIRELESS_LIMIT_TO_720P;
+		break;
+
+	case FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT:
+		*data = as->asic_cap->caps.WIRELESS_FULL_TIMING_ADJUSTMENT;
+		break;
+
+	case FEATURE_MODIFY_TIMINGS_FOR_WIRELESS:
+		*data = as->asic_cap->caps.WIRELESS_TIMING_ADJUSTMENT;
+		break;
+
+	case FEATURE_SUPPORTED_HDMI_CONNECTION_NUM:
+		*data =
+		as->asic_cap->data[ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM];
+		break;
+
+	case FEATURE_DETECT_REQUIRE_HPD_HIGH:
+		*data = as->asic_cap->caps.HPD_CHECK_FOR_EDID;
+		break;
+
+	case FEATURE_NO_HPD_LOW_POLLING_VCC_OFF:
+		*data = as->asic_cap->caps.NO_VCC_OFF_HPD_POLLING;
+		break;
+
+	case FEATURE_STUTTER_MODE:
+		*data = as->asic_cap->data[ASIC_DATA_STUTTERMODE];
+		break;
+
+	case FEATURE_WIRELESS_ENABLE:
+		*data = as->wireless_data.wireless_enable;
+		break;
+
+	case FEATURE_8BPP_SUPPORTED:
+		*data = as->asic_cap->caps.SUPPORT_8BPP;
+		break;
+
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+/* get_bool_value
+ *
+ * Get the boolean value of a given feature
+ */
+static bool get_bool_value(
+	const uint32_t set,
+	const uint32_t idx)
+{
+	if (idx >= 32) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	return ((set & (1 << idx)) != 0);
+}
+
+/*
+ * get_hpd_info
+ *
+ * Get HPD information from BIOS
+ */
+static bool get_hpd_info(struct adapter_service *as,
+	struct graphics_object_id id,
+	struct graphics_object_hpd_info *info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return BP_RESULT_OK == dcb->funcs->get_hpd_info(dcb, id, info);
+}
+
+/*
+ * lookup_feature_entry
+ *
+ * Find the entry index of a given feature in feature table
+ */
+static uint32_t lookup_feature_entry(
+	enum adapter_feature_id feature_id)
+{
+	uint32_t entries_num = get_feature_entries_num();
+	uint32_t i = 0;
+
+	while (i != entries_num) {
+		if (feature_entry_table[i].feature_id == feature_id)
+			break;
+
+		++i;
+	}
+
+	return i;
+}
+
+/*
+ * set_bool_value
+ *
+ * Set the boolean value of a given feature
+ */
+static void set_bool_value(
+	uint32_t *set,
+	const uint32_t idx,
+	bool value)
+{
+	if (idx >= 32) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	if (value)
+		*set |= (1 << idx);
+	else
+		*set &= ~(1 << idx);
+}
+
+/*
+ * generate_feature_set
+ *
+ * Generate the internal feature set from multiple data sources
+ */
+static bool generate_feature_set(
+		struct adapter_service *as,
+		const struct dal_override_parameters *param)
+{
+	uint32_t i = 0;
+	uint32_t value = 0;
+	uint32_t set_idx = 0;
+	uint32_t internal_idx = 0;
+	uint32_t entry_num = 0;
+	const struct feature_source_entry *entry = NULL;
+
+	dm_memset(adapter_feature_set, 0, sizeof(adapter_feature_set));
+	entry_num = get_feature_entries_num();
+
+
+	while (i != entry_num) {
+		entry = &feature_entry_table[i];
+
+		if (entry->feature_id <= FEATURE_UNKNOWN ||
+				entry->feature_id >= FEATURE_MAXIMUM) {
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+
+		set_idx = (uint32_t)((entry->feature_id - 1) / 32);
+		internal_idx = (uint32_t)((entry->feature_id - 1) % 32);
+
+		/* TODO: wireless, runtime parameter, vbios */
+		if (!override_default_parameters(as, param, i, &value)) {
+			if (!get_feature_value_from_data_sources(
+					as, i, &value)) {
+				/*
+				 * Can't find feature values from
+				 * above data sources
+				 * Assign default value
+				 */
+				value = entry->default_value;
+			}
+		}
+
+		if (entry->is_boolean_type)
+			set_bool_value(&adapter_feature_set[set_idx],
+					internal_idx,
+					value != 0);
+		else
+			adapter_feature_set[set_idx] = value;
+
+		i++;
+	}
+
+	return true;
+}
+
+
+/*
+ * create_hw_ctx
+ *
+ * Create HW context for adapter service. This is DCE specific.
+ */
+static struct hw_ctx_adapter_service *create_hw_ctx(
+	enum dce_version dce_version,
+	enum dce_environment dce_environment,
+	struct dc_context *ctx)
+{
+	if (IS_FPGA_MAXIMUS_DC(dce_environment))
+		return dal_adapter_service_create_hw_ctx_diag(ctx);
+
+	switch (dce_version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dal_adapter_service_create_hw_ctx_dce110(ctx);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dal_adapter_service_create_hw_ctx_dce110(ctx);
+#endif
+	default:
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+}
+
+/*
+ * adapter_service_destruct
+ *
+ * Release memory of objects in adapter service
+ */
+static void adapter_service_destruct(
+	struct adapter_service *as)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	dal_adapter_service_destroy_hw_ctx(&as->hw_ctx);
+	dal_i2caux_destroy(&as->i2caux);
+	dal_gpio_service_destroy(&as->gpio_service);
+	dal_asic_capability_destroy(&as->asic_cap);
+
+	dcb->funcs->destroy_integrated_info(dcb, &as->integrated_info);
+
+	if (as->dcb_internal) {
+		/* We are responsible only for destruction of Internal BIOS.
+		 * The External one will be destroyed by its creator. */
+		dal_bios_parser_destroy(&as->dcb_internal);
+	}
+}
+
+/*
+ * adapter_service_construct
+ *
+ * Construct the derived type of adapter service
+ */
+static bool adapter_service_construct(
+	struct adapter_service *as,
+	struct as_init_data *init_data)
+{
+	struct dc_bios *dcb;
+	enum dce_version dce_version;
+
+	if (!init_data)
+		return false;
+
+	/* Create ASIC capability */
+	as->ctx = init_data->ctx;
+	as->asic_cap = dal_asic_capability_create(
+			&init_data->hw_init_data, as->ctx);
+
+	if (!as->asic_cap) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	if (dal_adapter_service_get_dce_version(as) == DCE_VERSION_11_0) {
+		uint32_t i;
+
+		for (i = 0; i < ARRAY_SIZE(feature_entry_table); i++) {
+			enum adapter_feature_id id =
+				feature_entry_table[i].feature_id;
+			if (id == FEATURE_MAXIMIZE_URGENCY_WATERMARKS ||
+				id == FEATURE_MAXIMIZE_STUTTER_MARKS ||
+				id == FEATURE_MAXIMIZE_NBP_MARKS)
+				feature_entry_table[i].default_value = true;
+		}
+	}
+#endif
+
+	/* Generate feature set table */
+	if (!generate_feature_set(as, init_data->display_param)) {
+		ASSERT_CRITICAL(false);
+		goto failed_to_generate_features;
+	}
+
+	as->dce_environment = init_data->dce_environment;
+
+	if (init_data->vbios_override)
+		as->dcb_override = init_data->vbios_override;
+	else {
+		/* Create BIOS parser */
+		init_data->bp_init_data.ctx = init_data->ctx;
+
+		as->dcb_internal = dal_bios_parser_create(
+				&init_data->bp_init_data, as);
+
+		if (!as->dcb_internal) {
+			ASSERT_CRITICAL(false);
+			goto failed_to_create_bios_parser;
+		}
+	}
+
+	dcb = dal_adapter_service_get_bios_parser(as);
+
+	dce_version = dal_adapter_service_get_dce_version(as);
+
+	/* Create GPIO service */
+	as->gpio_service = dal_gpio_service_create(
+			dce_version,
+			as->dce_environment,
+			as->ctx);
+
+	if (!as->gpio_service) {
+		ASSERT_CRITICAL(false);
+		goto failed_to_create_gpio_service;
+	}
+
+	/* Create I2C AUX */
+	as->i2caux = dal_i2caux_create(as, as->ctx);
+
+	if (!as->i2caux) {
+		ASSERT_CRITICAL(false);
+		goto failed_to_create_i2caux;
+	}
+
+	/* Create Adapter Service HW Context*/
+	as->hw_ctx = create_hw_ctx(
+			dce_version,
+			as->dce_environment,
+			as->ctx);
+
+	if (!as->hw_ctx) {
+		ASSERT_CRITICAL(false);
+		goto failed_to_create_hw_ctx;
+	}
+
+	/* Avoid wireless encoder creation in upstream branch. */
+
+	/* Integrated info is not provided on discrete ASIC. NULL is allowed */
+	as->integrated_info = dcb->funcs->create_integrated_info(dcb);
+
+	dcb->funcs->post_init(dcb);
+
+	/* Generate backlight translation table and initializes
+			  other brightness properties */
+	as->backlight_caps_initialized = false;
+
+	get_platform_info_methods(as);
+
+	initialize_backlight_caps(as);
+
+	return true;
+
+failed_to_generate_features:
+	dal_adapter_service_destroy_hw_ctx(&as->hw_ctx);
+
+failed_to_create_hw_ctx:
+	dal_i2caux_destroy(&as->i2caux);
+
+failed_to_create_i2caux:
+	dal_gpio_service_destroy(&as->gpio_service);
+
+failed_to_create_gpio_service:
+	if (as->dcb_internal)
+		dal_bios_parser_destroy(&as->dcb_internal);
+
+failed_to_create_bios_parser:
+	dal_asic_capability_destroy(&as->asic_cap);
+
+	return false;
+}
+
+/*
+ * Global function definition
+ */
+
+/*
+ * dal_adapter_service_create
+ *
+ * Create adapter service
+ */
+struct adapter_service *dal_adapter_service_create(
+	struct as_init_data *init_data)
+{
+	struct adapter_service *as;
+
+	as = dm_alloc(init_data->ctx, sizeof(struct adapter_service));
+
+	if (!as) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (adapter_service_construct(as, init_data))
+		return as;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(init_data->ctx, as);
+
+	return NULL;
+}
+
+/*
+ * dal_adapter_service_destroy
+ *
+ * Destroy adapter service and objects it contains
+ */
+void dal_adapter_service_destroy(
+	struct adapter_service **as)
+{
+	if (!as) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	if (!*as) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	adapter_service_destruct(*as);
+
+	dm_free((*as)->ctx, *as);
+
+	*as = NULL;
+}
+
+/*
+ * dal_adapter_service_get_dce_version
+ *
+ * Get the DCE version of current ASIC
+ */
+enum dce_version dal_adapter_service_get_dce_version(
+	const struct adapter_service *as)
+{
+	uint32_t version = as->asic_cap->data[ASIC_DATA_DCE_VERSION];
+
+	switch (version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case 0x100:
+		return DCE_VERSION_10_0;
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case 0x110:
+		return DCE_VERSION_11_0;
+#endif
+	default:
+		ASSERT_CRITICAL(false);
+		return DCE_VERSION_UNKNOWN;
+	}
+}
+
+enum dce_environment dal_adapter_service_get_dce_environment(
+	const struct adapter_service *as)
+{
+	return as->dce_environment;
+}
+
+
+/*
+ * dal_adapter_service_get_controllers_num
+ *
+ * Get number of controllers
+ */
+uint8_t dal_adapter_service_get_controllers_num(
+	struct adapter_service *as)
+{
+	uint32_t result = as->asic_cap->data[ASIC_DATA_CONTROLLERS_NUM];
+
+	/* Check the "max num of controllers" feature,
+	 * use it for debugging purposes only */
+	/* TODO implement
+	 * dal_adapter_service_get_feature_value(as, ) */
+
+	return result;
+}
+
+/** Get total number of connectors.
+ *
+ * \param as	Adapter Service
+ *
+ * \return Total number of connectors. It is up-to-the caller to decide
+ *	if the number is valid.
+ */
+uint8_t dal_adapter_service_get_connectors_num(
+	struct adapter_service *as)
+{
+	uint8_t vbios_connectors_num = 0;
+	uint8_t wireless_connectors_num = 0;
+	struct dc_bios *dcb;
+
+	dcb = dal_adapter_service_get_bios_parser(as);
+
+	vbios_connectors_num = dcb->funcs->get_connectors_number(dcb);
+
+	wireless_connectors_num = wireless_get_connectors_num(as);
+
+	return vbios_connectors_num + wireless_connectors_num;
+}
+
+static bool is_wireless_object(struct graphics_object_id id)
+{
+	if ((id.type == OBJECT_TYPE_ENCODER &&
+		id.id == ENCODER_ID_INTERNAL_WIRELESS) ||
+		(id.type == OBJECT_TYPE_CONNECTOR && id.id ==
+			CONNECTOR_ID_WIRELESS) ||
+		(id.type == OBJECT_TYPE_CONNECTOR && id.id ==
+			CONNECTOR_ID_MIRACAST))
+		return true;
+	return false;
+}
+
+/**
+ * Get the number of source objects of an object
+ *
+ * \param [in] as: Adapter Service
+ *
+ * \param [in] id: The graphics object id
+ *
+ * \return
+ *     The number of the source objects of an object
+ */
+uint32_t dal_adapter_service_get_src_num(
+	struct adapter_service *as, struct graphics_object_id id)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (is_wireless_object(id))
+		return wireless_get_srcs_num(as, id);
+	else
+		return dcb->funcs->get_src_number(dcb, id);
+}
+
+/**
+ * Get the source objects of an object
+ *
+ * \param [in] id      The graphics object id
+ * \param [in] index   Enumerating index which starts at 0
+ *
+ * \return If enumerating successfully, return the VALID source object id,
+ *	otherwise, returns "zeroed out" object id.
+ *	Client should call dal_graphics_object_id_is_valid() to check
+ *	weather the id is valid.
+ */
+struct graphics_object_id dal_adapter_service_get_src_obj(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	uint32_t index)
+{
+	struct graphics_object_id src_object_id;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (is_wireless_object(id))
+		src_object_id = wireless_get_src_obj_id(as, id, index);
+	else {
+		if (BP_RESULT_OK != dcb->funcs->get_src_obj(dcb, id, index,
+				&src_object_id)) {
+			src_object_id =
+				dal_graphics_object_id_init(
+					0,
+					ENUM_ID_UNKNOWN,
+					OBJECT_TYPE_UNKNOWN);
+		}
+	}
+
+	return src_object_id;
+}
+
+/** Get connector object id associated with a connector index.
+ *
+ * \param as	Adapter Service
+ *
+ * \param connector_index Index of connector between zero and total number
+ *	returned by dal_adapter_service_get_connectors_num()
+ *
+ * \return graphics object id corresponding to the connector_index.
+ */
+struct graphics_object_id dal_adapter_service_get_connector_obj_id(
+		struct adapter_service *as,
+		uint8_t connector_index)
+{
+	struct dc_bios *dcb;
+	uint8_t bios_connectors_num;
+
+	dcb = dal_adapter_service_get_bios_parser(as);
+
+	bios_connectors_num = dcb->funcs->get_connectors_number(dcb);
+
+	if (connector_index >= bios_connectors_num)
+		return wireless_get_connector_id(as, connector_index);
+	else
+		return dcb->funcs->get_connector_id(dcb, connector_index);
+}
+
+bool dal_adapter_service_get_device_tag(
+		struct adapter_service *as,
+		struct graphics_object_id connector_object_id,
+		uint32_t device_tag_index,
+		struct connector_device_tag_info *info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (BP_RESULT_OK == dcb->funcs->get_device_tag(dcb,
+			connector_object_id, device_tag_index, info))
+		return true;
+	else
+		return false;
+}
+
+/* Check if DeviceId is supported by ATOM_OBJECT_HEADER support info */
+bool dal_adapter_service_is_device_id_supported(struct adapter_service *as,
+		struct device_id id)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return dcb->funcs->is_device_id_supported(dcb, id);
+}
+
+bool dal_adapter_service_is_meet_underscan_req(struct adapter_service *as)
+{
+	struct firmware_info fw_info;
+	enum bp_result bp_result = dal_adapter_service_get_firmware_info(
+		as, &fw_info);
+	uint32_t disp_clk_limit =
+		as->asic_cap->data[ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN];
+	if (BP_RESULT_OK == bp_result) {
+		dal_logger_write(as->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ADAPTER_SERVICE,
+			"Read firmware is NULL");
+		return false;
+	}
+	if (fw_info.default_display_engine_pll_frequency < disp_clk_limit)
+		return false;
+	return true;
+}
+
+bool dal_adapter_service_underscan_for_hdmi_only(struct adapter_service *as)
+{
+	return as->asic_cap->caps.UNDERSCAN_FOR_HDMI_ONLY;
+}
+/*
+ * dal_adapter_service_get_clock_sources_num
+ *
+ * Get number of clock sources
+ */
+uint8_t dal_adapter_service_get_clock_sources_num(
+	struct adapter_service *as)
+{
+	struct firmware_info fw_info;
+	uint32_t max_clk_src = 0;
+	uint32_t num = as->asic_cap->data[ASIC_DATA_CLOCKSOURCES_NUM];
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	/*
+	 * Check is system supports the use of the External clock source
+	 * as a clock source for DP
+	 */
+	enum bp_result bp_result = dcb->funcs->get_firmware_info(dcb, &fw_info);
+
+	if (BP_RESULT_OK == bp_result &&
+			fw_info.external_clock_source_frequency_for_dp != 0)
+		++num;
+
+	/*
+	 * Add clock source for wireless if supported
+	 */
+	num += (uint32_t)wireless_get_clocks_num(as);
+
+	/* Check the "max number of clock sources" feature */
+	if (dal_adapter_service_get_feature_value(
+			FEATURE_MAX_CLOCK_SOURCE_NUM,
+			&max_clk_src,
+			sizeof(uint32_t)))
+		if ((max_clk_src != 0) && (max_clk_src < num))
+			num = max_clk_src;
+
+	return num;
+}
+
+/*
+ * dal_adapter_service_get_func_controllers_num
+ *
+ * Get number of controllers
+ */
+uint8_t dal_adapter_service_get_func_controllers_num(
+	struct adapter_service *as)
+{
+	uint32_t result =
+		as->asic_cap->data[ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM];
+
+	/* Check the "max num of controllers" feature,
+	 * use it for debugging purposes only */
+
+	/* Limit number of controllers by OS */
+
+	struct asic_feature_flags flags;
+
+	flags.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS];
+
+	if (flags.bits.LEGACY_CLIENT &&
+		(result > LEGACY_MAX_NUM_OF_CONTROLLERS))
+		result = LEGACY_MAX_NUM_OF_CONTROLLERS;
+
+	return result;
+}
+
+/*
+ * dal_adapter_service_is_feature_supported
+ *
+ * Return if a given feature is supported by the ASIC. The feature has to be
+ * a boolean type.
+ */
+bool dal_adapter_service_is_feature_supported(
+	enum adapter_feature_id feature_id)
+{
+	bool data = 0;
+
+	dal_adapter_service_get_feature_value(feature_id, &data, sizeof(bool));
+
+	return data;
+}
+
+/**
+ * Reports maximum number of confunctional non-DP displays.
+ * Value can be overriden if FEATURE_REPORT_SINGLE_SELECTED_TIMING feature is
+ * enabled.
+ *
+ * \return
+ *     Maximum number of confunctional non-DP displays
+ */
+uint32_t dal_adapter_service_get_max_cofunc_non_dp_displays(void)
+{
+	uint32_t non_dp_displays = DEFAULT_NUM_COFUNC_NON_DP_DISPLAYS;
+
+	if (true == dal_adapter_service_get_feature_value(
+			FEATURE_MAX_COFUNC_NON_DP_DISPLAYS,
+			&non_dp_displays,
+			sizeof(non_dp_displays))) {
+		/* the cached value exist */
+		/* TODO: add more logic as per-DAL2 */
+	}
+
+	return non_dp_displays;
+}
+
+uint32_t dal_adapter_service_get_single_selected_timing_signals(void)
+{
+	uint32_t signals_bitmap = 0;
+
+	if (dal_adapter_service_is_feature_supported(
+			FEATURE_REPORT_SINGLE_SELECTED_TIMING)) {
+		/* the cached value exist */
+		/* TODO: add more logic as per-DAL2 */
+		signals_bitmap = 0;
+	}
+
+	return signals_bitmap;
+}
+
+/*
+ * dal_adapter_service_get_i2c_info
+ *
+ * Get I2C information from BIOS
+ */
+bool dal_adapter_service_get_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	struct graphics_object_i2c_info *i2c_info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (!i2c_info) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	return BP_RESULT_OK == dcb->funcs->get_i2c_info(dcb, id, i2c_info);
+}
+
+/*
+ * dal_adapter_service_obtain_ddc
+ *
+ * Obtain DDC
+ */
+struct ddc *dal_adapter_service_obtain_ddc(
+	struct adapter_service *as,
+	struct graphics_object_id id)
+{
+	struct graphics_object_i2c_info i2c_info;
+	struct gpio_ddc_hw_info hw_info;
+
+
+	if (!dal_adapter_service_get_i2c_info(as, id, &i2c_info))
+		return NULL;
+
+	hw_info.ddc_channel = i2c_info.i2c_line;
+	hw_info.hw_supported = i2c_info.i2c_hw_assist;
+
+	return dal_gpio_service_create_ddc(
+		as->gpio_service,
+		i2c_info.gpio_info.clk_a_register_index,
+		1 << i2c_info.gpio_info.clk_a_shift,
+		&hw_info);
+}
+
+/*
+ * dal_adapter_service_release_ddc
+ *
+ * Release DDC
+ */
+void dal_adapter_service_release_ddc(
+	struct adapter_service *as,
+	struct ddc *ddc)
+{
+	dal_gpio_service_destroy_ddc(&ddc);
+}
+
+/*
+ * dal_adapter_service_obtain_hpd_irq
+ *
+ * Obtain HPD interrupt request
+ */
+struct irq *dal_adapter_service_obtain_hpd_irq(
+	struct adapter_service *as,
+	struct graphics_object_id id)
+{
+	enum bp_result bp_result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+	struct graphics_object_hpd_info hpd_info;
+	struct gpio_pin_info pin_info;
+
+	if (!get_hpd_info(as, id, &hpd_info))
+		return NULL;
+
+	bp_result = dcb->funcs->get_gpio_pin_info(dcb,
+		hpd_info.hpd_int_gpio_uid, &pin_info);
+
+	if (bp_result != BP_RESULT_OK) {
+		ASSERT(bp_result == BP_RESULT_NORECORD);
+		return NULL;
+	}
+
+	return dal_gpio_service_create_irq(
+		as->gpio_service,
+		pin_info.offset,
+		pin_info.mask);
+}
+
+/*
+ * dal_adapter_service_release_irq
+ *
+ * Release interrupt request
+ */
+void dal_adapter_service_release_irq(
+	struct adapter_service *as,
+	struct irq *irq)
+{
+	dal_gpio_service_destroy_irq(&irq);
+}
+
+/*
+ * dal_adapter_service_get_ss_info_num
+ *
+ * Get number of spread spectrum entries from BIOS
+ */
+uint32_t dal_adapter_service_get_ss_info_num(
+	struct adapter_service *as,
+	enum as_signal_type signal)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return dcb->funcs->get_ss_entry_number(dcb, signal);
+}
+
+/*
+ * dal_adapter_service_get_ss_info
+ *
+ * Get spread spectrum info from BIOS
+ */
+bool dal_adapter_service_get_ss_info(
+	struct adapter_service *as,
+	enum as_signal_type signal,
+	uint32_t idx,
+	struct spread_spectrum_info *info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	enum bp_result bp_result = dcb->funcs->get_spread_spectrum_info(dcb,
+			signal, idx, info);
+
+	return BP_RESULT_OK == bp_result;
+}
+
+/*
+ * dal_adapter_service_get_integrated_info
+ *
+ * Get integrated information on BIOS
+ */
+bool dal_adapter_service_get_integrated_info(
+	struct adapter_service *as,
+	struct integrated_info *info)
+{
+	if (info == NULL || as->integrated_info == NULL)
+		return false;
+
+	dm_memmove(info, as->integrated_info, sizeof(struct integrated_info));
+
+	return true;
+}
+
+/*
+ * dal_adapter_service_is_dfs_bypass_enabled
+ *
+ * Check if DFS bypass is enabled
+ */
+bool dal_adapter_service_is_dfs_bypass_enabled(
+	struct adapter_service *as)
+{
+	if (as->integrated_info == NULL)
+		return false;
+	if ((as->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) &&
+		dal_adapter_service_is_feature_supported(
+			FEATURE_ENABLE_DFS_BYPASS))
+		return true;
+	else
+		return false;
+}
+
+/*
+ * dal_adapter_service_get_sw_i2c_speed
+ *
+ * Get SW I2C speed
+ */
+uint32_t dal_adapter_service_get_sw_i2c_speed(
+	struct adapter_service *as)
+{
+	/* TODO: only from ASIC caps. Feature key is not implemented*/
+	return as->asic_cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ];
+}
+
+/*
+ * dal_adapter_service_get_hw_i2c_speed
+ *
+ * Get HW I2C speed
+ */
+uint32_t dal_adapter_service_get_hw_i2c_speed(
+	struct adapter_service *as)
+{
+	/* TODO: only from ASIC caps. Feature key is not implemented*/
+	return as->asic_cap->data[ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ];
+}
+
+/*
+ * dal_adapter_service_get_mc_latency
+ *
+ * Get memory controller latency
+ */
+uint32_t dal_adapter_service_get_mc_latency(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_MC_LATENCY];
+}
+
+/*
+ * dal_adapter_service_get_asic_vram_bit_width
+ *
+ * Get the video RAM bit width set on the ASIC
+ */
+uint32_t dal_adapter_service_get_asic_vram_bit_width(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_VRAM_BITWIDTH];
+}
+
+/*
+ * dal_adapter_service_get_asic_bugs
+ *
+ * Get the bug flags set on this ASIC
+ */
+struct asic_bugs dal_adapter_service_get_asic_bugs(
+	struct adapter_service *as)
+{
+	return as->asic_cap->bugs;
+}
+
+
+struct dal_asic_runtime_flags dal_adapter_service_get_asic_runtime_flags(
+		struct adapter_service *as)
+{
+	return as->asic_cap->runtime_flags;
+}
+
+/*
+ * dal_adapter_service_get_line_buffer_size
+ *
+ * Get line buffer size
+ */
+uint32_t dal_adapter_service_get_line_buffer_size(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_LINEBUFFER_SIZE];
+}
+
+/*
+ * dal_adapter_service_get_bandwidth_tuning_params
+ *
+ * Get parameters for bandwidth tuning
+ */
+bool dal_adapter_service_get_bandwidth_tuning_params(
+	struct adapter_service *as,
+	union bandwidth_tuning_params *params)
+{
+	/* TODO: add implementation */
+	/* note: data comes from runtime parameters */
+	return false;
+}
+
+/*
+ * dal_adapter_service_get_feature_flags
+ *
+ * Get a copy of ASIC feature flags
+ */
+struct asic_feature_flags dal_adapter_service_get_feature_flags(
+	struct adapter_service *as)
+{
+	struct asic_feature_flags result = { { 0 } };
+
+	if (!as) {
+		ASSERT_CRITICAL(false);
+		return result;
+	}
+
+	result.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS];
+
+	return result;
+}
+
+/*
+ * dal_adapter_service_get_dram_bandwidth_efficiency
+ *
+ * Get efficiency of DRAM
+ */
+uint32_t dal_adapter_service_get_dram_bandwidth_efficiency(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY];
+}
+
+/*
+ * dal_adapter_service_obtain_gpio
+ *
+ * Obtain GPIO
+ */
+struct gpio *dal_adapter_service_obtain_gpio(
+	struct adapter_service *as,
+	enum gpio_id id,
+	uint32_t en)
+{
+	return dal_gpio_service_create_gpio_ex(
+		as->gpio_service, id, en,
+		GPIO_PIN_OUTPUT_STATE_DEFAULT);
+}
+
+/*
+ * dal_adapter_service_obtain_stereo_gpio
+ *
+ * Obtain GPIO for stereo3D
+ */
+struct gpio *dal_adapter_service_obtain_stereo_gpio(
+	struct adapter_service *as)
+{
+	const bool have_param_stereo_gpio = false;
+
+	struct asic_feature_flags result;
+
+	result.raw = as->asic_cap->data[ASIC_DATA_FEATURE_FLAGS];
+
+	/* Case 1 : Workstation stereo */
+	if (result.bits.WORKSTATION_STEREO) {
+		/* "active low" <--> "default 3d right eye polarity" = false */
+		return dal_gpio_service_create_gpio_ex(as->gpio_service,
+				GPIO_ID_GENERIC, GPIO_GENERIC_A,
+				GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW);
+	/* Case 2 : runtime parameter override for sideband stereo */
+	} else if (have_param_stereo_gpio) {
+		/* TODO implement */
+		return NULL;
+		/* Case 3 : VBIOS gives us GPIO for sideband stereo */
+	} else {
+		const struct graphics_object_id id =
+				dal_graphics_object_id_init(GENERIC_ID_STEREO,
+						ENUM_ID_1, OBJECT_TYPE_GENERIC);
+
+		struct bp_gpio_cntl_info cntl_info;
+		struct gpio_pin_info pin_info;
+		struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+		/* Get GPIO record for this object.
+		 * Stereo GPIO record should have exactly one entry
+		 * where active state defines stereosync polarity */
+		if (1 != dcb->funcs->get_gpio_record(
+						dcb, id, &cntl_info,
+						1)) {
+			return NULL;
+		} else if (BP_RESULT_OK
+				!= dcb->funcs->get_gpio_pin_info(
+						dcb, cntl_info.id,
+						&pin_info)) {
+			/*ASSERT_CRITICAL(false);*/
+			return NULL;
+		} else {
+			return dal_gpio_service_create_gpio_ex(as->gpio_service,
+					pin_info.offset, pin_info.mask,
+					cntl_info.state);
+		}
+	}
+}
+
+/*
+ * dal_adapter_service_release_gpio
+ *
+ * Release GPIO
+ */
+void dal_adapter_service_release_gpio(
+	struct adapter_service *as,
+	struct gpio *gpio)
+{
+	dal_gpio_service_destroy_gpio(&gpio);
+}
+
+/*
+ * dal_adapter_service_get_firmware_info
+ *
+ * Get firmware information from BIOS
+ */
+bool dal_adapter_service_get_firmware_info(
+	struct adapter_service *as,
+	struct firmware_info *info)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return dcb->funcs->get_firmware_info(dcb, info) == BP_RESULT_OK;
+}
+
+/*
+ * dal_adapter_service_get_audio_support
+ *
+ * Get information on audio support
+ */
+union audio_support dal_adapter_service_get_audio_support(
+	struct adapter_service *as)
+{
+	return dal_adapter_service_hw_ctx_get_audio_support(as->hw_ctx);
+}
+
+/*
+ * dal_adapter_service_get_stream_engines_num
+ *
+ * Get number of stream engines
+ */
+uint8_t dal_adapter_service_get_stream_engines_num(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_DIGFE_NUM];
+}
+
+/*
+ * dal_adapter_service_get_feature_value
+ *
+ * Get the cached value of a given feature. This value can be a boolean, int,
+ * or characters.
+ */
+bool dal_adapter_service_get_feature_value(
+	const enum adapter_feature_id feature_id,
+	void *data,
+	uint32_t size)
+{
+	uint32_t entry_idx = 0;
+	uint32_t set_idx = 0;
+	uint32_t set_internal_idx = 0;
+
+	if (feature_id >= FEATURE_MAXIMUM || feature_id <= FEATURE_UNKNOWN) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (data == NULL) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	entry_idx = lookup_feature_entry(feature_id);
+	set_idx = (uint32_t)((feature_id - 1)/32);
+	set_internal_idx = (uint32_t)((feature_id - 1) % 32);
+
+	if (entry_idx >= get_feature_entries_num()) {
+		/* Cannot find this entry */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (feature_entry_table[entry_idx].is_boolean_type) {
+		if (size != sizeof(bool)) {
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+
+		*(bool *)data = get_bool_value(adapter_feature_set[set_idx],
+				set_internal_idx);
+	} else {
+		if (size != sizeof(uint32_t)) {
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+
+		*(uint32_t *)data = adapter_feature_set[set_idx];
+	}
+
+	return true;
+}
+
+/*
+ * dal_adapter_service_get_memory_type_multiplier
+ *
+ * Get multiplier for the memory type
+ */
+uint32_t dal_adapter_service_get_memory_type_multiplier(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_MEMORYTYPE_MULTIPLIER];
+}
+
+/*
+ * dal_adapter_service_get_bios_parser
+ *
+ * Get BIOS parser handler
+ */
+struct dc_bios *dal_adapter_service_get_bios_parser(
+	struct adapter_service *as)
+{
+	return as->dcb_override ? as->dcb_override : as->dcb_internal;
+}
+
+/*
+ * dal_adapter_service_get_i2caux
+ *
+ * Get i2c aux handler
+ */
+struct i2caux *dal_adapter_service_get_i2caux(
+	struct adapter_service *as)
+{
+	return as->i2caux;
+}
+
+bool dal_adapter_service_initialize_hw_data(
+	struct adapter_service *as)
+{
+	return as->hw_ctx->funcs->power_up(as->hw_ctx);
+}
+
+struct graphics_object_id dal_adapter_service_enum_fake_path_resource(
+	struct adapter_service *as,
+	uint32_t index)
+{
+	return as->hw_ctx->funcs->enum_fake_path_resource(as->hw_ctx, index);
+}
+
+struct graphics_object_id dal_adapter_service_enum_stereo_sync_object(
+	struct adapter_service *as,
+	uint32_t index)
+{
+	return as->hw_ctx->funcs->enum_stereo_sync_object(as->hw_ctx, index);
+}
+
+struct graphics_object_id dal_adapter_service_enum_sync_output_object(
+	struct adapter_service *as,
+	uint32_t index)
+{
+	return as->hw_ctx->funcs->enum_sync_output_object(as->hw_ctx, index);
+}
+
+struct graphics_object_id dal_adapter_service_enum_audio_object(
+	struct adapter_service *as,
+	uint32_t index)
+{
+	return as->hw_ctx->funcs->enum_audio_object(as->hw_ctx, index);
+}
+
+
+void dal_adapter_service_update_audio_connectivity(
+	struct adapter_service *as,
+	uint32_t number_of_audio_capable_display_path)
+{
+	as->hw_ctx->funcs->update_audio_connectivity(
+		as->hw_ctx,
+		number_of_audio_capable_display_path,
+		dal_adapter_service_get_controllers_num(as));
+}
+
+bool dal_adapter_service_has_embedded_display_connector(
+	struct adapter_service *as)
+{
+	uint8_t index;
+	uint8_t num_connectors = dal_adapter_service_get_connectors_num(as);
+
+	if (num_connectors == 0 || num_connectors > ENUM_ID_COUNT)
+		return false;
+
+	for (index = 0; index < num_connectors; index++) {
+		struct graphics_object_id obj_id =
+			dal_adapter_service_get_connector_obj_id(as, index);
+		enum connector_id connector_id =
+			dal_graphics_object_id_get_connector_id(obj_id);
+
+		if ((connector_id == CONNECTOR_ID_LVDS) ||
+				(connector_id == CONNECTOR_ID_EDP))
+			return true;
+	}
+
+	return false;
+}
+
+bool dal_adapter_service_get_embedded_panel_info(
+	struct adapter_service *as,
+	struct embedded_panel_info *info)
+{
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (info == NULL)
+		/*TODO: add DALASSERT_MSG here*/
+		return false;
+
+	result = dcb->funcs->get_embedded_panel_info(dcb, info);
+
+	return result == BP_RESULT_OK;
+}
+
+bool dal_adapter_service_enum_embedded_panel_patch_mode(
+	struct adapter_service *as,
+	uint32_t index,
+	struct embedded_panel_patch_mode *mode)
+{
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (mode == NULL)
+		/*TODO: add DALASSERT_MSG here*/
+		return false;
+
+	result = dcb->funcs->enum_embedded_panel_patch_mode(dcb, index, mode);
+
+	return result == BP_RESULT_OK;
+}
+
+bool dal_adapter_service_get_faked_edid_len(
+	struct adapter_service *as,
+	uint32_t *len)
+{
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	result = dcb->funcs->get_faked_edid_len(dcb, len);
+
+	return result == BP_RESULT_OK;
+}
+
+bool dal_adapter_service_get_faked_edid_buf(
+	struct adapter_service *as,
+	uint8_t *buf,
+	uint32_t len)
+{
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	result = dcb->funcs->get_faked_edid_buf(dcb, buf, len);
+
+	return result == BP_RESULT_OK;
+
+}
+
+/*
+ * dal_adapter_service_is_fusion
+ *
+ * Is this Fusion ASIC
+ */
+bool dal_adapter_service_is_fusion(struct adapter_service *as)
+{
+	return as->asic_cap->caps.IS_FUSION;
+}
+
+/*
+ * dal_adapter_service_is_dfsbyass_dynamic
+ *
+ *
+ **/
+bool dal_adapter_service_is_dfsbyass_dynamic(struct adapter_service *as)
+{
+	return as->asic_cap->caps.DFSBYPASS_DYNAMIC_SUPPORT;
+}
+
+/*
+ * dal_adapter_service_should_optimize
+ *
+ * @brief Reports whether driver settings allow requested optimization
+ *
+ * @param
+ * as: adapter service handler
+ * feature: for which optimization is validated
+ *
+ * @return
+ * true if requested feature can be optimized
+ */
+bool dal_adapter_service_should_optimize(
+		struct adapter_service *as, enum optimization_feature feature)
+{
+	uint32_t supported_optimization = 0;
+	struct dal_asic_runtime_flags flags;
+
+	if (!dal_adapter_service_get_feature_value(FEATURE_OPTIMIZATION,
+			&supported_optimization, sizeof(uint32_t)))
+		return false;
+
+	/* Retrieve ASIC runtime flags */
+	flags = dal_adapter_service_get_asic_runtime_flags(as);
+
+	/* Check runtime flags against different optimization features */
+	switch (feature) {
+	case OF_SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY:
+		if (!flags.flags.bits.OPTIMIZED_DISPLAY_PROGRAMMING_ON_BOOT)
+			return false;
+		break;
+
+	case OF_SKIP_RESET_OF_ALL_HW_ON_S3RESUME:
+		if (as->integrated_info == NULL ||
+				!flags.flags.bits.SKIP_POWER_DOWN_ON_RESUME)
+			return false;
+		break;
+	case OF_SKIP_POWER_DOWN_INACTIVE_ENCODER:
+		if (!dal_adapter_service_get_asic_runtime_flags(as).flags.bits.
+			SKIP_POWER_DOWN_ON_RESUME)
+			return false;
+		break;
+	default:
+		break;
+	}
+
+	return (supported_optimization & feature) != 0;
+}
+
+/*
+ * dal_adapter_service_is_in_accelerated_mode
+ *
+ * @brief Determine if driver is in accelerated mode
+ *
+ * @param
+ * as: Adapter Service handler
+ *
+ * @out
+ * True if driver is in accelerated mode, false otherwise.
+ */
+bool dal_adapter_service_is_in_accelerated_mode(struct adapter_service *as)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	return dcb->funcs->is_accelerated_mode(dcb);
+}
+
+struct ddc *dal_adapter_service_obtain_ddc_from_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_i2c_info *info)
+{
+	struct gpio_ddc_hw_info hw_info = {
+		info->i2c_hw_assist,
+		info->i2c_line };
+	return dal_gpio_service_create_ddc(as->gpio_service,
+		info->gpio_info.clk_a_register_index,
+		(1 << info->gpio_info.clk_a_shift), &hw_info);
+}
+
+struct bdf_info dal_adapter_service_get_adapter_info(struct adapter_service *as)
+{
+	return as->bdf_info;
+}
+
+/*
+ * dal_adapter_service_should_psr_skip_wait_for_pll_lock
+ *
+ * @brief Determine if this ASIC needs to wait on PLL lock bit
+ *
+ * @param
+ * as: Adapter Service handle
+ *
+ * @out
+ * True if ASIC does not need to wait for PLL lock bit, i.e. skip the wait.
+ */
+bool dal_adapter_service_should_psr_skip_wait_for_pll_lock(
+	struct adapter_service *as)
+{
+	return as->asic_cap->caps.SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT;
+}
+
+bool dal_adapter_service_is_lid_open(struct adapter_service *as)
+{
+	bool is_lid_open = false;
+	struct platform_info_params params;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	params.data = &is_lid_open;
+	params.method = PM_GET_LID_STATE;
+
+	if ((PM_GET_LID_STATE & as->platform_methods_mask) &&
+		dm_get_platform_info(as->ctx, &params))
+		return is_lid_open;
+
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	return dcb->funcs->is_lid_open(dcb);
+#else
+	return false;
+#endif
+}
+
+bool dal_adapter_service_get_panel_backlight_default_levels(
+	struct adapter_service *as,
+	struct panel_backlight_levels *levels)
+{
+	if (!as->backlight_caps_initialized)
+		return false;
+
+	levels->ac_level_percentage = as->ac_level_percentage;
+	levels->dc_level_percentage = as->dc_level_percentage;
+	return true;
+}
+
+bool dal_adapter_service_get_panel_backlight_boundaries(
+	struct adapter_service *as,
+	struct panel_backlight_boundaries *boundaries)
+{
+	if (!as->backlight_caps_initialized)
+		return false;
+	if (boundaries != NULL) {
+		boundaries->min_signal_level = as->backlight_8bit_lut[0];
+		boundaries->max_signal_level =
+			as->backlight_8bit_lut[SIZEOF_BACKLIGHT_LUT - 1];
+		return true;
+	}
+	return false;
+}
+
+
+uint32_t dal_adapter_service_get_view_port_pixel_granularity(
+	struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY];
+}
+
+/**
+ * Get number of paths per DP 1.2 connector from the runtime parameter if it
+ * exists.
+ * A check to see if MST is supported for the generation of ASIC is done
+ *
+ * \return
+ *    Number of paths per DP 1.2 connector is exists in runtime parameters
+ *    or ASIC cap
+ */
+uint32_t dal_adapter_service_get_num_of_path_per_dp_mst_connector(
+		struct adapter_service *as)
+{
+	if (as->asic_cap->caps.DP_MST_SUPPORTED == 0) {
+		/* ASIC doesn't support DP MST at all */
+		return 0;
+	}
+
+	return as->asic_cap->data[ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR];
+}
+
+uint32_t dal_adapter_service_get_num_of_underlays(
+		struct adapter_service *as)
+{
+	return as->asic_cap->data[ASIC_DATA_NUM_OF_VIDEO_PLANES];
+}
+
+bool dal_adapter_service_get_encoder_cap_info(
+		struct adapter_service *as,
+		struct graphics_object_id id,
+		struct graphics_object_encoder_cap_info *info)
+{
+	struct bp_encoder_cap_info bp_cap_info = {0};
+	enum bp_result result;
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	if (NULL == info) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	/*
+	 * Retrieve Encoder Capability Information from VBIOS and store the
+	 * call result (success or fail)
+	 * Info from VBIOS about HBR2 has two fields:
+	 *
+	 * - dpHbr2Cap: indicates supported/not supported by HW Encoder
+	 * - dpHbr2En : indicates DP spec compliant/not compliant
+	 */
+	result = dcb->funcs->get_encoder_cap_info(dcb, id, &bp_cap_info);
+
+	/* Set dp_hbr2_validated flag (it's equal to Enable) */
+	info->dp_hbr2_validated = bp_cap_info.DP_HBR2_EN;
+
+	if (result == BP_RESULT_OK) {
+		info->dp_hbr2_cap = bp_cap_info.DP_HBR2_CAP;
+		return true;
+	}
+
+	return false;
+}
+
+bool dal_adapter_service_is_mc_tuning_req(struct adapter_service *as)
+{
+	return as->asic_cap->caps.NEED_MC_TUNING ? true : false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
new file mode 100644
index 000000000000..60464e89cc5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ADAPTER_SERVICE_H__
+#define __DAL_ADAPTER_SERVICE_H__
+
+/* Include */
+#include "dc_bios_types.h"
+#include "include/adapter_service_interface.h"
+#include "wireless_data_source.h"
+
+/*
+ * Forward declaration
+ */
+struct gpio_service;
+struct asic_cap;
+
+
+/* Adapter service */
+struct adapter_service {
+	struct dc_context *ctx;
+	struct asic_capability *asic_cap;
+	struct dc_bios *dcb_internal;/* created by DC */
+	struct dc_bios *dcb_override;/* supplied by creator of DC */
+	enum dce_environment dce_environment;
+	struct gpio_service *gpio_service;
+	struct i2caux *i2caux;
+	struct wireless_data wireless_data;
+	struct hw_ctx_adapter_service *hw_ctx;
+	struct integrated_info *integrated_info;
+	struct bdf_info bdf_info;
+	uint32_t platform_methods_mask;
+	uint32_t ac_level_percentage;
+	uint32_t dc_level_percentage;
+	uint32_t backlight_caps_initialized;
+	uint32_t backlight_8bit_lut[SIZEOF_BACKLIGHT_LUT];
+};
+
+/* Type of feature with its runtime parameter and default value */
+struct feature_source_entry {
+	enum adapter_feature_id feature_id;
+	uint32_t default_value;
+	bool is_boolean_type;
+};
+
+/* Stores entire ASIC features by sets */
+extern uint32_t adapter_feature_set[];
+
+#endif /* __DAL_ADAPTER_SERVICE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
new file mode 100644
index 000000000000..f10bee6f2b83
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "../hw_ctx_adapter_service.h"
+
+#include "hw_ctx_adapter_service_dce110.h"
+
+#include "include/logger_interface.h"
+#include "include/grph_object_id.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#ifndef mmCC_DC_HDMI_STRAPS
+#define mmCC_DC_HDMI_STRAPS 0x4819
+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40
+#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6
+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700
+#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8
+#endif
+
+static const struct graphics_object_id invalid_go = {
+	0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN, 0
+};
+
+/* Macro */
+#define AUDIO_STRAPS_HDMI_ENABLE 0x2
+
+#define FROM_HW_CTX(ptr) \
+	container_of((ptr), struct hw_ctx_adapter_service_dce110, base)
+
+static const uint32_t audio_index_reg_offset[] = {
+	/*CZ has 3 DIGs but 4 audio endpoints*/
+	mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX,
+	mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX,
+	mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX,
+	mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX
+};
+
+static const uint32_t audio_data_reg_offset[] = {
+	mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA,
+	mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA,
+	mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA,
+	mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA,
+};
+
+enum {
+	MAX_NUMBER_OF_AUDIO_PINS = 4
+};
+
+static void destruct(
+	struct hw_ctx_adapter_service_dce110 *hw_ctx)
+{
+	/* There is nothing to destruct at the moment */
+	dal_adapter_service_destruct_hw_ctx(&hw_ctx->base);
+}
+
+static void destroy(
+	struct hw_ctx_adapter_service *ptr)
+{
+	struct hw_ctx_adapter_service_dce110 *hw_ctx =
+		FROM_HW_CTX(ptr);
+
+	destruct(hw_ctx);
+
+	dm_free(ptr->ctx, hw_ctx);
+}
+
+/*
+ * enum_audio_object
+ *
+ * @brief enumerate audio object
+ *
+ * @param
+ * const struct hw_ctx_adapter_service *hw_ctx - [in] provides num of endpoints
+ * uint32_t index - [in] audio index
+ *
+ * @return
+ * grphic object id
+ */
+static struct graphics_object_id enum_audio_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	uint32_t number_of_connected_audio_endpoints =
+		FROM_HW_CTX(hw_ctx)->number_of_connected_audio_endpoints;
+
+	if (index >= number_of_connected_audio_endpoints ||
+			number_of_connected_audio_endpoints == 0)
+		return invalid_go;
+	else
+		return dal_graphics_object_id_init(
+			AUDIO_ID_INTERNAL_AZALIA,
+			(enum object_enum_id)(index + 1),
+			OBJECT_TYPE_AUDIO);
+}
+
+static uint32_t get_number_of_connected_audio_endpoints_multistream(
+		struct dc_context *ctx)
+{
+	uint32_t num_connected_audio_endpoints = 0;
+	uint32_t i;
+	uint32_t default_config =
+	ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT;
+
+	/* find the total number of streams available via the
+	 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT
+	 * registers (one for each pin) starting from pin 1
+	 * up to the max number of audio pins.
+	 * We stop on the first pin where
+	 * PORT_CONNECTIVITY == 1 (as instructed by HW team).
+	 */
+	for (i = 0; i < MAX_NUMBER_OF_AUDIO_PINS; i++) {
+		uint32_t value = 0;
+
+		set_reg_field_value(value,
+			default_config,
+			AZALIA_F0_CODEC_ENDPOINT_INDEX,
+			AZALIA_ENDPOINT_REG_INDEX);
+
+		dm_write_reg(ctx, audio_index_reg_offset[i], value);
+
+		value = 0;
+		value = dm_read_reg(ctx, audio_data_reg_offset[i]);
+
+		/* 1 means not supported*/
+		if (get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT,
+		PORT_CONNECTIVITY) == 1)
+			break;
+
+		num_connected_audio_endpoints++;
+	}
+
+	return num_connected_audio_endpoints;
+
+}
+
+/*
+ * get_number_of_connected_audio_endpoints
+ */
+static uint32_t get_number_of_connected_audio_endpoints(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	uint32_t addr = mmCC_DC_HDMI_STRAPS;
+	uint32_t value = 0;
+	uint32_t field = 0;
+
+	if (hw_ctx->cached_audio_straps == AUDIO_STRAPS_NOT_ALLOWED)
+		/* audio straps indicate no audio supported */
+		return 0;
+
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	field = get_reg_field_value(
+			value, CC_DC_HDMI_STRAPS, AUDIO_STREAM_NUMBER);
+	if (field == 1)
+		/* multi streams not supported */
+		return 1;
+	else if (field == 0)
+		/* multi streams supported */
+		return get_number_of_connected_audio_endpoints_multistream(
+				hw_ctx->ctx);
+
+	/* unexpected value */
+	ASSERT_CRITICAL(false);
+	return field;
+}
+
+
+/*
+ * power_up
+ *
+ * @brief
+ * Determine and cache audio support from register.
+ *
+ * @param
+ * struct hw_ctx_adapter_service *hw_ctx - [in] adapter service hw context
+ *
+ * @return
+ * true if succeed, false otherwise
+ */
+static bool power_up(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	struct hw_ctx_adapter_service_dce110 *hw_ctx_dce11 =
+			FROM_HW_CTX(hw_ctx);
+	/* Allow DP audio all the time
+	 * without additional pinstrap check on Fusion */
+
+
+	{
+		uint32_t value = 0;
+		uint32_t field = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, mmCC_DC_HDMI_STRAPS);
+		field = get_reg_field_value(
+				value, CC_DC_HDMI_STRAPS, HDMI_DISABLE);
+
+		if (field == 0) {
+			hw_ctx->cached_audio_straps = AUDIO_STRAPS_DP_HDMI_AUDIO;
+		} else {
+			value = dm_read_reg(
+					hw_ctx->ctx, mmDC_PINSTRAPS);
+			field = get_reg_field_value(
+						value,
+						DC_PINSTRAPS,
+						DC_PINSTRAPS_AUDIO);
+
+			if (field & AUDIO_STRAPS_HDMI_ENABLE)
+				hw_ctx->cached_audio_straps =
+					AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE;
+			else
+				hw_ctx->cached_audio_straps =
+						AUDIO_STRAPS_DP_AUDIO_ALLOWED;
+		}
+
+	}
+
+	/* get the number of connected audio endpoints */
+	hw_ctx_dce11->number_of_connected_audio_endpoints =
+		get_number_of_connected_audio_endpoints(hw_ctx);
+
+	return true;
+}
+
+static void update_audio_connectivity(
+	struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t number_of_audio_capable_display_path,
+	uint32_t number_of_controllers)
+{
+	/* this one should be empty on DCE110 */
+}
+
+static const struct hw_ctx_adapter_service_funcs funcs = {
+	.destroy = destroy,
+	.power_up = power_up,
+	.enum_fake_path_resource = NULL,
+	.enum_stereo_sync_object = NULL,
+	.enum_sync_output_object = NULL,
+	.enum_audio_object = enum_audio_object,
+	.update_audio_connectivity = update_audio_connectivity
+};
+
+static bool construct(
+	struct hw_ctx_adapter_service_dce110 *hw_ctx,
+	struct dc_context *ctx)
+{
+	if (!dal_adapter_service_construct_hw_ctx(&hw_ctx->base, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	hw_ctx->base.funcs = &funcs;
+	hw_ctx->number_of_connected_audio_endpoints = 0;
+
+	return true;
+}
+
+struct hw_ctx_adapter_service *
+	dal_adapter_service_create_hw_ctx_dce110(
+			struct dc_context *ctx)
+{
+	struct hw_ctx_adapter_service_dce110 *hw_ctx =
+			dm_alloc(ctx, sizeof(struct hw_ctx_adapter_service_dce110));
+
+	if (!hw_ctx) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(hw_ctx, ctx))
+		return &hw_ctx->base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, hw_ctx);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
new file mode 100644
index 000000000000..092b67173dc4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__
+#define __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__
+
+struct hw_ctx_adapter_service_dce110 {
+	struct hw_ctx_adapter_service base;
+	uint32_t number_of_connected_audio_endpoints;
+};
+
+struct hw_ctx_adapter_service *
+	dal_adapter_service_create_hw_ctx_dce110(
+			struct dc_context *ctx);
+
+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_DCE110_H__ */
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
new file mode 100644
index 000000000000..4f5f0403af84
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/* FPGA Diagnostics version of AS HW CTX. */
+
+#include "dm_services.h"
+
+#include "../hw_ctx_adapter_service.h"
+
+#include "hw_ctx_adapter_service_diag.h"
+
+#include "include/logger_interface.h"
+#include "include/grph_object_id.h"
+
+static const struct graphics_object_id invalid_go = {
+	0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN
+};
+
+static void destroy(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+}
+
+static bool power_up(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	return true;
+}
+
+static struct graphics_object_id enum_fake_path_resource(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_stereo_sync_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_sync_output_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_audio_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static void update_audio_connectivity(
+	struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t number_of_audio_capable_display_path,
+	uint32_t number_of_controllers)
+{
+}
+
+static const struct hw_ctx_adapter_service_funcs funcs = {
+	destroy,
+	power_up,
+	enum_fake_path_resource,
+	enum_stereo_sync_object,
+	enum_sync_output_object,
+	enum_audio_object,
+	update_audio_connectivity
+};
+
+static bool construct(
+	struct hw_ctx_adapter_service *hw_ctx,
+	struct dc_context *ctx)
+
+{
+	if (!dal_adapter_service_construct_hw_ctx(hw_ctx, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	hw_ctx->funcs = &funcs;
+
+	return true;
+}
+
+struct hw_ctx_adapter_service *dal_adapter_service_create_hw_ctx_diag(
+	struct dc_context *ctx)
+{
+	struct hw_ctx_adapter_service *hw_ctx = dm_alloc(ctx,
+			sizeof(*hw_ctx));
+
+	if (!hw_ctx) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(hw_ctx, ctx))
+		return hw_ctx;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, hw_ctx);
+
+	return NULL;
+}
+
+/*****************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
new file mode 100644
index 000000000000..39ae7524506c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_ADAPTER_SERVICE_DIAG_H__
+#define __DAL_HW_CTX_ADAPTER_SERVICE_DIAG_H__
+
+
+struct hw_ctx_adapter_service *dal_adapter_service_create_hw_ctx_diag(
+		struct dc_context *ctx);
+
+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_DIAG_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
new file mode 100644
index 000000000000..12eabe0c3f89
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/adapter_service_types.h"
+#include "include/grph_object_id.h"
+#include "hw_ctx_adapter_service.h"
+
+static const struct graphics_object_id invalid_go = {
+	0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN
+};
+
+static void destroy(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	/* Attention!
+	 * You must override impl method in derived class */
+	BREAK_TO_DEBUGGER();
+}
+
+static bool power_up(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	/* Attention!
+	 * You must override impl method in derived class */
+	BREAK_TO_DEBUGGER();
+
+	return false;
+}
+
+static struct graphics_object_id enum_fake_path_resource(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_stereo_sync_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_sync_output_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	return invalid_go;
+}
+
+static struct graphics_object_id enum_audio_object(
+	const struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t index)
+{
+	/* by default, we only allow one audio */
+
+	if (index > 0)
+		return invalid_go;
+	else if (hw_ctx->cached_audio_straps == AUDIO_STRAPS_NOT_ALLOWED)
+		return invalid_go;
+	else
+		return dal_graphics_object_id_init(
+			AUDIO_ID_INTERNAL_AZALIA,
+			ENUM_ID_1,
+			OBJECT_TYPE_AUDIO);
+}
+
+static void update_audio_connectivity(
+	struct hw_ctx_adapter_service *hw_ctx,
+	uint32_t number_of_audio_capable_display_path,
+	uint32_t number_of_controllers)
+{
+	/* Attention!
+	 * You must override impl method in derived class */
+	BREAK_TO_DEBUGGER();
+}
+
+static const struct hw_ctx_adapter_service_funcs funcs = {
+	destroy,
+	power_up,
+	enum_fake_path_resource,
+	enum_stereo_sync_object,
+	enum_sync_output_object,
+	enum_audio_object,
+	update_audio_connectivity
+};
+
+bool dal_adapter_service_construct_hw_ctx(
+	struct hw_ctx_adapter_service *hw_ctx,
+	struct dc_context *ctx)
+{
+
+	hw_ctx->ctx = ctx;
+	hw_ctx->funcs = &funcs;
+	hw_ctx->cached_audio_straps = AUDIO_STRAPS_NOT_ALLOWED;
+
+	return true;
+}
+
+union audio_support dal_adapter_service_hw_ctx_get_audio_support(
+	const struct hw_ctx_adapter_service *hw_ctx)
+{
+	union audio_support result;
+
+	result.raw = 0;
+
+	switch (hw_ctx->cached_audio_straps) {
+	case AUDIO_STRAPS_DP_HDMI_AUDIO:
+		result.bits.HDMI_AUDIO_NATIVE = true;
+		/* do not break ! */
+	case AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE:
+		result.bits.HDMI_AUDIO_ON_DONGLE = true;
+		/* do not break ! */
+	case AUDIO_STRAPS_DP_AUDIO_ALLOWED:
+		result.bits.DP_AUDIO = true;
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+void dal_adapter_service_destruct_hw_ctx(
+	struct hw_ctx_adapter_service *hw_ctx)
+{
+	/* There is nothing to destruct at the moment */
+}
+
+void dal_adapter_service_destroy_hw_ctx(
+	struct hw_ctx_adapter_service **ptr)
+{
+	if (!ptr || !*ptr) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*ptr)->funcs->destroy(*ptr);
+
+	*ptr = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
new file mode 100644
index 000000000000..f98c2d428b2a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_ADAPTER_SERVICE_H__
+#define __DAL_HW_CTX_ADAPTER_SERVICE_H__
+
+enum audio_straps {
+	AUDIO_STRAPS_NOT_ALLOWED = 0,
+	AUDIO_STRAPS_DP_AUDIO_ALLOWED,
+	AUDIO_STRAPS_DP_HDMI_AUDIO_ON_DONGLE,
+	AUDIO_STRAPS_DP_HDMI_AUDIO
+};
+
+struct hw_ctx_adapter_service;
+
+struct hw_ctx_adapter_service_funcs {
+	void (*destroy)(
+		struct hw_ctx_adapter_service *hw_ctx);
+	/* Initializes relevant HW registers
+	 * and caches relevant data from HW registers */
+	bool (*power_up)(
+		struct hw_ctx_adapter_service *hw_ctx);
+	/* Enumerate fake path resources */
+	struct graphics_object_id (*enum_fake_path_resource)(
+		const struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t index);
+	/* Enumerate stereo sync objects */
+	struct graphics_object_id (*enum_stereo_sync_object)(
+		const struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t index);
+	/* Enumerate (H/V) sync output objects */
+	struct graphics_object_id (*enum_sync_output_object)(
+		const struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t index);
+	/* Enumerate audio objects */
+	struct graphics_object_id (*enum_audio_object)(
+		const struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t index);
+	void (*update_audio_connectivity)(
+		struct hw_ctx_adapter_service *hw_ctx,
+		uint32_t number_of_audio_capable_display_path,
+		uint32_t number_of_controllers);
+};
+
+struct hw_ctx_adapter_service {
+	struct dc_context *ctx;
+	const struct hw_ctx_adapter_service_funcs *funcs;
+	enum audio_straps cached_audio_straps;
+};
+
+bool dal_adapter_service_construct_hw_ctx(
+	struct hw_ctx_adapter_service *hw_ctx,
+	struct dc_context *ctx);
+
+union audio_support dal_adapter_service_hw_ctx_get_audio_support(
+	const struct hw_ctx_adapter_service *hw_ctx);
+
+void dal_adapter_service_destruct_hw_ctx(
+	struct hw_ctx_adapter_service *hw_ctx);
+
+void dal_adapter_service_destroy_hw_ctx(
+	struct hw_ctx_adapter_service **ptr);
+
+#endif /* __DAL_HW_CTX_ADAPTER_SERVICE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
new file mode 100644
index 000000000000..0b1151ec5a2c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#include "dm_services.h"
+#include "adapter_service.h"
+#include "wireless_data_source.h"
+
+#include "atom.h"
+
+/*construct wireless data*/
+bool wireless_data_init(struct wireless_data *data,
+		struct dc_bios *dcb,
+		struct wireless_init_data *init_data)
+{
+	struct firmware_info info;
+
+	if (data == NULL || dcb == NULL || init_data == NULL) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	data->miracast_connector_enable = false;
+	data->wireless_disp_path_enable = false;
+	data->wireless_enable = false;
+
+	/* Wireless it not supported if VCE is not supported */
+	if (!init_data->vce_supported)
+		return true;
+
+	if (init_data->miracast_target_required)
+		data->miracast_connector_enable = true;
+
+	/*
+	 * If override is in place for platform support, we will both
+	 * enable wireless display as a feature (i.e. CCC aspect) and
+	 * enable the wireless display path without any further checks.
+	 */
+	if (init_data->platform_override) {
+		data->wireless_enable = true;
+		data->wireless_disp_path_enable = true;
+	} else {
+		/*
+		 * Check if SBIOS sets remote display enable, exposed
+		 * through VBIOS. This is only valid for APU, not dGPU
+		 */
+		dcb->funcs->get_firmware_info(dcb, &info);
+
+		if ((REMOTE_DISPLAY_ENABLE == info.remote_display_config) &&
+				init_data->fusion) {
+			data->wireless_enable = true;
+			data->wireless_disp_path_enable = true;
+		}
+	}
+
+	/*
+	 * If remote display path override is enabled, we enable just the
+	 * remote display path. This is mainly used for testing purposes
+	 */
+	if (init_data->remote_disp_path_override)
+		data->wireless_disp_path_enable = true;
+
+	return true;
+}
+
+uint8_t wireless_get_clocks_num(
+	struct adapter_service *as)
+{
+	if (as->wireless_data.wireless_enable ||
+		as->wireless_data.wireless_disp_path_enable)
+		return 1;
+	else
+		return 0;
+}
+
+static uint8_t wireless_get_encoders_num(
+	struct adapter_service *as)
+{
+	if (as->wireless_data.wireless_enable ||
+		as->wireless_data.wireless_disp_path_enable)
+		return 1;
+	else
+		return 0;
+}
+
+uint8_t wireless_get_connectors_num(
+	struct adapter_service *as)
+{
+	uint8_t wireless_connectors_num = 0;
+
+	if (as->wireless_data.wireless_enable &&
+		as->wireless_data.miracast_connector_enable)
+		wireless_connectors_num++;
+
+	if (as->wireless_data.wireless_disp_path_enable)
+		wireless_connectors_num++;
+
+	return wireless_connectors_num;
+}
+
+struct graphics_object_id wireless_get_connector_id(
+	struct adapter_service *as,
+	uint8_t index)
+{
+	struct graphics_object_id unknown_object_id =
+			dal_graphics_object_id_init(
+				0,
+				ENUM_ID_UNKNOWN,
+				OBJECT_TYPE_UNKNOWN);
+
+	if (!as->wireless_data.wireless_enable &&
+		!as->wireless_data.wireless_disp_path_enable)
+		return unknown_object_id;
+
+	else if (!as->wireless_data.miracast_connector_enable)
+		return dal_graphics_object_id_init(
+			CONNECTOR_ID_WIRELESS,
+			ENUM_ID_1,
+			OBJECT_TYPE_CONNECTOR);
+
+	switch (index) {
+	case 0:
+		return dal_graphics_object_id_init(
+			CONNECTOR_ID_WIRELESS,
+			ENUM_ID_1,
+			OBJECT_TYPE_CONNECTOR);
+		break;
+	case 1:
+		return dal_graphics_object_id_init(
+			CONNECTOR_ID_MIRACAST,
+			ENUM_ID_1,
+			OBJECT_TYPE_CONNECTOR);
+		break;
+	default:
+		return unknown_object_id;
+	}
+}
+
+uint8_t wireless_get_srcs_num(
+	struct adapter_service *as,
+	struct graphics_object_id id)
+{
+	switch (id.type) {
+	case OBJECT_TYPE_CONNECTOR:
+		return wireless_get_encoders_num(as);
+	case OBJECT_TYPE_ENCODER:
+		return 1;
+
+	default:
+		ASSERT_CRITICAL(false);
+		break;
+	}
+
+	return 0;
+}
+
+struct graphics_object_id wireless_get_src_obj_id(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	uint8_t index)
+{
+	if (index < wireless_get_srcs_num(as, id)) {
+		switch (id.type) {
+		case OBJECT_TYPE_CONNECTOR:
+			return dal_graphics_object_id_init(
+					ENCODER_ID_INTERNAL_WIRELESS,
+					ENUM_ID_1,
+					OBJECT_TYPE_ENCODER);
+			break;
+		case OBJECT_TYPE_ENCODER:
+			return dal_graphics_object_id_init(
+					0,
+					ENUM_ID_1,
+					OBJECT_TYPE_GPU);
+			break;
+		default:
+			ASSERT_CRITICAL(false);
+			break;
+		}
+	}
+
+	return dal_graphics_object_id_init(
+			0,
+			ENUM_ID_UNKNOWN,
+			OBJECT_TYPE_UNKNOWN);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
new file mode 100644
index 000000000000..b64089e3960e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_WIRELESS_DATA_SOURCE_H__
+#define __DAL_WIRELESS_DATA_SOURCE_H__
+
+/* Include */
+#include "include/grph_object_id.h"
+
+/*
+ * Forward declaration
+ */
+struct adapter_service;
+struct dc_bios;
+
+/* Wireless data init structure */
+struct wireless_init_data {
+	bool fusion; /* Fusion flag */
+	bool platform_override; /* Override for platform BIOS option */
+	bool remote_disp_path_override; /* Override enabling wireless path */
+	bool vce_supported; /* Existence of VCE block on this DCE */
+	bool miracast_target_required; /* OS requires Miracast target */
+};
+
+/* Wireless data */
+struct wireless_data {
+	bool wireless_enable;
+	bool wireless_disp_path_enable;
+	bool miracast_connector_enable;
+};
+
+
+/*construct wireless data*/
+bool wireless_data_init(
+	struct wireless_data *data,
+	struct dc_bios *dcb,
+	struct wireless_init_data *init_data);
+
+uint8_t wireless_get_clocks_num(
+	struct adapter_service *as);
+
+uint8_t wireless_get_connectors_num(
+	struct adapter_service *as);
+
+struct graphics_object_id wireless_get_connector_id(
+	struct adapter_service *as,
+	uint8_t connector_index);
+
+uint8_t wireless_get_srcs_num(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+struct graphics_object_id wireless_get_src_obj_id(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	uint8_t index);
+
+#endif /* __DAL_WIRELESS_DATA_SOURCE_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 07/26] drm/amd/dal: BIOS Parser
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (5 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 06/26] drm/amd/dal: Adapter Service Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 08/26] drm/amd/dal: I2C Aux Manager Harry Wentland
                     ` (18 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Wrapper to access Video BIOS command and data tables

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/bios/Makefile           |   26 +
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c      | 5029 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h      |   84 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c   |  198 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h   |  108 +
 drivers/gpu/drm/amd/dal/dc/bios/command_table.c    | 2730 +++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/command_table.h    |  117 +
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.c |  285 ++
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.h |   90 +
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.c |  484 ++
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.h |   34 +
 .../dc/bios/dce110/command_table_helper_dce110.c   |  366 ++
 .../dc/bios/dce110/command_table_helper_dce110.h   |   34 +
 13 files changed, 9585 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h

diff --git a/drivers/gpu/drm/amd/dal/dc/bios/Makefile b/drivers/gpu/drm/amd/dal/dc/bios/Makefile
new file mode 100644
index 000000000000..ddfe457e3a8b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for the 'bios' sub-component of DAL.
+# It provides the parsing and executing controls for atom bios image.
+
+BIOS = bios_parser.o bios_parser_helper.o command_table.o command_table_helper.o
+
+AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS))
+
+AMD_DAL_FILES += $(AMD_DAL_BIOS)
+
+ifndef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+AMD_DAL_FILES := $(filter-out $(AMDDALPATH)/dc/bios/bios_parser_helper.o,$(AMD_DAL_FILES))
+endif
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+
+ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce110/bios_parser_helper_dce110.o
+endif
+
+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
new file mode 100644
index 000000000000..4ce5f9fcf907
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
@@ -0,0 +1,5029 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "dc_bios_types.h"
+#include "include/adapter_service_interface.h"
+#include "include/grph_object_ctrl_defs.h"
+#include "include/bios_parser_interface.h"
+#include "include/i2caux_interface.h"
+#include "include/logger_interface.h"
+
+#include "command_table.h"
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+#include "bios_parser_helper.h"
+#endif
+#include "command_table_helper.h"
+#include "bios_parser.h"
+#include "bios_parser_interface.h"
+
+#define THREE_PERCENT_OF_10000 300
+
+#define LAST_RECORD_TYPE 0xff
+
+/* GUID to validate external display connection info table (aka OPM module) */
+static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = {
+	0x91, 0x6E, 0x57, 0x09,
+	0x3F, 0x6D, 0xD2, 0x11,
+	0x39, 0x8E, 0x00, 0xA0,
+	0xC9, 0x69, 0x72, 0x3B};
+
+#define GET_IMAGE(type, offset) ((type *) get_image(bp, offset, sizeof(type)))
+#define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
+
+static uint8_t *get_image(struct bios_parser *bp, uint32_t offset,
+	uint32_t size);
+static uint32_t get_record_size(uint8_t *record);
+static uint32_t get_edid_size(const ATOM_FAKE_EDID_PATCH_RECORD *edid);
+static enum object_type object_type_from_bios_object_id(
+	uint32_t bios_object_id);
+static struct graphics_object_id object_id_from_bios_object_id(
+	uint32_t bios_object_id);
+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id);
+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id);
+static enum connector_id connector_id_from_bios_object_id(
+	uint32_t bios_object_id);
+static uint32_t id_from_bios_object_id(enum object_type type,
+	uint32_t bios_object_id);
+static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id);
+static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id);
+static void get_atom_data_table_revision(
+	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
+	struct atom_data_revision *tbl_revision);
+static uint32_t get_dst_number_from_object(struct bios_parser *bp,
+	ATOM_OBJECT *object);
+static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
+	uint16_t **id_list);
+static uint32_t get_dest_obj_list(struct bios_parser *bp,
+	ATOM_OBJECT *object, uint16_t **id_list);
+static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
+	struct graphics_object_id id);
+static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
+	ATOM_I2C_RECORD *record,
+	struct graphics_object_i2c_info *info);
+static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+	ATOM_OBJECT *object);
+static struct device_id device_type_from_device_id(uint16_t device_id);
+static uint32_t signal_to_ss_id(enum as_signal_type signal);
+static uint32_t get_support_mask_for_device_id(struct device_id device_id);
+static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object);
+static void process_ext_display_connection_info(struct bios_parser *bp);
+
+
+#define BIOS_IMAGE_SIZE_OFFSET 2
+#define BIOS_IMAGE_SIZE_UNIT 512
+
+/*****************************************************************************/
+static bool bios_parser_construct(
+	struct bios_parser *bp,
+	struct bp_init_data *init,
+	struct adapter_service *as);
+
+static uint8_t bios_parser_get_connectors_number(
+	struct dc_bios *dcb);
+
+static enum bp_result bios_parser_get_embedded_panel_info(
+	struct dc_bios *dcb,
+	struct embedded_panel_info *info);
+
+/*****************************************************************************/
+
+struct dc_bios *dal_bios_parser_create(
+	struct bp_init_data *init, struct adapter_service *as)
+{
+	struct bios_parser *bp = NULL;
+
+	bp = dm_alloc(init->ctx, sizeof(struct bios_parser));
+	if (!bp)
+		return NULL;
+
+	if (bios_parser_construct(bp, init, as))
+		return &bp->base;
+
+	dm_free(init->ctx, bp);
+	BREAK_TO_DEBUGGER();
+	return NULL;
+}
+
+static void destruct(struct bios_parser *bp)
+{
+	if (bp->bios_local_image)
+		dm_free(bp->ctx, bp->bios_local_image);
+}
+
+void dal_bios_parser_destroy(struct dc_bios **dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(*dcb);
+
+	if (!bp) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct(bp);
+
+	dm_free((bp)->ctx, bp);
+	*dcb = NULL;
+}
+
+static void bios_parser_power_down(struct dc_bios *dcb)
+{
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	dal_bios_parser_set_scratch_lcd_scale(bp, bp->lcd_scale);
+#endif
+}
+
+static void bios_parser_power_up(struct dc_bios *dcb)
+{
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (bp->lcd_scale == LCD_SCALE_UNKNOWN)
+		bp->lcd_scale = dal_bios_parser_get_scratch_lcd_scale(bp);
+#endif
+}
+
+static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
+{
+	ATOM_OBJECT_TABLE *table;
+
+	uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
+
+	table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset);
+
+	if (!table)
+		return 0;
+	else
+		return table->ucNumberOfObjects;
+}
+
+static uint8_t bios_parser_get_encoders_number(struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	return get_number_of_objects(bp,
+		le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset));
+}
+
+static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	return get_number_of_objects(bp,
+		le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));
+}
+
+static uint32_t bios_parser_get_oem_ddc_lines_number(struct dc_bios *dcb)
+{
+	uint32_t number = 0;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (DATA_TABLES(OemInfo) != 0) {
+		ATOM_OEM_INFO *info;
+
+		info = GET_IMAGE(ATOM_OEM_INFO,
+			DATA_TABLES(OemInfo));
+
+		if (le16_to_cpu(info->sHeader.usStructureSize)
+			> sizeof(ATOM_COMMON_TABLE_HEADER)) {
+
+			number = (le16_to_cpu(info->sHeader.usStructureSize)
+				- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_I2C_ID_CONFIG_ACCESS);
+
+		}
+	}
+
+	return number;
+}
+
+static struct graphics_object_id bios_parser_get_encoder_id(
+	struct dc_bios *dcb,
+	uint32_t i)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct graphics_object_id object_id = dal_graphics_object_id_init(
+		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
+
+	uint32_t encoder_table_offset = bp->object_info_tbl_offset
+		+ le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
+
+	ATOM_OBJECT_TABLE *tbl =
+		GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
+
+	if (tbl && tbl->ucNumberOfObjects > i) {
+		const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID);
+
+		object_id = object_id_from_bios_object_id(id);
+	}
+
+	return object_id;
+}
+
+static struct graphics_object_id bios_parser_get_connector_id(
+	struct dc_bios *dcb,
+	uint8_t i)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct graphics_object_id object_id = dal_graphics_object_id_init(
+		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
+
+	uint32_t connector_table_offset = bp->object_info_tbl_offset
+		+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+
+	ATOM_OBJECT_TABLE *tbl =
+		GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset);
+
+	if (tbl && tbl->ucNumberOfObjects > i) {
+		const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID);
+
+		object_id = object_id_from_bios_object_id(id);
+	}
+
+	return object_id;
+}
+
+static uint32_t bios_parser_get_src_number(struct dc_bios *dcb,
+	struct graphics_object_id id)
+{
+	uint32_t offset;
+	uint8_t *number;
+	ATOM_OBJECT *object;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	object = get_bios_object(bp, id);
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+			+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	return *number;
+}
+
+static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb,
+	struct graphics_object_id id)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object = get_bios_object(bp, id);
+
+	return get_dst_number_from_object(bp, object);
+}
+
+static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
+	struct graphics_object_id object_id, uint32_t index,
+	struct graphics_object_id *src_object_id)
+{
+	uint32_t number;
+	uint16_t *id;
+	ATOM_OBJECT *object;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!src_object_id)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, object_id);
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return BP_RESULT_BADINPUT;
+	}
+
+	number = get_src_obj_list(bp, object, &id);
+
+	if (number <= index)
+		return BP_RESULT_BADINPUT;
+
+	*src_object_id = object_id_from_bios_object_id(id[index]);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb,
+	struct graphics_object_id object_id, uint32_t index,
+	struct graphics_object_id *dest_object_id)
+{
+	uint32_t number;
+	uint16_t *id;
+	ATOM_OBJECT *object;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!dest_object_id)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, object_id);
+
+	number = get_dest_obj_list(bp, object, &id);
+
+	if (number <= index)
+		return BP_RESULT_BADINPUT;
+
+	*dest_object_id = object_id_from_bios_object_id(id[index]);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_oem_ddc_info(struct dc_bios *dcb,
+	uint32_t index,
+	struct graphics_object_i2c_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (DATA_TABLES(OemInfo) != 0) {
+		ATOM_OEM_INFO *tbl;
+
+		tbl = GET_IMAGE(ATOM_OEM_INFO, DATA_TABLES(OemInfo));
+
+		if (le16_to_cpu(tbl->sHeader.usStructureSize)
+			> sizeof(ATOM_COMMON_TABLE_HEADER)) {
+			ATOM_I2C_RECORD record;
+			ATOM_I2C_ID_CONFIG_ACCESS *config;
+
+			dm_memset(&record, 0, sizeof(record));
+
+			config = &tbl->sucI2cId + index - 1;
+
+			record.sucI2cId.bfHW_Capable =
+				config->sbfAccess.bfHW_Capable;
+			record.sucI2cId.bfI2C_LineMux =
+				config->sbfAccess.bfI2C_LineMux;
+			record.sucI2cId.bfHW_EngineID =
+				config->sbfAccess.bfHW_EngineID;
+
+			return get_gpio_i2c_info(bp, &record, info);
+		}
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct graphics_object_i2c_info *info)
+{
+	uint32_t offset;
+	ATOM_OBJECT *object;
+	ATOM_COMMON_RECORD_HEADER *header;
+	ATOM_I2C_RECORD *record;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, id);
+
+	if (!object)
+		return BP_RESULT_BADINPUT;
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return BP_RESULT_BADBIOSTABLE;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+			!header->ucRecordSize)
+			break;
+
+		if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
+			&& sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {
+			/* get the I2C info */
+			record = (ATOM_I2C_RECORD *) header;
+
+			if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)
+				return BP_RESULT_OK;
+		}
+
+		offset += header->ucRecordSize;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result get_voltage_ddc_info_v1(uint8_t *i2c_line,
+	ATOM_COMMON_TABLE_HEADER *header,
+	uint8_t *address)
+{
+	enum bp_result result = BP_RESULT_NORECORD;
+	ATOM_VOLTAGE_OBJECT_INFO *info =
+		(ATOM_VOLTAGE_OBJECT_INFO *) address;
+
+	uint8_t *voltage_current_object = (uint8_t *) &info->asVoltageObj[0];
+
+	while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
+		ATOM_VOLTAGE_OBJECT *object =
+			(ATOM_VOLTAGE_OBJECT *) voltage_current_object;
+
+		if ((object->ucVoltageType == SET_VOLTAGE_INIT_MODE) &&
+			(object->ucVoltageType &
+				VOLTAGE_CONTROLLED_BY_I2C_MASK)) {
+
+			*i2c_line = object->asControl.ucVoltageControlI2cLine
+					^ 0x90;
+			result = BP_RESULT_OK;
+			break;
+		}
+
+		voltage_current_object += object->ucSize;
+	}
+	return result;
+}
+
+static enum bp_result get_voltage_ddc_info_v3(uint8_t *i2c_line,
+	uint32_t index,
+	ATOM_COMMON_TABLE_HEADER *header,
+	uint8_t *address)
+{
+	enum bp_result result = BP_RESULT_NORECORD;
+	ATOM_VOLTAGE_OBJECT_INFO_V3_1 *info =
+		(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *) address;
+
+	uint8_t *voltage_current_object =
+		(uint8_t *) (&(info->asVoltageObj[0]));
+
+	while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
+		ATOM_I2C_VOLTAGE_OBJECT_V3 *object =
+			(ATOM_I2C_VOLTAGE_OBJECT_V3 *) voltage_current_object;
+
+		if (object->sHeader.ucVoltageMode ==
+			ATOM_INIT_VOLTAGE_REGULATOR) {
+			if (object->sHeader.ucVoltageType == index) {
+				*i2c_line = object->ucVoltageControlI2cLine
+						^ 0x90;
+				result = BP_RESULT_OK;
+				break;
+			}
+		}
+
+		voltage_current_object += le16_to_cpu(object->sHeader.usSize);
+	}
+	return result;
+}
+
+static enum bp_result bios_parser_get_thermal_ddc_info(
+	struct dc_bios *dcb,
+	uint32_t i2c_channel_id,
+	struct graphics_object_i2c_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_I2C_ID_CONFIG_ACCESS *config;
+	ATOM_I2C_RECORD record;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	config = (ATOM_I2C_ID_CONFIG_ACCESS *) &i2c_channel_id;
+
+	record.sucI2cId.bfHW_Capable = config->sbfAccess.bfHW_Capable;
+	record.sucI2cId.bfI2C_LineMux = config->sbfAccess.bfI2C_LineMux;
+	record.sucI2cId.bfHW_EngineID = config->sbfAccess.bfHW_EngineID;
+
+	return get_gpio_i2c_info(bp, &record, info);
+}
+
+static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb,
+	uint32_t index,
+	struct graphics_object_i2c_info *info)
+{
+	uint8_t i2c_line = 0;
+	enum bp_result result = BP_RESULT_NORECORD;
+	uint8_t *voltage_info_address;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision = {0};
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!DATA_TABLES(VoltageObjectInfo))
+		return result;
+
+	voltage_info_address = get_image(bp,
+		DATA_TABLES(VoltageObjectInfo),
+		sizeof(ATOM_COMMON_TABLE_HEADER));
+
+	header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address;
+
+	get_atom_data_table_revision(header, &revision);
+
+	switch (revision.major) {
+	case 1:
+	case 2:
+		result = get_voltage_ddc_info_v1(&i2c_line, header,
+			voltage_info_address);
+		break;
+	case 3:
+		if (revision.minor != 1)
+			break;
+		result = get_voltage_ddc_info_v3(&i2c_line, index, header,
+			voltage_info_address);
+		break;
+	}
+
+	if (result == BP_RESULT_OK)
+		result = bios_parser_get_thermal_ddc_info(dcb,
+			i2c_line, info);
+
+
+	return result;
+}
+
+enum bp_result bios_parser_get_ddc_info_for_i2c_line(struct bios_parser *bp,
+	uint8_t i2c_line, struct graphics_object_i2c_info *info)
+{
+	uint32_t offset;
+	ATOM_OBJECT *object;
+	ATOM_OBJECT_TABLE *table;
+	uint32_t i;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+
+	offset += bp->object_info_tbl_offset;
+
+	table = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
+
+	if (!table)
+		return BP_RESULT_BADBIOSTABLE;
+
+	for (i = 0; i < table->ucNumberOfObjects; i++) {
+		object = &table->asObjects[i];
+
+		if (!object) {
+			BREAK_TO_DEBUGGER(); /* Invalid object id */
+			return BP_RESULT_BADINPUT;
+		}
+
+		offset = le16_to_cpu(object->usRecordOffset)
+				+ bp->object_info_tbl_offset;
+
+		for (;;) {
+			ATOM_COMMON_RECORD_HEADER *header =
+				GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+			if (!header)
+				return BP_RESULT_BADBIOSTABLE;
+
+			offset += header->ucRecordSize;
+
+			if (LAST_RECORD_TYPE == header->ucRecordType ||
+				!header->ucRecordSize)
+				break;
+
+			if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
+				&& sizeof(ATOM_I2C_RECORD) <=
+				header->ucRecordSize) {
+				ATOM_I2C_RECORD *record =
+					(ATOM_I2C_RECORD *) header;
+
+				if (i2c_line != record->sucI2cId.bfI2C_LineMux)
+					continue;
+
+				/* get the I2C info */
+				if (get_gpio_i2c_info(bp, record, info) ==
+					BP_RESULT_OK)
+					return BP_RESULT_OK;
+			}
+		}
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct graphics_object_hpd_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object;
+	ATOM_HPD_INT_RECORD *record = NULL;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, id);
+
+	if (!object)
+		return BP_RESULT_BADINPUT;
+
+	record = get_hpd_record(bp, object);
+
+	if (record != NULL) {
+		info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;
+		info->hpd_active = record->ucPlugged_PinState;
+		return BP_RESULT_OK;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static uint32_t bios_parser_get_gpio_record(
+	struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct bp_gpio_cntl_info *gpio_record,
+	uint32_t record_size)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_COMMON_RECORD_HEADER *header = NULL;
+	ATOM_OBJECT_GPIO_CNTL_RECORD *record = NULL;
+	ATOM_OBJECT *object = get_bios_object(bp, id);
+	uint32_t offset;
+	uint32_t pins_number;
+	uint32_t i;
+
+	if (!object)
+		return 0;
+
+	/* Initialise offset */
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		/* Get record header */
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+		if (!header || header->ucRecordType == LAST_RECORD_TYPE ||
+			!header->ucRecordSize)
+			break;
+
+		/* If this is gpio control record - stop. We found the record */
+		if (header->ucRecordType == ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE
+			&& header->ucRecordSize
+				>= sizeof(ATOM_OBJECT_GPIO_CNTL_RECORD)) {
+			record = (ATOM_OBJECT_GPIO_CNTL_RECORD *) header;
+			break;
+		}
+
+		/* Advance to next record */
+		offset += header->ucRecordSize;
+	}
+
+	/* If we did not find a record - return */
+	if (!record)
+		return 0;
+
+	/* Extract gpio IDs from bios record (make sure we do not exceed passed
+	 *  array size) */
+	pins_number = (record->ucNumberOfPins < record_size ?
+			record->ucNumberOfPins : record_size);
+	for (i = 0; i < pins_number; i++) {
+		uint8_t output_state = ((record->asGpio[i].ucGPIO_PinState
+			& GPIO_PIN_OUTPUT_STATE_MASK)
+			>> GPIO_PIN_OUTPUT_STATE_SHIFT);
+		gpio_record[i].id = record->asGpio[i].ucGPIOID;
+
+		switch (output_state) {
+		case GPIO_PIN_STATE_ACTIVE_LOW:
+			gpio_record[i].state =
+				GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW;
+			break;
+
+		case GPIO_PIN_STATE_ACTIVE_HIGH:
+			gpio_record[i].state =
+				GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH;
+			break;
+
+		default:
+			BREAK_TO_DEBUGGER(); /* Invalid Pin Output State */
+			break;
+		}
+	}
+
+	return pins_number;
+}
+
+enum bp_result bios_parser_get_device_tag_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object,
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)
+{
+	ATOM_COMMON_RECORD_HEADER *header;
+	uint32_t offset;
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return BP_RESULT_BADBIOSTABLE;
+
+		offset += header->ucRecordSize;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+			!header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=
+			header->ucRecordType)
+			continue;
+
+		if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)
+			continue;
+
+		*record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;
+		return BP_RESULT_OK;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_get_device_tag(
+	struct dc_bios *dcb,
+	struct graphics_object_id connector_object_id,
+	uint32_t device_tag_index,
+	struct connector_device_tag_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object;
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;
+	ATOM_CONNECTOR_DEVICE_TAG *device_tag;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	/* getBiosObject will return MXM object */
+	object = get_bios_object(bp, connector_object_id);
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return BP_RESULT_BADINPUT;
+	}
+
+	if (bios_parser_get_device_tag_record(bp, object, &record)
+		!= BP_RESULT_OK)
+		return BP_RESULT_NORECORD;
+
+	if (device_tag_index >= record->ucNumberOfDevice)
+		return BP_RESULT_NORECORD;
+
+	device_tag = &record->asDeviceTag[device_tag_index];
+
+	info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);
+	info->dev_id =
+		device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_firmware_info_v1_4(
+	struct bios_parser *bp,
+	struct firmware_info *info);
+static enum bp_result get_firmware_info_v2_1(
+	struct bios_parser *bp,
+	struct firmware_info *info);
+static enum bp_result get_firmware_info_v2_2(
+	struct bios_parser *bp,
+	struct firmware_info *info);
+
+static enum bp_result bios_parser_get_firmware_info(
+	struct dc_bios *dcb,
+	struct firmware_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision;
+
+	if (info && DATA_TABLES(FirmwareInfo)) {
+		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+			DATA_TABLES(FirmwareInfo));
+		get_atom_data_table_revision(header, &revision);
+		switch (revision.major) {
+		case 1:
+			switch (revision.minor) {
+			case 4:
+				result = get_firmware_info_v1_4(bp, info);
+				break;
+			default:
+				break;
+			}
+			break;
+
+		case 2:
+			switch (revision.minor) {
+			case 1:
+				result = get_firmware_info_v2_1(bp, info);
+				break;
+			case 2:
+				result = get_firmware_info_v2_2(bp, info);
+				break;
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	return result;
+}
+
+static enum bp_result get_firmware_info_v1_4(
+	struct bios_parser *bp,
+	struct firmware_info *info)
+{
+	ATOM_FIRMWARE_INFO_V1_4 *firmware_info =
+		GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,
+			DATA_TABLES(FirmwareInfo));
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!firmware_info)
+		return BP_RESULT_BADBIOSTABLE;
+
+	dm_memset(info, 0, sizeof(*info));
+
+	/* Pixel clock pll information. We need to convert from 10KHz units into
+	 * KHz units */
+	info->pll_info.crystal_frequency =
+		le16_to_cpu(firmware_info->usReferenceClock) * 10;
+	info->pll_info.min_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
+	info->pll_info.max_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
+	info->pll_info.min_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
+	info->pll_info.max_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
+
+	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
+		/* Since there is no information on the SS, report conservative
+		 * value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
+
+	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
+		/* Since there is no information on the SS,report conservative
+		 * value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_ss_info_v3_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info);
+
+static enum bp_result get_firmware_info_v2_1(
+	struct bios_parser *bp,
+	struct firmware_info *info)
+{
+	ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =
+		GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));
+	struct spread_spectrum_info internalSS;
+	uint32_t index;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!firmwareInfo)
+		return BP_RESULT_BADBIOSTABLE;
+
+	dm_memset(info, 0, sizeof(*info));
+
+	/* Pixel clock pll information. We need to convert from 10KHz units into
+	 * KHz units */
+	info->pll_info.crystal_frequency =
+		le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;
+	info->pll_info.min_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;
+	info->pll_info.max_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;
+	info->pll_info.min_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;
+	info->pll_info.max_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;
+	info->default_display_engine_pll_frequency =
+		le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;
+	info->external_clock_source_frequency_for_dp =
+		le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;
+	info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;
+
+	/* There should be only one entry in the SS info table for Memory Clock
+	 */
+	index = 0;
+	if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
+		/* Since there is no information for external SS, report
+		 *  conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+		ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {
+		if (internalSS.spread_spectrum_percentage) {
+			info->feature.memory_clk_ss_percentage =
+				internalSS.spread_spectrum_percentage;
+			if (internalSS.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.memory_clk_ss_percentage;
+				info->feature.memory_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	/* There should be only one entry in the SS info table for Engine Clock
+	 */
+	index = 1;
+	if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
+		/* Since there is no information for external SS, report
+		 * conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+		ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {
+		if (internalSS.spread_spectrum_percentage) {
+			info->feature.engine_clk_ss_percentage =
+				internalSS.spread_spectrum_percentage;
+			if (internalSS.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.engine_clk_ss_percentage;
+				info->feature.engine_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_firmware_info_v2_2(
+	struct bios_parser *bp,
+	struct firmware_info *info)
+{
+	ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
+	struct spread_spectrum_info internal_ss;
+	uint32_t index;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,
+		DATA_TABLES(FirmwareInfo));
+
+	if (!firmware_info)
+		return BP_RESULT_BADBIOSTABLE;
+
+	dm_memset(info, 0, sizeof(*info));
+
+	/* Pixel clock pll information. We need to convert from 10KHz units into
+	 * KHz units */
+	info->pll_info.crystal_frequency =
+		le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;
+	info->pll_info.min_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
+	info->pll_info.max_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
+	info->pll_info.min_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
+	info->pll_info.max_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
+	info->default_display_engine_pll_frequency =
+		le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;
+	info->external_clock_source_frequency_for_dp =
+		le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;
+
+	/* There should be only one entry in the SS info table for Memory Clock
+	 */
+	index = 0;
+	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
+		/* Since there is no information for external SS, report
+		 *  conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+			ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {
+		if (internal_ss.spread_spectrum_percentage) {
+			info->feature.memory_clk_ss_percentage =
+					internal_ss.spread_spectrum_percentage;
+			if (internal_ss.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.memory_clk_ss_percentage;
+				info->feature.memory_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	/* There should be only one entry in the SS info table for Engine Clock
+	 */
+	index = 1;
+	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
+		/* Since there is no information for external SS, report
+		 * conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+			ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {
+		if (internal_ss.spread_spectrum_percentage) {
+			info->feature.engine_clk_ss_percentage =
+					internal_ss.spread_spectrum_percentage;
+			if (internal_ss.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.engine_clk_ss_percentage;
+				info->feature.engine_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	/* Remote Display */
+	info->remote_display_config = firmware_info->ucRemoteDisplayConfig;
+
+	/* Is allowed minimum BL level */
+	info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;
+	/* Used starting from CI */
+	info->smu_gpu_pll_output_freq =
+			(uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_ss_info_v3_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info)
+{
+	ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;
+	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
+	uint32_t table_size;
+	uint32_t i;
+	uint32_t table_index = 0;
+
+	if (!ss_info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return BP_RESULT_UNSUPPORTED;
+
+	ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
+		DATA_TABLES(ASIC_InternalSS_Info));
+	table_size =
+		(le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
+				- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
+				&ss_table_header_include->asSpreadSpectrum[0];
+
+	dm_memset(ss_info, 0, sizeof(struct spread_spectrum_info));
+
+	for (i = 0; i < table_size; i++) {
+		if (tbl[i].ucClockIndication != (uint8_t) id)
+			continue;
+
+		if (table_index != index) {
+			table_index++;
+			continue;
+		}
+		/* VBIOS introduced new defines for Version 3, same values as
+		 *  before, so now use these new ones for Version 3.
+		 * Shouldn't affect field VBIOS's V3 as define values are still
+		 *  same.
+		 * #define SS_MODE_V3_CENTRE_SPREAD_MASK                0x01
+		 * #define SS_MODE_V3_EXTERNAL_SS_MASK                  0x02
+
+		 * Old VBIOS defines:
+		 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001
+		 * #define ATOM_EXTERNAL_SS_MASK                  0x00000002
+		 */
+
+		if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode)
+			ss_info->type.EXTERNAL = true;
+
+		if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode)
+			ss_info->type.CENTER_MODE = true;
+
+		/* Older VBIOS (in field) always provides SS percentage in 0.01%
+		 * units set Divider to 100 */
+		ss_info->spread_percentage_divider = 100;
+
+		/* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */
+		if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK
+				& tbl[i].ucSpreadSpectrumMode)
+			ss_info->spread_percentage_divider = 1000;
+
+		ss_info->type.STEP_AND_DELAY_INFO = false;
+		/* convert [10KHz] into [KHz] */
+		ss_info->target_clock_range =
+				le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
+		ss_info->spread_spectrum_percentage =
+				(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
+		ss_info->spread_spectrum_range =
+				(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
+
+		return BP_RESULT_OK;
+	}
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_transmitter_control(
+	struct dc_bios *dcb,
+	struct bp_transmitter_control *cntl)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.transmitter_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.transmitter_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_encoder_control(
+	struct dc_bios *dcb,
+	struct bp_encoder_control *cntl)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.dig_encoder_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.dig_encoder_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_adjust_pixel_clock(
+	struct dc_bios *dcb,
+	struct bp_adjust_pixel_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.adjust_display_pll)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.adjust_display_pll(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_pixel_clock(
+	struct dc_bios *dcb,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_pixel_clock)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_dce_clock(
+	struct dc_bios *dcb,
+	struct bp_set_dce_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_dce_clock)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_dce_clock(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_spread_spectrum_on_ppll(
+	struct dc_bios *dcb,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_spread_spectrum_on_ppll(
+			bp, bp_params, enable);
+
+}
+
+static enum bp_result bios_parser_program_crtc_timing(
+	struct dc_bios *dcb,
+	struct bp_hw_crtc_timing_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_crtc_timing)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
+}
+
+static enum bp_result bios_parser_program_display_engine_pll(
+	struct dc_bios *dcb,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.program_clock)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.program_clock(bp, bp_params);
+
+}
+
+static enum signal_type bios_parser_dac_load_detect(
+	struct dc_bios *dcb,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type display_signal)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.dac_load_detection)
+		return SIGNAL_TYPE_NONE;
+
+	return bp->cmd_tbl.dac_load_detection(bp, encoder, connector,
+		display_signal);
+}
+
+static enum bp_result bios_parser_get_divider_for_target_display_clock(
+	struct dc_bios *dcb,
+	struct bp_display_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.compute_memore_engine_pll)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.compute_memore_engine_pll(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_crtc(
+	struct dc_bios *dcb,
+	enum controller_id id,
+	bool enable)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_crtc)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_crtc(bp, id, enable);
+}
+
+static enum bp_result bios_parser_blank_crtc(
+	struct dc_bios *dcb,
+	struct bp_blank_crtc_parameters *bp_params,
+	bool blank)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.blank_crtc)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.blank_crtc(bp, bp_params, blank);
+}
+
+static enum bp_result bios_parser_crtc_source_select(
+	struct dc_bios *dcb,
+	struct bp_crtc_source_select *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.select_crtc_source)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.select_crtc_source(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_overscan(
+	struct dc_bios *dcb,
+	struct bp_hw_crtc_overscan_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_crtc_overscan)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_crtc_overscan(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_memory_requests(
+	struct dc_bios *dcb,
+	enum controller_id controller_id,
+	bool enable)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_crtc_mem_req)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_crtc_mem_req(bp, controller_id, enable);
+}
+
+static enum bp_result bios_parser_external_encoder_control(
+	struct dc_bios *dcb,
+	struct bp_external_encoder_control *cntl)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.external_encoder_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.external_encoder_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_enable_disp_power_gating(
+	struct dc_bios *dcb,
+	enum controller_id controller_id,
+	enum bp_pipe_control_action action)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_disp_power_gating)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
+		action);
+}
+
+static bool bios_parser_is_device_id_supported(
+	struct dc_bios *dcb,
+	struct device_id id)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	uint32_t mask = get_support_mask_for_device_id(id);
+
+	return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0;
+}
+
+static enum bp_result bios_parser_crt_control(
+	struct dc_bios *dcb,
+	enum engine_id engine_id,
+	bool enable,
+	uint32_t pixel_clock)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	uint8_t standard;
+
+	if (!bp->cmd_tbl.dac1_encoder_control &&
+		engine_id == ENGINE_ID_DACA)
+		return BP_RESULT_FAILURE;
+	if (!bp->cmd_tbl.dac2_encoder_control &&
+		engine_id == ENGINE_ID_DACB)
+		return BP_RESULT_FAILURE;
+	/* validate params */
+	switch (engine_id) {
+	case ENGINE_ID_DACA:
+	case ENGINE_ID_DACB:
+		break;
+	default:
+		/* unsupported engine */
+		return BP_RESULT_FAILURE;
+	}
+
+	standard = ATOM_DAC1_PS2; /* == ATOM_DAC2_PS2 */
+
+	if (enable) {
+		if (engine_id == ENGINE_ID_DACA) {
+			bp->cmd_tbl.dac1_encoder_control(bp, enable,
+				pixel_clock, standard);
+			if (bp->cmd_tbl.dac1_output_control != NULL)
+				bp->cmd_tbl.dac1_output_control(bp, enable);
+		} else {
+			bp->cmd_tbl.dac2_encoder_control(bp, enable,
+				pixel_clock, standard);
+			if (bp->cmd_tbl.dac2_output_control != NULL)
+				bp->cmd_tbl.dac2_output_control(bp, enable);
+		}
+	} else {
+		if (engine_id == ENGINE_ID_DACA) {
+			if (bp->cmd_tbl.dac1_output_control != NULL)
+				bp->cmd_tbl.dac1_output_control(bp, enable);
+			bp->cmd_tbl.dac1_encoder_control(bp, enable,
+				pixel_clock, standard);
+		} else {
+			if (bp->cmd_tbl.dac2_output_control != NULL)
+				bp->cmd_tbl.dac2_output_control(bp, enable);
+			bp->cmd_tbl.dac2_encoder_control(bp, enable,
+				pixel_clock, standard);
+		}
+	}
+
+	return BP_RESULT_OK;
+}
+
+static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	ATOM_COMMON_RECORD_HEADER *header;
+	uint32_t offset;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+			!header->ucRecordSize)
+			break;
+
+		if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType
+			&& sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize)
+			return (ATOM_HPD_INT_RECORD *) header;
+
+		offset += header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+/**
+ * Get I2C information of input object id
+ *
+ * search all records to find the ATOM_I2C_RECORD_TYPE record IR
+ */
+static ATOM_I2C_RECORD *get_i2c_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	ATOM_COMMON_RECORD_HEADER *record_header;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER();
+		/* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!record_header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == record_header->ucRecordType ||
+			0 == record_header->ucRecordSize)
+			break;
+
+		if (ATOM_I2C_RECORD_TYPE == record_header->ucRecordType &&
+			sizeof(ATOM_I2C_RECORD) <=
+			record_header->ucRecordSize) {
+			return (ATOM_I2C_RECORD *)record_header;
+		}
+
+		offset += record_header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+
+static enum bp_result get_ss_info_from_ss_info_table(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info);
+static enum bp_result get_ss_info_from_tbl(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info);
+/**
+ * bios_parser_get_spread_spectrum_info
+ * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
+ * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
+ * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,
+ * there is only one entry for each signal /ss id.  However, there is
+ * no planning of supporting multiple spread Sprectum entry for EverGreen
+ * @param [in] this
+ * @param [in] signal, ASSignalType to be converted to info index
+ * @param [in] index, number of entries that match the converted info index
+ * @param [out] ss_info, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_get_spread_spectrum_info(
+	struct dc_bios *dcb,
+	enum as_signal_type signal,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	uint32_t clk_id_ss = 0;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision tbl_revision;
+
+	if (!ss_info) /* check for bad input */
+		return BP_RESULT_BADINPUT;
+	/* signal translation */
+	clk_id_ss = signal_to_ss_id(signal);
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		if (!index)
+			return get_ss_info_from_ss_info_table(bp, clk_id_ss,
+				ss_info);
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+		DATA_TABLES(ASIC_InternalSS_Info));
+	get_atom_data_table_revision(header, &tbl_revision);
+
+	switch (tbl_revision.major) {
+	case 2:
+		switch (tbl_revision.minor) {
+		case 1:
+			/* there can not be more then one entry for Internal
+			 * SS Info table version 2.1 */
+			if (!index)
+				return get_ss_info_from_tbl(bp, clk_id_ss,
+						ss_info);
+			break;
+		default:
+			break;
+		}
+		break;
+
+	case 3:
+		switch (tbl_revision.minor) {
+		case 1:
+			return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info);
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+	/* there can not be more then one entry for SS Info table */
+	return result;
+}
+
+static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *info);
+
+/**
+ * get_ss_info_from_table
+ * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info table from the VBIOS
+ * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info.
+ *
+ * @param this
+ * @param id, spread sprectrum info index
+ * @param pSSinfo, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result get_ss_info_from_tbl(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info)
+{
+	if (!ss_info) /* check for bad input, if ss_info is not NULL */
+		return BP_RESULT_BADINPUT;
+	/* for SS_Info table only support DP and LVDS */
+	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
+		return get_ss_info_from_ss_info_table(bp, id, ss_info);
+	else
+		return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id,
+			ss_info);
+}
+
+/**
+ * get_ss_info_from_internal_ss_info_tbl_V2_1
+ * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1
+ * from the VBIOS
+ * There will not be multiple entry for Ver 2.1
+ *
+ * @param id, spread sprectrum info index
+ * @param pSSinfo, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *info)
+{
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header;
+	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
+	uint32_t tbl_size, i;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return result;
+
+	header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
+		DATA_TABLES(ASIC_InternalSS_Info));
+
+	dm_memset(info, 0, sizeof(struct spread_spectrum_info));
+
+	tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+					/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
+					&(header->asSpreadSpectrum[0]);
+	for (i = 0; i < tbl_size; i++) {
+		result = BP_RESULT_NORECORD;
+
+		if (tbl[i].ucClockIndication != (uint8_t)id)
+			continue;
+
+		if (ATOM_EXTERNAL_SS_MASK
+			& tbl[i].ucSpreadSpectrumMode) {
+			info->type.EXTERNAL = true;
+		}
+		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
+			& tbl[i].ucSpreadSpectrumMode) {
+			info->type.CENTER_MODE = true;
+		}
+		info->type.STEP_AND_DELAY_INFO = false;
+		/* convert [10KHz] into [KHz] */
+		info->target_clock_range =
+			le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
+		info->spread_spectrum_percentage =
+			(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
+		info->spread_spectrum_range =
+			(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
+		result = BP_RESULT_OK;
+		break;
+	}
+
+	return result;
+
+}
+
+/**
+ * get_ss_info_from_ss_info_table
+ * Get spread sprectrum information from the SS_Info table from the VBIOS
+ * if the pointer to info is NULL, indicate the caller what to know the number
+ * of entries that matches the id
+ * for, the SS_Info table, there should not be more than 1 entry match.
+ *
+ * @param [in] id, spread sprectrum id
+ * @param [out] pSSinfo, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result get_ss_info_from_ss_info_table(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info)
+{
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	ATOM_SPREAD_SPECTRUM_INFO *tbl;
+	ATOM_COMMON_TABLE_HEADER *header;
+	uint32_t table_size;
+	uint32_t i;
+	uint32_t id_local = SS_ID_UNKNOWN;
+	struct atom_data_revision revision;
+
+	/* exist of the SS_Info table */
+	/* check for bad input, pSSinfo can not be NULL */
+	if (!DATA_TABLES(SS_Info) || !ss_info)
+		return result;
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));
+	get_atom_data_table_revision(header, &revision);
+
+	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
+
+	if (1 != revision.major || 2 > revision.minor)
+		return result;
+
+	/* have to convert from Internal_SS format to SS_Info format */
+	switch (id) {
+	case ASIC_INTERNAL_SS_ON_DP:
+		id_local = SS_ID_DP1;
+		break;
+	case ASIC_INTERNAL_SS_ON_LVDS:
+	{
+		struct embedded_panel_info panel_info;
+
+		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
+				== BP_RESULT_OK)
+			id_local = panel_info.ss_id;
+		break;
+	}
+	default:
+		break;
+	}
+
+	if (id_local == SS_ID_UNKNOWN)
+		return result;
+
+	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
+			sizeof(ATOM_COMMON_TABLE_HEADER)) /
+					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
+
+	for (i = 0; i < table_size; i++) {
+		if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)
+			continue;
+
+		dm_memset(ss_info, 0, sizeof(struct spread_spectrum_info));
+
+		if (ATOM_EXTERNAL_SS_MASK &
+				tbl->asSS_Info[i].ucSpreadSpectrumType)
+			ss_info->type.EXTERNAL = true;
+
+		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &
+				tbl->asSS_Info[i].ucSpreadSpectrumType)
+			ss_info->type.CENTER_MODE = true;
+
+		ss_info->type.STEP_AND_DELAY_INFO = true;
+		ss_info->spread_spectrum_percentage =
+			(uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);
+		ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;
+		ss_info->step_and_delay_info.delay =
+			tbl->asSS_Info[i].ucSS_Delay;
+		ss_info->step_and_delay_info.recommended_ref_div =
+			tbl->asSS_Info[i].ucRecommendedRef_Div;
+		ss_info->spread_spectrum_range =
+			(uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;
+
+		/* there will be only one entry for each display type in SS_info
+		 * table */
+		result = BP_RESULT_OK;
+		break;
+	}
+
+	return result;
+}
+static enum bp_result get_embedded_panel_info_v1_2(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info);
+static enum bp_result get_embedded_panel_info_v1_3(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info);
+
+static enum bp_result bios_parser_get_embedded_panel_info(
+	struct dc_bios *dcb,
+	struct embedded_panel_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_COMMON_TABLE_HEADER *hdr;
+
+	if (!DATA_TABLES(LCD_Info))
+		return BP_RESULT_FAILURE;
+
+	hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));
+
+	if (!hdr)
+		return BP_RESULT_BADBIOSTABLE;
+
+	switch (hdr->ucTableFormatRevision) {
+	case 1:
+		switch (hdr->ucTableContentRevision) {
+		case 0:
+		case 1:
+		case 2:
+			return get_embedded_panel_info_v1_2(bp, info);
+		case 3:
+			return get_embedded_panel_info_v1_3(bp, info);
+		default:
+			break;
+		}
+		default:
+			break;
+	}
+
+	return BP_RESULT_FAILURE;
+}
+
+static enum bp_result get_embedded_panel_info_v1_2(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info)
+{
+	ATOM_LVDS_INFO_V12 *lvds;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(LVDS_Info))
+		return BP_RESULT_UNSUPPORTED;
+
+	lvds =
+		GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
+
+	if (!lvds)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != lvds->sHeader.ucTableFormatRevision
+		|| 2 > lvds->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	dm_memset(info, 0, sizeof(struct embedded_panel_info));
+
+	/* We need to convert from 10KHz units into KHz units*/
+	info->lcd_timing.pixel_clk =
+		le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
+	/* usHActive does not include borders, according to VBIOS team*/
+	info->lcd_timing.horizontal_addressable =
+		le16_to_cpu(lvds->sLCDTiming.usHActive);
+	/* usHBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now.  May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.horizontal_blanking_time =
+			le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
+	/* usVActive does not include borders, according to VBIOS team*/
+	info->lcd_timing.vertical_addressable =
+			le16_to_cpu(lvds->sLCDTiming.usVActive);
+	/* usVBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now. May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.vertical_blanking_time =
+		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
+	info->lcd_timing.horizontal_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
+	info->lcd_timing.horizontal_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
+	info->lcd_timing.vertical_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
+	info->lcd_timing.vertical_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
+	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
+	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
+	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
+	info->lcd_timing.misc_info.H_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
+	info->lcd_timing.misc_info.V_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
+	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
+	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
+	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
+	info->lcd_timing.misc_info.COMPOSITE_SYNC =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
+	info->lcd_timing.misc_info.INTERLACE =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
+	info->lcd_timing.misc_info.DOUBLE_CLOCK =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
+	info->ss_id = lvds->ucSS_Id;
+
+	{
+		uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
+		/* Get minimum supported refresh rate*/
+		if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
+			info->supported_rr.REFRESH_RATE_30HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
+			info->supported_rr.REFRESH_RATE_40HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
+			info->supported_rr.REFRESH_RATE_48HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
+			info->supported_rr.REFRESH_RATE_50HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
+			info->supported_rr.REFRESH_RATE_60HZ = 1;
+	}
+
+	/*Drr panel support can be reported by VBIOS*/
+	if (LCDPANEL_CAP_DRR_SUPPORTED
+			& lvds->ucLCDPanel_SpecialHandlingCap)
+		info->drr_enabled = 1;
+
+	if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
+
+	if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.RGB888 = true;
+
+	info->lcd_timing.misc_info.GREY_LEVEL =
+		(uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
+			lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
+
+	if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.SPATIAL = true;
+
+	if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.TEMPORAL = true;
+
+	if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.API_ENABLED = true;
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_embedded_panel_info_v1_3(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info)
+{
+	ATOM_LCD_INFO_V13 *lvds;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(LCD_Info))
+		return BP_RESULT_UNSUPPORTED;
+
+	lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
+
+	if (!lvds)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (!((1 == lvds->sHeader.ucTableFormatRevision)
+			&& (3 <= lvds->sHeader.ucTableContentRevision)))
+		return BP_RESULT_UNSUPPORTED;
+
+	dm_memset(info, 0, sizeof(struct embedded_panel_info));
+
+	/* We need to convert from 10KHz units into KHz units */
+	info->lcd_timing.pixel_clk =
+			le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
+	/* usHActive does not include borders, according to VBIOS team */
+	info->lcd_timing.horizontal_addressable =
+			le16_to_cpu(lvds->sLCDTiming.usHActive);
+	/* usHBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now.  May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.horizontal_blanking_time =
+		le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
+	/* usVActive does not include borders, according to VBIOS team*/
+	info->lcd_timing.vertical_addressable =
+		le16_to_cpu(lvds->sLCDTiming.usVActive);
+	/* usVBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now. May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.vertical_blanking_time =
+		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
+	info->lcd_timing.horizontal_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
+	info->lcd_timing.horizontal_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
+	info->lcd_timing.vertical_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
+	info->lcd_timing.vertical_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
+	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
+	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
+	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
+	info->lcd_timing.misc_info.H_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
+	info->lcd_timing.misc_info.V_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
+	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
+	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
+	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
+	info->lcd_timing.misc_info.COMPOSITE_SYNC =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
+	info->lcd_timing.misc_info.INTERLACE =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
+	info->lcd_timing.misc_info.DOUBLE_CLOCK =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
+	info->ss_id = lvds->ucSS_Id;
+
+	/* Drr panel support can be reported by VBIOS*/
+	if (LCDPANEL_CAP_V13_DRR_SUPPORTED
+			& lvds->ucLCDPanel_SpecialHandlingCap)
+		info->drr_enabled = 1;
+
+	/* Get supported refresh rate*/
+	if (info->drr_enabled == 1) {
+		uint8_t min_rr =
+				lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
+		uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
+
+		if (min_rr != 0) {
+			if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_30HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_40HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_48HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_50HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_60HZ = 1;
+		} else {
+			if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
+				info->supported_rr.REFRESH_RATE_30HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
+				info->supported_rr.REFRESH_RATE_40HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
+				info->supported_rr.REFRESH_RATE_48HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
+				info->supported_rr.REFRESH_RATE_50HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
+				info->supported_rr.REFRESH_RATE_60HZ = 1;
+		}
+	}
+
+	if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
+		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
+
+	if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
+		info->lcd_timing.misc_info.RGB888 = true;
+
+	info->lcd_timing.misc_info.GREY_LEVEL =
+			(uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
+				lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
+
+	return BP_RESULT_OK;
+}
+
+/**
+ * bios_parser_get_encoder_cap_info
+ *
+ * @brief
+ *  Get encoder capability information of input object id
+ *
+ * @param object_id, Object id
+ * @param object_id, encoder cap information structure
+ *
+ * @return Bios parser result code
+ *
+ */
+static enum bp_result bios_parser_get_encoder_cap_info(
+	struct dc_bios *dcb,
+	struct graphics_object_id object_id,
+	struct bp_encoder_cap_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object;
+	ATOM_ENCODER_CAP_RECORD *record = NULL;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, object_id);
+
+	if (!object)
+		return BP_RESULT_BADINPUT;
+
+	record = get_encoder_cap_record(bp, object);
+	if (!record)
+		return BP_RESULT_NORECORD;
+
+	info->DP_HBR2_CAP = record->usHBR2Cap;
+	info->DP_HBR2_EN = record->usHBR2En;
+	return BP_RESULT_OK;
+}
+
+/**
+ * get_encoder_cap_record
+ *
+ * @brief
+ *  Get encoder cap record for the object
+ *
+ * @param object, ATOM object
+ *
+ * @return atom encoder cap record
+ *
+ * @note
+ *  search all records to find the ATOM_ENCODER_CAP_RECORD record
+ */
+static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	ATOM_COMMON_RECORD_HEADER *header;
+	uint32_t offset;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+					+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		offset += header->ucRecordSize;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				!header->ucRecordSize)
+			break;
+
+		if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
+			continue;
+
+		if (sizeof(ATOM_ENCODER_CAP_RECORD) <= header->ucRecordSize)
+			return (ATOM_ENCODER_CAP_RECORD *)header;
+	}
+
+	return NULL;
+}
+
+/**
+ * bios_parser_get_din_connector_info
+ * @brief
+ *   Get GPIO record for the DIN connector, this GPIO tells whether there is a
+ *    CV dumb dongle
+ *   attached to the DIN connector to perform load detection for the the
+ *    appropriate signal
+ *
+ * @param id - DIN connector object id
+ * @param info             - GPIO record infor
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_get_din_connector_info(
+	struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct din_connector_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_COMMON_RECORD_HEADER *header;
+	ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD *record = NULL;
+	ATOM_OBJECT *object;
+	uint32_t offset;
+	enum bp_result result = BP_RESULT_NORECORD;
+
+	/* no output buffer provided */
+	if (!info) {
+		BREAK_TO_DEBUGGER(); /* Invalid output buffer */
+		return BP_RESULT_BADINPUT;
+	}
+
+	object = get_bios_object(bp, id);
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */;
+		return BP_RESULT_BADINPUT;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+						+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header) {
+			result = BP_RESULT_BADBIOSTABLE;
+			break;
+		}
+
+		offset += header->ucRecordSize;
+
+		/* get out of the loop if no more records */
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				!header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD_TYPE !=
+				header->ucRecordType)
+			continue;
+
+		if (sizeof(ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD)
+				> header->ucRecordSize)
+			continue;
+
+		record = (ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD *)header;
+		result = BP_RESULT_OK;
+		break;
+	}
+
+	/* return if the record not found */
+	if (result != BP_RESULT_OK)
+		return result;
+
+	info->gpio_id = record->ucGPIOID;
+	info->gpio_tv_active_state = (record->ucTVActiveState != 0);
+
+	return result;
+}
+
+static uint32_t get_ss_entry_number(
+	struct bios_parser *bp,
+	uint32_t id);
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
+	struct bios_parser *bp,
+	uint32_t id);
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
+	struct bios_parser *bp,
+	uint32_t id);
+static uint32_t get_ss_entry_number_from_ss_info_tbl(
+	struct bios_parser *bp,
+	uint32_t id);
+
+/**
+ * BiosParserObject::GetNumberofSpreadSpectrumEntry
+ * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
+ * the VBIOS that match the SSid (to be converted from signal)
+ *
+ * @param[in] signal, ASSignalType to be converted to SSid
+ * @return number of SS Entry that match the signal
+ */
+static uint32_t bios_parser_get_ss_entry_number(
+	struct dc_bios *dcb,
+	enum as_signal_type signal)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	uint32_t ss_id = 0;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision;
+
+	ss_id = signal_to_ss_id(signal);
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+			DATA_TABLES(ASIC_InternalSS_Info));
+	get_atom_data_table_revision(header, &revision);
+
+	switch (revision.major) {
+	case 2:
+		switch (revision.minor) {
+		case 1:
+			return get_ss_entry_number(bp, ss_id);
+		default:
+			break;
+		}
+		break;
+	case 3:
+		switch (revision.minor) {
+		case 1:
+			return
+				get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
+						bp, ss_id);
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+
+/**
+ * get_ss_entry_number_from_ss_info_tbl
+ * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
+ *
+ * @note There can only be one entry for each id for SS_Info Table
+ *
+ * @param [in] id, spread spectrum id
+ * @return number of SS Entry that match the id
+ */
+static uint32_t get_ss_entry_number_from_ss_info_tbl(
+	struct bios_parser *bp,
+	uint32_t id)
+{
+	ATOM_SPREAD_SPECTRUM_INFO *tbl;
+	ATOM_COMMON_TABLE_HEADER *header;
+	uint32_t table_size;
+	uint32_t i;
+	uint32_t number = 0;
+	uint32_t id_local = SS_ID_UNKNOWN;
+	struct atom_data_revision revision;
+
+	/* SS_Info table exist */
+	if (!DATA_TABLES(SS_Info))
+		return number;
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+			DATA_TABLES(SS_Info));
+	get_atom_data_table_revision(header, &revision);
+
+	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
+			DATA_TABLES(SS_Info));
+
+	if (1 != revision.major || 2 > revision.minor)
+		return number;
+
+	/* have to convert from Internal_SS format to SS_Info format */
+	switch (id) {
+	case ASIC_INTERNAL_SS_ON_DP:
+		id_local = SS_ID_DP1;
+		break;
+	case ASIC_INTERNAL_SS_ON_LVDS: {
+		struct embedded_panel_info panel_info;
+
+		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
+				== BP_RESULT_OK)
+			id_local = panel_info.ss_id;
+		break;
+	}
+	default:
+		break;
+	}
+
+	if (id_local == SS_ID_UNKNOWN)
+		return number;
+
+	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
+			sizeof(ATOM_COMMON_TABLE_HEADER)) /
+					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
+
+	for (i = 0; i < table_size; i++)
+		if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
+			number = 1;
+			break;
+		}
+
+	return number;
+}
+
+
+/**
+ * get_ss_entry_number
+ * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info table from the VBIOS
+ * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info.
+ *
+ * @param id, spread sprectrum info index
+ * @return Bios parser result code
+ */
+static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
+{
+	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
+		return get_ss_entry_number_from_ss_info_tbl(bp, id);
+
+	return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
+}
+
+/**
+ * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
+ * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
+ * Ver 2.1 from the VBIOS
+ * There will not be multiple entry for Ver 2.1
+ *
+ * @param id, spread sprectrum info index
+ * @return number of SS Entry that match the id
+ */
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
+	struct bios_parser *bp,
+	uint32_t id)
+{
+	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
+	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
+	uint32_t size;
+	uint32_t i;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return 0;
+
+	header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
+			DATA_TABLES(ASIC_InternalSS_Info));
+
+	size = (le16_to_cpu(header_include->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+						/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
+				&header_include->asSpreadSpectrum[0];
+	for (i = 0; i < size; i++)
+		if (tbl[i].ucClockIndication == (uint8_t)id)
+			return 1;
+
+	return 0;
+}
+/**
+ * get_ss_entry_number_from_internal_ss_info_table_V3_1
+ * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
+ * the VBIOS that matches id
+ *
+ * @param[in]  id, spread sprectrum id
+ * @return number of SS Entry that match the id
+ */
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
+	struct bios_parser *bp,
+	uint32_t id)
+{
+	uint32_t number = 0;
+	ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
+	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
+	uint32_t size;
+	uint32_t i;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return number;
+
+	header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
+			DATA_TABLES(ASIC_InternalSS_Info));
+	size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
+			sizeof(ATOM_COMMON_TABLE_HEADER)) /
+					sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
+				&header_include->asSpreadSpectrum[0];
+
+	for (i = 0; i < size; i++)
+		if (tbl[i].ucClockIndication == (uint8_t)id)
+			number++;
+
+	return number;
+}
+
+static ATOM_FAKE_EDID_PATCH_RECORD *get_faked_edid_record(
+	struct bios_parser *bp)
+{
+	uint32_t size;
+	uint8_t *record;
+	ATOM_LVDS_INFO_V12 *info;
+
+	if (!DATA_TABLES(LVDS_Info))
+		return NULL;
+
+	info = GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
+
+	if (!info)
+		return NULL;
+
+	if (1 != info->sHeader.ucTableFormatRevision
+			|| 2 > info->sHeader.ucTableContentRevision)
+		return NULL;
+
+	if (!le16_to_cpu(info->usExtInfoTableOffset))
+		return NULL;
+
+	record = GET_IMAGE(uint8_t, DATA_TABLES(LVDS_Info)
+			+ le16_to_cpu(info->usExtInfoTableOffset));
+
+	if (!record)
+		return NULL;
+
+	for (;;) {
+		if (ATOM_RECORD_END_TYPE == *record)
+			return NULL;
+
+		if (LCD_FAKE_EDID_PATCH_RECORD_TYPE == *record)
+			break;
+
+		size = get_record_size(record);
+
+		if (!size)
+			return NULL;
+
+		record += size;
+	}
+
+	return (ATOM_FAKE_EDID_PATCH_RECORD *)record;
+}
+
+static enum bp_result bios_parser_get_faked_edid_len(
+	struct dc_bios *dcb,
+	uint32_t *len)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_FAKE_EDID_PATCH_RECORD *edid_record = get_faked_edid_record(bp);
+
+	if (!edid_record)
+		return BP_RESULT_NORECORD;
+
+	*len = get_edid_size(edid_record);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_faked_edid_buf(
+	struct dc_bios *dcb,
+	uint8_t *buff,
+	uint32_t len)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_FAKE_EDID_PATCH_RECORD *edid_record = get_faked_edid_record(bp);
+	uint32_t edid_size;
+
+	if (!edid_record)
+		return BP_RESULT_NORECORD;
+
+	edid_size = get_edid_size(edid_record);
+
+	if (len < edid_size)
+		return BP_RESULT_BADINPUT; /* buffer not big enough to fill */
+
+	dm_memmove(buff, &edid_record->ucFakeEDIDString, edid_size);
+
+	return BP_RESULT_OK;
+}
+
+/**
+ * bios_parser_get_gpio_pin_info
+ * Get GpioPin information of input gpio id
+ *
+ * @param gpio_id, GPIO ID
+ * @param info, GpioPin information structure
+ * @return Bios parser result code
+ * @note
+ *  to get the GPIO PIN INFO, we need:
+ *  1. get the GPIO_ID from other object table, see GetHPDInfo()
+ *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
+ *  offset/mask
+ */
+static enum bp_result bios_parser_get_gpio_pin_info(
+	struct dc_bios *dcb,
+	uint32_t gpio_id,
+	struct gpio_pin_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_GPIO_PIN_LUT *header;
+	uint32_t count = 0;
+	uint32_t i = 0;
+
+	if (!DATA_TABLES(GPIO_Pin_LUT))
+		return BP_RESULT_BADBIOSTABLE;
+
+	header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT));
+	if (!header)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT)
+			> le16_to_cpu(header->sHeader.usStructureSize))
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != header->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	count = (le16_to_cpu(header->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
+	for (i = 0; i < count; ++i) {
+		if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
+			continue;
+
+		info->offset =
+			(uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
+		info->offset_y = info->offset + 2;
+		info->offset_en = info->offset + 1;
+		info->offset_mask = info->offset - 1;
+
+		info->mask = (uint32_t) (1 <<
+			header->asGPIO_Pin[i].ucGpioPinBitShift);
+		info->mask_y = info->mask + 2;
+		info->mask_en = info->mask + 1;
+		info->mask_mask = info->mask - 1;
+
+		return BP_RESULT_OK;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+/**
+ * BiosParserObject::EnumEmbeddedPanelPatchMode
+ * Get embedded panel patch mode
+ *
+ * @param index, mode index
+ * @param info, embedded panel patch mode structure
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_enum_embedded_panel_patch_mode(
+	struct dc_bios *dcb,
+	uint32_t index,
+	struct embedded_panel_patch_mode *mode)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	uint32_t record_size;
+	uint32_t record_index;
+	uint8_t *record;
+	ATOM_LVDS_INFO_V12 *info;
+	ATOM_PATCH_RECORD_MODE *mode_record;
+	ATOM_MASTER_LIST_OF_DATA_TABLES *list_of_tables;
+
+	if (!mode)
+		return BP_RESULT_BADINPUT;
+
+	list_of_tables = &bp->master_data_tbl->ListOfDataTables;
+	if (!list_of_tables->LVDS_Info)
+		return BP_RESULT_UNSUPPORTED;
+
+	info = GET_IMAGE(ATOM_LVDS_INFO_V12, list_of_tables->LVDS_Info);
+
+	if (!info)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != info->sHeader.ucTableFormatRevision
+			|| 2 > info->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	if (!le16_to_cpu(info->usExtInfoTableOffset))
+		return BP_RESULT_UNSUPPORTED;
+
+	record = GET_IMAGE(uint8_t, list_of_tables->LVDS_Info +
+			le16_to_cpu(info->usExtInfoTableOffset));
+
+	if (!record)
+		return BP_RESULT_BADBIOSTABLE;
+
+	for (record_index = 0;;) {
+		if (ATOM_RECORD_END_TYPE == *record)
+			return BP_RESULT_NORECORD;
+
+		if (LCD_MODE_PATCH_RECORD_MODE_TYPE == *record) {
+			if (record_index == index)
+				break;
+			record_index++;
+		}
+
+		record_size = get_record_size(record);
+
+		if (!record_size)
+			return BP_RESULT_NORECORD;
+
+		record += record_size;
+	}
+
+	mode_record = (ATOM_PATCH_RECORD_MODE *) record;
+
+	mode->width = le16_to_cpu(mode_record->usHDisp);
+	mode->height = le16_to_cpu(mode_record->usVDisp);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
+	ATOM_I2C_RECORD *record,
+	struct graphics_object_i2c_info *info)
+{
+	ATOM_GPIO_I2C_INFO *header;
+	uint32_t count = 0;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	/* get the GPIO_I2C info */
+	if (!DATA_TABLES(GPIO_I2C_Info))
+		return BP_RESULT_BADBIOSTABLE;
+
+	header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
+	if (!header)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
+			> le16_to_cpu(header->sHeader.usStructureSize))
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != header->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	/* get data count */
+	count = (le16_to_cpu(header->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+	if (count < record->sucI2cId.bfI2C_LineMux)
+		return BP_RESULT_BADBIOSTABLE;
+
+	/* get the GPIO_I2C_INFO */
+	info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
+	info->i2c_line = record->sucI2cId.bfI2C_LineMux;
+	info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
+	info->i2c_slave_address = record->ucI2CAddr;
+
+	info->gpio_info.clk_mask_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
+	info->gpio_info.clk_en_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
+	info->gpio_info.clk_y_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
+	info->gpio_info.clk_a_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
+	info->gpio_info.data_mask_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
+	info->gpio_info.data_en_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
+	info->gpio_info.data_y_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
+	info->gpio_info.data_a_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
+
+	info->gpio_info.clk_mask_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
+	info->gpio_info.clk_en_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkEnShift;
+	info->gpio_info.clk_y_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
+	info->gpio_info.clk_a_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
+	info->gpio_info.data_mask_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
+	info->gpio_info.data_en_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataEnShift;
+	info->gpio_info.data_y_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
+	info->gpio_info.data_a_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
+
+	return BP_RESULT_OK;
+}
+
+static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
+	struct graphics_object_id id)
+{
+	uint32_t offset;
+	ATOM_OBJECT_TABLE *tbl;
+	uint32_t i;
+
+	switch (id.type) {
+	case OBJECT_TYPE_ENCODER:
+		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
+		break;
+
+	case OBJECT_TYPE_CONNECTOR:
+		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+		break;
+
+	case OBJECT_TYPE_ROUTER:
+		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
+		break;
+
+	case OBJECT_TYPE_GENERIC:
+		if (bp->object_info_tbl.revision.minor < 3)
+			return NULL;
+		offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
+		break;
+
+	default:
+		return NULL;
+	}
+
+	offset += bp->object_info_tbl_offset;
+
+	tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
+	if (!tbl)
+		return NULL;
+
+	for (i = 0; i < tbl->ucNumberOfObjects; i++)
+		if (dal_graphics_object_id_is_equal(id,
+				object_id_from_bios_object_id(
+						le16_to_cpu(tbl->asObjects[i].usObjectID))))
+			return &tbl->asObjects[i];
+
+	return NULL;
+}
+
+static uint32_t get_dest_obj_list(struct bios_parser *bp,
+	ATOM_OBJECT *object, uint16_t **id_list)
+{
+	uint32_t offset;
+	uint8_t *number;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+						+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	offset += sizeof(uint8_t);
+	offset += sizeof(uint16_t) * (*number);
+
+	number = GET_IMAGE(uint8_t, offset);
+	if ((!number) || (!*number))
+		return 0;
+
+	offset += sizeof(uint8_t);
+	*id_list = (uint16_t *)get_image(bp, offset,
+			*number * sizeof(uint16_t));
+
+	if (!*id_list)
+		return 0;
+
+	return *number;
+}
+
+static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
+	uint16_t **id_list)
+{
+	uint32_t offset;
+	uint8_t *number;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+					+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	offset += sizeof(uint8_t);
+	*id_list = (uint16_t *)get_image(bp, offset,
+			*number * sizeof(uint16_t));
+
+	if (!*id_list)
+		return 0;
+
+	return *number;
+}
+
+static uint32_t get_dst_number_from_object(struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	uint8_t *number;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+					+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	offset += sizeof(uint8_t);
+	offset += sizeof(uint16_t) * (*number);
+
+	number = GET_IMAGE(uint8_t, offset);
+
+	if (!number)
+		return 0;
+
+	return *number;
+}
+
+static uint8_t *get_image(struct bios_parser *bp,
+	uint32_t offset,
+	uint32_t size)
+{
+	if (bp->bios && offset + size < bp->bios_size)
+		return bp->bios + offset;
+	else
+		return NULL;
+}
+
+static uint32_t get_record_size(uint8_t *record)
+{
+	switch (*record) {
+	case LCD_MODE_PATCH_RECORD_MODE_TYPE:
+		return sizeof(ATOM_PATCH_RECORD_MODE);
+
+	case LCD_RTS_RECORD_TYPE:
+		return sizeof(ATOM_LCD_RTS_RECORD);
+
+	case LCD_CAP_RECORD_TYPE:
+		return sizeof(ATOM_LCD_MODE_CONTROL_CAP);
+
+	case LCD_FAKE_EDID_PATCH_RECORD_TYPE: {
+		ATOM_FAKE_EDID_PATCH_RECORD *fake_record =
+				(ATOM_FAKE_EDID_PATCH_RECORD *) record;
+		uint32_t edid_size = get_edid_size(fake_record);
+
+		return sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + edid_size
+				- sizeof(fake_record->ucFakeEDIDString);
+	}
+
+	case LCD_PANEL_RESOLUTION_RECORD_TYPE:
+		return sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
+
+	default:
+		return 0;
+	}
+}
+
+static uint32_t get_edid_size(const ATOM_FAKE_EDID_PATCH_RECORD *edid)
+{
+	uint32_t length = edid->ucFakeEDIDLength;
+
+	if (length < 128)
+		length = length * 128;
+
+	return length;
+}
+
+static struct graphics_object_id object_id_from_bios_object_id(
+	uint32_t bios_object_id)
+{
+	enum object_type type;
+	enum object_enum_id enum_id;
+	struct graphics_object_id go_id = { 0 };
+
+	type = object_type_from_bios_object_id(bios_object_id);
+
+	if (OBJECT_TYPE_UNKNOWN == type)
+		return go_id;
+
+	enum_id = enum_id_from_bios_object_id(bios_object_id);
+
+	if (ENUM_ID_UNKNOWN == enum_id)
+		return go_id;
+
+	go_id = dal_graphics_object_id_init(
+			id_from_bios_object_id(type, bios_object_id), enum_id, type);
+
+	return go_id;
+}
+
+static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK)
+				>> OBJECT_TYPE_SHIFT;
+	enum object_type object_type;
+
+	switch (bios_object_type) {
+	case GRAPH_OBJECT_TYPE_GPU:
+		object_type = OBJECT_TYPE_GPU;
+		break;
+	case GRAPH_OBJECT_TYPE_ENCODER:
+		object_type = OBJECT_TYPE_ENCODER;
+		break;
+	case GRAPH_OBJECT_TYPE_CONNECTOR:
+		object_type = OBJECT_TYPE_CONNECTOR;
+		break;
+	case GRAPH_OBJECT_TYPE_ROUTER:
+		object_type = OBJECT_TYPE_ROUTER;
+		break;
+	case GRAPH_OBJECT_TYPE_GENERIC:
+		object_type = OBJECT_TYPE_GENERIC;
+		break;
+	default:
+		object_type = OBJECT_TYPE_UNKNOWN;
+		break;
+	}
+
+	return object_type;
+}
+
+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_enum_id =
+			(bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+	enum object_enum_id id;
+
+	switch (bios_enum_id) {
+	case GRAPH_OBJECT_ENUM_ID1:
+		id = ENUM_ID_1;
+		break;
+	case GRAPH_OBJECT_ENUM_ID2:
+		id = ENUM_ID_2;
+		break;
+	case GRAPH_OBJECT_ENUM_ID3:
+		id = ENUM_ID_3;
+		break;
+	case GRAPH_OBJECT_ENUM_ID4:
+		id = ENUM_ID_4;
+		break;
+	case GRAPH_OBJECT_ENUM_ID5:
+		id = ENUM_ID_5;
+		break;
+	case GRAPH_OBJECT_ENUM_ID6:
+		id = ENUM_ID_6;
+		break;
+	case GRAPH_OBJECT_ENUM_ID7:
+		id = ENUM_ID_7;
+		break;
+	default:
+		id = ENUM_ID_UNKNOWN;
+		break;
+	}
+
+	return id;
+}
+
+static uint32_t id_from_bios_object_id(enum object_type type,
+	uint32_t bios_object_id)
+{
+	switch (type) {
+	case OBJECT_TYPE_GPU:
+		return gpu_id_from_bios_object_id(bios_object_id);
+	case OBJECT_TYPE_ENCODER:
+		return (uint32_t)encoder_id_from_bios_object_id(bios_object_id);
+	case OBJECT_TYPE_CONNECTOR:
+		return (uint32_t)connector_id_from_bios_object_id(
+				bios_object_id);
+	case OBJECT_TYPE_GENERIC:
+		return generic_id_from_bios_object_id(bios_object_id);
+	default:
+		return 0;
+	}
+}
+
+static enum connector_id connector_id_from_bios_object_id(
+	uint32_t bios_object_id)
+{
+	uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id);
+
+	enum connector_id id;
+
+	switch (bios_connector_id) {
+	case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I:
+		id = CONNECTOR_ID_SINGLE_LINK_DVII;
+		break;
+	case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I:
+		id = CONNECTOR_ID_DUAL_LINK_DVII;
+		break;
+	case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D:
+		id = CONNECTOR_ID_SINGLE_LINK_DVID;
+		break;
+	case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D:
+		id = CONNECTOR_ID_DUAL_LINK_DVID;
+		break;
+	case CONNECTOR_OBJECT_ID_VGA:
+		id = CONNECTOR_ID_VGA;
+		break;
+	case CONNECTOR_OBJECT_ID_HDMI_TYPE_A:
+		id = CONNECTOR_ID_HDMI_TYPE_A;
+		break;
+	case CONNECTOR_OBJECT_ID_LVDS:
+		id = CONNECTOR_ID_LVDS;
+		break;
+	case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR:
+		id = CONNECTOR_ID_PCIE;
+		break;
+	case CONNECTOR_OBJECT_ID_HARDCODE_DVI:
+		id = CONNECTOR_ID_HARDCODE_DVI;
+		break;
+	case CONNECTOR_OBJECT_ID_DISPLAYPORT:
+		id = CONNECTOR_ID_DISPLAY_PORT;
+		break;
+	case CONNECTOR_OBJECT_ID_eDP:
+		id = CONNECTOR_ID_EDP;
+		break;
+	case CONNECTOR_OBJECT_ID_MXM:
+		id = CONNECTOR_ID_MXM;
+		break;
+	default:
+		id = CONNECTOR_ID_UNKNOWN;
+		break;
+	}
+
+	return id;
+}
+
+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id);
+	enum encoder_id id;
+
+	switch (bios_encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		id = ENCODER_ID_INTERNAL_LVDS;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+		id = ENCODER_ID_INTERNAL_TMDS1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS2:
+		id = ENCODER_ID_INTERNAL_TMDS2;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+		id = ENCODER_ID_INTERNAL_DAC1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+		id = ENCODER_ID_INTERNAL_DAC2;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		id = ENCODER_ID_INTERNAL_LVTM1;
+		break;
+	case ENCODER_OBJECT_ID_HDMI_INTERNAL:
+		id = ENCODER_ID_INTERNAL_HDMI;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		id = ENCODER_ID_INTERNAL_KLDSCP_DAC1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		id = ENCODER_ID_INTERNAL_KLDSCP_DAC2;
+		break;
+	case ENCODER_OBJECT_ID_MVPU_FPGA:
+		id = ENCODER_ID_EXTERNAL_MVPU_FPGA;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+		id = ENCODER_ID_INTERNAL_DDI;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+		id = ENCODER_ID_INTERNAL_UNIPHY;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		id = ENCODER_ID_INTERNAL_UNIPHY1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		id = ENCODER_ID_INTERNAL_UNIPHY2;
+		break;
+	case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */
+		id = ENCODER_ID_EXTERNAL_NUTMEG;
+		break;
+	case ENCODER_OBJECT_ID_TRAVIS:
+		id = ENCODER_ID_EXTERNAL_TRAVIS;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
+		id = ENCODER_ID_INTERNAL_UNIPHY3;
+		break;
+	default:
+		id = ENCODER_ID_UNKNOWN;
+		ASSERT(0);
+		break;
+	}
+
+	return id;
+}
+
+uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+}
+
+enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id);
+
+	enum generic_id id;
+
+	switch (bios_generic_id) {
+	case GENERIC_OBJECT_ID_MXM_OPM:
+		id = GENERIC_ID_MXM_OPM;
+		break;
+	case GENERIC_OBJECT_ID_GLSYNC:
+		id = GENERIC_ID_GLSYNC;
+		break;
+	case GENERIC_OBJECT_ID_STEREO_PIN:
+		id = GENERIC_ID_STEREO;
+		break;
+	default:
+		id = GENERIC_ID_UNKNOWN;
+		break;
+	}
+
+	return id;
+}
+
+static struct device_id device_type_from_device_id(uint16_t device_id)
+{
+
+	struct device_id result_device_id;
+
+	switch (device_id) {
+	case ATOM_DEVICE_LCD1_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_LCD;
+		result_device_id.enum_id = 1;
+		break;
+
+	case ATOM_DEVICE_LCD2_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_LCD;
+		result_device_id.enum_id = 2;
+		break;
+
+	case ATOM_DEVICE_CRT1_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_CRT;
+		result_device_id.enum_id = 1;
+		break;
+
+	case ATOM_DEVICE_CRT2_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_CRT;
+		result_device_id.enum_id = 2;
+		break;
+
+	case ATOM_DEVICE_DFP1_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 1;
+		break;
+
+	case ATOM_DEVICE_DFP2_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 2;
+		break;
+
+	case ATOM_DEVICE_DFP3_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 3;
+		break;
+
+	case ATOM_DEVICE_DFP4_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 4;
+		break;
+
+	case ATOM_DEVICE_DFP5_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 5;
+		break;
+
+	case ATOM_DEVICE_DFP6_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 6;
+		break;
+
+	default:
+		BREAK_TO_DEBUGGER(); /* Invalid device Id */
+		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
+		result_device_id.enum_id = 0;
+	}
+	return result_device_id;
+}
+
+static void get_atom_data_table_revision(
+	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
+	struct atom_data_revision *tbl_revision)
+{
+	if (!tbl_revision)
+		return;
+
+	/* initialize the revision to 0 which is invalid revision */
+	tbl_revision->major = 0;
+	tbl_revision->minor = 0;
+
+	if (!atom_data_tbl)
+		return;
+
+	tbl_revision->major =
+			(uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
+	tbl_revision->minor =
+			(uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
+}
+
+static uint32_t signal_to_ss_id(enum as_signal_type signal)
+{
+	uint32_t clk_id_ss = 0;
+
+	switch (signal) {
+	case AS_SIGNAL_TYPE_DVI:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
+		break;
+	case AS_SIGNAL_TYPE_HDMI:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
+		break;
+	case AS_SIGNAL_TYPE_LVDS:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
+		break;
+	case AS_SIGNAL_TYPE_DISPLAY_PORT:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
+		break;
+	case AS_SIGNAL_TYPE_GPU_PLL:
+		clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
+		break;
+	default:
+		break;
+	}
+	return clk_id_ss;
+}
+
+static uint32_t get_support_mask_for_device_id(struct device_id device_id)
+{
+	enum dal_device_type device_type = device_id.device_type;
+	uint32_t enum_id = device_id.enum_id;
+
+	switch (device_type) {
+	case DEVICE_TYPE_LCD:
+		switch (enum_id) {
+		case 1:
+			return ATOM_DEVICE_LCD1_SUPPORT;
+		case 2:
+			return ATOM_DEVICE_LCD2_SUPPORT;
+		default:
+			break;
+		}
+		break;
+		case DEVICE_TYPE_CRT:
+			switch (enum_id) {
+			case 1:
+				return ATOM_DEVICE_CRT1_SUPPORT;
+			case 2:
+				return ATOM_DEVICE_CRT2_SUPPORT;
+			default:
+				break;
+			}
+			break;
+			case DEVICE_TYPE_DFP:
+				switch (enum_id) {
+				case 1:
+					return ATOM_DEVICE_DFP1_SUPPORT;
+				case 2:
+					return ATOM_DEVICE_DFP2_SUPPORT;
+				case 3:
+					return ATOM_DEVICE_DFP3_SUPPORT;
+				case 4:
+					return ATOM_DEVICE_DFP4_SUPPORT;
+				case 5:
+					return ATOM_DEVICE_DFP5_SUPPORT;
+				case 6:
+					return ATOM_DEVICE_DFP6_SUPPORT;
+				default:
+					break;
+				}
+				break;
+				case DEVICE_TYPE_CV:
+					switch (enum_id) {
+					case 1:
+						return ATOM_DEVICE_CV_SUPPORT;
+					default:
+						break;
+					}
+					break;
+					case DEVICE_TYPE_TV:
+						switch (enum_id) {
+						case 1:
+							return ATOM_DEVICE_TV1_SUPPORT;
+						default:
+							break;
+						}
+						break;
+						default:
+							break;
+	};
+
+	/* Unidentified device ID, return empty support mask. */
+	return 0;
+}
+
+/**
+ *  HwContext interface for writing MM registers
+ */
+
+static bool i2c_read(
+	struct bios_parser *bp,
+	struct graphics_object_i2c_info *i2c_info,
+	uint8_t *buffer,
+	uint32_t length)
+{
+	struct ddc *ddc;
+	uint8_t offset[2] = { 0, 0 };
+	bool result = false;
+	struct i2c_command cmd;
+
+	ddc = dal_adapter_service_obtain_ddc_from_i2c_info(bp->as, i2c_info);
+
+	if (!ddc)
+		return result;
+
+	/*Using SW engine */
+	cmd.engine = I2C_COMMAND_ENGINE_SW;
+	cmd.speed = dal_adapter_service_get_sw_i2c_speed(bp->as);
+
+	{
+		struct i2c_payload payloads[] = {
+				{
+						.address = i2c_info->i2c_slave_address >> 1,
+						.data = offset,
+						.length = sizeof(offset),
+						.write = true
+				},
+				{
+						.address = i2c_info->i2c_slave_address >> 1,
+						.data = buffer,
+						.length = length,
+						.write = false
+				}
+		};
+
+		cmd.payloads = payloads;
+		cmd.number_of_payloads = ARRAY_SIZE(payloads);
+
+		result = dal_i2caux_submit_i2c_command(
+				dal_adapter_service_get_i2caux(bp->as),
+				ddc,
+				&cmd);
+	}
+
+	dal_adapter_service_release_ddc(bp->as, ddc);
+
+	return result;
+}
+
+/**
+ * Read external display connection info table through i2c.
+ * validate the GUID and checksum.
+ *
+ * @return enum bp_result whether all data was sucessfully read
+ */
+static enum bp_result get_ext_display_connection_info(
+	struct bios_parser *bp,
+	ATOM_OBJECT *opm_object,
+	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl)
+{
+	bool config_tbl_present = false;
+	ATOM_I2C_RECORD *i2c_record = NULL;
+	uint32_t i = 0;
+
+	if (opm_object == NULL)
+		return BP_RESULT_BADINPUT;
+
+	i2c_record = get_i2c_record(bp, opm_object);
+
+	if (i2c_record != NULL) {
+		ATOM_GPIO_I2C_INFO *gpio_i2c_header;
+		struct graphics_object_i2c_info i2c_info;
+
+		gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO,
+				bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info);
+
+		if (NULL == gpio_i2c_header)
+			return BP_RESULT_BADBIOSTABLE;
+
+		if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) !=
+				BP_RESULT_OK)
+			return BP_RESULT_BADBIOSTABLE;
+
+		if (i2c_read(
+				bp,
+				&i2c_info,
+				(uint8_t *)ext_display_connection_info_tbl,
+				sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) {
+			config_tbl_present = true;
+		}
+	}
+
+	/* Validate GUID */
+	if (config_tbl_present)
+		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) {
+			if (ext_display_connection_info_tbl->ucGuid[i]
+														!= ext_display_connection_guid[i]) {
+				config_tbl_present = false;
+				break;
+			}
+		}
+
+	/* Validate checksum */
+	if (config_tbl_present) {
+		uint8_t check_sum = 0;
+		uint8_t *buf =
+				(uint8_t *)ext_display_connection_info_tbl;
+
+		for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO);
+				i++) {
+			check_sum += buf[i];
+		}
+
+		if (check_sum != 0)
+			config_tbl_present = false;
+	}
+
+	if (config_tbl_present)
+		return BP_RESULT_OK;
+	else
+		return BP_RESULT_FAILURE;
+}
+
+/*
+ * Gets the first device ID in the same group as the given ID for enumerating.
+ * For instance, if any DFP device ID is passed, returns the device ID for DFP1.
+ *
+ * The first device ID in the same group as the passed device ID, or 0 if no
+ * matching device group found.
+ */
+static uint32_t enum_first_device_id(uint32_t dev_id)
+{
+	/* Return the first in the group that this ID belongs to. */
+	if (dev_id & ATOM_DEVICE_CRT_SUPPORT)
+		return ATOM_DEVICE_CRT1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_DFP_SUPPORT)
+		return ATOM_DEVICE_DFP1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_LCD_SUPPORT)
+		return ATOM_DEVICE_LCD1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_TV_SUPPORT)
+		return ATOM_DEVICE_TV1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_CV_SUPPORT)
+		return ATOM_DEVICE_CV_SUPPORT;
+
+	/* No group found for this device ID. */
+
+	dm_error("%s: incorrect input %d\n", __func__, dev_id);
+	/* No matching support flag for given device ID */
+	return 0;
+}
+
+/*
+ * Gets the next device ID in the group for a given device ID.
+ *
+ * The current device ID being enumerated on.
+ *
+ * The next device ID in the group, or 0 if no device exists.
+ */
+static uint32_t enum_next_dev_id(uint32_t dev_id)
+{
+	/* Get next device ID in the group. */
+	switch (dev_id) {
+	case ATOM_DEVICE_CRT1_SUPPORT:
+		return ATOM_DEVICE_CRT2_SUPPORT;
+	case ATOM_DEVICE_LCD1_SUPPORT:
+		return ATOM_DEVICE_LCD2_SUPPORT;
+	case ATOM_DEVICE_DFP1_SUPPORT:
+		return ATOM_DEVICE_DFP2_SUPPORT;
+	case ATOM_DEVICE_DFP2_SUPPORT:
+		return ATOM_DEVICE_DFP3_SUPPORT;
+	case ATOM_DEVICE_DFP3_SUPPORT:
+		return ATOM_DEVICE_DFP4_SUPPORT;
+	case ATOM_DEVICE_DFP4_SUPPORT:
+		return ATOM_DEVICE_DFP5_SUPPORT;
+	case ATOM_DEVICE_DFP5_SUPPORT:
+		return ATOM_DEVICE_DFP6_SUPPORT;
+	}
+
+	/* Done enumerating through devices. */
+	return 0;
+}
+
+/*
+ * Returns the new device tag record for patched BIOS object.
+ *
+ * [IN] pExtDisplayPath - External display path to copy device tag from.
+ * [IN] deviceSupport - Bit vector for device ID support flags.
+ * [OUT] pDeviceTag - Device tag structure to fill with patched data.
+ *
+ * True if a compatible device ID was found, false otherwise.
+ */
+static bool get_patched_device_tag(
+	struct bios_parser *bp,
+	EXT_DISPLAY_PATH *ext_display_path,
+	uint32_t device_support,
+	ATOM_CONNECTOR_DEVICE_TAG *device_tag)
+{
+	uint32_t dev_id;
+	/* Use fallback behaviour if not supported. */
+	if (!bp->remap_device_tags) {
+		device_tag->ulACPIDeviceEnum =
+				cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
+		device_tag->usDeviceID =
+				cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceTag));
+		return true;
+	}
+
+	/* Find the first unused in the same group. */
+	dev_id = enum_first_device_id(le16_to_cpu(ext_display_path->usDeviceTag));
+	while (dev_id != 0) {
+		/* Assign this device ID if supported. */
+		if ((device_support & dev_id) != 0) {
+			device_tag->ulACPIDeviceEnum =
+					cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
+			device_tag->usDeviceID = cpu_to_le16((USHORT) dev_id);
+			return true;
+		}
+
+		dev_id = enum_next_dev_id(dev_id);
+	}
+
+	/* No compatible device ID found. */
+	return false;
+}
+
+/*
+ * Adds a device tag to a BIOS object's device tag record if there is
+ * matching device ID supported.
+ *
+ * pObject - Pointer to the BIOS object to add the device tag to.
+ * pExtDisplayPath - Display path to retrieve base device ID from.
+ * pDeviceSupport - Pointer to bit vector for supported device IDs.
+ */
+static void add_device_tag_from_ext_display_path(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object,
+	EXT_DISPLAY_PATH *ext_display_path,
+	uint32_t *device_support)
+{
+	/* Get device tag record for object. */
+	ATOM_CONNECTOR_DEVICE_TAG *device_tag = NULL;
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD *device_tag_record = NULL;
+	enum bp_result result =
+			bios_parser_get_device_tag_record(
+					bp, object, &device_tag_record);
+
+	if ((le16_to_cpu(ext_display_path->usDeviceTag) != CONNECTOR_OBJECT_ID_NONE)
+			&& (result == BP_RESULT_OK)) {
+		uint8_t index;
+
+		if ((device_tag_record->ucNumberOfDevice == 1) &&
+				(le16_to_cpu(device_tag_record->asDeviceTag[0].usDeviceID) == 0)) {
+			/*Workaround bug in current VBIOS releases where
+			 * ucNumberOfDevice = 1 but there is no actual device
+			 * tag data. This w/a is temporary until the updated
+			 * VBIOS is distributed. */
+			device_tag_record->ucNumberOfDevice =
+					device_tag_record->ucNumberOfDevice - 1;
+		}
+
+		/* Attempt to find a matching device ID. */
+		index = device_tag_record->ucNumberOfDevice;
+		device_tag = &device_tag_record->asDeviceTag[index];
+		if (get_patched_device_tag(
+				bp,
+				ext_display_path,
+				*device_support,
+				device_tag)) {
+			/* Update cached device support to remove assigned ID.
+			 */
+			*device_support &= ~le16_to_cpu(device_tag->usDeviceID);
+			device_tag_record->ucNumberOfDevice++;
+		}
+	}
+}
+
+/*
+ * Read out a single EXT_DISPLAY_PATH from the external display connection info
+ * table. The specific entry in the table is determined by the enum_id passed
+ * in.
+ *
+ * EXT_DISPLAY_PATH describing a single Configuration table entry
+ */
+
+#define INVALID_CONNECTOR 0xffff
+
+static EXT_DISPLAY_PATH *get_ext_display_path_entry(
+	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *config_table,
+	uint32_t bios_object_id)
+{
+	EXT_DISPLAY_PATH *ext_display_path;
+	uint32_t ext_display_path_index =
+			((bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT) - 1;
+
+	if (ext_display_path_index >= MAX_NUMBER_OF_EXT_DISPLAY_PATH)
+		return NULL;
+
+	ext_display_path = &config_table->sPath[ext_display_path_index];
+
+	if (le16_to_cpu(ext_display_path->usDeviceConnector) == INVALID_CONNECTOR)
+		ext_display_path->usDeviceConnector = cpu_to_le16(0);
+
+	return ext_display_path;
+}
+
+/*
+ * Get AUX/DDC information of input object id
+ *
+ * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
+ * IR
+ */
+static ATOM_CONNECTOR_AUXDDC_LUT_RECORD *get_ext_connector_aux_ddc_lut_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	ATOM_COMMON_RECORD_HEADER *header;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER();
+		/* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+					+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				0 == header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE ==
+				header->ucRecordType &&
+				sizeof(ATOM_CONNECTOR_AUXDDC_LUT_RECORD) <=
+				header->ucRecordSize)
+			return (ATOM_CONNECTOR_AUXDDC_LUT_RECORD *)(header);
+
+		offset += header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+/*
+ * Get AUX/DDC information of input object id
+ *
+ * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
+ * IR
+ */
+static ATOM_CONNECTOR_HPDPIN_LUT_RECORD *get_ext_connector_hpd_pin_lut_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	ATOM_COMMON_RECORD_HEADER *header;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER();
+		/* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+					+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				0 == header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE ==
+				header->ucRecordType &&
+				sizeof(ATOM_CONNECTOR_HPDPIN_LUT_RECORD) <=
+				header->ucRecordSize)
+			return (ATOM_CONNECTOR_HPDPIN_LUT_RECORD *)header;
+
+		offset += header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+/*
+ * Check whether we need to patch the VBIOS connector info table with
+ * data from an external display connection info table.  This is
+ * necessary to support MXM boards with an OPM (output personality
+ * module).  With these designs, the VBIOS connector info table
+ * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
+ * the external connection info table through i2c and then looks up the
+ * connector ID to find the real connector type (e.g. DFP1).
+ *
+ */
+static enum bp_result patch_bios_image_from_ext_display_connection_info(
+	struct bios_parser *bp)
+{
+	ATOM_OBJECT_TABLE *connector_tbl;
+	uint32_t connector_tbl_offset;
+	struct graphics_object_id object_id;
+	ATOM_OBJECT *object;
+	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ext_display_connection_info_tbl;
+	EXT_DISPLAY_PATH *ext_display_path;
+	ATOM_CONNECTOR_AUXDDC_LUT_RECORD *aux_ddc_lut_record = NULL;
+	ATOM_I2C_RECORD *i2c_record = NULL;
+	ATOM_CONNECTOR_HPDPIN_LUT_RECORD *hpd_pin_lut_record = NULL;
+	ATOM_HPD_INT_RECORD *hpd_record = NULL;
+	ATOM_OBJECT_TABLE *encoder_table;
+	uint32_t encoder_table_offset;
+	ATOM_OBJECT *opm_object = NULL;
+	uint32_t i = 0;
+	struct graphics_object_id opm_object_id =
+			dal_graphics_object_id_init(
+					GENERIC_ID_MXM_OPM,
+					ENUM_ID_1,
+					OBJECT_TYPE_GENERIC);
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD *dev_tag_record;
+	uint32_t cached_device_support =
+			le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport);
+
+	uint32_t dst_number;
+	uint16_t *dst_object_id_list;
+
+	opm_object = get_bios_object(bp, opm_object_id);
+	if (!opm_object)
+		return BP_RESULT_UNSUPPORTED;
+
+	dm_memset(&ext_display_connection_info_tbl, 0,
+			sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO));
+
+	connector_tbl_offset = bp->object_info_tbl_offset
+			+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+	connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
+
+	/* Read Connector info table from EEPROM through i2c */
+	if (get_ext_display_connection_info(
+			bp,
+			opm_object,
+			&ext_display_connection_info_tbl) != BP_RESULT_OK) {
+		if (bp->headless_no_opm) {
+			/* Failed to read OPM, remove all non-CF connectors. */
+			for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) {
+				object = &connector_tbl->asObjects[i];
+				object_id = object_id_from_bios_object_id(
+						le16_to_cpu(object->usObjectID));
+				if (OBJECT_TYPE_CONNECTOR == object_id.type)
+					object->usObjectID = cpu_to_le16(0);
+			}
+
+			return BP_RESULT_OK;
+		}
+
+		dal_logger_write(bp->ctx->logger,
+				LOG_MAJOR_BIOS,
+				LOG_MINOR_BIOS_CMD_TABLE,
+				"%s: Failed to read Connection Info Table", __func__);
+		return BP_RESULT_UNSUPPORTED;
+	}
+
+	/* Get pointer to AUX/DDC and HPD LUTs */
+	aux_ddc_lut_record =
+			get_ext_connector_aux_ddc_lut_record(bp, opm_object);
+	hpd_pin_lut_record =
+			get_ext_connector_hpd_pin_lut_record(bp, opm_object);
+
+	if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL))
+		return BP_RESULT_UNSUPPORTED;
+
+	/* Cache support bits for currently unmapped device types. */
+	if (bp->remap_device_tags) {
+		for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) {
+			uint32_t j;
+			/* Remove support for all non-MXM connectors. */
+			object = &connector_tbl->asObjects[i];
+			object_id = object_id_from_bios_object_id(
+					le16_to_cpu(object->usObjectID));
+			if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
+					(CONNECTOR_ID_MXM == object_id.id))
+				continue;
+
+			/* Remove support for all device tags. */
+			if (bios_parser_get_device_tag_record(
+					bp, object, &dev_tag_record) != BP_RESULT_OK)
+				continue;
+
+			for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) {
+				ATOM_CONNECTOR_DEVICE_TAG *device_tag =
+						&dev_tag_record->asDeviceTag[j];
+				cached_device_support &=
+						~le16_to_cpu(device_tag->usDeviceID);
+			}
+		}
+	}
+
+	/* Find all MXM connector objects and patch them with connector info
+	 * from the external display connection info table. */
+	for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
+		uint32_t j;
+
+		object = &connector_tbl->asObjects[i];
+		object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
+		if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
+				(CONNECTOR_ID_MXM != object_id.id))
+			continue;
+
+		/* Get the correct connection info table entry based on the enum
+		 * id. */
+		ext_display_path = get_ext_display_path_entry(
+				&ext_display_connection_info_tbl,
+				le16_to_cpu(object->usObjectID));
+		if (!ext_display_path)
+			return BP_RESULT_FAILURE;
+
+		/* Patch device connector ID */
+		object->usObjectID =
+				cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector));
+
+		/* Patch device tag, ulACPIDeviceEnum. */
+		add_device_tag_from_ext_display_path(
+				bp,
+				object,
+				ext_display_path,
+				&cached_device_support);
+
+		/* Patch HPD info */
+		if (ext_display_path->ucExtHPDPINLutIndex <
+				MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) {
+			hpd_record = get_hpd_record(bp, object);
+			if (hpd_record) {
+				uint8_t index =
+						ext_display_path->ucExtHPDPINLutIndex;
+				hpd_record->ucHPDIntGPIOID =
+						hpd_pin_lut_record->ucHPDPINMap[index];
+			} else {
+				BREAK_TO_DEBUGGER();
+				/* Invalid hpd record */
+				return BP_RESULT_FAILURE;
+			}
+		}
+
+		/* Patch I2C/AUX info */
+		if (ext_display_path->ucExtHPDPINLutIndex <
+				MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) {
+			i2c_record = get_i2c_record(bp, object);
+			if (i2c_record) {
+				uint8_t index =
+						ext_display_path->ucExtAUXDDCLutIndex;
+				i2c_record->sucI2cId =
+						aux_ddc_lut_record->ucAUXDDCMap[index];
+			} else {
+				BREAK_TO_DEBUGGER();
+				/* Invalid I2C record */
+				return BP_RESULT_FAILURE;
+			}
+		}
+
+		/* Merge with other MXM connectors that map to the same physical
+		 * connector. */
+		for (j = i + 1;
+				j < connector_tbl->ucNumberOfObjects; j++) {
+			ATOM_OBJECT *next_object;
+			struct graphics_object_id next_object_id;
+			EXT_DISPLAY_PATH *next_ext_display_path;
+
+			next_object = &connector_tbl->asObjects[j];
+			next_object_id = object_id_from_bios_object_id(
+					le16_to_cpu(next_object->usObjectID));
+
+			if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) &&
+					(CONNECTOR_ID_MXM == next_object_id.id))
+				continue;
+
+			next_ext_display_path = get_ext_display_path_entry(
+					&ext_display_connection_info_tbl,
+					le16_to_cpu(next_object->usObjectID));
+
+			if (next_ext_display_path == NULL)
+				return BP_RESULT_FAILURE;
+
+			/* Merge if using same connector. */
+			if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) ==
+					le16_to_cpu(ext_display_path->usDeviceConnector)) &&
+					(le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) {
+				/* Clear duplicate connector from table. */
+				next_object->usObjectID = cpu_to_le16(0);
+				add_device_tag_from_ext_display_path(
+						bp,
+						object,
+						ext_display_path,
+						&cached_device_support);
+			}
+		}
+	}
+
+	/* Find all encoders which have an MXM object as their destination.
+	 *  Replace the MXM object with the real connector Id from the external
+	 *  display connection info table */
+
+	encoder_table_offset = bp->object_info_tbl_offset
+			+ le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
+	encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
+
+	for (i = 0; i < encoder_table->ucNumberOfObjects; i++) {
+		uint32_t j;
+
+		object = &encoder_table->asObjects[i];
+
+		dst_number = get_dest_obj_list(bp, object, &dst_object_id_list);
+
+		for (j = 0; j < dst_number; j++) {
+			object_id = object_id_from_bios_object_id(
+					dst_object_id_list[j]);
+
+			if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
+					(CONNECTOR_ID_MXM != object_id.id))
+				continue;
+
+			/* Get the correct connection info table entry based on
+			 * the enum id. */
+			ext_display_path =
+					get_ext_display_path_entry(
+							&ext_display_connection_info_tbl,
+							dst_object_id_list[j]);
+
+			if (ext_display_path == NULL)
+				return BP_RESULT_FAILURE;
+
+			dst_object_id_list[j] =
+					le16_to_cpu(ext_display_path->usDeviceConnector);
+		}
+	}
+
+	return BP_RESULT_OK;
+}
+
+/*
+ * Check whether we need to patch the VBIOS connector info table with
+ * data from an external display connection info table.  This is
+ * necessary to support MXM boards with an OPM (output personality
+ * module).  With these designs, the VBIOS connector info table
+ * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
+ * the external connection info table through i2c and then looks up the
+ * connector ID to find the real connector type (e.g. DFP1).
+ *
+ */
+
+static void process_ext_display_connection_info(struct bios_parser *bp)
+{
+	ATOM_OBJECT_TABLE *connector_tbl;
+	uint32_t connector_tbl_offset;
+	struct graphics_object_id object_id;
+	ATOM_OBJECT *object;
+	bool mxm_connector_found = false;
+	bool null_entry_found = false;
+	uint32_t i = 0;
+
+	connector_tbl_offset = bp->object_info_tbl_offset +
+			le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+	connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
+
+	/* Look for MXM connectors to determine whether we need patch the VBIOS
+	 * connector info table. Look for null entries to determine whether we
+	 * need to compact connector table. */
+	for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
+		object = &connector_tbl->asObjects[i];
+		object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
+
+		if ((OBJECT_TYPE_CONNECTOR == object_id.type) &&
+				(CONNECTOR_ID_MXM == object_id.id)) {
+			/* Once we found MXM connector - we can break */
+			mxm_connector_found = true;
+			break;
+		} else if (OBJECT_TYPE_CONNECTOR != object_id.type) {
+			/* We need to continue looping - to check if MXM
+			 * connector present */
+			null_entry_found = true;
+		}
+	}
+
+	/* Patch BIOS image */
+	if (mxm_connector_found || null_entry_found) {
+		uint32_t connectors_num = 0;
+		uint8_t *original_bios;
+		/* Step 1: Replace bios image with the new copy which will be
+		 * patched */
+		bp->bios_local_image = dm_alloc(bp->ctx, bp->bios_size);
+		if (bp->bios_local_image == NULL) {
+			BREAK_TO_DEBUGGER();
+			/* Failed to alloc bp->bios_local_image */
+			return;
+		}
+
+		dm_memmove(bp->bios_local_image, bp->bios, bp->bios_size);
+		original_bios = bp->bios;
+		bp->bios = bp->bios_local_image;
+		connector_tbl =
+				GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
+
+		/* Step 2: (only if MXM connector found) Patch BIOS image with
+		 * info from external module */
+		if (mxm_connector_found &&
+				patch_bios_image_from_ext_display_connection_info(bp) !=
+						BP_RESULT_OK) {
+			/* Patching the bios image has failed. We will copy
+			 * again original image provided and afterwards
+			 * only remove null entries */
+			dm_memmove(
+					bp->bios_local_image,
+					original_bios,
+					bp->bios_size);
+		}
+
+		/* Step 3: Compact connector table (remove null entries, valid
+		 * entries moved to beginning) */
+		for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
+			object = &connector_tbl->asObjects[i];
+			object_id = object_id_from_bios_object_id(
+					le16_to_cpu(object->usObjectID));
+
+			if (OBJECT_TYPE_CONNECTOR != object_id.type)
+				continue;
+
+			if (i != connectors_num) {
+				dm_memmove(
+						&connector_tbl->
+						asObjects[connectors_num],
+						object,
+						sizeof(ATOM_OBJECT));
+			}
+			++connectors_num;
+		}
+		connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num;
+	}
+}
+
+static void bios_parser_post_init(struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	process_ext_display_connection_info(bp);
+}
+
+static bool bios_parser_is_accelerated_mode(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	return bp->bios_helper->is_accelerated_mode(
+			bp->ctx);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+	return false;
+#endif
+}
+
+/**
+ * bios_parser_set_scratch_connected
+ *
+ * @brief
+ *  update VBIOS scratch register about connected displays
+ *
+ * @param
+ *  bool - update scratch register or just prepare info to be updated
+ *  bool - connection state
+ *  const ConnectorDeviceTagInfo* - pointer to device type and enum ID
+ */
+static void bios_parser_set_scratch_connected(
+	struct dc_bios *dcb,
+	struct graphics_object_id connector_id,
+	bool connected,
+	const struct connector_device_tag_info *device_tag)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_connected(
+			bp->ctx,
+			connector_id, connected, device_tag);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+/**
+ * bios_parser_set_scratch_critical_state
+ *
+ * @brief
+ *  update critical state bit in VBIOS scratch register
+ *
+ * @param
+ *  bool - to set or reset state
+ */
+static void bios_parser_set_scratch_critical_state(
+	struct dc_bios *dcb,
+	bool state)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_critical_state(
+			bp->ctx, state);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+static void bios_parser_set_scratch_acc_mode_change(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_acc_mode_change(
+			bp->ctx);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+/**
+ * bios_parser_prepare_scratch_active_and_requested
+ *
+ * @brief
+ *  update VBIOS scratch registers about active and requested displays
+ *
+ * @param
+ *  enum controller_id - controller Id
+ *  enum signal_type signal - signal type used on display
+ *  const struct connector_device_tag_info * - pointer to display type and
+ *  enum Id
+ */
+static void bios_parser_prepare_scratch_active_and_requested(
+	struct dc_bios *dcb,
+	enum controller_id controller_id,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->prepare_scratch_active_and_requested(
+			bp->ctx,
+			&bp->vbios_helper_data,
+			controller_id,
+			signal,
+			device_tag);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+static void bios_parser_set_scratch_active_and_requested(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_active_and_requested(
+			bp->ctx,
+			&bp->vbios_helper_data);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+/*
+ * get_integrated_info_v8
+ *
+ * @brief
+ * Get V8 integrated BIOS information
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result get_integrated_info_v8(
+	struct bios_parser *bp,
+	struct integrated_info *info)
+{
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
+	uint32_t i;
+
+	info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
+			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
+
+	if (info_v8 != NULL) {
+		info->boot_up_engine_clock =
+				le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
+		info->dentist_vco_freq =
+				le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
+		info->boot_up_uma_clock =
+				le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
+
+		for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->disp_clk_voltage[i].max_supported_clk =
+					le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
+							ulMaximumSupportedCLK) * 10;
+			info->disp_clk_voltage[i].voltage_index =
+					le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
+		}
+
+		info->boot_up_req_display_vector =
+				le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
+		info->gpu_cap_info =
+				le32_to_cpu(info_v8->ulGPUCapInfo);
+
+		/*
+		 * system_config: Bit[0] = 0 : PCIE power gating disabled
+		 *                       = 1 : PCIE power gating enabled
+		 *                Bit[1] = 0 : DDR-PLL shut down disabled
+		 *                       = 1 : DDR-PLL shut down enabled
+		 *                Bit[2] = 0 : DDR-PLL power down disabled
+		 *                       = 1 : DDR-PLL power down enabled
+		 */
+		info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
+		info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
+		info->boot_up_nb_voltage =
+				le16_to_cpu(info_v8->usBootUpNBVoltage);
+		info->ext_disp_conn_info_offset =
+				le16_to_cpu(info_v8->usExtDispConnInfoOffset);
+		info->memory_type = info_v8->ucMemoryType;
+		info->ma_channel_number = info_v8->ucUMAChannelNumber;
+		info->gmc_restore_reset_time =
+				le32_to_cpu(info_v8->ulGMCRestoreResetTime);
+
+		info->minimum_n_clk =
+				le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
+		for (i = 1; i < 4; ++i)
+			info->minimum_n_clk =
+					info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
+							info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
+
+		info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
+		info->ddr_dll_power_up_time =
+				le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
+		info->ddr_pll_power_up_time =
+				le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
+		info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
+		info->lvds_ss_percentage =
+				le16_to_cpu(info_v8->usLvdsSSPercentage);
+		info->lvds_sspread_rate_in_10hz =
+				le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
+		info->hdmi_ss_percentage =
+				le16_to_cpu(info_v8->usHDMISSPercentage);
+		info->hdmi_sspread_rate_in_10hz =
+				le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
+		info->dvi_ss_percentage =
+				le16_to_cpu(info_v8->usDVISSPercentage);
+		info->dvi_sspread_rate_in_10_hz =
+				le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
+
+		info->max_lvds_pclk_freq_in_single_link =
+				le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
+		info->lvds_misc = info_v8->ucLvdsMisc;
+		info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
+				info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
+		info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
+				info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
+		info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
+				info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
+		info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
+				info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
+		info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
+				info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
+		info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
+				info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
+		info->lvds_off_to_on_delay_in_4ms =
+				info_v8->ucLVDSOffToOnDelay_in4Ms;
+		info->lvds_bit_depth_control_val =
+				le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
+
+		for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->avail_s_clk[i].supported_s_clk =
+					le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
+			info->avail_s_clk[i].voltage_index =
+					le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
+			info->avail_s_clk[i].voltage_id =
+					le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
+		}
+
+		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
+			info->ext_disp_conn_info.gu_id[i] =
+					info_v8->sExtDispConnInfo.ucGuid[i];
+		}
+
+		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
+			info->ext_disp_conn_info.path[i].device_connector_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
+
+			info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
+
+			info->ext_disp_conn_info.path[i].device_tag =
+					le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
+			info->ext_disp_conn_info.path[i].device_acpi_enum =
+					le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
+			info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
+					info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
+			info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
+					info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
+			info->ext_disp_conn_info.path[i].channel_mapping.raw =
+					info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
+		}
+		info->ext_disp_conn_info.checksum =
+				info_v8->sExtDispConnInfo.ucChecksum;
+
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*
+ * get_integrated_info_v8
+ *
+ * @brief
+ * Get V8 integrated BIOS information
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result get_integrated_info_v9(
+	struct bios_parser *bp,
+	struct integrated_info *info)
+{
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
+	uint32_t i;
+
+	info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
+			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
+
+	if (info_v9 != NULL) {
+		info->boot_up_engine_clock =
+				le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
+		info->dentist_vco_freq =
+				le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
+		info->boot_up_uma_clock =
+				le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
+
+		for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->disp_clk_voltage[i].max_supported_clk =
+					le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
+			info->disp_clk_voltage[i].voltage_index =
+					le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
+		}
+
+		info->boot_up_req_display_vector =
+				le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
+		info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
+
+		/*
+		 * system_config: Bit[0] = 0 : PCIE power gating disabled
+		 *                       = 1 : PCIE power gating enabled
+		 *                Bit[1] = 0 : DDR-PLL shut down disabled
+		 *                       = 1 : DDR-PLL shut down enabled
+		 *                Bit[2] = 0 : DDR-PLL power down disabled
+		 *                       = 1 : DDR-PLL power down enabled
+		 */
+		info->system_config = le32_to_cpu(info_v9->ulSystemConfig);
+		info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
+		info->boot_up_nb_voltage =
+				le16_to_cpu(info_v9->usBootUpNBVoltage);
+		info->ext_disp_conn_info_offset =
+				le16_to_cpu(info_v9->usExtDispConnInfoOffset);
+		info->memory_type = info_v9->ucMemoryType;
+		info->ma_channel_number = info_v9->ucUMAChannelNumber;
+		info->gmc_restore_reset_time =
+				le32_to_cpu(info_v9->ulGMCRestoreResetTime);
+
+		info->minimum_n_clk =
+				le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
+		for (i = 1; i < 4; ++i)
+			info->minimum_n_clk =
+					info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
+							info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
+
+		info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
+		info->ddr_dll_power_up_time =
+				le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
+		info->ddr_pll_power_up_time =
+				le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
+		info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
+		info->lvds_ss_percentage =
+				le16_to_cpu(info_v9->usLvdsSSPercentage);
+		info->lvds_sspread_rate_in_10hz =
+				le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
+		info->hdmi_ss_percentage =
+				le16_to_cpu(info_v9->usHDMISSPercentage);
+		info->hdmi_sspread_rate_in_10hz =
+				le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
+		info->dvi_ss_percentage =
+				le16_to_cpu(info_v9->usDVISSPercentage);
+		info->dvi_sspread_rate_in_10_hz =
+				le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
+
+		info->max_lvds_pclk_freq_in_single_link =
+				le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
+		info->lvds_misc = info_v9->ucLvdsMisc;
+		info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
+				info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
+		info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
+				info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
+		info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
+				info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
+		info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
+				info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
+		info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
+				info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
+		info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
+				info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
+		info->lvds_off_to_on_delay_in_4ms =
+				info_v9->ucLVDSOffToOnDelay_in4Ms;
+		info->lvds_bit_depth_control_val =
+				le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
+
+		for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->avail_s_clk[i].supported_s_clk =
+					le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
+			info->avail_s_clk[i].voltage_index =
+					le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
+			info->avail_s_clk[i].voltage_id =
+					le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
+		}
+
+		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
+			info->ext_disp_conn_info.gu_id[i] =
+					info_v9->sExtDispConnInfo.ucGuid[i];
+		}
+
+		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
+			info->ext_disp_conn_info.path[i].device_connector_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
+
+			info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
+
+			info->ext_disp_conn_info.path[i].device_tag =
+					le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
+			info->ext_disp_conn_info.path[i].device_acpi_enum =
+					le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
+			info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
+					info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
+			info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
+					info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
+			info->ext_disp_conn_info.path[i].channel_mapping.raw =
+					info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
+		}
+		info->ext_disp_conn_info.checksum =
+				info_v9->sExtDispConnInfo.ucChecksum;
+
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*
+ * construct_integrated_info
+ *
+ * @brief
+ * Get integrated BIOS information based on table revision
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result construct_integrated_info(
+	struct bios_parser *bp,
+	struct integrated_info *info)
+{
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision;
+
+	if (info != NULL &&
+			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
+		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+				bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
+
+		get_atom_data_table_revision(header, &revision);
+
+		/* Don't need to check major revision as they are all 1 */
+		switch (revision.minor) {
+		case 8:
+			result = get_integrated_info_v8(bp, info);
+			break;
+		case 9:
+			result = get_integrated_info_v9(bp, info);
+			break;
+		default:
+			return result;
+
+		}
+	}
+
+	/* Sort voltage table from low to high*/
+	if (result == BP_RESULT_OK) {
+		struct clock_voltage_caps temp = {0, 0};
+		uint32_t i;
+		uint32_t j;
+
+		for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+			for (j = i; j > 0; --j) {
+				if (
+						info->disp_clk_voltage[j].max_supported_clk <
+						info->disp_clk_voltage[j-1].max_supported_clk) {
+					/* swap j and j - 1*/
+					temp = info->disp_clk_voltage[j-1];
+					info->disp_clk_voltage[j-1] =
+							info->disp_clk_voltage[j];
+					info->disp_clk_voltage[j] = temp;
+				}
+			}
+		}
+
+	}
+
+	return result;
+}
+
+
+static struct integrated_info *bios_parser_create_integrated_info(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct integrated_info *info = NULL;
+
+	info = dm_alloc(bp->ctx, sizeof(struct integrated_info));
+
+	if (info == NULL) {
+		ASSERT_CRITICAL(0);
+		return NULL;
+	}
+
+	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
+		return info;
+
+	dm_free(bp->ctx, info);
+
+	return NULL;
+}
+
+static void bios_parser_destroy_integrated_info(
+	struct dc_bios *dcb,
+	struct integrated_info **info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (info == NULL) {
+		ASSERT_CRITICAL(0);
+		return;
+	}
+
+	if (*info != NULL) {
+		dm_free(bp->ctx, *info);
+		*info = NULL;
+	}
+}
+
+/******************************************************************************
+ * Stub-functions */
+static bool is_lid_open(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static bool is_lid_status_changed(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static bool is_display_config_changed(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static void set_scratch_lcd_scale(
+	struct dc_bios *bios,
+	enum lcd_scale scale)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static enum lcd_scale get_scratch_lcd_scale(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return LCD_SCALE_NONE;
+}
+
+static void get_bios_event_info(
+	struct dc_bios *bios,
+	struct bios_event_info *info)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static void update_requested_backlight_level(
+	struct dc_bios *bios,
+	uint32_t backlight_8bit)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static uint32_t get_requested_backlight_level(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return 0;
+}
+
+static void take_backlight_control(
+	struct dc_bios *bios,
+	bool cntl)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static bool is_active_display(
+	struct dc_bios *bios,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static enum controller_id get_embedded_display_controller_id(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return CONTROLLER_ID_UNDEFINED;
+}
+
+static uint32_t get_embedded_display_refresh_rate(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return 0;
+}
+
+/******************************************************************************/
+
+static const struct dc_vbios_funcs vbios_funcs = {
+	.get_connectors_number = bios_parser_get_connectors_number,
+
+	.power_down = bios_parser_power_down,
+
+	.power_up = bios_parser_power_up,
+
+	.get_encoders_number = bios_parser_get_encoders_number,
+
+	.get_oem_ddc_lines_number = bios_parser_get_oem_ddc_lines_number,
+
+	.get_encoder_id = bios_parser_get_encoder_id,
+
+	.get_connector_id = bios_parser_get_connector_id,
+
+	.get_src_number = bios_parser_get_src_number,
+
+	.get_dst_number = bios_parser_get_dst_number,
+
+	.get_gpio_record = bios_parser_get_gpio_record,
+
+	.get_src_obj = bios_parser_get_src_obj,
+
+	.get_dst_obj = bios_parser_get_dst_obj,
+
+	.get_i2c_info = bios_parser_get_i2c_info,
+
+	.get_oem_ddc_info = bios_parser_get_oem_ddc_info,
+
+	.get_voltage_ddc_info = bios_parser_get_voltage_ddc_info,
+
+	.get_thermal_ddc_info = bios_parser_get_thermal_ddc_info,
+
+	.get_hpd_info = bios_parser_get_hpd_info,
+
+	.get_device_tag = bios_parser_get_device_tag,
+
+	.get_firmware_info = bios_parser_get_firmware_info,
+
+	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
+
+	.get_ss_entry_number = bios_parser_get_ss_entry_number,
+
+	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
+
+	.enum_embedded_panel_patch_mode = bios_parser_enum_embedded_panel_patch_mode,
+
+	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
+
+	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
+
+	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
+
+	.get_faked_edid_len = bios_parser_get_faked_edid_len,
+
+	.get_faked_edid_buf = bios_parser_get_faked_edid_buf,
+
+	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,
+
+	.get_din_connector_info = bios_parser_get_din_connector_info,
+
+	.is_lid_open = is_lid_open,
+
+	.is_lid_status_changed = is_lid_status_changed,
+
+	.is_display_config_changed = is_display_config_changed,
+
+	.is_accelerated_mode = bios_parser_is_accelerated_mode,
+
+	.set_scratch_lcd_scale = set_scratch_lcd_scale,
+
+	.get_scratch_lcd_scale = get_scratch_lcd_scale,
+
+	.get_bios_event_info = get_bios_event_info,
+
+	.update_requested_backlight_level = update_requested_backlight_level,
+
+	.get_requested_backlight_level = get_requested_backlight_level,
+
+	.take_backlight_control = take_backlight_control,
+
+	.is_active_display = is_active_display,
+
+	.get_embedded_display_controller_id = get_embedded_display_controller_id,
+
+	.get_embedded_display_refresh_rate = get_embedded_display_refresh_rate,
+
+	.set_scratch_connected = bios_parser_set_scratch_connected,
+
+	.prepare_scratch_active_and_requested = bios_parser_prepare_scratch_active_and_requested,
+
+	.set_scratch_active_and_requested = bios_parser_set_scratch_active_and_requested,
+
+	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
+
+	.set_scratch_acc_mode_change = bios_parser_set_scratch_acc_mode_change,
+
+	.is_device_id_supported = bios_parser_is_device_id_supported,
+
+	/* COMMANDS */
+	.encoder_control = bios_parser_encoder_control,
+
+	.transmitter_control = bios_parser_transmitter_control,
+
+	.crt_control = bios_parser_crt_control,
+
+	.enable_crtc = bios_parser_enable_crtc,
+
+	.adjust_pixel_clock = bios_parser_adjust_pixel_clock,
+
+	.set_pixel_clock = bios_parser_set_pixel_clock,
+
+	.set_dce_clock = bios_parser_set_dce_clock,
+
+	.enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,
+
+	.program_crtc_timing = bios_parser_program_crtc_timing,
+
+	.blank_crtc = bios_parser_blank_crtc,
+
+	.set_overscan = bios_parser_set_overscan,
+
+	.crtc_source_select = bios_parser_crtc_source_select,
+
+	.program_display_engine_pll = bios_parser_program_display_engine_pll,
+
+	.get_divider_for_target_display_clock = bios_parser_get_divider_for_target_display_clock,
+
+	.dac_load_detect = bios_parser_dac_load_detect,
+
+	.enable_memory_requests = bios_parser_enable_memory_requests,
+
+	.external_encoder_control = bios_parser_external_encoder_control,
+
+	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
+
+	.post_init = bios_parser_post_init,
+
+	.create_integrated_info = bios_parser_create_integrated_info,
+
+	.destroy_integrated_info = bios_parser_destroy_integrated_info,
+};
+
+static bool bios_parser_construct(
+	struct bios_parser *bp,
+	struct bp_init_data *init,
+	struct adapter_service *as)
+{
+	uint16_t *rom_header_offset = NULL;
+	ATOM_ROM_HEADER *rom_header = NULL;
+	ATOM_OBJECT_HEADER *object_info_tbl;
+	enum dce_version dce_version;
+
+	if (!as)
+		return false;
+
+	if (!init)
+		return false;
+
+	if (!init->bios)
+		return false;
+
+	bp->base.funcs = &vbios_funcs;
+
+	dce_version = dal_adapter_service_get_dce_version(as);
+	bp->ctx = init->ctx;
+	bp->as = as;
+	bp->bios = init->bios;
+	bp->bios_size = bp->bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
+	bp->bios_local_image = NULL;
+	bp->lcd_scale = LCD_SCALE_UNKNOWN;
+
+	rom_header_offset =
+	GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
+
+	if (!rom_header_offset)
+		return false;
+
+	rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);
+
+	if (!rom_header)
+		return false;
+
+	bp->master_data_tbl =
+	GET_IMAGE(ATOM_MASTER_DATA_TABLE,
+		rom_header->usMasterDataTableOffset);
+
+	if (!bp->master_data_tbl)
+		return false;
+
+	bp->object_info_tbl_offset = DATA_TABLES(Object_Header);
+
+	if (!bp->object_info_tbl_offset)
+		return false;
+
+	object_info_tbl =
+	GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);
+
+	if (!object_info_tbl)
+		return false;
+
+	get_atom_data_table_revision(&object_info_tbl->sHeader,
+		&bp->object_info_tbl.revision);
+
+	if (bp->object_info_tbl.revision.major == 1
+		&& bp->object_info_tbl.revision.minor >= 3) {
+		ATOM_OBJECT_HEADER_V3 *tbl_v3;
+
+		tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,
+			bp->object_info_tbl_offset);
+		if (!tbl_v3)
+			return false;
+
+		bp->object_info_tbl.v1_3 = tbl_v3;
+	} else if (bp->object_info_tbl.revision.major == 1
+		&& bp->object_info_tbl.revision.minor >= 1)
+		bp->object_info_tbl.v1_1 = object_info_tbl;
+	else
+		return false;
+
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	bp->vbios_helper_data.active = 0;
+	bp->vbios_helper_data.requested = 0;
+	dal_bios_parser_init_bios_helper(bp, dce_version);
+#endif
+	dal_bios_parser_init_cmd_tbl(bp);
+	dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
+
+	return true;
+}
+
+/******************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
new file mode 100644
index 000000000000..f8fa10889fd9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_H__
+#define __DAL_BIOS_PARSER_H__
+
+#include "dc_bios_types.h"
+#include "bios_parser_helper.h"
+
+struct atom_data_revision {
+	uint32_t major;
+	uint32_t minor;
+};
+
+struct object_info_table {
+	struct atom_data_revision revision;
+	union {
+		ATOM_OBJECT_HEADER *v1_1;
+		ATOM_OBJECT_HEADER_V3 *v1_3;
+	};
+};
+
+enum spread_spectrum_id {
+	SS_ID_UNKNOWN = 0,
+	SS_ID_DP1 = 0xf1,
+	SS_ID_DP2 = 0xf2,
+	SS_ID_LVLINK_2700MHZ = 0xf3,
+	SS_ID_LVLINK_1620MHZ = 0xf4
+};
+
+struct bios_parser {
+	struct dc_bios base;
+	struct dc_context *ctx;
+	struct adapter_service *as;
+
+	struct object_info_table object_info_tbl;
+	uint32_t object_info_tbl_offset;
+	ATOM_MASTER_DATA_TABLE *master_data_tbl;
+
+	uint8_t *bios;
+	uint32_t bios_size;
+
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	const struct bios_parser_helper *bios_helper;
+	struct vbios_helper_data vbios_helper_data;
+#endif /* CONFIG_DRM_AMD_DAL_VBIOS_PRESENT */
+
+	const struct command_table_helper *cmd_helper;
+	struct cmd_tbl cmd_tbl;
+
+	uint8_t *bios_local_image;
+	enum lcd_scale lcd_scale;
+
+	bool remap_device_tags;
+	bool headless_no_opm;
+};
+
+/* Bios Parser from DC Bios */
+#define BP_FROM_DCB(dc_bios) \
+	container_of(dc_bios, struct bios_parser, base)
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
new file mode 100644
index 000000000000..0aa227aa557a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "bios_parser_helper.h"
+#include "command_table_helper.h"
+#include "command_table.h"
+#include "bios_parser.h"
+
+bool dal_bios_parser_init_bios_helper(
+	struct bios_parser *bp,
+	enum dce_version version)
+{
+	switch (version) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		bp->bios_helper = dal_bios_parser_helper_dce110_get_table();
+		return true;
+
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		bp->bios_helper = dal_bios_parser_helper_dce110_get_table();
+		return true;
+
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+bool dal_bios_parser_is_lid_open(
+	struct bios_parser *bp)
+{
+	const struct graphics_object_id encoder = dal_graphics_object_id_init(
+		ENCODER_ID_INTERNAL_UNIPHY,
+		ENUM_ID_UNKNOWN,
+		OBJECT_TYPE_UNKNOWN);
+	const struct graphics_object_id connector = dal_graphics_object_id_init(
+		CONNECTOR_ID_LVDS,
+		ENUM_ID_UNKNOWN,
+		OBJECT_TYPE_UNKNOWN);
+
+	enum signal_type signal;
+
+	/* check if VBIOS reported LCD as connected */
+	signal = bp->bios_helper->detect_sink(bp->ctx,
+		encoder, connector, SIGNAL_TYPE_LVDS);
+
+	if (signal == SIGNAL_TYPE_NONE)
+		return false;
+
+	return bp->bios_helper->is_lid_open(bp->ctx);
+}
+
+bool dal_bios_parser_is_lid_status_changed(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->is_lid_status_changed(
+			bp->ctx);
+}
+
+bool dal_bios_parser_is_display_config_changed(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->is_display_config_changed(
+			bp->ctx);
+}
+
+/**
+* dal_bios_parser_set_scratch_lcd_scale
+*
+* @brief
+*  update VBIOS scratch pad registers about LCD scale
+*
+* @param
+*  bool - to set to full panel mode or aspect-ratio mode
+*/
+void dal_bios_parser_set_scratch_lcd_scale(
+	struct bios_parser *bp,
+	enum lcd_scale scale)
+{
+	bp->bios_helper->set_scratch_lcd_scale(
+		bp->ctx, scale);
+}
+
+/**
+* dal_bios_parser_get_scratch_lcd_scale
+*
+* @brief
+*  get LCD Scale Mode from VBIOS scratch register
+*
+* @param
+*  NONE
+*/
+enum lcd_scale  dal_bios_parser_get_scratch_lcd_scale(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_scratch_lcd_scale(
+			bp->ctx);
+}
+
+void dal_bios_parser_get_bios_event_info(
+	struct bios_parser *bp,
+	struct bios_event_info *info)
+{
+	bp->bios_helper->get_bios_event_info(
+		bp->ctx, info);
+}
+
+/* ABM related */
+
+void dal_bios_parser_update_requested_backlight_level(
+	struct bios_parser *bp,
+	uint32_t backlight_8bit)
+{
+	bp->bios_helper->update_requested_backlight_level(
+		bp->ctx,
+		backlight_8bit);
+}
+
+uint32_t dal_bios_parser_get_requested_backlight_level(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_requested_backlight_level(
+			bp->ctx);
+}
+
+void dal_bios_parser_take_backlight_control(
+	struct bios_parser *bp,
+	bool cntl)
+{
+	bp->bios_helper->take_backlight_control(
+		bp->ctx, cntl);
+}
+
+/**
+ * dal_bios_parser_is_active_display
+ *  Check video bios active display.
+ */
+bool dal_bios_parser_is_active_display(
+	struct bios_parser *bp,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag)
+{
+	return bp->bios_helper->is_active_display(
+			bp->ctx, signal, device_tag);
+}
+
+/**
+ * dal_bios_parser_get_embedded_display_controller_id
+ * Get controller ID for embedded display from scratch registers
+ */
+enum controller_id dal_bios_parser_get_embedded_display_controller_id(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_embedded_display_controller_id(
+			bp->ctx);
+}
+
+/**
+ * dal_bios_parser_get_embedded_display_refresh_rate
+ * Get refresh rate for embedded display from scratch registers
+ */
+uint32_t dal_bios_parser_get_embedded_display_refresh_rate(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_embedded_display_refresh_rate(
+			bp->ctx);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
new file mode 100644
index 000000000000..1ad745561d15
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_HELPER_H__
+#define __DAL_BIOS_PARSER_HELPER_H__
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce110/bios_parser_helper_dce110.h"
+#endif
+
+struct bios_parser;
+
+struct vbios_helper_data {
+	uint32_t active;
+	uint32_t requested;
+};
+
+struct bios_parser_helper {
+	enum signal_type (*detect_sink)(
+		struct dc_context *ctx,
+		struct graphics_object_id encoder,
+		struct graphics_object_id connector,
+		enum signal_type signal);
+	bool (*is_lid_open)(
+		struct dc_context *ctx);
+	bool (*is_lid_status_changed)(
+		struct dc_context *ctx);
+	bool (*is_display_config_changed)(
+		struct dc_context *ctx);
+	void (*set_scratch_acc_mode_change)(
+		struct dc_context *ctx);
+	bool (*is_accelerated_mode)(
+		struct dc_context *ctx);
+	void (*set_scratch_critical_state)(
+		struct dc_context *ctx,
+		bool state);
+	void (*prepare_scratch_active_and_requested)(
+		struct dc_context *ctx,
+		struct vbios_helper_data *data,
+		enum controller_id id, enum signal_type s,
+		const struct connector_device_tag_info *dev_tag);
+	void (*set_scratch_active_and_requested)(
+		struct dc_context *ctx,
+		struct vbios_helper_data *d);
+	void (*set_scratch_connected)(
+		struct dc_context *ctx,
+		struct graphics_object_id id,
+		bool connected,
+		const struct connector_device_tag_info *device_tag);
+	void (*set_scratch_lcd_scale)(
+		struct dc_context *ctx,
+		enum lcd_scale lcd_scale_request);
+	enum lcd_scale (*get_scratch_lcd_scale)(
+		struct dc_context *ctx);
+	uint32_t (*fmt_control)(
+		struct dc_context *ctx,
+		enum controller_id id, uint32_t *value);
+	uint32_t (*fmt_bit_depth_control)(
+		struct dc_context *ctx,
+		enum controller_id id,
+		uint32_t *value);
+	void (*get_bios_event_info)(
+		struct dc_context *ctx,
+		struct bios_event_info *info);
+	void (*take_backlight_control)(
+		struct dc_context *ctx, bool control);
+	uint32_t (*get_requested_backlight_level)(
+		struct dc_context *ctx);
+	void (*update_requested_backlight_level)(
+		struct dc_context *ctx,
+		uint32_t backlight_8bit);
+	bool (*is_active_display)(
+		struct dc_context *ctx,
+		enum signal_type signal,
+		const struct connector_device_tag_info *dev_tag);
+	enum controller_id (*get_embedded_display_controller_id)(
+		struct dc_context *ctx);
+	uint32_t (*get_embedded_display_refresh_rate)(
+		struct dc_context *ctx);
+};
+
+bool dal_bios_parser_init_bios_helper(
+	struct bios_parser *bp,
+	enum dce_version ver);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c
new file mode 100644
index 000000000000..3bc52f5bab24
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c
@@ -0,0 +1,2730 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_interface.h"
+
+#include "command_table.h"
+#include "command_table_helper.h"
+#include "bios_parser_helper.h"
+#include "bios_parser.h"
+
+#define EXEC_BIOS_CMD_TABLE(command, params)\
+	(cgs_atom_exec_cmd_table(bp->ctx->cgs_device, \
+		GetIndexIntoMasterTable(COMMAND, command), \
+		&params) == 0)
+
+#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
+	cgs_atom_get_cmd_table_revs(bp->ctx->cgs_device, \
+		GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
+
+#define BIOS_CMD_TABLE_PARA_REVISION(command)\
+	dm_bios_cmd_table_para_revision(bp->ctx, \
+		GetIndexIntoMasterTable(COMMAND, command))
+
+
+static void init_dig_encoder_control(struct bios_parser *bp);
+static void init_transmitter_control(struct bios_parser *bp);
+static void init_set_pixel_clock(struct bios_parser *bp);
+static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);
+static void init_adjust_display_pll(struct bios_parser *bp);
+static void init_dac_encoder_control(struct bios_parser *bp);
+static void init_dac_output_control(struct bios_parser *bp);
+static void init_dac_load_detection(struct bios_parser *bp);
+static void init_blank_crtc(struct bios_parser *bp);
+static void init_set_crtc_timing(struct bios_parser *bp);
+static void init_set_crtc_overscan(struct bios_parser *bp);
+static void init_select_crtc_source(struct bios_parser *bp);
+static void init_enable_crtc(struct bios_parser *bp);
+static void init_enable_crtc_mem_req(struct bios_parser *bp);
+static void init_compute_memore_engine_pll(struct bios_parser *bp);
+static void init_external_encoder_control(struct bios_parser *bp);
+static void init_enable_disp_power_gating(struct bios_parser *bp);
+static void init_program_clock(struct bios_parser *bp);
+static void init_set_dce_clock(struct bios_parser *bp);
+
+void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
+{
+	init_dig_encoder_control(bp);
+	init_transmitter_control(bp);
+	init_set_pixel_clock(bp);
+	init_enable_spread_spectrum_on_ppll(bp);
+	init_adjust_display_pll(bp);
+	init_dac_encoder_control(bp);
+	init_dac_output_control(bp);
+	init_dac_load_detection(bp);
+	init_blank_crtc(bp);
+	init_set_crtc_timing(bp);
+	init_set_crtc_overscan(bp);
+	init_select_crtc_source(bp);
+	init_enable_crtc(bp);
+	init_enable_crtc_mem_req(bp);
+	init_program_clock(bp);
+	init_compute_memore_engine_pll(bp);
+	init_external_encoder_control(bp);
+	init_enable_disp_power_gating(bp);
+	init_set_dce_clock(bp);
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  D I G E N C O D E R C O N T R O L
+ **
+ ********************************************************************************
+ *******************************************************************************/
+static enum bp_result encoder_control_digx_v3(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+
+static enum bp_result encoder_control_digx_v4(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+static void init_encoder_control_dig_v1(struct bios_parser *bp);
+
+static void init_dig_encoder_control(struct bios_parser *bp)
+{
+	uint32_t version =
+		BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl);
+
+	switch (version) {
+	case 4:
+		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;
+		break;
+	case 2:
+		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;
+		break;
+	default:
+		init_encoder_control_dig_v1(bp);
+		break;
+	}
+}
+
+static enum bp_result encoder_control_dig_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+static enum bp_result encoder_control_dig1_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+static enum bp_result encoder_control_dig2_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+
+static void init_encoder_control_dig_v1(struct bios_parser *bp)
+{
+	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
+
+	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))
+		cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;
+	else
+		cmd_tbl->encoder_control_dig1 = NULL;
+
+	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))
+		cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;
+	else
+		cmd_tbl->encoder_control_dig2 = NULL;
+
+	cmd_tbl->dig_encoder_control = encoder_control_dig_v1;
+}
+
+static enum bp_result encoder_control_dig_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
+
+	if (cntl != NULL)
+		switch (cntl->engine_id) {
+		case ENGINE_ID_DIGA:
+			if (cmd_tbl->encoder_control_dig1 != NULL)
+				result =
+					cmd_tbl->encoder_control_dig1(bp, cntl);
+			break;
+		case ENGINE_ID_DIGB:
+			if (cmd_tbl->encoder_control_dig2 != NULL)
+				result =
+					cmd_tbl->encoder_control_dig2(bp, cntl);
+			break;
+
+		default:
+			break;
+		}
+
+	return result;
+}
+
+static enum bp_result encoder_control_dig1_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
+
+	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
+
+	if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result encoder_control_dig2_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
+
+	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
+
+	if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result encoder_control_digx_v3(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0};
+
+	if (LANE_COUNT_FOUR < cntl->lanes_number)
+		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
+	else
+		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
+
+	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
+	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+	params.ucEncoderMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					cntl->signal,
+					cntl->enable_dp_audio);
+	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+
+	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+
+	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result encoder_control_digx_v4(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};
+
+	if (LANE_COUNT_FOUR < cntl->lanes_number)
+		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
+	else
+		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
+
+
+	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
+	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+	params.ucEncoderMode =
+			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
+					cntl->signal,
+					cntl->enable_dp_audio));
+	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+
+	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+
+	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  TRANSMITTER CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result transmitter_control_v2(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v3(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v4(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v1_5(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v1_6(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+
+static void init_transmitter_control(struct bios_parser *bp)
+{
+	uint8_t frev;
+	uint8_t crev;
+
+	if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
+			frev, crev) != 0)
+		BREAK_TO_DEBUGGER();
+	switch (crev) {
+	case 2:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v3;
+		break;
+	case 4:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v4;
+		break;
+	case 5:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;
+		break;
+	case 6:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
+		break;
+	default:
+		bp->cmd_tbl.transmitter_control = NULL;
+		break;
+	}
+}
+
+static enum bp_result transmitter_control_v2(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;
+	enum connector_id connector_id =
+		dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (cntl->transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+	case TRANSMITTER_TRAVIS_LCD:
+		break;
+	default:
+		return BP_RESULT_BADINPUT;
+	}
+
+	switch (cntl->action) {
+	case TRANSMITTER_CONTROL_INIT:
+		if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||
+				(CONNECTOR_ID_DUAL_LINK_DVID == connector_id))
+			/* on INIT this bit should be set according to the
+			 * phisycal connector
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* connector object id */
+		params.usInitInfo =
+				cpu_to_le16((uint8_t)cntl->connector_obj_id.id);
+		break;
+	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
+		/* votage swing and pre-emphsis */
+		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
+		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
+		break;
+	default:
+		/* if dual-link */
+		if (LANE_COUNT_FOUR < cntl->lanes_number) {
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 20KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
+		} else
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 10KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+		break;
+	}
+
+	/* 00 - coherent mode
+	 * 01 - incoherent mode
+	 */
+
+	params.acConfig.fCoherentMode = cntl->coherent;
+
+	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
+			|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
+			|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
+		/* Bit2: Transmitter Link selection
+		 * =0 when bit0=0, single link A/C/E, when bit0=1,
+		 * master link A/C/E
+		 * =1 when bit0=0, single link B/D/F, when bit0=1,
+		 * master link B/D/F
+		 */
+		params.acConfig.ucLinkSel = 1;
+
+	if (ENGINE_ID_DIGB == cntl->engine_id)
+		/* Bit3: Transmitter data source selection
+		 * =0 DIGA is data source.
+		 * =1 DIGB is data source.
+		 * This bit is only useful when ucAction= ATOM_ENABLE
+		 */
+		params.acConfig.ucEncoderSel = 1;
+
+	if (CONNECTOR_ID_DISPLAY_PORT == connector_id)
+		/* Bit4: DP connector flag
+		 * =0 connector is none-DP connector
+		 * =1 connector is DP connector
+		 */
+		params.acConfig.fDPConnector = 1;
+
+	/* Bit[7:6]: Transmitter selection
+	 * =0 UNIPHY_ENCODER: UNIPHYA/B
+	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
+	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
+	 * =3 reserved
+	 */
+	params.acConfig.ucTransmitterSel =
+			(uint8_t)bp->cmd_helper->transmitter_bp_to_atom(
+					cntl->transmitter);
+
+	params.ucAction = (uint8_t)cntl->action;
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v3(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;
+	uint32_t pll_id;
+	enum connector_id conn_id =
+			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
+	const struct command_table_helper *cmd = bp->cmd_helper;
+	bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id)
+					|| (CONNECTOR_ID_DUAL_LINK_DVID == conn_id);
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (cntl->transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+	case TRANSMITTER_TRAVIS_LCD:
+		break;
+	default:
+		return BP_RESULT_BADINPUT;
+	}
+
+	if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))
+		return BP_RESULT_BADINPUT;
+
+	/* fill information based on the action */
+	switch (cntl->action) {
+	case TRANSMITTER_CONTROL_INIT:
+		if (dual_link_conn) {
+			/* on INIT this bit should be set according to the
+			 * phisycal connector
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+		}
+
+		/* connector object id */
+		params.usInitInfo =
+				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
+		break;
+	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
+		/* votage swing and pre-emphsis */
+		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
+		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
+		break;
+	default:
+		if (dual_link_conn && cntl->multi_path)
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* if dual-link */
+		if (LANE_COUNT_FOUR < cntl->lanes_number) {
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 20KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
+		} else {
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 10KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+			if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+				switch (cntl->color_depth) {
+				case COLOR_DEPTH_101010:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 30) / 24);
+					break;
+				case COLOR_DEPTH_121212:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 36) / 24);
+					break;
+				case COLOR_DEPTH_161616:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 48) / 24);
+					break;
+				default:
+					break;
+				}
+		}
+		break;
+	}
+
+	/* 00 - coherent mode
+	 * 01 - incoherent mode
+	 */
+
+	params.acConfig.fCoherentMode = cntl->coherent;
+
+	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
+		/* Bit2: Transmitter Link selection
+		 * =0 when bit0=0, single link A/C/E, when bit0=1,
+		 * master link A/C/E
+		 * =1 when bit0=0, single link B/D/F, when bit0=1,
+		 * master link B/D/F
+		 */
+		params.acConfig.ucLinkSel = 1;
+
+	if (ENGINE_ID_DIGB == cntl->engine_id)
+		/* Bit3: Transmitter data source selection
+		 * =0 DIGA is data source.
+		 * =1 DIGB is data source.
+		 * This bit is only useful when ucAction= ATOM_ENABLE
+		 */
+		params.acConfig.ucEncoderSel = 1;
+
+	/* Bit[7:6]: Transmitter selection
+	 * =0 UNIPHY_ENCODER: UNIPHYA/B
+	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
+	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
+	 * =3 reserved
+	 */
+	params.acConfig.ucTransmitterSel =
+			(uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);
+
+	params.ucLaneNum = (uint8_t)cntl->lanes_number;
+
+	params.acConfig.ucRefClkSource = (uint8_t)pll_id;
+
+	params.ucAction = (uint8_t)cntl->action;
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v4(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params;
+	uint32_t ref_clk_src_id;
+	enum connector_id conn_id =
+			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
+	const struct command_table_helper *cmd = bp->cmd_helper;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (cntl->transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+	case TRANSMITTER_TRAVIS_LCD:
+		break;
+	default:
+		return BP_RESULT_BADINPUT;
+	}
+
+	if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))
+		return BP_RESULT_BADINPUT;
+
+	switch (cntl->action) {
+	case TRANSMITTER_CONTROL_INIT:
+	{
+		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
+				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
+			/* on INIT this bit should be set according to the
+			 * phisycal connector
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* connector object id */
+		params.usInitInfo =
+				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
+	}
+	break;
+	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
+		/* votage swing and pre-emphsis */
+		params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select);
+		params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings);
+		break;
+	default:
+		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
+				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* if dual-link */
+		if (LANE_COUNT_FOUR < cntl->lanes_number)
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 20KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
+		else {
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 10KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+
+			if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+				switch (cntl->color_depth) {
+				case COLOR_DEPTH_101010:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 30) / 24);
+					break;
+				case COLOR_DEPTH_121212:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 36) / 24);
+					break;
+				case COLOR_DEPTH_161616:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 48) / 24);
+					break;
+				default:
+					break;
+				}
+		}
+		break;
+	}
+
+	/* 00 - coherent mode
+	 * 01 - incoherent mode
+	 */
+
+	params.acConfig.fCoherentMode = cntl->coherent;
+
+	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
+		/* Bit2: Transmitter Link selection
+		 * =0 when bit0=0, single link A/C/E, when bit0=1,
+		 * master link A/C/E
+		 * =1 when bit0=0, single link B/D/F, when bit0=1,
+		 * master link B/D/F
+		 */
+		params.acConfig.ucLinkSel = 1;
+
+	if (ENGINE_ID_DIGB == cntl->engine_id)
+		/* Bit3: Transmitter data source selection
+		 * =0 DIGA is data source.
+		 * =1 DIGB is data source.
+		 * This bit is only useful when ucAction= ATOM_ENABLE
+		 */
+		params.acConfig.ucEncoderSel = 1;
+
+	/* Bit[7:6]: Transmitter selection
+	 * =0 UNIPHY_ENCODER: UNIPHYA/B
+	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
+	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
+	 * =3 reserved
+	 */
+	params.acConfig.ucTransmitterSel =
+		(uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter));
+	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+	params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id);
+	params.ucAction = (uint8_t)(cntl->action);
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v1_5(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	const struct command_table_helper *cmd = bp->cmd_helper;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params;
+
+	dm_memset(&params, 0, sizeof(params));
+	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
+	params.ucAction = (uint8_t)cntl->action;
+	params.ucLaneNum = (uint8_t)cntl->lanes_number;
+	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
+
+	params.ucDigMode =
+		cmd->signal_type_to_atom_dig_mode(cntl->signal);
+	params.asConfig.ucPhyClkSrcId =
+		cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id);
+	/* 00 - coherent mode */
+	params.asConfig.ucCoherentMode = cntl->coherent;
+	params.asConfig.ucHPDSel =
+		cmd->hpd_sel_to_atom(cntl->hpd_sel);
+	params.ucDigEncoderSel =
+		cmd->dig_encoder_sel_to_atom(cntl->engine_id);
+	params.ucDPLaneSet = (uint8_t) cntl->lane_settings;
+	params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10));
+	/*
+	 * In SI/TN case, caller have to set usPixelClock as following:
+	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
+	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
+	 * DVI single link mode: usPixelClock = pixel clock
+	 * DVI dual link mode: usPixelClock = pixel clock
+	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
+	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
+	 * LVDS mode: usPixelClock = pixel clock
+	 */
+	switch (cntl->signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.usSymClock =
+				cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.usSymClock =
+				cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.usSymClock =
+				cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v1_6(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+	const struct command_table_helper *cmd = bp->cmd_helper;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
+
+	dm_memset(&params, 0, sizeof(params));
+	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
+	params.ucAction = (uint8_t)cntl->action;
+
+	if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
+		params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
+	else
+		params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
+
+	params.ucLaneNum = (uint8_t)cntl->lanes_number;
+	params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
+	params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
+	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
+	params.ulSymClock = cntl->pixel_clock/10;
+
+	/*
+	 * In SI/TN case, caller have to set usPixelClock as following:
+	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
+	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
+	 * DVI single link mode: usPixelClock = pixel clock
+	 * DVI dual link mode: usPixelClock = pixel clock
+	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
+	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
+	 * LVDS mode: usPixelClock = pixel clock
+	 */
+	switch (cntl->signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.ulSymClock =
+				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.ulSymClock =
+				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.ulSymClock =
+				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+#endif
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET PIXEL CLOCK
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result set_pixel_clock_v3(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result set_pixel_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result set_pixel_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result set_pixel_clock_v7(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+
+static void init_set_pixel_clock(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
+	case 3:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
+		break;
+	case 5:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
+		break;
+	case 6:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
+		break;
+	case 7:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
+		break;
+	default:
+		bp->cmd_tbl.set_pixel_clock = NULL;
+		break;
+	}
+}
+
+static enum bp_result set_pixel_clock_v3(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	PIXEL_CLOCK_PARAMETERS_V3 *params;
+	SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
+
+	dm_memset(&allocation, 0, sizeof(allocation));
+
+	if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
+		allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
+	else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
+		allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
+	else
+		return BP_RESULT_BADINPUT;
+
+	allocation.sPCLKInput.usRefDiv =
+			cpu_to_le16((uint16_t)bp_params->reference_divider);
+	allocation.sPCLKInput.usFbDiv =
+			cpu_to_le16((uint16_t)bp_params->feedback_divider);
+	allocation.sPCLKInput.ucFracFbDiv =
+			(uint8_t)bp_params->fractional_feedback_divider;
+	allocation.sPCLKInput.ucPostDiv =
+			(uint8_t)bp_params->pixel_clock_post_divider;
+
+	/* We need to convert from KHz units into 10KHz units */
+	allocation.sPCLKInput.usPixelClock =
+			cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
+
+	params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
+	params->ucTransmitterId =
+			bp->cmd_helper->encoder_id_to_atom(
+					dal_graphics_object_id_get_encoder_id(
+							bp_params->encoder_object_id));
+	params->ucEncoderMode =
+			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
+					bp_params->signal_type, false));
+
+	if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+		params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
+
+	if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
+		params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
+
+	if (CONTROLLER_ID_D1 != bp_params->controller_id)
+		params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
+
+	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
+/* video bios did not define this: */
+typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
+	PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
+	/* Caller doesn't need to init this portion */
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
+} SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
+#endif
+
+#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
+/* video bios did not define this: */
+typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
+	PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
+	/* Caller doesn't need to init this portion */
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
+} SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
+#endif
+
+static enum bp_result set_pixel_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
+	uint8_t controller_id;
+	uint32_t pll_id;
+
+	dm_memset(&clk, 0, sizeof(clk));
+
+	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+			&& bp->cmd_helper->controller_id_to_atom(
+					bp_params->controller_id, &controller_id)) {
+		clk.sPCLKInput.ucCRTC = controller_id;
+		clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
+		clk.sPCLKInput.ucRefDiv =
+				(uint8_t)(bp_params->reference_divider);
+		clk.sPCLKInput.usFbDiv =
+				cpu_to_le16((uint16_t)(bp_params->feedback_divider));
+		clk.sPCLKInput.ulFbDivDecFrac =
+				cpu_to_le32(bp_params->fractional_feedback_divider);
+		clk.sPCLKInput.ucPostDiv =
+				(uint8_t)(bp_params->pixel_clock_post_divider);
+		clk.sPCLKInput.ucTransmitterID =
+				bp->cmd_helper->encoder_id_to_atom(
+						dal_graphics_object_id_get_encoder_id(
+								bp_params->encoder_object_id));
+		clk.sPCLKInput.ucEncoderMode =
+				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+						bp_params->signal_type, false);
+
+		/* We need to convert from KHz units into 10KHz units */
+		clk.sPCLKInput.usPixelClock =
+				cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
+
+		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
+
+		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_MISC_REF_DIV_SRC;
+
+		/* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
+		 * =1:30bpp, =2:32bpp
+		 * driver choose program it itself, i.e. here we program it
+		 * to 888 by default.
+		 */
+
+		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
+			result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+static enum bp_result set_pixel_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
+	uint8_t controller_id;
+	uint32_t pll_id;
+
+	dm_memset(&clk, 0, sizeof(clk));
+
+	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+			&& bp->cmd_helper->controller_id_to_atom(
+					bp_params->controller_id, &controller_id)) {
+		/* Note: VBIOS still wants to use ucCRTC name which is now
+		 * 1 byte in ULONG
+		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
+		 *{
+		 * target the pixel clock to drive the CRTC timing.
+		 * ULONG ulPixelClock:24;
+		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
+		 * previous version.
+		 * ATOM_CRTC1~6, indicate the CRTC controller to
+		 * ULONG ucCRTC:8;
+		 * drive the pixel clock. not used for DCPLL case.
+		 *}CRTC_PIXEL_CLOCK_FREQ;
+		 *union
+		 *{
+		 * pixel clock and CRTC id frequency
+		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
+		 * ULONG ulDispEngClkFreq; dispclk frequency
+		 *};
+		 */
+		clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
+		clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
+		clk.sPCLKInput.ucRefDiv =
+				(uint8_t) bp_params->reference_divider;
+		clk.sPCLKInput.usFbDiv =
+				cpu_to_le16((uint16_t) bp_params->feedback_divider);
+		clk.sPCLKInput.ulFbDivDecFrac =
+				cpu_to_le32(bp_params->fractional_feedback_divider);
+		clk.sPCLKInput.ucPostDiv =
+				(uint8_t) bp_params->pixel_clock_post_divider;
+		clk.sPCLKInput.ucTransmitterID =
+				bp->cmd_helper->encoder_id_to_atom(
+						dal_graphics_object_id_get_encoder_id(
+								bp_params->encoder_object_id));
+		clk.sPCLKInput.ucEncoderMode =
+				(uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
+						bp_params->signal_type, false);
+
+		/* We need to convert from KHz units into 10KHz units */
+		clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
+				cpu_to_le32(bp_params->target_pixel_clock / 10);
+
+		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
+		}
+
+		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
+		}
+
+		/* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
+		 * 24bpp =1:30bpp, =2:32bpp
+		 * driver choose program it itself, i.e. here we pass required
+		 * target rate that includes deep color.
+		 */
+
+		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
+			result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+static enum bp_result set_pixel_clock_v7(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+	PIXEL_CLOCK_PARAMETERS_V7 clk;
+	uint8_t controller_id;
+	uint32_t pll_id;
+
+	dm_memset(&clk, 0, sizeof(clk));
+
+	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+			&& bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
+		/* Note: VBIOS still wants to use ucCRTC name which is now
+		 * 1 byte in ULONG
+		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
+		 *{
+		 * target the pixel clock to drive the CRTC timing.
+		 * ULONG ulPixelClock:24;
+		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
+		 * previous version.
+		 * ATOM_CRTC1~6, indicate the CRTC controller to
+		 * ULONG ucCRTC:8;
+		 * drive the pixel clock. not used for DCPLL case.
+		 *}CRTC_PIXEL_CLOCK_FREQ;
+		 *union
+		 *{
+		 * pixel clock and CRTC id frequency
+		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
+		 * ULONG ulDispEngClkFreq; dispclk frequency
+		 *};
+		 */
+		clk.ucCRTC = controller_id;
+		clk.ucPpll = (uint8_t) pll_id;
+		clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
+		clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
+
+		/* We need to convert from KHz units into 10KHz units */
+		clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10);
+
+		clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
+
+		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
+
+		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
+
+		if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
+
+		if (bp_params->flags.SUPPORT_YUV_420)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
+
+		if (bp_params->flags.SET_XTALIN_REF_SRC)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
+
+		if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
+
+		if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
+
+		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
+			result = BP_RESULT_OK;
+	}
+#endif
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE PIXEL CLOCK SS
+ **
+ ********************************************************************************
+ *******************************************************************************/
+static enum bp_result enable_spread_spectrum_on_ppll_v1(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable);
+static enum bp_result enable_spread_spectrum_on_ppll_v2(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable);
+static enum bp_result enable_spread_spectrum_on_ppll_v3(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable);
+
+static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
+	case 1:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
+				enable_spread_spectrum_on_ppll_v1;
+		break;
+	case 2:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
+				enable_spread_spectrum_on_ppll_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
+				enable_spread_spectrum_on_ppll_v3;
+		break;
+	default:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_spread_spectrum_on_ppll_v1(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if ((enable == true) && (bp_params->percentage > 0))
+		params.ucEnable = ATOM_ENABLE;
+	else
+		params.ucEnable = ATOM_DISABLE;
+
+	params.usSpreadSpectrumPercentage =
+			cpu_to_le16((uint16_t)bp_params->percentage);
+	params.ucSpreadSpectrumStep =
+			(uint8_t)bp_params->ver1.step;
+	params.ucSpreadSpectrumDelay =
+			(uint8_t)bp_params->ver1.delay;
+	/* convert back to unit of 10KHz */
+	params.ucSpreadSpectrumRange =
+			(uint8_t)(bp_params->ver1.range / 10000);
+
+	if (bp_params->flags.EXTERNAL_SS)
+		params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
+
+	if (bp_params->flags.CENTER_SPREAD)
+		params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
+
+	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
+		params.ucPpll = ATOM_PPLL1;
+	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
+		params.ucPpll = ATOM_PPLL2;
+	else
+		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
+
+	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result enable_spread_spectrum_on_ppll_v2(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
+	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
+	else
+		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
+
+	if ((enable == true) && (bp_params->percentage > 0)) {
+		params.ucEnable = ATOM_ENABLE;
+
+		params.usSpreadSpectrumPercentage =
+				cpu_to_le16((uint16_t)(bp_params->percentage));
+		params.usSpreadSpectrumStep =
+				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
+
+		if (bp_params->flags.EXTERNAL_SS)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
+
+		if (bp_params->flags.CENTER_SPREAD)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
+
+		/* Both amounts need to be left shifted first before bit
+		 * comparison. Otherwise, the result will always be zero here
+		 */
+		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
+				((bp_params->ds.feedback_amount <<
+						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
+						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
+						((bp_params->ds.nfrac_amount <<
+								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
+								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
+	} else
+		params.ucEnable = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result enable_spread_spectrum_on_ppll_v3(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (bp_params->pll_id) {
+	case CLOCK_SOURCE_ID_PLL0:
+		/* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
+		 * not for SI display clock.
+		 */
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
+		break;
+	case CLOCK_SOURCE_ID_PLL1:
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
+		break;
+
+	case CLOCK_SOURCE_ID_PLL2:
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
+		break;
+
+	case CLOCK_SOURCE_ID_DCPLL:
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
+		break;
+
+	default:
+		BREAK_TO_DEBUGGER();
+		/* Unexpected PLL value!! */
+		return result;
+	}
+
+	if (enable == true) {
+		params.ucEnable = ATOM_ENABLE;
+
+		params.usSpreadSpectrumAmountFrac =
+				cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
+		params.usSpreadSpectrumStep =
+				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
+
+		if (bp_params->flags.EXTERNAL_SS)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
+		if (bp_params->flags.CENTER_SPREAD)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
+
+		/* Both amounts need to be left shifted first before bit
+		 * comparison. Otherwise, the result will always be zero here
+		 */
+		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
+				((bp_params->ds.feedback_amount <<
+						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
+						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
+						((bp_params->ds.nfrac_amount <<
+								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
+								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
+	} else
+		params.ucEnable = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ADJUST DISPLAY PLL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result adjust_display_pll_v2(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params);
+static enum bp_result adjust_display_pll_v3(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params);
+
+static void init_adjust_display_pll(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
+	case 2:
+		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
+		break;
+	default:
+		bp->cmd_tbl.adjust_display_pll = NULL;
+		break;
+	}
+}
+
+static enum bp_result adjust_display_pll_v2(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
+
+	/* We need to convert from KHz units into 10KHz units and then convert
+	 * output pixel clock back 10KHz-->KHz */
+	uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
+
+	params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
+	params.ucTransmitterID =
+			bp->cmd_helper->encoder_id_to_atom(
+					dal_graphics_object_id_get_encoder_id(
+							bp_params->encoder_object_id));
+	params.ucEncodeMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					bp_params->signal_type, false);
+	return result;
+}
+
+static enum bp_result adjust_display_pll_v3(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
+	uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	/* We need to convert from KHz units into 10KHz units and then convert
+	 * output pixel clock back 10KHz-->KHz */
+	params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
+	params.sInput.ucTransmitterID =
+			bp->cmd_helper->encoder_id_to_atom(
+					dal_graphics_object_id_get_encoder_id(
+							bp_params->encoder_object_id));
+	params.sInput.ucEncodeMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					bp_params->signal_type, false);
+
+	if (bp_params->ss_enable == true)
+		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
+
+	if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
+		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
+
+	if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
+		/* Convert output pixel clock back 10KHz-->KHz: multiply
+		 * original pixel clock in KHz by ratio
+		 * [output pxlClk/input pxlClk] */
+		uint64_t pixel_clk_10_khz_out =
+				(uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
+		uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
+
+		if (pixel_clk_10_kHz_in != 0) {
+			bp_params->adjusted_pixel_clock =
+					div_u64(pixel_clk * pixel_clk_10_khz_out,
+							pixel_clk_10_kHz_in);
+		} else {
+			bp_params->adjusted_pixel_clock = 0;
+			BREAK_TO_DEBUGGER();
+		}
+
+		bp_params->reference_divider = params.sOutput.ucRefDiv;
+		bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
+
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC ENCODER CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result dac1_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard);
+static enum bp_result dac2_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard);
+
+static void init_dac_encoder_control(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
+	case 1:
+		bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac1_encoder_control = NULL;
+		break;
+	}
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
+	case 1:
+		bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac2_encoder_control = NULL;
+		break;
+	}
+}
+
+static void dac_encoder_control_prepare_params(
+	DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard)
+{
+	params->ucDacStandard = dac_standard;
+	if (enable)
+		params->ucAction = ATOM_ENABLE;
+	else
+		params->ucAction = ATOM_DISABLE;
+
+	/* We need to convert from KHz units into 10KHz units
+	 * it looks as if the TvControl do not care about pixel clock
+	 */
+	params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
+}
+
+static enum bp_result dac1_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
+
+	dac_encoder_control_prepare_params(
+		&params,
+		enable,
+		pixel_clock,
+		dac_standard);
+
+	if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result dac2_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
+
+	dac_encoder_control_prepare_params(
+		&params,
+		enable,
+		pixel_clock,
+		dac_standard);
+
+	if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC OUTPUT CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+static enum bp_result dac1_output_control_v1(
+	struct bios_parser *bp,
+	bool enable);
+static enum bp_result dac2_output_control_v1(
+	struct bios_parser *bp,
+	bool enable);
+
+static void init_dac_output_control(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
+	case 1:
+		bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac1_output_control = NULL;
+		break;
+	}
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
+	case 1:
+		bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac2_output_control = NULL;
+		break;
+	}
+}
+
+static enum bp_result dac1_output_control_v1(
+	struct bios_parser *bp, bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
+
+	if (enable)
+		params.ucAction = ATOM_ENABLE;
+	else
+		params.ucAction = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result dac2_output_control_v1(
+	struct bios_parser *bp, bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
+
+	if (enable)
+		params.ucAction = ATOM_ENABLE;
+	else
+		params.ucAction = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC LOAD DETECTION
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum signal_type dac_load_detection_v3(
+	struct bios_parser *bp,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type display_signal);
+
+static void init_dac_load_detection(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC_LoadDetection)) {
+	case 3:
+		bp->cmd_tbl.dac_load_detection = dac_load_detection_v3;
+		break;
+	default:
+		bp->cmd_tbl.dac_load_detection = NULL;
+		break;
+	}
+}
+
+static enum signal_type dac_load_detection_v3(
+	struct bios_parser *bp,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type display_signal)
+{
+	DAC_LOAD_DETECTION_PS_ALLOCATION params;
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	/* load detection is cupported for CRT, TV and CV */
+	switch (display_signal) {
+	case SIGNAL_TYPE_RGB:
+		switch (dal_graphics_object_id_get_encoder_id(encoder)) {
+		case ENCODER_ID_INTERNAL_DAC1:
+		case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+			params.sDacload.usDeviceID =
+				cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
+			break;
+		case ENCODER_ID_INTERNAL_DAC2:
+		case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+			params.sDacload.usDeviceID =
+				cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
+			break;
+		default:
+			break;
+		}
+		break;
+		default:
+			return signal;
+	}
+
+	/* set the encoder to detect on */
+	switch (dal_graphics_object_id_get_encoder_id(encoder)) {
+	case ENCODER_ID_INTERNAL_DAC1:
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+		params.sDacload.ucDacType = ATOM_DAC_A;
+		break;
+	case ENCODER_ID_INTERNAL_DAC2:
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+		params.sDacload.ucDacType = ATOM_DAC_B;
+		break;
+	default:
+		return signal;
+	}
+
+	if (!EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params))
+		return signal;
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	signal = bp->bios_helper->detect_sink(
+			bp->ctx,
+			encoder,
+			connector,
+			display_signal);
+#else
+	BREAK_TO_DEBUGGER(); /* VBios is needed */
+#endif
+
+	return signal;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                 BLANK CRTC
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result blank_crtc_v1(
+	struct bios_parser *bp,
+	struct bp_blank_crtc_parameters *bp_params,
+	bool blank);
+
+static void init_blank_crtc(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(BlankCRTC)) {
+	case 1:
+		bp->cmd_tbl.blank_crtc = blank_crtc_v1;
+		break;
+	default:
+		bp->cmd_tbl.blank_crtc = NULL;
+		break;
+	}
+}
+
+static enum bp_result blank_crtc_v1(
+	struct bios_parser *bp,
+	struct bp_blank_crtc_parameters *bp_params,
+	bool blank)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	BLANK_CRTC_PARAMETERS params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
+			&atom_controller_id)) {
+		params.ucCRTC = (uint8_t)atom_controller_id;
+
+		if (blank)
+			params.ucBlanking = ATOM_BLANKING;
+		else
+			params.ucBlanking = ATOM_BLANKING_OFF;
+		params.usBlackColorRCr =
+				cpu_to_le16((uint16_t)bp_params->black_color_rcr);
+		params.usBlackColorGY =
+				cpu_to_le16((uint16_t)bp_params->black_color_gy);
+		params.usBlackColorBCb =
+				cpu_to_le16((uint16_t)bp_params->black_color_bcb);
+
+		if (EXEC_BIOS_CMD_TABLE(BlankCRTC, params))
+			result = BP_RESULT_OK;
+	} else
+		/* Not support more than two CRTC as current ASIC, update this
+		 * if needed.
+		 */
+		result = BP_RESULT_BADINPUT;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET CRTC TIMING
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result set_crtc_using_dtd_timing_v3(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params);
+static enum bp_result set_crtc_timing_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params);
+
+static void init_set_crtc_timing(struct bios_parser *bp)
+{
+	uint32_t dtd_version =
+			BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
+	if (dtd_version > 2)
+		switch (dtd_version) {
+		case 3:
+			bp->cmd_tbl.set_crtc_timing =
+					set_crtc_using_dtd_timing_v3;
+			break;
+		default:
+			bp->cmd_tbl.set_crtc_timing = NULL;
+			break;
+		}
+	else
+		switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
+		case 1:
+			bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
+			break;
+		default:
+			bp->cmd_tbl.set_crtc_timing = NULL;
+			break;
+		}
+}
+
+static enum bp_result set_crtc_timing_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+
+	params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
+	params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
+	params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
+	params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
+	params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
+	params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
+	params.usV_SyncStart =
+			cpu_to_le16((uint16_t)(bp_params->v_sync_start));
+	params.usV_SyncWidth =
+			cpu_to_le16((uint16_t)(bp_params->v_sync_width));
+
+
+	/* VBIOS does not expect any value except zero into this call, for
+	 * underscan use another entry ProgramOverscan call but when mode
+	 * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
+	 * but when same ,but 60 Hz there is corruption
+	 * DAL1 does not allow the mode 1776x1000@60
+	 */
+	params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
+	params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
+	params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
+	params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
+
+	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
+
+	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
+
+	if (bp_params->flags.INTERLACE) {
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
+
+		/* original DAL code has this condition to apply tis for
+		 * non-TV/CV only due to complex MV testing for possible
+		 * impact
+		 * if (pACParameters->signal != SignalType_YPbPr &&
+		 *  pACParameters->signal != SignalType_Composite &&
+		 *  pACParameters->signal != SignalType_SVideo)
+		 */
+		/* HW will deduct 0.5 line from 2nd feild.
+		 * i.e. for 1080i, it is 2 lines for 1st field, 2.5
+		 * lines for the 2nd feild. we need input as 5 instead
+		 * of 4, but it is 4 either from Edid data
+		 * (spec CEA 861) or CEA timing table.
+		 */
+		params.usV_SyncStart =
+				cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
+	}
+
+	if (bp_params->flags.HORZ_COUNT_BY_TWO)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
+
+	if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result set_crtc_using_dtd_timing_v3(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+
+	/* bios usH_Size wants h addressable size */
+	params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
+	/* bios usH_Blanking_Time wants borders included in blanking */
+	params.usH_Blanking_Time =
+			cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
+	/* bios usV_Size wants v addressable size */
+	params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
+	/* bios usV_Blanking_Time wants borders included in blanking */
+	params.usV_Blanking_Time =
+			cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
+	/* bios usHSyncOffset is the offset from the end of h addressable,
+	 * our horizontalSyncStart is the offset from the beginning
+	 * of h addressable */
+	params.usH_SyncOffset =
+			cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
+	params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
+	/* bios usHSyncOffset is the offset from the end of v addressable,
+	 * our verticalSyncStart is the offset from the beginning of
+	 * v addressable */
+	params.usV_SyncOffset =
+			cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
+	params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
+
+	/* we assume that overscan from original timing does not get bigger
+	 * than 255
+	 * we will program all the borders in the Set CRTC Overscan call below
+	 */
+
+	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
+
+	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
+
+
+	if (bp_params->flags.INTERLACE)	{
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
+
+		/* original DAL code has this condition to apply this
+		 * for non-TV/CV only
+		 * due to complex MV testing for possible impact
+		 * if ( pACParameters->signal != SignalType_YPbPr &&
+		 *  pACParameters->signal != SignalType_Composite &&
+		 *  pACParameters->signal != SignalType_SVideo)
+		 */
+		{
+			/* HW will deduct 0.5 line from 2nd feild.
+			 * i.e. for 1080i, it is 2 lines for 1st field,
+			 * 2.5 lines for the 2nd feild. we need input as 5
+			 * instead of 4.
+			 * but it is 4 either from Edid data (spec CEA 861)
+			 * or CEA timing table.
+			 */
+			params.usV_SyncOffset =
+					cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1);
+
+		}
+	}
+
+	if (bp_params->flags.HORZ_COUNT_BY_TWO)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
+
+	if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET CRTC OVERSCAN
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result set_crtc_overscan_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_overscan_parameters *bp_params);
+
+static void init_set_crtc_overscan(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_OverScan))	{
+	case 1:
+		bp->cmd_tbl.set_crtc_overscan = set_crtc_overscan_v1;
+		break;
+	default:
+		bp->cmd_tbl.set_crtc_overscan = NULL;
+		break;
+	}
+}
+
+static enum bp_result set_crtc_overscan_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_overscan_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_CRTC_OVERSCAN_PARAMETERS params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+	else
+		return BP_RESULT_BADINPUT;
+
+	params.usOverscanRight =
+			cpu_to_le16((uint16_t)bp_params->h_overscan_right);
+	params.usOverscanLeft =
+			cpu_to_le16((uint16_t)bp_params->h_overscan_left);
+	params.usOverscanBottom =
+			cpu_to_le16((uint16_t)bp_params->v_overscan_bottom);
+	params.usOverscanTop =
+			cpu_to_le16((uint16_t)bp_params->v_overscan_top);
+
+	if (EXEC_BIOS_CMD_TABLE(SetCRTC_OverScan, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SELECT CRTC SOURCE
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result select_crtc_source_v2(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params);
+static enum bp_result select_crtc_source_v3(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params);
+
+static void init_select_crtc_source(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) {
+	case 2:
+		bp->cmd_tbl.select_crtc_source = select_crtc_source_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
+		break;
+	default:
+		bp->cmd_tbl.select_crtc_source = NULL;
+		break;
+	}
+}
+
+static enum bp_result select_crtc_source_v2(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SELECT_CRTC_SOURCE_PARAMETERS_V2 params;
+	uint8_t atom_controller_id;
+	uint32_t atom_engine_id;
+	enum signal_type s = bp_params->signal;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	/* set controller id */
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+	else
+		return BP_RESULT_FAILURE;
+
+	/* set encoder id */
+	if (bp->cmd_helper->engine_bp_to_atom(
+			bp_params->engine_id, &atom_engine_id))
+		params.ucEncoderID = (uint8_t)atom_engine_id;
+	else
+		return BP_RESULT_FAILURE;
+
+	if (SIGNAL_TYPE_EDP == s ||
+			(SIGNAL_TYPE_DISPLAY_PORT == s &&
+					SIGNAL_TYPE_LVDS == bp_params->sink_signal))
+		s = SIGNAL_TYPE_LVDS;
+
+	params.ucEncodeMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					s, bp_params->enable_dp_audio);
+
+	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result select_crtc_source_v3(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params)
+{
+	bool result = BP_RESULT_FAILURE;
+	SELECT_CRTC_SOURCE_PARAMETERS_V3 params;
+	uint8_t atom_controller_id;
+	uint32_t atom_engine_id;
+	enum signal_type s = bp_params->signal;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
+			&atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+	else
+		return result;
+
+	if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
+			&atom_engine_id))
+		params.ucEncoderID = (uint8_t)atom_engine_id;
+	else
+		return result;
+
+	if (SIGNAL_TYPE_EDP == s ||
+			(SIGNAL_TYPE_DISPLAY_PORT == s &&
+					SIGNAL_TYPE_LVDS == bp_params->sink_signal))
+		s = SIGNAL_TYPE_LVDS;
+
+	params.ucEncodeMode =
+			bp->cmd_helper->encoder_mode_bp_to_atom(
+					s, bp_params->enable_dp_audio);
+	/* Needed for VBIOS Random Spatial Dithering feature */
+	params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth);
+
+	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE CRTC
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result enable_crtc_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable);
+
+static void init_enable_crtc(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
+	case 1:
+		bp->cmd_tbl.enable_crtc = enable_crtc_v1;
+		break;
+	default:
+		bp->cmd_tbl.enable_crtc = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_crtc_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable)
+{
+	bool result = BP_RESULT_FAILURE;
+	ENABLE_CRTC_PARAMETERS params = {0};
+	uint8_t id;
+
+	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
+		params.ucCRTC = id;
+	else
+		return BP_RESULT_BADINPUT;
+
+	if (enable)
+		params.ucEnable = ATOM_ENABLE;
+	else
+		params.ucEnable = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE CRTC MEM REQ
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result enable_crtc_mem_req_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable);
+
+static void init_enable_crtc_mem_req(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
+	case 1:
+		bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
+		break;
+	default:
+		bp->cmd_tbl.enable_crtc_mem_req = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_crtc_mem_req_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable)
+{
+	bool result = BP_RESULT_BADINPUT;
+	ENABLE_CRTC_PARAMETERS params = {0};
+	uint8_t id;
+
+	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
+		params.ucCRTC = id;
+
+		if (enable)
+			params.ucEnable = ATOM_ENABLE;
+		else
+			params.ucEnable = ATOM_DISABLE;
+
+		if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
+			result = BP_RESULT_OK;
+		else
+			result = BP_RESULT_FAILURE;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DISPLAY PLL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result program_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result program_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+
+static void init_program_clock(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
+	case 5:
+		bp->cmd_tbl.program_clock = program_clock_v5;
+		break;
+	case 6:
+		bp->cmd_tbl.program_clock = program_clock_v6;
+		break;
+	default:
+		bp->cmd_tbl.program_clock = NULL;
+		break;
+	}
+}
+
+static enum bp_result program_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
+	uint32_t atom_pll_id;
+
+	dm_memset(&params, 0, sizeof(params));
+	if (!bp->cmd_helper->clock_source_id_to_atom(
+			bp_params->pll_id, &atom_pll_id)) {
+		BREAK_TO_DEBUGGER(); /* Invalid Inpute!! */
+		return BP_RESULT_BADINPUT;
+	}
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
+	params.sPCLKInput.usPixelClock =
+			cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10));
+	params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
+
+	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
+
+	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result program_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
+	uint32_t atom_pll_id;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (!bp->cmd_helper->clock_source_id_to_atom(
+			bp_params->pll_id, &atom_pll_id)) {
+		BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
+		return BP_RESULT_BADINPUT;
+	}
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
+	params.sPCLKInput.ulDispEngClkFreq =
+			cpu_to_le32(bp_params->target_pixel_clock / 10);
+
+	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
+
+	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
+		/* True display clock is returned by VBIOS if DFS bypass
+		 * is enabled. */
+		bp_params->dfs_bypass_display_clock =
+				(uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                 COMPUTE MEMORY ENGINE PLL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result compute_memore_engine_pll_v4(
+	struct bios_parser *bp,
+	struct bp_display_clock_parameters *bp_params);
+
+static void init_compute_memore_engine_pll(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(ComputeMemoryEnginePLL)) {
+	case 4:
+		bp->cmd_tbl.compute_memore_engine_pll =
+				compute_memore_engine_pll_v4;
+		break;
+	default:
+		bp->cmd_tbl.compute_memore_engine_pll = NULL;
+		break;
+	}
+}
+
+static enum bp_result compute_memore_engine_pll_v4(
+	struct bios_parser *bp,
+	struct bp_display_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	params.ulClock = cpu_to_le32(bp_params->target_display_clock / 10);
+
+	/* Initialize this to the target clock in case this call fails */
+	bp_params->actual_display_clock = bp_params->target_display_clock;
+
+	if (EXEC_BIOS_CMD_TABLE(ComputeMemoryEnginePLL, params)) {
+		/* Convert from 10KHz units back to KHz */
+		bp_params->actual_display_clock =
+				le32_to_cpu(params.ulClock) * 10;
+		bp_params->actual_post_divider_id = params.ucPostDiv;
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  EXTERNAL ENCODER CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result external_encoder_control_v3(
+	struct bios_parser *bp,
+	struct bp_external_encoder_control *cntl);
+
+static void init_external_encoder_control(
+	struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
+	case 3:
+		bp->cmd_tbl.external_encoder_control =
+				external_encoder_control_v3;
+		break;
+	default:
+		bp->cmd_tbl.external_encoder_control = NULL;
+		break;
+	}
+}
+
+static enum bp_result external_encoder_control_v3(
+	struct bios_parser *bp,
+	struct bp_external_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	/* we need use _PS_Alloc struct */
+	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
+	EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
+	struct graphics_object_id encoder;
+	bool is_input_signal_dp = false;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	cntl_params = &params.sExtEncoder;
+
+	encoder = cntl->encoder_id;
+
+	/* check if encoder supports external encoder control table */
+	switch (dal_graphics_object_id_get_encoder_id(encoder)) {
+	case ENCODER_ID_EXTERNAL_NUTMEG:
+	case ENCODER_ID_EXTERNAL_TRAVIS:
+		is_input_signal_dp = true;
+		break;
+
+	default:
+		BREAK_TO_DEBUGGER();
+		return BP_RESULT_BADINPUT;
+	}
+
+	/* Fill information based on the action
+	 *
+	 * Bit[6:4]: indicate external encoder, applied to all functions.
+	 * =0: external encoder1, mapped to external encoder enum id1
+	 * =1: external encoder2, mapped to external encoder enum id2
+	 *
+	 * enum ObjectEnumId
+	 * {
+	 *  EnumId_Unknown = 0,
+	 *  EnumId_1,
+	 *  EnumId_2,
+	 * };
+	 */
+	cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
+
+	switch (cntl->action) {
+	case EXTERNAL_ENCODER_CONTROL_INIT:
+		/* output display connector type. Only valid in encoder
+		 * initialization */
+		cntl_params->usConnectorId =
+				cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
+		break;
+	case EXTERNAL_ENCODER_CONTROL_SETUP:
+		/* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
+		 * 10KHz
+		 * output display device pixel clock frequency in unit of 10KHz.
+		 * Only valid in setup and enableoutput
+		 */
+		cntl_params->usPixelClock =
+				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+		/* Indicate display output signal type drive by external
+		 * encoder, only valid in setup and enableoutput */
+		cntl_params->ucEncoderMode =
+				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+						cntl->signal, false);
+
+		if (is_input_signal_dp) {
+			/* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
+			 * only valid in encoder setup with DP mode. */
+			if (LINK_RATE_HIGH == cntl->link_rate)
+				cntl_params->ucConfig |= 1;
+			/* output color depth Indicate encoder data bpc format
+			 * in DP mode, only valid in encoder setup in DP mode.
+			 */
+			cntl_params->ucBitPerColor =
+					(uint8_t)(cntl->color_depth);
+		}
+		/* Indicate how many lanes used by external encoder, only valid
+		 * in encoder setup and enableoutput. */
+		cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
+		break;
+	case EXTERNAL_ENCODER_CONTROL_ENABLE:
+		cntl_params->usPixelClock =
+				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+		cntl_params->ucEncoderMode =
+				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+						cntl->signal, false);
+		cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
+		break;
+	default:
+		break;
+	}
+
+	cntl_params->ucAction = (uint8_t)cntl->action;
+
+	if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
+		result = BP_RESULT_OK;
+
+	if (EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT == cntl->action) {
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+		if (BP_RESULT_OK == result)
+			/* get VBIOS result from scratch register.
+			 * ExternalEncoderControl runs detection and save result
+			 * in BIOS scratch registers. */
+			cntl->signal = bp->bios_helper->detect_sink(
+					bp->ctx,
+					encoder,
+					cntl->connector_obj_id,
+					cntl->signal);
+		else/* BIOS table does not work. */
+#endif
+		{
+			BREAK_TO_DEBUGGER(); /* VBios is needed */
+			cntl->signal = SIGNAL_TYPE_NONE;
+		}
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE DISPLAY POWER GATING
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result enable_disp_power_gating_v2_1(
+	struct bios_parser *bp,
+	enum controller_id crtc_id,
+	enum bp_pipe_control_action action);
+
+static void init_enable_disp_power_gating(
+	struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
+	case 1:
+		bp->cmd_tbl.enable_disp_power_gating =
+				enable_disp_power_gating_v2_1;
+		break;
+	default:
+		bp->cmd_tbl.enable_disp_power_gating = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_disp_power_gating_v2_1(
+	struct bios_parser *bp,
+	enum controller_id crtc_id,
+	enum bp_pipe_control_action action)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 params = {0};
+	uint8_t atom_crtc_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
+		params.ucDispPipeId = atom_crtc_id;
+	else
+		return BP_RESULT_BADINPUT;
+
+	params.ucEnable =
+			bp->cmd_helper->disp_power_gating_action_to_atom(action);
+
+	if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET DCE CLOCK
+ **
+ ********************************************************************************
+ *******************************************************************************/
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+static enum bp_result set_dce_clock_v2_1(
+	struct bios_parser *bp,
+	struct bp_set_dce_clock_parameters *bp_params);
+#endif
+
+static void init_set_dce_clock(struct bios_parser *bp)
+{
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
+	case 1:
+		bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
+		break;
+	default:
+		bp->cmd_tbl.set_dce_clock = NULL;
+		break;
+	}
+#endif
+}
+
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+static enum bp_result set_dce_clock_v2_1(
+	struct bios_parser *bp,
+	struct bp_set_dce_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
+	uint32_t atom_pll_id;
+	uint32_t atom_clock_type;
+	const struct command_table_helper *cmd = bp->cmd_helper;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
+			!cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
+		return BP_RESULT_BADINPUT;
+
+	params.asParam.ucDCEClkSrc  = atom_pll_id;
+	params.asParam.ucDCEClkType = atom_clock_type;
+
+	if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
+		if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
+
+		if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
+
+		if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
+
+		if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
+	}
+	else
+		/* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
+		/* We need to convert from KHz units into 10KHz units */
+		params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
+
+	if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
+		/* Convert from 10KHz units back to KHz */
+		bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table.h b/drivers/gpu/drm/amd/dal/dc/bios/command_table.h
new file mode 100644
index 000000000000..3cb0c7f8c202
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_H__
+#define __DAL_COMMAND_TABLE_H__
+
+struct bios_parser;
+struct bp_encoder_control;
+
+struct cmd_tbl {
+	enum bp_result (*dig_encoder_control)(
+		struct bios_parser *bp,
+		struct bp_encoder_control *control);
+	enum bp_result (*encoder_control_dig1)(
+		struct bios_parser *bp,
+		struct bp_encoder_control *control);
+	enum bp_result (*encoder_control_dig2)(
+		struct bios_parser *bp,
+		struct bp_encoder_control *control);
+	enum bp_result (*transmitter_control)(
+		struct bios_parser *bp,
+		struct bp_transmitter_control *control);
+	enum bp_result (*set_pixel_clock)(
+		struct bios_parser *bp,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*enable_spread_spectrum_on_ppll)(
+		struct bios_parser *bp,
+		struct bp_spread_spectrum_parameters *bp_params,
+		bool enable);
+	enum bp_result (*adjust_display_pll)(
+		struct bios_parser *bp,
+		struct bp_adjust_pixel_clock_parameters *bp_params);
+	enum bp_result (*dac1_encoder_control)(
+		struct bios_parser *bp,
+		bool enable,
+		uint32_t pixel_clock,
+		uint8_t dac_standard);
+	enum bp_result (*dac2_encoder_control)(
+		struct bios_parser *bp,
+		bool enable,
+		uint32_t pixel_clock,
+		uint8_t dac_standard);
+	enum bp_result (*dac1_output_control)(
+		struct bios_parser *bp,
+		bool enable);
+	enum bp_result (*dac2_output_control)(
+		struct bios_parser *bp,
+		bool enable);
+	enum signal_type (*dac_load_detection)(
+		struct bios_parser *bp,
+		struct graphics_object_id encoder,
+		struct graphics_object_id connector,
+		enum signal_type display_signal);
+	enum bp_result (*blank_crtc)(
+		struct bios_parser *bp,
+		struct bp_blank_crtc_parameters *bp_params,
+		bool blank);
+	enum bp_result (*set_crtc_timing)(
+		struct bios_parser *bp,
+		struct bp_hw_crtc_timing_parameters *bp_params);
+	enum bp_result (*set_crtc_overscan)(
+		struct bios_parser *bp,
+		struct bp_hw_crtc_overscan_parameters *bp_params);
+	enum bp_result (*select_crtc_source)(
+		struct bios_parser *bp,
+		struct bp_crtc_source_select *bp_params);
+	enum bp_result (*enable_crtc)(
+		struct bios_parser *bp,
+		enum controller_id controller_id,
+		bool enable);
+	enum bp_result (*enable_crtc_mem_req)(
+		struct bios_parser *bp,
+		enum controller_id controller_id,
+		bool enable);
+	enum bp_result (*program_clock)(
+		struct bios_parser *bp,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*compute_memore_engine_pll)(
+		struct bios_parser *bp,
+		struct bp_display_clock_parameters *bp_params);
+	enum bp_result (*external_encoder_control)(
+			struct bios_parser *bp,
+			struct bp_external_encoder_control *cntl);
+	enum bp_result (*enable_disp_power_gating)(
+		struct bios_parser *bp,
+		enum controller_id crtc_id,
+		enum bp_pipe_control_action action);
+	enum bp_result (*set_dce_clock)(
+		struct bios_parser *bp,
+		struct bp_set_dce_clock_parameters *bp_params);
+};
+
+void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
new file mode 100644
index 000000000000..566604ea877a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "include/adapter_service_types.h"
+
+#include "command_table_helper.h"
+
+bool dal_bios_parser_init_cmd_tbl_helper(
+	const struct command_table_helper **h,
+	enum dce_version dce)
+{
+	switch (dce) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		*h = dal_cmd_tbl_helper_dce110_get_table();
+		return true;
+#endif
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		*h = dal_cmd_tbl_helper_dce110_get_table();
+		return true;
+#endif
+
+	default:
+		/* Unsupported DCE */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+/* real implementations */
+
+bool dal_cmd_table_helper_controller_id_to_atom(
+	enum controller_id id,
+	uint8_t *atom_id)
+{
+	if (atom_id == NULL) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	switch (id) {
+	case CONTROLLER_ID_D0:
+		*atom_id = ATOM_CRTC1;
+		return true;
+	case CONTROLLER_ID_D1:
+		*atom_id = ATOM_CRTC2;
+		return true;
+	case CONTROLLER_ID_D2:
+		*atom_id = ATOM_CRTC3;
+		return true;
+	case CONTROLLER_ID_D3:
+		*atom_id = ATOM_CRTC4;
+		return true;
+	case CONTROLLER_ID_D4:
+		*atom_id = ATOM_CRTC5;
+		return true;
+	case CONTROLLER_ID_D5:
+		*atom_id = ATOM_CRTC6;
+		return true;
+	case CONTROLLER_ID_UNDERLAY0:
+		*atom_id = ATOM_UNDERLAY_PIPE0;
+		return true;
+	case CONTROLLER_ID_UNDEFINED:
+		*atom_id = ATOM_CRTC_INVALID;
+		return true;
+	default:
+		/* Wrong controller id */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+/**
+* translate_transmitter_bp_to_atom
+*
+* @brief
+*  Translate the Transmitter to the corresponding ATOM BIOS value
+*
+* @param
+*   input transmitter
+*   output digitalTransmitter
+*    // =00: Digital Transmitter1 ( UNIPHY linkAB )
+*    // =01: Digital Transmitter2 ( UNIPHY linkCD )
+*    // =02: Digital Transmitter3 ( UNIPHY linkEF )
+*/
+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom(
+	enum transmitter t)
+{
+	switch (t) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_TRAVIS_LCD:
+		return 0;
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+		return 1;
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+		return 2;
+	default:
+		/* Invalid Transmitter Type! */
+		BREAK_TO_DEBUGGER();
+		return 0;
+	}
+}
+
+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom(
+	enum signal_type s,
+	bool enable_dp_audio)
+{
+	switch (s) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		return ATOM_ENCODER_MODE_DVI;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		return ATOM_ENCODER_MODE_HDMI;
+	case SIGNAL_TYPE_LVDS:
+		return ATOM_ENCODER_MODE_LVDS;
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+		if (enable_dp_audio)
+			return ATOM_ENCODER_MODE_DP_AUDIO;
+		else
+			return ATOM_ENCODER_MODE_DP;
+	case SIGNAL_TYPE_RGB:
+		return ATOM_ENCODER_MODE_CRT;
+	default:
+		return ATOM_ENCODER_MODE_CRT;
+	}
+}
+
+void dal_cmd_table_helper_assign_control_parameter(
+	const struct command_table_helper *h,
+	struct bp_encoder_control *control,
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param)
+{
+	/* there are three transmitter blocks, each one has two links 4-lanes
+	 * each, A+B, C+D, E+F, Uniphy A, C and E are enumerated as link 0 in
+	 * each transmitter block B, D and F as link 1, third transmitter block
+	 * has non splitable links (UniphyE and UniphyF can not be configured
+	 * separately to drive two different streams)
+	 */
+	if ((control->transmitter == TRANSMITTER_UNIPHY_B) ||
+		(control->transmitter == TRANSMITTER_UNIPHY_D) ||
+		(control->transmitter == TRANSMITTER_UNIPHY_F)) {
+		/* Bit2: Link Select
+		 * =0: PHY linkA/C/E
+		 * =1: PHY linkB/D/F
+		 */
+		ctrl_param->acConfig.ucLinkSel = 1;
+	}
+
+	/* Bit[4:3]: Transmitter Selection
+	 * =00: Digital Transmitter1 ( UNIPHY linkAB )
+	 * =01: Digital Transmitter2 ( UNIPHY linkCD )
+	 * =02: Digital Transmitter3 ( UNIPHY linkEF )
+	 * =03: Reserved
+	 */
+	ctrl_param->acConfig.ucTransmitterSel =
+		(uint8_t)(h->transmitter_bp_to_atom(control->transmitter));
+
+	/* We need to convert from KHz units into 10KHz units */
+	ctrl_param->ucAction = h->encoder_action_to_atom(control->action);
+	ctrl_param->usPixelClock = cpu_to_le16((uint16_t)(control->pixel_clock / 10));
+	ctrl_param->ucEncoderMode =
+		(uint8_t)(h->encoder_mode_bp_to_atom(
+			control->signal, control->enable_dp_audio));
+	ctrl_param->ucLaneNum = (uint8_t)(control->lanes_number);
+}
+
+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src(
+	enum clock_source_id id,
+	uint32_t *ref_clk_src_id)
+{
+	if (ref_clk_src_id == NULL) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	switch (id) {
+	case CLOCK_SOURCE_ID_PLL1:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL;
+		return true;
+	case CLOCK_SOURCE_ID_PLL2:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL;
+		return true;
+	case CLOCK_SOURCE_ID_DCPLL:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL;
+		return true;
+	case CLOCK_SOURCE_ID_EXTERNAL:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK;
+		return true;
+	case CLOCK_SOURCE_ID_UNDEFINED:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID;
+		return true;
+	default:
+		/* Unsupported clock source id */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+uint8_t dal_cmd_table_helper_encoder_id_to_atom(
+	enum encoder_id id)
+{
+	switch (id) {
+	case ENCODER_ID_INTERNAL_LVDS:
+		return ENCODER_OBJECT_ID_INTERNAL_LVDS;
+	case ENCODER_ID_INTERNAL_TMDS1:
+		return ENCODER_OBJECT_ID_INTERNAL_TMDS1;
+	case ENCODER_ID_INTERNAL_TMDS2:
+		return ENCODER_OBJECT_ID_INTERNAL_TMDS2;
+	case ENCODER_ID_INTERNAL_DAC1:
+		return ENCODER_OBJECT_ID_INTERNAL_DAC1;
+	case ENCODER_ID_INTERNAL_DAC2:
+		return ENCODER_OBJECT_ID_INTERNAL_DAC2;
+	case ENCODER_ID_INTERNAL_LVTM1:
+		return ENCODER_OBJECT_ID_INTERNAL_LVTM1;
+	case ENCODER_ID_INTERNAL_HDMI:
+		return ENCODER_OBJECT_ID_HDMI_INTERNAL;
+	case ENCODER_ID_EXTERNAL_TRAVIS:
+		return ENCODER_OBJECT_ID_TRAVIS;
+	case ENCODER_ID_EXTERNAL_NUTMEG:
+		return ENCODER_OBJECT_ID_NUTMEG;
+	case ENCODER_ID_INTERNAL_KLDSCP_TMDS1:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
+	case ENCODER_ID_EXTERNAL_MVPU_FPGA:
+		return ENCODER_OBJECT_ID_MVPU_FPGA;
+	case ENCODER_ID_INTERNAL_DDI:
+		return ENCODER_OBJECT_ID_INTERNAL_DDI;
+	case ENCODER_ID_INTERNAL_UNIPHY:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY;
+	case ENCODER_ID_INTERNAL_KLDSCP_LVTMA:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA;
+	case ENCODER_ID_INTERNAL_UNIPHY1:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY1;
+	case ENCODER_ID_INTERNAL_UNIPHY2:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY2;
+	case ENCODER_ID_INTERNAL_UNIPHY3:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY3;
+	case ENCODER_ID_INTERNAL_WIRELESS:
+		return ENCODER_OBJECT_ID_INTERNAL_VCE;
+	case ENCODER_ID_UNKNOWN:
+		return ENCODER_OBJECT_ID_NONE;
+	default:
+		/* Invalid encoder id */
+		BREAK_TO_DEBUGGER();
+		return ENCODER_OBJECT_ID_NONE;
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
new file mode 100644
index 000000000000..4646cabd2b40
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_HELPER_H__
+#define __DAL_COMMAND_TABLE_HELPER_H__
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce110/command_table_helper_dce110.h"
+#endif
+
+struct command_table_helper {
+	bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id);
+	uint8_t (*encoder_action_to_atom)(
+			enum bp_encoder_control_action action);
+	uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s,
+			bool enable_dp_audio);
+	bool (*engine_bp_to_atom)(enum engine_id engine_id,
+			uint32_t *atom_engine_id);
+	void (*assign_control_parameter)(
+			const struct command_table_helper *h,
+			struct bp_encoder_control *control,
+			DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param);
+	bool (*clock_source_id_to_atom)(enum clock_source_id id,
+			uint32_t *atom_pll_id);
+	bool (*clock_source_id_to_ref_clk_src)(
+			enum clock_source_id id,
+			uint32_t *ref_clk_src_id);
+	uint8_t (*transmitter_bp_to_atom)(enum transmitter t);
+	uint8_t (*encoder_id_to_atom)(enum encoder_id id);
+	uint8_t (*clock_source_id_to_atom_phy_clk_src_id)(
+			enum clock_source_id id);
+	uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s);
+	uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id);
+	uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id);
+	uint8_t (*phy_id_to_atom)(enum transmitter t);
+	uint8_t (*disp_power_gating_action_to_atom)(
+			enum bp_pipe_control_action action);
+	bool (*dc_clock_type_to_atom)(enum bp_dce_clock_type id,
+			uint32_t *atom_clock_type);
+    uint8_t (*transmitter_color_depth_to_atom)(enum transmitter_color_depth id);
+};
+
+bool dal_bios_parser_init_cmd_tbl_helper(const struct command_table_helper **h,
+	enum dce_version dce);
+
+bool dal_cmd_table_helper_controller_id_to_atom(
+	enum controller_id id,
+	uint8_t *atom_id);
+
+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom(
+	enum signal_type s,
+	bool enable_dp_audio);
+
+void dal_cmd_table_helper_assign_control_parameter(
+	const struct command_table_helper *h,
+	struct bp_encoder_control *control,
+DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param);
+
+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src(
+	enum clock_source_id id,
+	uint32_t *ref_clk_src_id);
+
+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom(
+	enum transmitter t);
+
+uint8_t dal_cmd_table_helper_encoder_id_to_atom(
+	enum encoder_id id);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
new file mode 100644
index 000000000000..85d3103a1de7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
@@ -0,0 +1,484 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "include/adapter_service_types.h"
+#include "include/logger_interface.h"
+
+#include "../bios_parser_helper.h"
+
+#include "dce/dce_11_0_d.h"
+#include "bif/bif_5_1_d.h"
+
+/**
+ * set_scratch_acc_mode_change
+ *
+ * @brief
+ *  set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when
+ *  VGA/non-Accelerated mode is set
+ *
+ * @param
+ *  struct dc_context *ctx - [in] DAL context
+ */
+static void set_scratch_acc_mode_change(
+	struct dc_context *ctx)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = 0;
+
+	value = dm_read_reg(ctx, addr);
+
+	value |= ATOM_S6_ACC_MODE;
+
+	dm_write_reg(ctx, addr, value);
+}
+
+/*
+ * set_scratch_active_and_requested
+ *
+ * @brief
+ * Set VBIOS scratch pad registers about active and requested displays
+ *
+ * @param
+ * struct dc_context *ctx - [in] DAL context for register accessing
+ * struct vbios_helper_data *d - [in] values to write
+ */
+static void set_scratch_active_and_requested(
+	struct dc_context *ctx,
+	struct vbios_helper_data *d)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* mmBIOS_SCRATCH_3 = mmBIOS_SCRATCH_0 + ATOM_ACTIVE_INFO_DEF */
+	addr = mmBIOS_SCRATCH_3;
+
+	value = dm_read_reg(ctx, addr);
+
+	value &= ~ATOM_S3_DEVICE_ACTIVE_MASK;
+	value |= (d->active & ATOM_S3_DEVICE_ACTIVE_MASK);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* mmBIOS_SCRATCH_6 =  mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF */
+	addr = mmBIOS_SCRATCH_6;
+
+	value = dm_read_reg(ctx, addr);
+
+	value &= ~ATOM_S6_ACC_REQ_MASK;
+	value |= (d->requested & ATOM_S6_ACC_REQ_MASK);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* mmBIOS_SCRATCH_5 =  mmBIOS_SCRATCH_0 + ATOM_DOS_REQ_INFO_DEF */
+	addr = mmBIOS_SCRATCH_5;
+
+	value = dm_read_reg(ctx, addr);
+
+	value &= ~ATOM_S5_DOS_REQ_DEVICEw0;
+	value |= (d->active & ATOM_S5_DOS_REQ_DEVICEw0);
+
+	dm_write_reg(ctx, addr, value);
+
+	d->active = 0;
+	d->requested = 0;
+}
+
+/**
+ * get LCD Scale Mode from VBIOS scratch register
+ */
+static enum lcd_scale get_scratch_lcd_scale(
+	struct dc_context *ctx)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = 0;
+
+	value = dm_read_reg(ctx, addr);
+
+	if (value & ATOM_S6_REQ_LCD_EXPANSION_FULL)
+		return LCD_SCALE_FULLPANEL;
+	else if (value & ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO)
+		return LCD_SCALE_ASPECTRATIO;
+	else
+		return LCD_SCALE_NONE;
+}
+
+/**
+ * prepare_scratch_active_and_requested
+ *
+ * @brief
+ *  prepare and update VBIOS scratch pad registers about active and requested
+ *  displays
+ *
+ * @param
+ * data - helper's shared data
+ * enum controller_ild - controller Id
+ * enum signal_type - signal type used on display
+ * const struct connector_device_tag_info* - pointer to display type and enum id
+ */
+static void prepare_scratch_active_and_requested(
+	struct dc_context *ctx,
+	struct vbios_helper_data *data,
+	enum controller_id id,
+	enum signal_type s,
+	const struct connector_device_tag_info *dev_tag)
+{
+	switch (s) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		if (dev_tag->dev_id.device_type == DEVICE_TYPE_DFP)
+			switch (dev_tag->dev_id.enum_id) {
+			case 1:
+				data->requested |= ATOM_S6_ACC_REQ_DFP1;
+				data->active |= ATOM_S3_DFP1_ACTIVE;
+				break;
+			case 2:
+				data->requested |= ATOM_S6_ACC_REQ_DFP2;
+				data->active |= ATOM_S3_DFP2_ACTIVE;
+				break;
+			case 3:
+				data->requested |= ATOM_S6_ACC_REQ_DFP3;
+				data->active |= ATOM_S3_DFP3_ACTIVE;
+				break;
+			case 4:
+				data->requested |= ATOM_S6_ACC_REQ_DFP4;
+				data->active |= ATOM_S3_DFP4_ACTIVE;
+				break;
+			case 5:
+				data->requested |= ATOM_S6_ACC_REQ_DFP5;
+				data->active |= ATOM_S3_DFP5_ACTIVE;
+				break;
+			case 6:
+				data->requested |= ATOM_S6_ACC_REQ_DFP6;
+				data->active |= ATOM_S3_DFP6_ACTIVE;
+				break;
+			default:
+				break;
+			}
+		break;
+	case SIGNAL_TYPE_LVDS:
+	case SIGNAL_TYPE_EDP:
+		data->requested |= ATOM_S6_ACC_REQ_LCD1;
+		data->active |= ATOM_S3_LCD1_ACTIVE;
+		break;
+	case SIGNAL_TYPE_RGB:
+		if (dev_tag->dev_id.device_type == DEVICE_TYPE_CRT)
+			switch (dev_tag->dev_id.enum_id) {
+			case 1:
+				data->requested |= ATOM_S6_ACC_REQ_CRT1;
+				data->active |= ATOM_S3_CRT1_ACTIVE;
+				break;
+			case 2:
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_BIOS,
+					LOG_MINOR_COMPONENT_BIOS,
+					"%s: DAL does not support DAC2!\n",
+					__func__);
+				break;
+			default:
+				break;
+			}
+		break;
+	default:
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_BIOS,
+				LOG_MINOR_COMPONENT_BIOS,
+				"%s: No such signal!\n",
+				__func__);
+		break;
+	}
+}
+
+/*
+ * is_accelerated_mode
+ *
+ * @brief
+ *  set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when
+ *  VGA/non-Accelerated mode is set
+ *
+ * @param
+ * struct dc_context *ctx
+ *
+ * @return
+ * true if in acceleration mode, false otherwise.
+ */
+static bool is_accelerated_mode(
+	struct dc_context *ctx)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	return (value & ATOM_S6_ACC_MODE) ? true : false;
+}
+
+#define BIOS_SCRATCH0_DAC_B_SHIFT 8
+
+/**
+ * detect_sink
+ *
+ * @brief
+ *  read VBIOS scratch register to determine whether display for the specified
+ *  signal is present and return the actual sink signal type
+ *  For analog signals VBIOS load detection has to be called prior reading the
+ *  register
+ *
+ * @param
+ *  encoder - encoder id (to specify DAC)
+ *  connector - connector id (to check CV on DIN)
+ *  signal - signal (as display type) to check
+ *
+ * @return
+ *  signal_type - actual (on the sink) signal type detected
+ */
+static enum signal_type detect_sink(
+	struct dc_context *ctx,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type signal)
+{
+	uint32_t bios_scratch0;
+	uint32_t encoder_id = encoder.id;
+	/* after DCE 10.x does not support DAC2, so assert and return
+	 * SIGNAL_TYPE_NONE */
+	if (encoder_id == ENCODER_ID_INTERNAL_DAC2
+		|| encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC2) {
+		ASSERT(false);
+		return SIGNAL_TYPE_NONE;
+	}
+
+	bios_scratch0 = dm_read_reg(ctx,
+		mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF);
+
+	/* In further processing we use DACB masks. If we want detect load on
+	 * DACA, we need to shift the register so DACA bits will be in place of
+	 * DACB bits
+	 */
+	if (encoder_id == ENCODER_ID_INTERNAL_DAC1
+		|| encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC1
+		|| encoder_id == ENCODER_ID_EXTERNAL_NUTMEG
+		|| encoder_id == ENCODER_ID_EXTERNAL_TRAVIS) {
+		bios_scratch0 <<= BIOS_SCRATCH0_DAC_B_SHIFT;
+	}
+
+	switch (signal) {
+	case SIGNAL_TYPE_RGB: {
+		if (bios_scratch0 & ATOM_S0_CRT2_MASK)
+			return SIGNAL_TYPE_RGB;
+		break;
+	}
+	case SIGNAL_TYPE_LVDS: {
+		if (bios_scratch0 & ATOM_S0_LCD1)
+			return SIGNAL_TYPE_LVDS;
+		break;
+	}
+	case SIGNAL_TYPE_EDP: {
+		if (bios_scratch0 & ATOM_S0_LCD1)
+			return SIGNAL_TYPE_EDP;
+		break;
+	}
+	default:
+		break;
+	}
+
+	return SIGNAL_TYPE_NONE;
+}
+
+/**
+ * set_scratch_connected
+ *
+ * @brief
+ *    update BIOS_SCRATCH_0 register about connected displays
+ *
+ * @param
+ * bool - update scratch register or just prepare info to be updated
+ * bool - connection state
+ * const struct connector_device_tag_info * - pointer to device type and enum ID
+ */
+static void set_scratch_connected(
+	struct dc_context *ctx,
+	struct graphics_object_id id,
+	bool connected,
+	const struct connector_device_tag_info *device_tag)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	uint32_t update = 0;
+
+	switch (device_tag->dev_id.device_type) {
+	case DEVICE_TYPE_LCD:
+		/* For LCD VBIOS will update LCD Panel connected bit always and
+		 * Lid state bit based on SBIOS info do not do anything here
+		 * for LCD
+		 */
+		break;
+	case DEVICE_TYPE_CRT:
+		/*
+		 * CRT is not supported in DCE11
+		 */
+		break;
+	case DEVICE_TYPE_DFP:
+		switch (device_tag->dev_id.enum_id) {
+		case 1:
+			update |= ATOM_S0_DFP1;
+			break;
+		case 2:
+			update |= ATOM_S0_DFP2;
+			break;
+		case 3:
+			update |= ATOM_S0_DFP3;
+			break;
+		case 4:
+			update |= ATOM_S0_DFP4;
+			break;
+		case 5:
+			update |= ATOM_S0_DFP5;
+			break;
+		case 6:
+			update |= ATOM_S0_DFP6;
+			break;
+		default:
+			break;
+		}
+		break;
+	case DEVICE_TYPE_CV:
+		/* DCE 8.0 does not support CV,
+		 * so don't do anything */
+		break;
+
+	case DEVICE_TYPE_TV:
+		/* For TV VBIOS will update S-Video or
+		 * Composite scratch bits on DAL_LoadDetect
+		 * when called by driver, do not do anything
+		 * here for TV
+		 */
+		break;
+
+	default:
+		break;
+
+	}
+
+	/* update scratch register */
+	addr = mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF;
+
+	value = dm_read_reg(ctx, addr);
+
+	if (connected)
+		value |= update;
+	else
+		value &= ~update;
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_scratch_critical_state(
+	struct dc_context *ctx,
+	bool state)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	if (state)
+		value |= ATOM_S6_CRITICAL_STATE;
+	else
+		value &= ~ATOM_S6_CRITICAL_STATE;
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_scratch_lcd_scale(
+	struct dc_context *ctx,
+	enum lcd_scale lcd_scale_request)
+{
+	DAL_LOGGER_NOT_IMPL(
+		LOG_MINOR_COMPONENT_BIOS,
+		"Bios Parser:%s\n",
+		__func__);
+}
+
+static bool is_lid_open(struct dc_context *ctx)
+{
+	uint32_t bios_scratch6;
+
+	bios_scratch6 =
+		dm_read_reg(
+			ctx,
+			mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF);
+
+	/* lid is open if the bit is not set */
+	if (!(bios_scratch6 & ATOM_S6_LID_STATE))
+		return true;
+
+	return false;
+}
+
+/* function table */
+static const struct bios_parser_helper bios_parser_helper_funcs = {
+	.detect_sink = detect_sink,
+	.fmt_bit_depth_control = NULL,
+	.fmt_control = NULL,
+	.get_bios_event_info = NULL,
+	.get_embedded_display_controller_id = NULL,
+	.get_embedded_display_refresh_rate = NULL,
+	.get_requested_backlight_level = NULL,
+	.get_scratch_lcd_scale = get_scratch_lcd_scale,
+	.is_accelerated_mode = is_accelerated_mode,
+	.is_active_display = NULL,
+	.is_display_config_changed = NULL,
+	.is_lid_open = is_lid_open,
+	.is_lid_status_changed = NULL,
+	.prepare_scratch_active_and_requested =
+			prepare_scratch_active_and_requested,
+	.set_scratch_acc_mode_change = set_scratch_acc_mode_change,
+	.set_scratch_active_and_requested = set_scratch_active_and_requested,
+	.set_scratch_connected = set_scratch_connected,
+	.set_scratch_critical_state = set_scratch_critical_state,
+	.set_scratch_lcd_scale = set_scratch_lcd_scale,
+	.take_backlight_control = NULL,
+	.update_requested_backlight_level = NULL,
+};
+
+/*
+ * dal_bios_parser_dce110_init_bios_helper
+ *
+ * @brief
+ * Initialize BIOS helper functions
+ *
+ * @param
+ * const struct command_table_helper **h - [out] struct of functions
+ *
+ */
+
+const struct bios_parser_helper *dal_bios_parser_helper_dce110_get_table()
+{
+	return &bios_parser_helper_funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
new file mode 100644
index 000000000000..915f31ab9c1a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_HELPER_DCE110_H__
+#define __DAL_BIOS_PARSER_HELPER_DCE110_H__
+
+struct bios_parser_helper;
+
+/* Initialize BIOS helper functions */
+const struct bios_parser_helper *dal_bios_parser_helper_dce110_get_table(void);
+
+#endif /* __DAL_BIOS_PARSER_HELPER_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
new file mode 100644
index 000000000000..614ba94ac0c3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "include/adapter_service_types.h"
+
+#include "../command_table_helper.h"
+
+static uint8_t phy_id_to_atom(enum transmitter t)
+{
+	uint8_t atom_phy_id;
+
+	switch (t) {
+	case TRANSMITTER_UNIPHY_A:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYA;
+		break;
+	case TRANSMITTER_UNIPHY_B:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYB;
+		break;
+	case TRANSMITTER_UNIPHY_C:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYC;
+		break;
+	case TRANSMITTER_UNIPHY_D:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYD;
+		break;
+	case TRANSMITTER_UNIPHY_E:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYE;
+		break;
+	case TRANSMITTER_UNIPHY_F:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYF;
+		break;
+	case TRANSMITTER_UNIPHY_G:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYG;
+		break;
+	default:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYA;
+		break;
+	}
+	return atom_phy_id;
+}
+
+
+static uint8_t signal_type_to_atom_dig_mode(enum signal_type s)
+{
+	uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
+
+	switch (s) {
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_EDP:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
+		break;
+	case SIGNAL_TYPE_LVDS:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS;
+		break;
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
+		break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI;
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST;
+		break;
+	default:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
+		break;
+	}
+
+	return atom_dig_mode;
+}
+
+static uint8_t clock_source_id_to_atom_phy_clk_src_id(
+		enum clock_source_id id)
+{
+	uint8_t atom_phy_clk_src_id = 0;
+
+	switch (id) {
+	case CLOCK_SOURCE_ID_PLL0:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL;
+		break;
+	case CLOCK_SOURCE_ID_PLL1:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
+		break;
+	case CLOCK_SOURCE_ID_PLL2:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL;
+		break;
+	case CLOCK_SOURCE_ID_EXTERNAL:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT;
+		break;
+	default:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
+		break;
+	}
+
+	return atom_phy_clk_src_id >> 2;
+}
+
+static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
+{
+	uint8_t atom_hpd_sel = 0;
+
+	switch (id) {
+	case HPD_SOURCEID1:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL;
+		break;
+	case HPD_SOURCEID2:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL;
+		break;
+	case HPD_SOURCEID3:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL;
+		break;
+	case HPD_SOURCEID4:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL;
+		break;
+	case HPD_SOURCEID5:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL;
+		break;
+	case HPD_SOURCEID6:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL;
+		break;
+	case HPD_SOURCEID_UNKNOWN:
+	default:
+		atom_hpd_sel = 0;
+		break;
+	}
+	return atom_hpd_sel >> 4;
+}
+
+static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
+{
+	uint8_t atom_dig_encoder_sel = 0;
+
+	switch (id) {
+	case ENGINE_ID_DIGA:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
+		break;
+	case ENGINE_ID_DIGB:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL;
+		break;
+	case ENGINE_ID_DIGC:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL;
+		break;
+	case ENGINE_ID_DIGD:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL;
+		break;
+	case ENGINE_ID_DIGE:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL;
+		break;
+	case ENGINE_ID_DIGF:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL;
+		break;
+	case ENGINE_ID_DIGG:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL;
+		break;
+	case ENGINE_ID_UNKNOWN:
+		 /* No DIG_FRONT is associated to DIG_BACKEND */
+		atom_dig_encoder_sel = 0;
+		break;
+	default:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
+		break;
+	}
+
+	return atom_dig_encoder_sel;
+}
+
+static bool clock_source_id_to_atom(
+	enum clock_source_id id,
+	uint32_t *atom_pll_id)
+{
+	bool result = true;
+
+	if (atom_pll_id != NULL)
+		switch (id) {
+		case CLOCK_SOURCE_ID_PLL0:
+			*atom_pll_id = ATOM_PPLL0;
+			break;
+		case CLOCK_SOURCE_ID_PLL1:
+			*atom_pll_id = ATOM_PPLL1;
+			break;
+		case CLOCK_SOURCE_ID_PLL2:
+			*atom_pll_id = ATOM_PPLL2;
+			break;
+		case CLOCK_SOURCE_ID_EXTERNAL:
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			break;
+		case CLOCK_SOURCE_ID_DFS:
+			*atom_pll_id = ATOM_EXT_PLL1;
+			break;
+		case CLOCK_SOURCE_ID_VCE:
+			/* for VCE encoding,
+			 * we need to pass in ATOM_PPLL_INVALID
+			 */
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			break;
+		case CLOCK_SOURCE_ID_DP_DTO:
+			/* When programming DP DTO PLL ID should be invalid */
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			break;
+		case CLOCK_SOURCE_ID_UNDEFINED:
+			/* Should not happen */
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			result = false;
+			break;
+		default:
+			result = false;
+			break;
+		}
+
+	return result;
+}
+
+static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id)
+{
+	bool result = false;
+
+	if (atom_engine_id != NULL)
+		switch (id) {
+		case ENGINE_ID_DIGA:
+			*atom_engine_id = ASIC_INT_DIG1_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGB:
+			*atom_engine_id = ASIC_INT_DIG2_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGC:
+			*atom_engine_id = ASIC_INT_DIG3_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGD:
+			*atom_engine_id = ASIC_INT_DIG4_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGE:
+			*atom_engine_id = ASIC_INT_DIG5_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGF:
+			*atom_engine_id = ASIC_INT_DIG6_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGG:
+			*atom_engine_id = ASIC_INT_DIG7_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DACA:
+			*atom_engine_id = ASIC_INT_DAC1_ENCODER_ID;
+			result = true;
+			break;
+		default:
+			break;
+		}
+
+	return result;
+}
+
+static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action)
+{
+	uint8_t atom_action = 0;
+
+	switch (action) {
+	case ENCODER_CONTROL_ENABLE:
+		atom_action = ATOM_ENABLE;
+		break;
+	case ENCODER_CONTROL_DISABLE:
+		atom_action = ATOM_DISABLE;
+		break;
+	case ENCODER_CONTROL_SETUP:
+		atom_action = ATOM_ENCODER_CMD_SETUP;
+		break;
+	case ENCODER_CONTROL_INIT:
+		atom_action = ATOM_ENCODER_INIT;
+		break;
+	default:
+		BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */
+		break;
+	}
+
+	return atom_action;
+}
+
+static uint8_t disp_power_gating_action_to_atom(
+	enum bp_pipe_control_action action)
+{
+	uint8_t atom_pipe_action = 0;
+
+	switch (action) {
+	case ASIC_PIPE_DISABLE:
+		atom_pipe_action = ATOM_DISABLE;
+		break;
+	case ASIC_PIPE_ENABLE:
+		atom_pipe_action = ATOM_ENABLE;
+		break;
+	case ASIC_PIPE_INIT:
+		atom_pipe_action = ATOM_INIT;
+		break;
+	default:
+		ASSERT_CRITICAL(false); /* Unhandle action in driver! */
+		break;
+	}
+
+	return atom_pipe_action;
+}
+
+/* function table */
+static const struct command_table_helper command_table_helper_funcs = {
+	.controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom,
+	.encoder_action_to_atom = encoder_action_to_atom,
+	.engine_bp_to_atom = engine_bp_to_atom,
+	.clock_source_id_to_atom = clock_source_id_to_atom,
+	.clock_source_id_to_atom_phy_clk_src_id =
+			clock_source_id_to_atom_phy_clk_src_id,
+	.signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode,
+	.hpd_sel_to_atom = hpd_sel_to_atom,
+	.dig_encoder_sel_to_atom = dig_encoder_sel_to_atom,
+	.phy_id_to_atom = phy_id_to_atom,
+	.disp_power_gating_action_to_atom = disp_power_gating_action_to_atom,
+	.assign_control_parameter = NULL,
+	.clock_source_id_to_ref_clk_src = NULL,
+	.transmitter_bp_to_atom = NULL,
+	.encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom,
+	.encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom,
+};
+
+/*
+ * dal_cmd_tbl_helper_dce110_get_table
+ *
+ * @brief
+ * Initialize command table helper functions
+ *
+ * @param
+ * const struct command_table_helper **h - [out] struct of functions
+ *
+ */
+const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table()
+{
+	return &command_table_helper_funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
new file mode 100644
index 000000000000..eb60c2ead992
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_HELPER_DCE110_H__
+#define __DAL_COMMAND_TABLE_HELPER_DCE110_H__
+
+struct command_table_helper;
+
+/* Initialize command table helper functions */
+const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table(void);
+
+#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 08/26] drm/amd/dal: I2C Aux Manager
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (6 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 07/26] drm/amd/dal: BIOS Parser Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 09/26] drm/amd/dal: IRQ Service Harry Wentland
                     ` (17 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Implements low-level communication layer over I2C and Aux lines using
GPIO handles.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |  33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     | 567 ++++++++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     | 119 +++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   | 788 +++++++++++++++++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |  56 ++
 .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |  25 +
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    | 954 +++++++++++++++++++++
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |  58 ++
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    | 172 ++++
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |  43 +
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   | 266 ++++++
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |  39 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    | 112 +++
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |  33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         | 129 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |  67 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     | 121 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     | 113 +++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  | 286 ++++++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |  77 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  | 246 ++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |  80 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  | 614 +++++++++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |  81 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         | 529 ++++++++++++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         | 123 +++
 26 files changed, 5731 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h

diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile b/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
new file mode 100644
index 000000000000..390d83d649f5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
@@ -0,0 +1,33 @@
+#
+# Makefile for the 'i2c' sub-component of DAL.
+# It provides the control and status of HW i2c engine of the adapter.
+
+I2CAUX = aux_engine.o engine_base.o i2caux.o i2c_engine.o \
+	 i2c_generic_hw_engine.o i2c_hw_engine.o i2c_sw_engine.o
+
+AMD_DAL_I2CAUX = $(addprefix $(AMDDALPATH)/dc/i2caux/,$(I2CAUX))
+
+AMD_DAL_FILES += $(AMD_DAL_I2CAUX)
+
+
+###############################################################################
+# DCE 11x family
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+I2CAUX_DCE110 = i2caux_dce110.o i2c_sw_engine_dce110.o i2c_hw_engine_dce110.o \
+	aux_engine_dce110.o
+
+AMD_DAL_I2CAUX_DCE110 = $(addprefix $(AMDDALPATH)/dc/i2caux/dce110/,$(I2CAUX_DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_I2CAUX_DCE110)
+endif
+
+###############################################################################
+# Diagnostics on FPGA
+###############################################################################
+I2CAUX_DIAG = i2caux_diag.o
+
+AMD_DAL_I2CAUX_DIAG = $(addprefix $(AMDDALPATH)/dc/i2caux/diagnostics/,$(I2CAUX_DIAG))
+
+AMD_DAL_FILES += $(AMD_DAL_I2CAUX_DIAG)
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
new file mode 100644
index 000000000000..7042d10ee7dc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "aux_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "include/link_service_types.h"
+
+/*
+ * This unit
+ */
+
+enum {
+	AUX_INVALID_REPLY_RETRY_COUNTER = 1,
+	AUX_TIMED_OUT_RETRY_COUNTER = 2,
+	AUX_DEFER_RETRY_COUNTER = 6
+};
+
+#define FROM_ENGINE(ptr) \
+	container_of((ptr), struct aux_engine, base)
+
+enum i2caux_engine_type dal_aux_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_AUX;
+}
+
+bool dal_aux_engine_acquire(
+	struct engine *engine,
+	struct ddc *ddc)
+{
+	struct aux_engine *aux_engine = FROM_ENGINE(engine);
+
+	enum gpio_result result;
+
+	result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
+		GPIO_DDC_CONFIG_TYPE_MODE_AUX);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	if (!aux_engine->funcs->acquire_engine(aux_engine)) {
+		dal_ddc_close(ddc);
+		return false;
+	}
+
+	engine->ddc = ddc;
+
+	return true;
+}
+
+struct read_command_context {
+	uint8_t *buffer;
+	uint8_t current_read_length;
+	uint32_t offset;
+	enum i2caux_transaction_status status;
+
+	struct aux_request_transaction_data request;
+	struct aux_reply_transaction_data reply;
+
+	uint8_t returned_byte;
+
+	uint32_t timed_out_retry_aux;
+	uint32_t invalid_reply_retry_aux;
+	uint32_t defer_retry_aux;
+	uint32_t defer_retry_i2c;
+	uint32_t invalid_reply_retry_aux_on_ack;
+
+	bool transaction_complete;
+	bool operation_succeeded;
+};
+
+static void process_read_reply(
+	struct aux_engine *engine,
+	struct read_command_context *ctx)
+{
+	engine->funcs->process_channel_reply(engine, &ctx->reply);
+
+	switch (ctx->reply.status) {
+	case AUX_TRANSACTION_REPLY_AUX_ACK:
+		ctx->defer_retry_aux = 0;
+		if (ctx->returned_byte > ctx->current_read_length) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else if (ctx->returned_byte < ctx->current_read_length) {
+			ctx->current_read_length -= ctx->returned_byte;
+
+			ctx->offset += ctx->returned_byte;
+
+			++ctx->invalid_reply_retry_aux_on_ack;
+
+			if (ctx->invalid_reply_retry_aux_on_ack >
+				AUX_INVALID_REPLY_RETRY_COUNTER) {
+				ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+				ctx->operation_succeeded = false;
+			}
+		} else {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+			ctx->transaction_complete = true;
+			ctx->operation_succeeded = true;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_NACK:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+		ctx->operation_succeeded = false;
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_DEFER:
+		++ctx->defer_retry_aux;
+
+		if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_I2C_DEFER:
+		ctx->defer_retry_aux = 0;
+
+		++ctx->defer_retry_i2c;
+
+		if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static void process_read_request(
+	struct aux_engine *engine,
+	struct read_command_context *ctx)
+{
+	enum aux_channel_operation_result operation_result;
+
+	engine->funcs->submit_channel_request(engine, &ctx->request);
+
+	operation_result = engine->funcs->get_channel_status(
+		engine, &ctx->returned_byte);
+
+	switch (operation_result) {
+	case AUX_CHANNEL_OPERATION_SUCCEEDED:
+		if (ctx->returned_byte > ctx->current_read_length) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else {
+			ctx->timed_out_retry_aux = 0;
+			ctx->invalid_reply_retry_aux = 0;
+
+			ctx->reply.length = ctx->returned_byte;
+			ctx->reply.data = ctx->buffer;
+
+			process_read_reply(engine, ctx);
+		}
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
+		++ctx->invalid_reply_retry_aux;
+
+		if (ctx->invalid_reply_retry_aux >
+			AUX_INVALID_REPLY_RETRY_COUNTER) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else
+			dm_delay_in_microseconds(engine->base.ctx, 400);
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
+		++ctx->timed_out_retry_aux;
+
+		if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		} else {
+			/* DP 1.2a, table 2-58:
+			 * "S3: AUX Request CMD PENDING:
+			 * retry 3 times, with 400usec wait on each"
+			 * The HW timeout is set to 550usec,
+			 * so we should not wait here */
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static bool read_command(
+	struct aux_engine *engine,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction)
+{
+	struct read_command_context ctx;
+
+	ctx.buffer = request->payload.data;
+	ctx.current_read_length = request->payload.length;
+	ctx.offset = 0;
+	ctx.timed_out_retry_aux = 0;
+	ctx.invalid_reply_retry_aux = 0;
+	ctx.defer_retry_aux = 0;
+	ctx.defer_retry_i2c = 0;
+	ctx.invalid_reply_retry_aux_on_ack = 0;
+	ctx.transaction_complete = false;
+	ctx.operation_succeeded = true;
+
+	if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_DP;
+		ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ;
+		ctx.request.address = request->payload.address;
+	} else if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
+		ctx.request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_READ;
+		ctx.request.address = request->payload.address >> 1;
+	} else {
+		/* in DAL2, there was no return in such case */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	ctx.request.delay = 0;
+
+	do {
+		dm_memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length);
+
+		ctx.request.data = ctx.buffer + ctx.offset;
+		ctx.request.length = ctx.current_read_length;
+
+		process_read_request(engine, &ctx);
+
+		request->status = ctx.status;
+
+		if (ctx.operation_succeeded && !ctx.transaction_complete)
+			if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
+				dm_sleep_in_milliseconds(engine->base.ctx, engine->delay);
+	} while (ctx.operation_succeeded && !ctx.transaction_complete);
+
+	return ctx.operation_succeeded;
+}
+
+struct write_command_context {
+	bool mot;
+
+	uint8_t *buffer;
+	uint8_t current_write_length;
+	enum i2caux_transaction_status status;
+
+	struct aux_request_transaction_data request;
+	struct aux_reply_transaction_data reply;
+
+	uint8_t returned_byte;
+
+	uint32_t timed_out_retry_aux;
+	uint32_t invalid_reply_retry_aux;
+	uint32_t defer_retry_aux;
+	uint32_t defer_retry_i2c;
+	uint32_t max_defer_retry;
+	uint32_t ack_m_retry;
+
+	uint8_t reply_data[DEFAULT_AUX_MAX_DATA_SIZE];
+
+	bool transaction_complete;
+	bool operation_succeeded;
+};
+
+static void process_write_reply(
+	struct aux_engine *engine,
+	struct write_command_context *ctx)
+{
+	engine->funcs->process_channel_reply(engine, &ctx->reply);
+
+	switch (ctx->reply.status) {
+	case AUX_TRANSACTION_REPLY_AUX_ACK:
+		ctx->operation_succeeded = true;
+
+		if (ctx->returned_byte) {
+			ctx->request.action = ctx->mot ?
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
+
+			ctx->current_write_length = 0;
+
+			++ctx->ack_m_retry;
+
+			if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) {
+				ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+				ctx->operation_succeeded = false;
+			} else
+				dm_delay_in_microseconds(engine->base.ctx, 300);
+		} else {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+			ctx->defer_retry_aux = 0;
+			ctx->ack_m_retry = 0;
+			ctx->transaction_complete = true;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_NACK:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+		ctx->operation_succeeded = false;
+	break;
+	case AUX_TRANSACTION_REPLY_AUX_DEFER:
+		++ctx->defer_retry_aux;
+
+		if (ctx->defer_retry_aux > ctx->max_defer_retry) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	case AUX_TRANSACTION_REPLY_I2C_DEFER:
+		ctx->defer_retry_aux = 0;
+		ctx->current_write_length = 0;
+
+		ctx->request.action = ctx->mot ?
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
+
+		++ctx->defer_retry_i2c;
+
+		if (ctx->defer_retry_i2c > ctx->max_defer_retry) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static void process_write_request(
+	struct aux_engine *engine,
+	struct write_command_context *ctx)
+{
+	enum aux_channel_operation_result operation_result;
+
+	engine->funcs->submit_channel_request(engine, &ctx->request);
+
+	operation_result = engine->funcs->get_channel_status(
+		engine, &ctx->returned_byte);
+
+	switch (operation_result) {
+	case AUX_CHANNEL_OPERATION_SUCCEEDED:
+		ctx->timed_out_retry_aux = 0;
+		ctx->invalid_reply_retry_aux = 0;
+
+		ctx->reply.length = ctx->returned_byte;
+		ctx->reply.data = ctx->reply_data;
+
+		process_write_reply(engine, ctx);
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
+		++ctx->invalid_reply_retry_aux;
+
+		if (ctx->invalid_reply_retry_aux >
+			AUX_INVALID_REPLY_RETRY_COUNTER) {
+			ctx->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR;
+			ctx->operation_succeeded = false;
+		} else
+			dm_delay_in_microseconds(engine->base.ctx, 400);
+	break;
+	case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
+		++ctx->timed_out_retry_aux;
+
+		if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) {
+			ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			ctx->operation_succeeded = false;
+		} else {
+			/* DP 1.2a, table 2-58:
+			 * "S3: AUX Request CMD PENDING:
+			 * retry 3 times, with 400usec wait on each"
+			 * The HW timeout is set to 550usec,
+			 * so we should not wait here */
+		}
+	break;
+	default:
+		ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN;
+		ctx->operation_succeeded = false;
+	}
+}
+
+static bool write_command(
+	struct aux_engine *engine,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction)
+{
+	struct write_command_context ctx;
+
+	ctx.mot = middle_of_transaction;
+	ctx.buffer = request->payload.data;
+	ctx.current_write_length = request->payload.length;
+	ctx.timed_out_retry_aux = 0;
+	ctx.invalid_reply_retry_aux = 0;
+	ctx.defer_retry_aux = 0;
+	ctx.defer_retry_i2c = 0;
+	ctx.ack_m_retry = 0;
+	ctx.transaction_complete = false;
+	ctx.operation_succeeded = true;
+
+	if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_DP;
+		ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE;
+		ctx.request.address = request->payload.address;
+	} else if (request->payload.address_space ==
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) {
+		ctx.request.type = AUX_TRANSACTION_TYPE_I2C;
+		ctx.request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+		ctx.request.address = request->payload.address >> 1;
+	} else {
+		/* in DAL2, there was no return in such case */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	ctx.request.delay = 0;
+
+	ctx.max_defer_retry =
+		(engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ?
+			engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER;
+
+	do {
+		ctx.request.data = ctx.buffer;
+		ctx.request.length = ctx.current_write_length;
+
+		process_write_request(engine, &ctx);
+
+		request->status = ctx.status;
+
+		if (ctx.operation_succeeded && !ctx.transaction_complete)
+			if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C)
+				dm_sleep_in_milliseconds(engine->base.ctx, engine->delay);
+	} while (ctx.operation_succeeded && !ctx.transaction_complete);
+
+	return ctx.operation_succeeded;
+}
+
+static bool end_of_transaction_command(
+	struct aux_engine *engine,
+	struct i2caux_transaction_request *request)
+{
+	struct i2caux_transaction_request dummy_request;
+	uint8_t dummy_data;
+
+	/* [tcheng] We only need to send the stop (read with MOT = 0)
+	 * for I2C-over-Aux, not native AUX */
+
+	if (request->payload.address_space !=
+		I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C)
+		return false;
+
+	dummy_request.operation = request->operation;
+	dummy_request.payload.address_space = request->payload.address_space;
+	dummy_request.payload.address = request->payload.address;
+
+	/*
+	 * Add a dummy byte due to some receiver quirk
+	 * where one byte is sent along with MOT = 0.
+	 * Ideally this should be 0.
+	 */
+
+	dummy_request.payload.length = 0;
+	dummy_request.payload.data = &dummy_data;
+
+	if (request->operation == I2CAUX_TRANSACTION_READ)
+		return read_command(engine, &dummy_request, false);
+	else
+		return write_command(engine, &dummy_request, false);
+
+	/* according Syed, it does not need now DoDummyMOT */
+}
+
+bool dal_aux_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction)
+{
+	struct aux_engine *aux_engine = FROM_ENGINE(engine);
+
+	bool result;
+	bool mot_used = true;
+
+	switch (request->operation) {
+	case I2CAUX_TRANSACTION_READ:
+		result = read_command(aux_engine, request, mot_used);
+	break;
+	case I2CAUX_TRANSACTION_WRITE:
+		result = write_command(aux_engine, request, mot_used);
+	break;
+	default:
+		result = false;
+	}
+
+	/* [tcheng]
+	 * need to send stop for the last transaction to free up the AUX
+	 * if the above command fails, this would be the last transaction */
+
+	if (!middle_of_transaction || !result)
+		end_of_transaction_command(aux_engine, request);
+
+	/* mask AUX interrupt */
+
+	return result;
+}
+
+bool dal_aux_engine_construct(
+	struct aux_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2caux_construct_engine(&engine->base, ctx))
+		return false;
+	engine->delay = 0;
+	engine->max_defer_write_retry = 0;
+	return true;
+}
+
+void dal_aux_engine_destruct(
+	struct aux_engine *engine)
+{
+	dal_i2caux_destruct_engine(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
new file mode 100644
index 000000000000..474f5e911f49
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUX_ENGINE_H__
+#define __DAL_AUX_ENGINE_H__
+
+enum aux_transaction_type {
+	AUX_TRANSACTION_TYPE_DP,
+	AUX_TRANSACTION_TYPE_I2C
+};
+
+struct aux_request_transaction_data {
+	enum aux_transaction_type type;
+	enum i2caux_transaction_action action;
+	/* 20-bit AUX channel transaction address */
+	uint32_t address;
+	/* delay, in 100-microsecond units */
+	uint8_t delay;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum aux_transaction_reply {
+	AUX_TRANSACTION_REPLY_AUX_ACK = 0x00,
+	AUX_TRANSACTION_REPLY_AUX_NACK = 0x01,
+	AUX_TRANSACTION_REPLY_AUX_DEFER = 0x02,
+
+	AUX_TRANSACTION_REPLY_I2C_ACK = 0x00,
+	AUX_TRANSACTION_REPLY_I2C_NACK = 0x10,
+	AUX_TRANSACTION_REPLY_I2C_DEFER = 0x20,
+
+	AUX_TRANSACTION_REPLY_INVALID = 0xFF
+};
+
+struct aux_reply_transaction_data {
+	enum aux_transaction_reply status;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum aux_channel_operation_result {
+	AUX_CHANNEL_OPERATION_SUCCEEDED,
+	AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN,
+	AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY,
+	AUX_CHANNEL_OPERATION_FAILED_TIMEOUT
+};
+
+struct aux_engine;
+
+struct aux_engine_funcs {
+	void (*destroy)(
+		struct aux_engine **ptr);
+	bool (*acquire_engine)(
+		struct aux_engine *engine);
+	void (*configure)(
+		struct aux_engine *engine,
+		union aux_config cfg);
+	bool (*start_gtc_sync)(
+		struct aux_engine *engine);
+	void (*stop_gtc_sync)(
+		struct aux_engine *engine);
+	void (*submit_channel_request)(
+		struct aux_engine *engine,
+		struct aux_request_transaction_data *request);
+	void (*process_channel_reply)(
+		struct aux_engine *engine,
+		struct aux_reply_transaction_data *reply);
+	enum aux_channel_operation_result (*get_channel_status)(
+		struct aux_engine *engine,
+		uint8_t *returned_bytes);
+};
+
+struct aux_engine {
+	struct engine base;
+	const struct aux_engine_funcs *funcs;
+	/* following values are expressed in milliseconds */
+	uint32_t delay;
+	uint32_t max_defer_write_retry;
+};
+
+bool dal_aux_engine_construct(
+	struct aux_engine *engine,
+	struct dc_context *ctx);
+
+void dal_aux_engine_destruct(
+	struct aux_engine *engine);
+bool dal_aux_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *request,
+	bool middle_of_transaction);
+bool dal_aux_engine_acquire(
+	struct engine *ptr,
+	struct ddc *ddc);
+enum i2caux_engine_type dal_aux_engine_get_engine_type(
+	const struct engine *engine);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
new file mode 100644
index 000000000000..f9c55435b5a0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
@@ -0,0 +1,788 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../engine.h"
+#include "../aux_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "aux_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct aux_engine *'
+ * to 'struct aux_engine_dce110 *'
+ */
+#define FROM_AUX_ENGINE(ptr) \
+	container_of((ptr), struct aux_engine_dce110, base)
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct aux_engine_dce110 *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base))
+
+static void release_engine(
+	struct engine *engine)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_ENGINE(engine);
+
+	const uint32_t addr = aux_engine->addr.aux_arb_control;
+
+	uint32_t value = dm_read_reg(engine->ctx, addr);
+
+	set_reg_field_value(
+		value,
+		1,
+		AUX_ARB_CONTROL,
+		AUX_SW_DONE_USING_AUX_REG);
+
+	dm_write_reg(engine->ctx, addr, value);
+}
+
+static void destruct(
+	struct aux_engine_dce110 *engine);
+
+static void destroy(
+	struct aux_engine **aux_engine)
+{
+	struct aux_engine_dce110 *engine = FROM_AUX_ENGINE(*aux_engine);
+
+	destruct(engine);
+
+	dm_free((*aux_engine)->base.ctx, engine);
+
+	*aux_engine = NULL;
+}
+
+#define SW_CAN_ACCESS_AUX 1
+
+static bool acquire_engine(
+	struct aux_engine *engine)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+	uint32_t value;
+	uint32_t field;
+
+	/* enable AUX before request SW to access AUX */
+	{
+		const uint32_t addr = aux_engine->addr.aux_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		field = get_reg_field_value(
+				value,
+				AUX_CONTROL,
+				AUX_EN);
+
+		if (field == 0) {
+			uint8_t counter = 0;
+
+			set_reg_field_value(
+				value,
+				1,
+				AUX_CONTROL,
+				AUX_EN);
+
+			/*DP_AUX block as part of the enable sequence*/
+			set_reg_field_value(
+				value,
+				1,
+				AUX_CONTROL,
+				AUX_RESET);
+
+			dm_write_reg(engine->base.ctx, addr, value);
+
+			/*poll HW to make sure reset it done*/
+			do {
+				dm_delay_in_microseconds(engine->base.ctx, 1);
+
+				value = dm_read_reg(engine->base.ctx, addr);
+
+				field = get_reg_field_value(
+						value,
+						AUX_CONTROL,
+						AUX_RESET_DONE);
+
+				counter++;
+
+			} while ((field == 0) && (counter < 11));
+
+			set_reg_field_value(
+				value,
+				0,
+				AUX_CONTROL,
+				AUX_RESET);
+
+			dm_write_reg(engine->base.ctx, addr, value);
+
+			counter = 0;
+
+			do {
+				dm_delay_in_microseconds(engine->base.ctx, 1);
+
+				value = dm_read_reg(engine->base.ctx, addr);
+
+				field = get_reg_field_value(
+						value,
+						AUX_CONTROL,
+						AUX_RESET_DONE);
+
+				counter++;
+
+			} while ((field == 1) && (counter < 11));
+		} /*if (field)*/
+	}
+
+	/* request SW to access AUX */
+	{
+		const uint32_t addr = aux_engine->addr.aux_arb_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_ARB_CONTROL,
+			AUX_SW_USE_AUX_REG_REQ);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		field = get_reg_field_value(
+				value,
+				AUX_ARB_CONTROL,
+				AUX_REG_RW_CNTL_STATUS);
+
+		return field == SW_CAN_ACCESS_AUX;
+	}
+}
+
+static void configure(
+	struct aux_engine *engine,
+	union aux_config cfg)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+
+	const uint32_t addr = aux_engine->addr.aux_control;
+
+	uint32_t value = dm_read_reg(engine->base.ctx, addr);
+
+	set_reg_field_value(
+		value,
+		(0 != cfg.bits.ALLOW_AUX_WHEN_HPD_LOW),
+		AUX_CONTROL,
+		AUX_IGNORE_HPD_DISCON);
+
+	dm_write_reg(engine->base.ctx, addr, value);
+}
+
+static bool start_gtc_sync(
+	struct aux_engine *engine)
+{
+	/*TODO*/
+	return false;
+}
+
+static void stop_gtc_sync(
+	struct aux_engine *engine)
+{
+	/*TODO*/
+}
+
+#define COMPOSE_AUX_SW_DATA_16_20(command, address) \
+	((command) | ((0xF0000 & (address)) >> 16))
+
+#define COMPOSE_AUX_SW_DATA_8_15(address) \
+	((0xFF00 & (address)) >> 8)
+
+#define COMPOSE_AUX_SW_DATA_0_7(address) \
+	(0xFF & (address))
+
+static void submit_channel_request(
+	struct aux_engine *engine,
+	struct aux_request_transaction_data *request)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+	uint32_t value;
+	uint32_t length;
+
+	bool is_write =
+		((request->type == AUX_TRANSACTION_TYPE_DP) &&
+		 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
+		((request->type == AUX_TRANSACTION_TYPE_I2C) &&
+		((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
+		 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
+
+	/* clear_aux_error */
+	{
+		const uint32_t addr = mmAUXN_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXN_IMPCAL,
+			AUXN_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXN_IMPCAL,
+			AUXN_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+	{
+		const uint32_t addr = mmAUXP_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXP_IMPCAL,
+			AUXP_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXP_IMPCAL,
+			AUXP_CALOUT_ERROR_AK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	/* force_default_calibrate */
+	{
+		const uint32_t addr = mmAUXN_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXN_IMPCAL,
+			AUXN_IMPCAL_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXN_IMPCAL,
+			AUXN_IMPCAL_OVERRIDE_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+	{
+		const uint32_t addr = mmAUXP_IMPCAL;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUXP_IMPCAL,
+			AUXP_IMPCAL_OVERRIDE_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUXP_IMPCAL,
+			AUXP_IMPCAL_OVERRIDE_ENABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	/* set the delay and the number of bytes to write */
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			request->delay,
+			AUX_SW_CONTROL,
+			AUX_SW_START_DELAY);
+
+		/* The length include
+		 * the 4 bit header and the 20 bit address
+		 * (that is 3 byte).
+		 * If the requested length is non zero this means
+		 * an addition byte specifying the length is required. */
+
+		length = request->length ? 4 : 3;
+		if (is_write)
+			length += request->length;
+
+		set_reg_field_value(
+			value,
+			length,
+			AUX_SW_CONTROL,
+			AUX_SW_WR_BYTES);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	/* program action and address and payload data (if 'is_write') */
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_data;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_INDEX);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_DATA_RW);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_DATA,
+			AUX_SW_AUTOINCREMENT_DISABLE);
+
+		set_reg_field_value(
+			value,
+			COMPOSE_AUX_SW_DATA_16_20(
+				request->action, request->address),
+			AUX_SW_DATA,
+			AUX_SW_DATA);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_AUTOINCREMENT_DISABLE);
+
+		set_reg_field_value(
+			value,
+			COMPOSE_AUX_SW_DATA_8_15(request->address),
+			AUX_SW_DATA,
+			AUX_SW_DATA);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			COMPOSE_AUX_SW_DATA_0_7(request->address),
+			AUX_SW_DATA,
+			AUX_SW_DATA);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		if (request->length) {
+			set_reg_field_value(
+				value,
+				request->length - 1,
+				AUX_SW_DATA,
+				AUX_SW_DATA);
+
+			dm_write_reg(engine->base.ctx, addr, value);
+		}
+
+		if (is_write) {
+			/* Load the HW buffer with the Data to be sent.
+			 * This is relevant for write operation.
+			 * For read, the data recived data will be
+			 * processed in process_channel_reply(). */
+			uint32_t i = 0;
+
+			while (i < request->length) {
+
+				set_reg_field_value(
+					value,
+					request->data[i],
+					AUX_SW_DATA,
+					AUX_SW_DATA);
+
+				dm_write_reg(
+					engine->base.ctx, addr, value);
+
+				++i;
+			}
+		}
+	}
+
+	{
+		const uint32_t addr = aux_engine->addr.aux_interrupt_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_INTERRUPT_CONTROL,
+			AUX_SW_DONE_ACK);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_control;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_CONTROL,
+			AUX_SW_GO);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+	}
+}
+
+static void process_channel_reply(
+	struct aux_engine *engine,
+	struct aux_reply_transaction_data *reply)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+
+	/* Need to do a read to get the number of bytes to process
+	 * Alternatively, this information can be passed -
+	 * but that causes coupling which isn't good either. */
+
+	uint32_t bytes_replied;
+	uint32_t value;
+
+	{
+		const uint32_t addr = aux_engine->addr.aux_sw_status;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		bytes_replied = get_reg_field_value(
+				value,
+				AUX_SW_STATUS,
+				AUX_SW_REPLY_BYTE_COUNT);
+	}
+
+	if (bytes_replied) {
+		uint32_t reply_result;
+
+		const uint32_t addr = aux_engine->addr.aux_sw_data;
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			AUX_SW_DATA,
+			AUX_SW_INDEX);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_DATA,
+			AUX_SW_AUTOINCREMENT_DISABLE);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		set_reg_field_value(
+			value,
+			1,
+			AUX_SW_DATA,
+			AUX_SW_DATA_RW);
+
+		dm_write_reg(engine->base.ctx, addr, value);
+
+		value = dm_read_reg(engine->base.ctx, addr);
+
+		reply_result = get_reg_field_value(
+				value,
+				AUX_SW_DATA,
+				AUX_SW_DATA);
+
+		reply_result = reply_result >> 4;
+
+		switch (reply_result) {
+		case 0: /* ACK */ {
+			uint32_t i = 0;
+
+			/* first byte was already used
+			 * to get the command status */
+			--bytes_replied;
+
+			while (i < bytes_replied) {
+				value = dm_read_reg(
+					engine->base.ctx, addr);
+
+				reply->data[i] = get_reg_field_value(
+						value,
+						AUX_SW_DATA,
+						AUX_SW_DATA);
+
+				++i;
+			}
+
+			reply->status = AUX_TRANSACTION_REPLY_AUX_ACK;
+		}
+		break;
+		case 1: /* NACK */
+			reply->status = AUX_TRANSACTION_REPLY_AUX_NACK;
+		break;
+		case 2: /* DEFER */
+			reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER;
+		break;
+		case 4: /* AUX ACK / I2C NACK */
+			reply->status = AUX_TRANSACTION_REPLY_I2C_NACK;
+		break;
+		case 8: /* AUX ACK / I2C DEFER */
+			reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER;
+		break;
+		default:
+			reply->status = AUX_TRANSACTION_REPLY_INVALID;
+		}
+	} else {
+		/* Need to handle an error case...
+		 * hopefully, upper layer function won't call this function
+		 * if the number of bytes in the reply was 0
+		 * because there was surely an error that was asserted
+		 * that should have been handled
+		 * for hot plug case, this could happens*/
+		if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
+			ASSERT_CRITICAL(false);
+	}
+}
+
+static enum aux_channel_operation_result get_channel_status(
+	struct aux_engine *engine,
+	uint8_t *returned_bytes)
+{
+	struct aux_engine_dce110 *aux_engine = FROM_AUX_ENGINE(engine);
+
+	const uint32_t addr = aux_engine->addr.aux_sw_status;
+
+	uint32_t value;
+	uint32_t aux_sw_done;
+
+	if (returned_bytes == NULL) {
+		/*caller pass NULL pointer*/
+		ASSERT_CRITICAL(false);
+		return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
+	}
+	*returned_bytes = 0;
+
+	/* poll to make sure that SW_DONE is asserted */
+	{
+		uint32_t time_elapsed = 0;
+
+		do {
+			value = dm_read_reg(engine->base.ctx, addr);
+
+			aux_sw_done = get_reg_field_value(
+					value,
+					AUX_SW_STATUS,
+					AUX_SW_DONE);
+
+			if (aux_sw_done)
+				break;
+
+			dm_delay_in_microseconds(engine->base.ctx, 10);
+
+			time_elapsed += 10;
+		} while (time_elapsed < aux_engine->timeout_period);
+
+
+	}
+
+	/* Note that the following bits are set in 'status.bits'
+	 * during CTS 4.2.1.2:
+	 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
+	 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
+	 *
+	 * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
+	 * HW debugging bit and should be ignored. */
+	if (aux_sw_done) {
+		if (get_reg_field_value(
+			value,
+			AUX_SW_STATUS,
+			AUX_SW_RX_TIMEOUT_STATE) ||
+			get_reg_field_value(
+				value,
+				AUX_SW_STATUS,
+				AUX_SW_RX_TIMEOUT))
+			return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
+		else if (get_reg_field_value(
+			value,
+			AUX_SW_STATUS,
+			AUX_SW_RX_INVALID_STOP))
+			return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
+
+		*returned_bytes = get_reg_field_value(
+				value,
+				AUX_SW_STATUS,
+				AUX_SW_REPLY_BYTE_COUNT);
+		if (*returned_bytes == 0)
+			return
+			AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
+		else {
+			*returned_bytes -= 1;
+			return AUX_CHANNEL_OPERATION_SUCCEEDED;
+		}
+	} else {
+		/*time_elapsed >= aux_engine->timeout_period */
+		if (!(value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
+			ASSERT_CRITICAL(false);
+		return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
+	}
+}
+
+static const int32_t aux_channel_offset[] = {
+	mmDP_AUX0_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX1_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX2_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX3_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX4_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL,
+	mmDP_AUX5_AUX_CONTROL - mmDP_AUX0_AUX_CONTROL
+};
+
+static const struct aux_engine_funcs aux_engine_funcs = {
+	.destroy = destroy,
+	.acquire_engine = acquire_engine,
+	.configure = configure,
+	.start_gtc_sync = start_gtc_sync,
+	.stop_gtc_sync = stop_gtc_sync,
+	.submit_channel_request = submit_channel_request,
+	.process_channel_reply = process_channel_reply,
+	.get_channel_status = get_channel_status,
+};
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.submit_request = dal_aux_engine_submit_request,
+	.keep_power_up_count = dal_i2caux_keep_power_up_count,
+	.get_engine_type = dal_aux_engine_get_engine_type,
+	.acquire = dal_aux_engine_acquire,
+};
+
+static bool construct(
+	struct aux_engine_dce110 *engine,
+	const struct aux_engine_dce110_init_data *aux_init_data)
+{
+	int32_t offset;
+
+	if (aux_init_data->engine_id >=
+		sizeof(aux_channel_offset) / sizeof(int32_t)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (!dal_aux_engine_construct(
+		&engine->base, aux_init_data->ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+	engine->base.base.funcs = &engine_funcs;
+	engine->base.funcs = &aux_engine_funcs;
+	offset = aux_channel_offset[aux_init_data->engine_id];
+	engine->addr.aux_control = mmAUX_CONTROL + offset;
+	engine->addr.aux_arb_control = mmAUX_ARB_CONTROL + offset;
+	engine->addr.aux_sw_data = mmAUX_SW_DATA + offset;
+	engine->addr.aux_sw_control = mmAUX_SW_CONTROL + offset;
+	engine->addr.aux_interrupt_control = mmAUX_INTERRUPT_CONTROL + offset;
+	engine->addr.aux_sw_status = mmAUX_SW_STATUS + offset;
+	engine->addr.aux_gtc_sync_control = mmAUX_GTC_SYNC_CONTROL + offset;
+	engine->addr.aux_gtc_sync_status = mmAUX_GTC_SYNC_STATUS + offset;
+	engine->addr.aux_gtc_sync_controller_status =
+		mmAUX_GTC_SYNC_CONTROLLER_STATUS + offset;
+
+	engine->timeout_period = aux_init_data->timeout_period;
+
+	return true;
+}
+
+static void destruct(
+	struct aux_engine_dce110 *engine)
+{
+	dal_aux_engine_destruct(&engine->base);
+}
+
+struct aux_engine *dal_aux_engine_dce110_create(
+	const struct aux_engine_dce110_init_data *aux_init_data)
+{
+	struct aux_engine_dce110 *engine;
+
+	if (!aux_init_data) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	engine = dm_alloc(aux_init_data->ctx, sizeof(*engine));
+
+	if (!engine) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(engine, aux_init_data))
+		return &engine->base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(aux_init_data->ctx, engine);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
new file mode 100644
index 000000000000..ec6899ed5b40
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUX_ENGINE_DCE110_H__
+#define __DAL_AUX_ENGINE_DCE110_H__
+
+#include "../aux_engine.h"
+
+struct aux_engine_dce110 {
+	struct aux_engine base;
+	struct {
+		uint32_t aux_control;
+		uint32_t aux_arb_control;
+		uint32_t aux_sw_data;
+		uint32_t aux_sw_control;
+		uint32_t aux_interrupt_control;
+		uint32_t aux_sw_status;
+		uint32_t aux_gtc_sync_control;
+		uint32_t aux_gtc_sync_status;
+		uint32_t aux_gtc_sync_controller_status;
+	} addr;
+	uint32_t timeout_period;
+};
+
+struct aux_engine_dce110_init_data {
+	uint32_t engine_id;
+	uint32_t timeout_period;
+	struct dc_context *ctx;
+};
+
+struct aux_engine *dal_aux_engine_dce110_create(
+	const struct aux_engine_dce110_init_data *aux_init_data);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
new file mode 100644
index 000000000000..e6b6a972a0e5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
new file mode 100644
index 000000000000..2517f44f7297
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
@@ -0,0 +1,954 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "include/i2caux_interface.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_hw_engine.h"
+#include "../i2c_generic_hw_engine.h"
+/*
+ * Header of this unit
+ */
+
+#include "i2c_hw_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+/*
+ * This unit
+ */
+
+enum dc_i2c_status {
+	DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
+	DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
+	DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW
+};
+
+enum dc_i2c_arbitration {
+	DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
+	DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
+};
+
+enum {
+	/* No timeout in HW
+	 * (timeout implemented in SW by querying status) */
+	I2C_SETUP_TIME_LIMIT = 255,
+	I2C_HW_BUFFER_SIZE = 144
+};
+
+/*
+ * @brief
+ * Cast pointer to 'struct i2c_hw_engine *'
+ * to pointer 'struct i2c_hw_engine_dce110 *'
+ */
+#define FROM_I2C_HW_ENGINE(ptr) \
+	container_of((ptr), struct i2c_hw_engine_dce110, base)
+/*
+ * @brief
+ * Cast pointer to 'struct i2c_engine *'
+ * to pointer to 'struct i2c_hw_engine_dce110 *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
+
+/*
+ * @brief
+ * Cast pointer to 'struct engine *'
+ * to 'pointer to struct i2c_hw_engine_dce110 *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+
+static void disable_i2c_hw_engine(
+	struct i2c_hw_engine_dce110 *engine)
+{
+	const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
+	uint32_t value = 0;
+
+	struct dc_context *ctx = NULL;
+
+	ctx = engine->base.base.base.ctx;
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		DC_I2C_DDC1_SETUP,
+		DC_I2C_DDC1_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void release_engine(
+	struct engine *engine)
+{
+	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
+
+	struct i2c_engine *base = NULL;
+	bool safe_to_reset;
+	uint32_t value = 0;
+
+	base = &hw_engine->base.base;
+
+	/* Restore original HW engine speed */
+
+	base->funcs->set_speed(base, hw_engine->base.original_speed);
+
+	/* Release I2C */
+	{
+		value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION);
+
+		set_reg_field_value(
+				value,
+				1,
+				DC_I2C_ARBITRATION,
+				DC_I2C_SW_DONE_USING_I2C_REG);
+
+		dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value);
+	}
+
+	/* Reset HW engine */
+	{
+		uint32_t i2c_sw_status = 0;
+
+		value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
+
+		i2c_sw_status = get_reg_field_value(
+				value,
+				DC_I2C_SW_STATUS,
+				DC_I2C_SW_STATUS);
+		/* if used by SW, safe to reset */
+		safe_to_reset = (i2c_sw_status == 1);
+	}
+	{
+		value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
+
+		if (safe_to_reset)
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_CONTROL,
+				DC_I2C_SOFT_RESET);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_CONTROL,
+			DC_I2C_SW_STATUS_RESET);
+
+		dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
+	}
+
+	/* HW I2c engine - clock gating feature */
+	if (!hw_engine->engine_keep_power_up_count)
+		disable_i2c_hw_engine(hw_engine);
+}
+
+static void keep_power_up_count(
+	struct engine *engine,
+	bool keep_power_up)
+{
+	struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
+
+	if (keep_power_up)
+		++hw_engine->engine_keep_power_up_count;
+	else {
+		--hw_engine->engine_keep_power_up_count;
+
+		if (!hw_engine->engine_keep_power_up_count)
+			disable_i2c_hw_engine(hw_engine);
+	}
+}
+
+static bool setup_engine(
+	struct i2c_engine *i2c_engine)
+{
+	uint32_t value = 0;
+	struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine);
+
+	/* Program pin select */
+	{
+		const uint32_t addr = mmDC_I2C_CONTROL;
+
+		value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_GO);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SOFT_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SEND_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SW_STATUS_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_TRANSACTION_COUNT);
+
+		set_reg_field_value(
+			value,
+			engine->engine_id,
+			DC_I2C_CONTROL,
+			DC_I2C_DDC_SELECT);
+
+
+		dm_write_reg(i2c_engine->base.ctx, addr, value);
+	}
+
+	/* Program time limit */
+	{
+		const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
+
+		value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			I2C_SETUP_TIME_LIMIT,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_TIME_LIMIT);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_ENABLE);
+
+		dm_write_reg(i2c_engine->base.ctx, addr, value);
+	}
+
+	/* Program HW priority
+	 * set to High - interrupt software I2C at any time
+	 * Enable restart of SW I2C that was interrupted by HW
+	 * disable queuing of software while I2C is in use by HW */
+	{
+		value = dm_read_reg(i2c_engine->base.ctx,
+				mmDC_I2C_ARBITRATION);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_ARBITRATION,
+			DC_I2C_NO_QUEUED_SW_GO);
+
+		set_reg_field_value(
+			value,
+			DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
+			DC_I2C_ARBITRATION,
+			DC_I2C_SW_PRIORITY);
+
+		dm_write_reg(i2c_engine->base.ctx,
+				mmDC_I2C_ARBITRATION, value);
+	}
+
+	return true;
+}
+
+static uint32_t get_speed(
+	const struct i2c_engine *i2c_engine)
+{
+	const struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine);
+
+	const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
+
+	uint32_t pre_scale = 0;
+
+	uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+	pre_scale = get_reg_field_value(
+			value,
+			DC_I2C_DDC1_SPEED,
+			DC_I2C_DDC1_PRESCALE);
+
+	/* [anaumov] it seems following is unnecessary */
+	/*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
+
+	return pre_scale ?
+		engine->reference_frequency / pre_scale :
+		engine->base.default_speed;
+}
+
+static void set_speed(
+	struct i2c_engine *i2c_engine,
+	uint32_t speed)
+{
+	struct i2c_hw_engine_dce110 *engine = FROM_I2C_ENGINE(i2c_engine);
+
+	if (speed) {
+		const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
+
+		uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			engine->reference_frequency / speed,
+			DC_I2C_DDC1_SPEED,
+			DC_I2C_DDC1_PRESCALE);
+
+		set_reg_field_value(
+			value,
+			2,
+			DC_I2C_DDC1_SPEED,
+			DC_I2C_DDC1_THRESHOLD);
+
+		/*DCE11, HW add 100Khz support for I2c*/
+		if (speed > 50) {
+			set_reg_field_value(
+				value,
+				2,
+				DC_I2C_DDC1_SPEED,
+				DC_I2C_DDC1_START_STOP_TIMING_CNTL);
+		} else {
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_DDC1_SPEED,
+				DC_I2C_DDC1_START_STOP_TIMING_CNTL);
+		}
+
+		dm_write_reg(i2c_engine->base.ctx, addr, value);
+	}
+}
+
+static inline void reset_hw_engine(struct engine *engine)
+{
+	uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_CONTROL,
+		DC_I2C_SOFT_RESET);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_CONTROL,
+		DC_I2C_SW_STATUS_RESET);
+
+	dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
+}
+
+static bool is_hw_busy(struct engine *engine)
+{
+	uint32_t i2c_sw_status = 0;
+
+	uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
+
+	i2c_sw_status = get_reg_field_value(
+			value,
+			DC_I2C_SW_STATUS,
+			DC_I2C_SW_STATUS);
+
+	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
+		return false;
+
+	reset_hw_engine(engine);
+
+	value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
+
+	i2c_sw_status = get_reg_field_value(
+			value,
+			DC_I2C_SW_STATUS,
+			DC_I2C_SW_STATUS);
+
+	return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
+}
+
+/*
+ * @brief
+ * DC_GPIO_DDC MM register offsets
+ */
+static const uint32_t transaction_addr[] = {
+	mmDC_I2C_TRANSACTION0,
+	mmDC_I2C_TRANSACTION1,
+	mmDC_I2C_TRANSACTION2,
+	mmDC_I2C_TRANSACTION3
+};
+
+static bool process_transaction(
+	struct i2c_hw_engine_dce110 *engine,
+	struct i2c_request_transaction_data *request)
+{
+	uint8_t length = request->length;
+	uint8_t *buffer = request->data;
+
+	bool last_transaction = false;
+	uint32_t value = 0;
+
+	struct dc_context *ctx = NULL;
+
+	ctx = engine->base.base.base.ctx;
+
+	{
+		const uint32_t addr =
+			transaction_addr[engine->transaction_count];
+
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_TRANSACTION0,
+			DC_I2C_STOP_ON_NACK0);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_TRANSACTION0,
+			DC_I2C_START0);
+
+
+		if ((engine->transaction_count == 3) ||
+		(request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
+		(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
+
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_TRANSACTION0,
+				DC_I2C_STOP0);
+
+			last_transaction = true;
+		} else
+			set_reg_field_value(
+				value,
+				0,
+				DC_I2C_TRANSACTION0,
+				DC_I2C_STOP0);
+
+		set_reg_field_value(
+			value,
+			(0 != (request->action &
+					I2CAUX_TRANSACTION_ACTION_I2C_READ)),
+			DC_I2C_TRANSACTION0,
+			DC_I2C_RW0);
+
+		set_reg_field_value(
+			value,
+			length,
+			DC_I2C_TRANSACTION0,
+			DC_I2C_COUNT0);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* Write the I2C address and I2C data
+	 * into the hardware circular buffer, one byte per entry.
+	 * As an example, the 7-bit I2C slave address for CRT monitor
+	 * for reading DDC/EDID information is 0b1010001.
+	 * For an I2C send operation, the LSB must be programmed to 0;
+	 * for I2C receive operation, the LSB must be programmed to 1. */
+
+	{
+		value = 0;
+
+		set_reg_field_value(
+			value,
+			false,
+			DC_I2C_DATA,
+			DC_I2C_DATA_RW);
+
+		set_reg_field_value(
+			value,
+			request->address,
+			DC_I2C_DATA,
+			DC_I2C_DATA);
+
+		if (engine->transaction_count == 0) {
+			set_reg_field_value(
+				value,
+				0,
+				DC_I2C_DATA,
+				DC_I2C_INDEX);
+
+			/*enable index write*/
+			set_reg_field_value(
+				value,
+				1,
+				DC_I2C_DATA,
+				DC_I2C_INDEX_WRITE);
+
+			engine->buffer_used_write = 0;
+		}
+
+		dm_write_reg(ctx, mmDC_I2C_DATA, value);
+
+		engine->buffer_used_write++;
+
+		if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
+
+			set_reg_field_value(
+				value,
+				0,
+				DC_I2C_DATA,
+				DC_I2C_INDEX_WRITE);
+
+			while (length) {
+
+				set_reg_field_value(
+					value,
+					*buffer++,
+					DC_I2C_DATA,
+					DC_I2C_DATA);
+
+				dm_write_reg(ctx, mmDC_I2C_DATA, value);
+
+				engine->buffer_used_write++;
+				--length;
+			}
+		}
+	}
+
+	++engine->transaction_count;
+	engine->buffer_used_bytes += length + 1;
+
+	return last_transaction;
+}
+
+static void execute_transaction(
+	struct i2c_hw_engine_dce110 *engine)
+{
+	uint32_t value = 0;
+	struct dc_context *ctx = NULL;
+
+	ctx = engine->base.base.base.ctx;
+
+	{
+		const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
+
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_DATA_DRIVE_EN);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_CLK_DRIVE_EN);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_DATA_DRIVE_SEL);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_INTRA_TRANSACTION_DELAY);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_INTRA_BYTE_DELAY);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = mmDC_I2C_CONTROL;
+
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SOFT_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SW_STATUS_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_SEND_RESET);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_I2C_CONTROL,
+			DC_I2C_GO);
+
+		set_reg_field_value(
+			value,
+			engine->transaction_count - 1,
+			DC_I2C_CONTROL,
+			DC_I2C_TRANSACTION_COUNT);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* start I2C transfer */
+	{
+		const uint32_t addr = mmDC_I2C_CONTROL;
+
+		value	= dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			1,
+			DC_I2C_CONTROL,
+			DC_I2C_GO);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* all transactions were executed and HW buffer became empty
+	 * (even though it actually happens when status becomes DONE) */
+	engine->transaction_count = 0;
+	engine->buffer_used_bytes = 0;
+}
+
+static void submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *request)
+{
+	request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	if (!process_transaction(FROM_I2C_ENGINE(engine), request))
+		return;
+
+	if (is_hw_busy(&engine->base)) {
+		request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
+		return;
+	}
+
+	execute_transaction(FROM_I2C_ENGINE(engine));
+}
+
+static void process_channel_reply(
+	struct i2c_engine *engine,
+	struct i2c_reply_transaction_data *reply)
+{
+	uint8_t length = reply->length;
+	uint8_t *buffer = reply->data;
+
+	struct i2c_hw_engine_dce110 *i2c_hw_engine_dce110 =
+		FROM_I2C_ENGINE(engine);
+
+	uint32_t value = 0;
+
+	/*set index*/
+	set_reg_field_value(
+		value,
+		i2c_hw_engine_dce110->buffer_used_write,
+		DC_I2C_DATA,
+		DC_I2C_INDEX);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_DATA,
+		DC_I2C_DATA_RW);
+
+	set_reg_field_value(
+		value,
+		1,
+		DC_I2C_DATA,
+		DC_I2C_INDEX_WRITE);
+
+	dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value);
+
+	while (length) {
+		/* after reading the status,
+		 * if the I2C operation executed successfully
+		 * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
+		 * should read data bytes from I2C circular data buffer */
+
+		value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA);
+
+		*buffer++ = get_reg_field_value(
+				value,
+				DC_I2C_DATA,
+				DC_I2C_DATA);
+
+		--length;
+	}
+}
+
+static enum i2c_channel_operation_result get_channel_status(
+	struct i2c_engine *engine,
+	uint8_t *returned_bytes)
+{
+	uint32_t i2c_sw_status = 0;
+	uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS);
+
+	i2c_sw_status = get_reg_field_value(
+			value,
+			DC_I2C_SW_STATUS,
+			DC_I2C_SW_STATUS);
+
+	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
+		return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK)
+		return I2C_CHANNEL_OPERATION_NO_RESPONSE;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK)
+		return I2C_CHANNEL_OPERATION_TIMEOUT;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK)
+		return I2C_CHANNEL_OPERATION_FAILED;
+	else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK)
+		return I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	/* in DAL2, I2C_RESULT_OK was returned */
+	return I2C_CHANNEL_OPERATION_NOT_STARTED;
+}
+
+static uint8_t get_hw_buffer_available_size(
+	const struct i2c_hw_engine *engine)
+{
+	return I2C_HW_BUFFER_SIZE -
+		FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes;
+}
+
+static uint32_t get_transaction_timeout(
+	const struct i2c_hw_engine *engine,
+	uint32_t length)
+{
+	uint32_t speed = engine->base.funcs->get_speed(&engine->base);
+
+	uint32_t period_timeout;
+	uint32_t num_of_clock_stretches;
+
+	if (!speed)
+		return 0;
+
+	period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
+
+	num_of_clock_stretches = 1 + (length << 3) + 1;
+	num_of_clock_stretches +=
+		(FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) +
+		(FROM_I2C_HW_ENGINE(engine)->transaction_count << 1);
+
+	return period_timeout * num_of_clock_stretches;
+}
+
+static void destroy(
+	struct i2c_engine **i2c_engine)
+{
+	struct i2c_hw_engine_dce110 *engine_dce110 =
+			FROM_I2C_ENGINE(*i2c_engine);
+
+	dal_i2c_hw_engine_destruct(&engine_dce110->base);
+
+	dm_free((*i2c_engine)->base.ctx, engine_dce110);
+
+	*i2c_engine = NULL;
+}
+/*
+ * @brief
+ * DC_I2C_DDC1_SETUP MM register offsets
+ *
+ * @note
+ * The indices of this offset array are DDC engine IDs
+ */
+static const int32_t ddc_setup_offset[] = {
+
+	mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */
+	mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */
+	mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */
+	mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */
+	mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */
+	mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */
+	mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */
+};
+
+/*
+ * @brief
+ * DC_I2C_DDC1_SPEED MM register offsets
+ *
+ * @note
+ * The indices of this offset array are DDC engine IDs
+ */
+static const int32_t ddc_speed_offset[] = {
+	mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */
+	mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */
+	mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */
+	mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */
+	mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */
+	mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */
+	mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */
+};
+
+static const struct i2c_engine_funcs i2c_engine_funcs = {
+	.destroy = destroy,
+	.get_speed = get_speed,
+	.set_speed = set_speed,
+	.setup_engine = setup_engine,
+	.submit_channel_request = submit_channel_request,
+	.process_channel_reply = process_channel_reply,
+	.get_channel_status = get_channel_status,
+	.acquire_engine = dal_i2c_hw_engine_acquire_engine,
+};
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.keep_power_up_count = keep_power_up_count,
+	.get_engine_type = dal_i2c_hw_engine_get_engine_type,
+	.acquire = dal_i2c_engine_acquire,
+	.submit_request = dal_i2c_hw_engine_submit_request,
+};
+
+static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = {
+	.get_hw_buffer_available_size = get_hw_buffer_available_size,
+	.get_transaction_timeout = get_transaction_timeout,
+	.wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result,
+};
+
+static bool construct(
+	struct i2c_hw_engine_dce110 *engine_dce110,
+	const struct i2c_hw_engine_dce110_create_arg *arg)
+{
+	uint32_t xtal_ref_div = 0;
+	uint32_t value = 0;
+
+	/*ddc_setup_offset of dce80 and dce110 have the same register name
+	 * but different offset. Do not need different array*/
+	if (arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t))
+		return false;
+	if (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t))
+		return false;
+	if (!arg->reference_frequency)
+		return false;
+
+	if (!dal_i2c_hw_engine_construct(&engine_dce110->base, arg->ctx))
+		return false;
+
+	engine_dce110->base.base.base.funcs = &engine_funcs;
+	engine_dce110->base.base.funcs = &i2c_engine_funcs;
+	engine_dce110->base.funcs = &i2c_hw_engine_funcs;
+	engine_dce110->base.default_speed = arg->default_speed;
+
+	engine_dce110->engine_id = arg->engine_id;
+
+	engine_dce110->buffer_used_bytes = 0;
+	engine_dce110->transaction_count = 0;
+	engine_dce110->engine_keep_power_up_count = 1;
+
+	/*values which are not included by arg*/
+	engine_dce110->addr.DC_I2C_DDCX_SETUP =
+		mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id];
+	engine_dce110->addr.DC_I2C_DDCX_SPEED =
+		mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id];
+
+
+	value = dm_read_reg(
+		engine_dce110->base.base.base.ctx,
+		mmMICROSECOND_TIME_BASE_DIV);
+
+	xtal_ref_div = get_reg_field_value(
+			value,
+			MICROSECOND_TIME_BASE_DIV,
+			XTAL_REF_DIV);
+
+	if (xtal_ref_div == 0) {
+		dal_logger_write(
+				engine_dce110->base.base.base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_I2C_AUX,
+				"Invalid base timer divider\n",
+				__func__);
+		xtal_ref_div = 2;
+	}
+
+	/*Calculating Reference Clock by divding original frequency by
+	 * XTAL_REF_DIV.
+	 * At upper level, uint32_t reference_frequency =
+	 *  dal_i2caux_get_reference_clock(as) >> 1
+	 *  which already divided by 2. So we need x2 to get original
+	 *  reference clock from ppll_info
+	 */
+	engine_dce110->reference_frequency =
+		(arg->reference_frequency * 2) / xtal_ref_div;
+
+
+	return true;
+}
+
+struct i2c_engine *dal_i2c_hw_engine_dce110_create(
+	const struct i2c_hw_engine_dce110_create_arg *arg)
+{
+	struct i2c_hw_engine_dce110 *engine_dce10;
+
+	if (!arg) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	engine_dce10 = dm_alloc(arg->ctx, sizeof(struct i2c_hw_engine_dce110));
+
+	if (!engine_dce10) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(engine_dce10, arg))
+		return &engine_dce10->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(arg->ctx, engine_dce10);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
new file mode 100644
index 000000000000..fc2ae365f8ed
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_HW_ENGINE_DCE110_H__
+#define __DAL_I2C_HW_ENGINE_DCE110_H__
+
+struct i2c_hw_engine_dce110 {
+	struct i2c_hw_engine base;
+	struct {
+		uint32_t DC_I2C_DDCX_SETUP;
+		uint32_t DC_I2C_DDCX_SPEED;
+	} addr;
+	uint32_t engine_id;
+	/* expressed in kilohertz */
+	uint32_t reference_frequency;
+	/* number of bytes currently used in HW buffer */
+	uint32_t buffer_used_bytes;
+	/* number of bytes used for write transaction in HW buffer
+	 * - this will be used as the index to read from*/
+	uint32_t buffer_used_write;
+	/* number of pending transactions (before GO) */
+	uint32_t transaction_count;
+	uint32_t engine_keep_power_up_count;
+};
+
+struct i2c_hw_engine_dce110_create_arg {
+	uint32_t engine_id;
+	uint32_t reference_frequency;
+	uint32_t default_speed;
+	struct dc_context *ctx;
+};
+
+struct i2c_engine *dal_i2c_hw_engine_dce110_create(
+	const struct i2c_hw_engine_dce110_create_arg *arg);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
new file mode 100644
index 000000000000..f060b25d1618
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_sw_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_sw_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct i2c_sw_engine *'
+ * to 'struct i2c_sw_engine_dce110 *'
+ */
+#define FROM_I2C_SW_ENGINE(ptr) \
+	container_of((ptr), struct i2c_sw_engine_dce110, base)
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_sw_engine_dce80 *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	FROM_I2C_SW_ENGINE(container_of((ptr), struct i2c_sw_engine, base))
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_sw_engine_dce80 *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+static void release_engine(
+	struct engine *engine)
+{
+}
+
+static void destruct(
+	struct i2c_sw_engine_dce110 *engine)
+{
+	dal_i2c_sw_engine_destruct(&engine->base);
+}
+
+static void destroy(
+	struct i2c_engine **engine)
+{
+	struct i2c_sw_engine_dce110 *sw_engine = FROM_I2C_ENGINE(*engine);
+
+	destruct(sw_engine);
+
+	dm_free((*engine)->base.ctx, sw_engine);
+
+	*engine = NULL;
+}
+
+static bool acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc_handle)
+{
+	return dal_i2caux_i2c_sw_engine_acquire_engine(engine, ddc_handle);
+}
+
+static const struct i2c_engine_funcs i2c_engine_funcs = {
+	.acquire_engine = acquire_engine,
+	.destroy = destroy,
+	.get_speed = dal_i2c_sw_engine_get_speed,
+	.set_speed = dal_i2c_sw_engine_set_speed,
+	.setup_engine = dal_i2c_engine_setup_i2c_engine,
+	.submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
+	.process_channel_reply = dal_i2c_engine_process_channel_reply,
+	.get_channel_status = dal_i2c_sw_engine_get_channel_status,
+};
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.get_engine_type = dal_i2c_sw_engine_get_engine_type,
+	.acquire = dal_i2c_engine_acquire,
+	.submit_request = dal_i2c_sw_engine_submit_request,
+	.keep_power_up_count = dal_i2caux_keep_power_up_count,
+};
+
+static bool construct(
+	struct i2c_sw_engine_dce110 *engine_dce110,
+	const struct i2c_sw_engine_dce110_create_arg *arg_dce110)
+{
+	struct i2c_sw_engine_create_arg arg_base;
+
+	arg_base.ctx = arg_dce110->ctx;
+	arg_base.default_speed = arg_dce110->default_speed;
+
+	if (!dal_i2c_sw_engine_construct(
+			&engine_dce110->base, &arg_base)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	/*struct engine   struct engine_funcs*/
+	engine_dce110->base.base.base.funcs = &engine_funcs;
+	/*struct i2c_engine  struct i2c_engine_funcs*/
+	engine_dce110->base.base.funcs = &i2c_engine_funcs;
+	engine_dce110->base.default_speed = arg_dce110->default_speed;
+	engine_dce110->engine_id = arg_dce110->engine_id;
+
+	return true;
+}
+
+struct i2c_engine *dal_i2c_sw_engine_dce110_create(
+	const struct i2c_sw_engine_dce110_create_arg *arg)
+{
+	struct i2c_sw_engine_dce110 *engine_dce110;
+
+	if (!arg) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	engine_dce110 = dm_alloc(arg->ctx, sizeof(struct i2c_sw_engine_dce110));
+
+	if (!engine_dce110) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(engine_dce110, arg))
+		return &engine_dce110->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(arg->ctx, engine_dce110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
new file mode 100644
index 000000000000..c48c61f540a8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_SW_ENGINE_DCE110_H__
+#define __DAL_I2C_SW_ENGINE_DCE110_H__
+
+struct i2c_sw_engine_dce110 {
+	struct i2c_sw_engine base;
+	uint32_t engine_id;
+};
+
+struct i2c_sw_engine_dce110_create_arg {
+	uint32_t engine_id;
+	uint32_t default_speed;
+	struct dc_context *ctx;
+};
+
+struct i2c_engine *dal_i2c_sw_engine_dce110_create(
+	const struct i2c_sw_engine_dce110_create_arg *arg);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
new file mode 100644
index 000000000000..9c88762dbd0c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../i2caux.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_sw_engine.h"
+#include "../i2c_hw_engine.h"
+
+/*
+ * Header of this unit
+ */
+#include "i2caux_dce110.h"
+
+#include "i2c_sw_engine_dce110.h"
+#include "i2c_hw_engine_dce110.h"
+#include "aux_engine_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+/*cast pointer to struct i2caux TO pointer to struct i2caux_dce110*/
+#define FROM_I2C_AUX(ptr) \
+	container_of((ptr), struct i2caux_dce110, base)
+
+static void destruct(
+	struct i2caux_dce110 *i2caux_dce110)
+{
+	dal_i2caux_destruct(&i2caux_dce110->base);
+}
+
+static void destroy(
+	struct i2caux **i2c_engine)
+{
+	struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(*i2c_engine);
+
+	destruct(i2caux_dce110);
+
+	dm_free((*i2c_engine)->ctx, i2caux_dce110);
+
+	*i2c_engine = NULL;
+}
+
+static struct i2c_engine *acquire_i2c_hw_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux);
+
+	struct i2c_engine *engine = NULL;
+	/* generic hw engine is not used for EDID read
+	 * It may be needed for external i2c device, like thermal chip,
+	 * TODO will be implemented when needed.
+	 * check dce80 bool non_generic for generic hw engine;
+	 */
+
+	if (!ddc)
+		return NULL;
+
+	if (dal_ddc_is_hw_supported(ddc)) {
+		enum gpio_ddc_line line = dal_ddc_get_line(ddc);
+
+		if (line < GPIO_DDC_LINE_COUNT)
+			engine = i2caux->i2c_hw_engines[line];
+	}
+
+	if (!engine)
+		return NULL;
+
+	if (!i2caux_dce110->i2c_hw_buffer_in_use &&
+		engine->base.funcs->acquire(&engine->base, ddc)) {
+		i2caux_dce110->i2c_hw_buffer_in_use = true;
+		return engine;
+	}
+
+	return NULL;
+}
+
+static void release_engine(
+	struct i2caux *i2caux,
+	struct engine *engine)
+{
+	struct i2caux_dce110 *i2caux_dce110 = FROM_I2C_AUX(i2caux);
+
+	if (engine->funcs->get_engine_type(engine) ==
+		I2CAUX_ENGINE_TYPE_I2C_DDC_HW)
+		i2caux_dce110->i2c_hw_buffer_in_use = false;
+
+	dal_i2caux_release_engine(i2caux, engine);
+}
+
+static const enum gpio_ddc_line hw_ddc_lines[] = {
+	GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_DDC2,
+	GPIO_DDC_LINE_DDC3,
+	GPIO_DDC_LINE_DDC4,
+	GPIO_DDC_LINE_DDC5,
+	GPIO_DDC_LINE_DDC6,
+};
+
+static const enum gpio_ddc_line hw_aux_lines[] = {
+	GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_DDC2,
+	GPIO_DDC_LINE_DDC3,
+	GPIO_DDC_LINE_DDC4,
+	GPIO_DDC_LINE_DDC5,
+	GPIO_DDC_LINE_DDC6,
+};
+
+/* function table */
+static const struct i2caux_funcs i2caux_funcs = {
+	.destroy = destroy,
+	.acquire_i2c_hw_engine = acquire_i2c_hw_engine,
+	.release_engine = release_engine,
+	.acquire_i2c_sw_engine = dal_i2caux_acquire_i2c_sw_engine,
+	.acquire_aux_engine = dal_i2caux_acquire_aux_engine,
+};
+
+static bool construct(
+	struct i2caux_dce110 *i2caux_dce110,
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	uint32_t i = 0;
+	uint32_t reference_frequency = 0;
+	bool use_i2c_sw_engine = false;
+	struct i2caux *base = NULL;
+	/*TODO: For CZ bring up, if dal_i2caux_get_reference_clock
+	 * does not return 48KHz, we need hard coded for 48Khz.
+	 * Some BIOS setting incorrect cause this
+	 * For production, we always get value from BIOS*/
+	reference_frequency =
+		dal_i2caux_get_reference_clock(as) >> 1;
+
+	use_i2c_sw_engine = dal_adapter_service_is_feature_supported(
+		FEATURE_RESTORE_USAGE_I2C_SW_ENGINE);
+
+	base = &i2caux_dce110->base;
+
+	if (!dal_i2caux_construct(base, as, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	i2caux_dce110->base.funcs = &i2caux_funcs;
+	i2caux_dce110->i2c_hw_buffer_in_use = false;
+	/* Create I2C engines (DDC lines per connector)
+	 * different I2C/AUX usage cases, DDC, Generic GPIO, AUX.
+	 */
+	do {
+		enum gpio_ddc_line line_id = hw_ddc_lines[i];
+
+		struct i2c_hw_engine_dce110_create_arg hw_arg_dce110;
+
+		if (use_i2c_sw_engine) {
+			struct i2c_sw_engine_dce110_create_arg sw_arg;
+
+			sw_arg.engine_id = i;
+			sw_arg.default_speed = base->default_i2c_sw_speed;
+			sw_arg.ctx = ctx;
+			base->i2c_sw_engines[line_id] =
+				dal_i2c_sw_engine_dce110_create(&sw_arg);
+		}
+
+		hw_arg_dce110.engine_id = i;
+		hw_arg_dce110.reference_frequency = reference_frequency;
+		hw_arg_dce110.default_speed = base->default_i2c_hw_speed;
+		hw_arg_dce110.ctx = ctx;
+
+		base->i2c_hw_engines[line_id] =
+			dal_i2c_hw_engine_dce110_create(&hw_arg_dce110);
+
+		++i;
+	} while (i < ARRAY_SIZE(hw_ddc_lines));
+
+	/* Create AUX engines for all lines which has assisted HW AUX
+	 * 'i' (loop counter) used as DDC/AUX engine_id */
+
+	i = 0;
+
+	do {
+		enum gpio_ddc_line line_id = hw_aux_lines[i];
+
+		struct aux_engine_dce110_init_data aux_init_data;
+
+		aux_init_data.engine_id = i;
+		aux_init_data.timeout_period = base->aux_timeout_period;
+		aux_init_data.ctx = ctx;
+
+		base->aux_engines[line_id] =
+			dal_aux_engine_dce110_create(&aux_init_data);
+
+		++i;
+	} while (i < ARRAY_SIZE(hw_aux_lines));
+
+	/*TODO Generic I2C SW and HW*/
+
+	return true;
+}
+
+/*
+ * dal_i2caux_dce110_create
+ *
+ * @brief
+ * public interface to allocate memory for DCE11 I2CAUX
+ *
+ * @param
+ * struct adapter_service *as - [in]
+ * struct dc_context *ctx - [in]
+ *
+ * @return
+ * pointer to the base struct of DCE11 I2CAUX
+ */
+struct i2caux *dal_i2caux_dce110_create(
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	struct i2caux_dce110 *i2caux_dce110 =
+		dm_alloc(ctx, sizeof(struct i2caux_dce110));
+
+	if (!i2caux_dce110) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(i2caux_dce110, as, ctx))
+		return &i2caux_dce110->base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, i2caux_dce110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
new file mode 100644
index 000000000000..1a7ba1baf3d0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_AUX_DCE110_H__
+#define __DAL_I2C_AUX_DCE110_H__
+
+struct i2caux_dce110 {
+	struct i2caux base;
+	/* indicate the I2C HW circular buffer is in use */
+	bool i2c_hw_buffer_in_use;
+};
+
+struct i2caux *dal_i2caux_dce110_create(
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+#endif /* __DAL_I2C_AUX_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
new file mode 100644
index 000000000000..f4bc39d786c8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "../i2caux.h"
+#include "../engine.h"
+#include "../i2c_engine.h"
+#include "../i2c_sw_engine.h"
+#include "../i2c_hw_engine.h"
+
+/*
+ * Header of this unit
+ */
+#include "i2caux_diag.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+static void destruct(
+	struct i2caux *i2caux)
+{
+	dal_i2caux_destruct(i2caux);
+}
+
+static void destroy(
+	struct i2caux **i2c_engine)
+{
+	destruct(*i2c_engine);
+
+	dm_free((*i2c_engine)->ctx, *i2c_engine);
+
+	*i2c_engine = NULL;
+}
+
+
+
+/* function table */
+static const struct i2caux_funcs i2caux_funcs = {
+	.destroy = destroy,
+	.acquire_i2c_hw_engine = NULL,
+	.release_engine = NULL,
+	.acquire_i2c_sw_engine = NULL,
+	.acquire_aux_engine = NULL,
+};
+
+static bool construct(
+	struct i2caux *i2caux,
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	if (!dal_i2caux_construct(i2caux, as, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	i2caux->funcs = &i2caux_funcs;
+
+	return true;
+}
+
+struct i2caux *dal_i2caux_diag_fpga_create(
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	struct i2caux *i2caux =	dm_alloc(ctx, sizeof(struct i2caux));
+
+	if (!i2caux) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(i2caux, as, ctx))
+		return i2caux;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, i2caux);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
new file mode 100644
index 000000000000..3de250bd7660
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_AUX_DIAG_FPGA_H__
+#define __DAL_I2C_AUX_DIAG_FPGA_H__
+
+struct i2caux *dal_i2caux_diag_fpga_create(
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+#endif /* __DAL_I2C_AUX_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
new file mode 100644
index 000000000000..d3635f884579
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ENGINE_H__
+#define __DAL_ENGINE_H__
+
+enum i2caux_transaction_operation {
+	I2CAUX_TRANSACTION_READ,
+	I2CAUX_TRANSACTION_WRITE
+};
+
+enum i2caux_transaction_address_space {
+	I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1,
+	I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD
+};
+
+struct i2caux_transaction_payload {
+	enum i2caux_transaction_address_space address_space;
+	uint32_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum i2caux_transaction_status {
+	I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L),
+	I2CAUX_TRANSACTION_STATUS_SUCCEEDED,
+	I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY,
+	I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT,
+	I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR,
+	I2CAUX_TRANSACTION_STATUS_FAILED_NACK,
+	I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE,
+	I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION,
+	I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION,
+	I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW
+};
+
+struct i2caux_transaction_request {
+	enum i2caux_transaction_operation operation;
+	struct i2caux_transaction_payload payload;
+	enum i2caux_transaction_status status;
+};
+
+enum i2caux_engine_type {
+	I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L),
+	I2CAUX_ENGINE_TYPE_AUX,
+	I2CAUX_ENGINE_TYPE_I2C_DDC_HW,
+	I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW,
+	I2CAUX_ENGINE_TYPE_I2C_SW
+};
+
+enum i2c_default_speed {
+	I2CAUX_DEFAULT_I2C_HW_SPEED = 50,
+	I2CAUX_DEFAULT_I2C_SW_SPEED = 50
+};
+
+enum i2caux_transaction_action {
+	I2CAUX_TRANSACTION_ACTION_I2C_WRITE = 0x00,
+	I2CAUX_TRANSACTION_ACTION_I2C_READ = 0x10,
+	I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST = 0x20,
+
+	I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT = 0x40,
+	I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT = 0x50,
+	I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT = 0x60,
+
+	I2CAUX_TRANSACTION_ACTION_DP_WRITE = 0x80,
+	I2CAUX_TRANSACTION_ACTION_DP_READ = 0x90
+};
+
+struct engine;
+
+struct engine_funcs {
+	enum i2caux_engine_type (*get_engine_type)(
+		const struct engine *engine);
+	bool (*acquire)(
+		struct engine *engine,
+		struct ddc *ddc);
+	bool (*submit_request)(
+		struct engine *engine,
+		struct i2caux_transaction_request *request,
+		bool middle_of_transaction);
+	/* [anaumov] Actually, following method is meaningful
+	 * only in I2C HW engines */
+	void (*keep_power_up_count)(
+		struct engine *engine,
+		bool keep_power_up);
+	void (*release_engine)(
+		struct engine *engine);
+};
+
+struct engine {
+	const struct engine_funcs *funcs;
+	struct ddc *ddc;
+	struct dc_context *ctx;
+};
+
+bool dal_i2caux_construct_engine(
+	struct engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2caux_destruct_engine(
+	struct engine *engine);
+
+void dal_i2caux_keep_power_up_count(
+	struct engine *engine,
+	bool keep_power_up);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c b/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
new file mode 100644
index 000000000000..9c472b9db5ba
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+void dal_i2caux_keep_power_up_count(
+	struct engine *engine,
+	bool keep_power_up)
+{
+
+}
+
+bool dal_i2caux_construct_engine(
+	struct engine *engine,
+	struct dc_context *ctx)
+{
+	engine->ddc = NULL;
+	engine->ctx = ctx;
+	return true;
+}
+
+void dal_i2caux_destruct_engine(
+	struct engine *engine)
+{
+	/* nothing to do */
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
new file mode 100644
index 000000000000..dccb1c51a3be
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define FROM_ENGINE(ptr) \
+	container_of((ptr), struct i2c_engine, base)
+
+bool dal_i2c_engine_acquire(
+	struct engine *engine,
+	struct ddc *ddc_handle)
+{
+	struct i2c_engine *i2c_engine = FROM_ENGINE(engine);
+
+	uint32_t counter = 0;
+	bool result;
+
+	do {
+		result = i2c_engine->funcs->acquire_engine(
+			i2c_engine, ddc_handle);
+
+		if (result)
+			break;
+
+		/* i2c_engine is busy by VBios, lets wait and retry */
+
+		dm_delay_in_microseconds(engine->ctx, 10);
+
+		++counter;
+	} while (counter < 2);
+
+	if (result) {
+		if (!i2c_engine->funcs->setup_engine(i2c_engine)) {
+			engine->funcs->release_engine(engine);
+			result = false;
+		}
+	}
+
+	return result;
+}
+
+bool dal_i2c_engine_setup_i2c_engine(
+	struct i2c_engine *engine)
+{
+	/* Derivative classes do not have to override this */
+
+	return true;
+}
+
+void dal_i2c_engine_submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *request)
+{
+
+}
+
+void dal_i2c_engine_process_channel_reply(
+	struct i2c_engine *engine,
+	struct i2c_reply_transaction_data *reply)
+{
+
+}
+
+bool dal_i2c_engine_construct(
+	struct i2c_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2caux_construct_engine(&engine->base, ctx))
+		return false;
+
+	engine->timeout_delay = 0;
+	return true;
+}
+
+void dal_i2c_engine_destruct(
+	struct i2c_engine *engine)
+{
+	dal_i2caux_destruct_engine(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
new file mode 100644
index 000000000000..20299fd08e9c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_ENGINE_H__
+#define __DAL_I2C_ENGINE_H__
+
+enum i2c_channel_operation_result {
+	I2C_CHANNEL_OPERATION_SUCCEEDED,
+	I2C_CHANNEL_OPERATION_FAILED,
+	I2C_CHANNEL_OPERATION_NOT_GRANTED,
+	I2C_CHANNEL_OPERATION_IS_BUSY,
+	I2C_CHANNEL_OPERATION_NO_HANDLE_PROVIDED,
+	I2C_CHANNEL_OPERATION_CHANNEL_IN_USE,
+	I2C_CHANNEL_OPERATION_CHANNEL_CLIENT_MAX_ALLOWED,
+	I2C_CHANNEL_OPERATION_ENGINE_BUSY,
+	I2C_CHANNEL_OPERATION_TIMEOUT,
+	I2C_CHANNEL_OPERATION_NO_RESPONSE,
+	I2C_CHANNEL_OPERATION_HW_REQUEST_I2C_BUS,
+	I2C_CHANNEL_OPERATION_WRONG_PARAMETER,
+	I2C_CHANNEL_OPERATION_OUT_NB_OF_RETRIES,
+	I2C_CHANNEL_OPERATION_NOT_STARTED
+};
+
+struct i2c_request_transaction_data {
+	enum i2caux_transaction_action action;
+	enum i2c_channel_operation_result status;
+	uint8_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+struct i2c_reply_transaction_data {
+	uint8_t length;
+	uint8_t *data;
+};
+
+struct i2c_engine;
+
+struct i2c_engine_funcs {
+	void (*destroy)(
+		struct i2c_engine **ptr);
+	uint32_t (*get_speed)(
+		const struct i2c_engine *engine);
+	void (*set_speed)(
+		struct i2c_engine *engine,
+		uint32_t speed);
+	bool (*acquire_engine)(
+		struct i2c_engine *engine,
+		struct ddc *ddc);
+	bool (*setup_engine)(
+		struct i2c_engine *engine);
+	void (*submit_channel_request)(
+		struct i2c_engine *engine,
+		struct i2c_request_transaction_data *request);
+	void (*process_channel_reply)(
+		struct i2c_engine *engine,
+		struct i2c_reply_transaction_data *reply);
+	enum i2c_channel_operation_result (*get_channel_status)(
+		struct i2c_engine *engine,
+		uint8_t *returned_bytes);
+};
+
+struct i2c_engine {
+	struct engine base;
+	const struct i2c_engine_funcs *funcs;
+	uint32_t timeout_delay;
+};
+
+bool dal_i2c_engine_construct(
+	struct i2c_engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2c_engine_destruct(
+	struct i2c_engine *engine);
+
+bool dal_i2c_engine_setup_i2c_engine(
+	struct i2c_engine *engine);
+
+void dal_i2c_engine_submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *request);
+
+void dal_i2c_engine_process_channel_reply(
+	struct i2c_engine *engine,
+	struct i2c_reply_transaction_data *reply);
+
+bool dal_i2c_engine_acquire(
+	struct engine *ptr,
+	struct ddc *ddc_handle);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
new file mode 100644
index 000000000000..6429b55dd697
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+#include "i2c_engine.h"
+#include "i2c_hw_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_generic_hw_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct i2c_hw_engine *'
+ * to 'struct i2c_generic_hw_engine *'
+ */
+#define FROM_I2C_HW_ENGINE(ptr) \
+	container_of((ptr), struct i2c_generic_hw_engine, base)
+
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_generic_hw_engine *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_generic_hw_engine *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW;
+}
+
+/*
+ * @brief
+ * Single transaction handling.
+ * Since transaction may be bigger than HW buffer size,
+ * it divides transaction to sub-transactions
+ * and uses batch transaction feature of the engine.
+ */
+bool dal_i2c_generic_hw_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction)
+{
+	struct i2c_generic_hw_engine *hw_engine = FROM_ENGINE(engine);
+
+	struct i2c_hw_engine *base = &hw_engine->base;
+
+	uint8_t max_payload_size =
+		base->funcs->get_hw_buffer_available_size(base);
+
+	bool initial_stop_bit = !middle_of_transaction;
+
+	struct i2c_generic_transaction_attributes attributes;
+
+	enum i2c_channel_operation_result operation_result =
+		I2C_CHANNEL_OPERATION_FAILED;
+
+	bool result = false;
+
+	/* setup transaction initial properties */
+
+	uint8_t address = i2caux_request->payload.address;
+	uint8_t *current_payload = i2caux_request->payload.data;
+	uint8_t remaining_payload_size = i2caux_request->payload.length;
+
+	bool first_iteration = true;
+
+	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+		attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_READ;
+	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+		attributes.action = I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+	else {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
+		return false;
+	}
+
+	/* Do batch transaction.
+	 * Divide read/write data into payloads which fit HW buffer size.
+	 * 1. Single transaction:
+	 *    start_bit = 1, stop_bit depends on session state, ack_on_read = 0;
+	 * 2. Start of batch transaction:
+	 *    start_bit = 1, stop_bit = 0, ack_on_read = 1;
+	 * 3. Middle of batch transaction:
+	 *    start_bit = 0, stop_bit = 0, ack_on_read = 1;
+	 * 4. End of batch transaction:
+	 *    start_bit = 0, stop_bit depends on session state, ack_on_read = 0.
+	 * Session stop bit is set if 'middle_of_transaction' = 0. */
+
+	while (remaining_payload_size) {
+		uint8_t current_transaction_size;
+		uint8_t current_payload_size;
+
+		bool last_iteration;
+		bool stop_bit;
+
+		/* Calculate current transaction size and payload size.
+		 * Transaction size = total number of bytes in transaction,
+		 * including slave's address;
+		 * Payload size = number of data bytes in transaction. */
+
+		if (first_iteration) {
+			/* In the first sub-transaction we send slave's address
+			 * thus we need to reserve one byte for it */
+			current_transaction_size =
+			(remaining_payload_size > max_payload_size - 1) ?
+				max_payload_size :
+				remaining_payload_size + 1;
+
+			current_payload_size = current_transaction_size - 1;
+		} else {
+			/* Second and further sub-transactions will have
+			 * entire buffer reserved for data */
+			current_transaction_size =
+				(remaining_payload_size > max_payload_size) ?
+				max_payload_size :
+				remaining_payload_size;
+
+			current_payload_size = current_transaction_size;
+		}
+
+		last_iteration =
+			(remaining_payload_size == current_payload_size);
+
+		stop_bit = last_iteration ? initial_stop_bit : false;
+
+		/* write slave device address */
+
+		if (first_iteration)
+			hw_engine->funcs->write_address(hw_engine, address);
+
+		/* write current portion of data, if requested */
+
+		if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+			hw_engine->funcs->write_data(
+				hw_engine,
+				current_payload,
+				current_payload_size);
+
+		/* execute transaction */
+
+		attributes.start_bit = first_iteration;
+		attributes.stop_bit = stop_bit;
+		attributes.last_read = last_iteration;
+		attributes.transaction_size = current_transaction_size;
+
+		hw_engine->funcs->execute_transaction(hw_engine, &attributes);
+
+		/* wait until transaction is processed; if it fails - quit */
+
+		operation_result = base->funcs->wait_on_operation_result(
+			base,
+			base->funcs->get_transaction_timeout(
+				base, current_transaction_size),
+			I2C_CHANNEL_OPERATION_ENGINE_BUSY);
+
+		if (operation_result != I2C_CHANNEL_OPERATION_SUCCEEDED)
+			break;
+
+		/* read current portion of data, if requested */
+
+		/* the read offset should be 1 for first sub-transaction,
+		 * and 0 for any next one */
+
+		if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+			hw_engine->funcs->read_data(hw_engine, current_payload,
+				current_payload_size, first_iteration ? 1 : 0);
+
+		/* update loop variables */
+
+		first_iteration = false;
+		current_payload += current_payload_size;
+		remaining_payload_size -= current_payload_size;
+	}
+
+	/* update transaction status */
+
+	switch (operation_result) {
+	case I2C_CHANNEL_OPERATION_SUCCEEDED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+		result = true;
+	break;
+	case I2C_CHANNEL_OPERATION_NO_RESPONSE:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+	break;
+	case I2C_CHANNEL_OPERATION_TIMEOUT:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+	break;
+	case I2C_CHANNEL_OPERATION_FAILED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
+	break;
+	default:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
+	}
+
+	return result;
+}
+
+/*
+ * @brief
+ * Returns number of microseconds to wait until timeout to be considered
+ */
+uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout(
+	const struct i2c_hw_engine *engine,
+	uint32_t length)
+{
+	const struct i2c_engine *base = &engine->base;
+
+	uint32_t speed = base->funcs->get_speed(base);
+
+	if (!speed)
+		return 0;
+
+	/* total timeout = period_timeout * (start + data bits count + stop) */
+
+	return ((1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed) *
+		(1 + (length << 3) + 1);
+}
+
+bool dal_i2c_generic_hw_engine_construct(
+	struct i2c_generic_hw_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2c_hw_engine_construct(&engine->base, ctx))
+		return false;
+	return true;
+}
+
+void dal_i2c_generic_hw_engine_destruct(
+	struct i2c_generic_hw_engine *engine)
+{
+	dal_i2c_hw_engine_destruct(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
new file mode 100644
index 000000000000..52f2aa248d95
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_GENERIC_HW_ENGINE_H__
+#define __DAL_I2C_GENERIC_HW_ENGINE_H__
+
+struct i2c_generic_transaction_attributes {
+	enum i2caux_transaction_action action;
+	uint8_t transaction_size;
+	bool start_bit;
+	bool stop_bit;
+	bool last_read;
+};
+
+struct i2c_generic_hw_engine;
+
+struct i2c_generic_hw_engine_funcs {
+	void (*write_address)(
+		struct i2c_generic_hw_engine *engine,
+		uint8_t address);
+	void (*write_data)(
+		struct i2c_generic_hw_engine *engine,
+		const uint8_t *buffer,
+		uint8_t length);
+	void (*read_data)(
+		struct i2c_generic_hw_engine *engine,
+		uint8_t *buffer,
+		uint8_t length,
+		uint32_t offset);
+	void (*execute_transaction)(
+		struct i2c_generic_hw_engine *engine,
+		struct i2c_generic_transaction_attributes *attributes);
+};
+
+struct i2c_generic_hw_engine {
+	struct i2c_hw_engine base;
+	const struct i2c_generic_hw_engine_funcs *funcs;
+};
+
+bool dal_i2c_generic_hw_engine_construct(
+	struct i2c_generic_hw_engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2c_generic_hw_engine_destruct(
+	struct i2c_generic_hw_engine *engine);
+enum i2caux_engine_type dal_i2c_generic_hw_engine_get_engine_type(
+	const struct engine *engine);
+bool dal_i2c_generic_hw_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction);
+uint32_t dal_i2c_generic_hw_engine_get_transaction_timeout(
+	const struct i2c_hw_engine *engine,
+	uint32_t length);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
new file mode 100644
index 000000000000..b02ba7927d5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+#include "i2c_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_hw_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_hw_engine *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	container_of((ptr), struct i2c_hw_engine, base)
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_hw_engine *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_I2C_DDC_HW;
+}
+
+bool dal_i2c_hw_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction)
+{
+	struct i2c_hw_engine *hw_engine = FROM_ENGINE(engine);
+
+	struct i2c_request_transaction_data request;
+
+	uint32_t transaction_timeout;
+
+	enum i2c_channel_operation_result operation_result;
+
+	bool result = false;
+
+	/* We need following:
+	 * transaction length will not exceed
+	 * the number of free bytes in HW buffer (minus one for address)*/
+
+	if (i2caux_request->payload.length >=
+		hw_engine->funcs->get_hw_buffer_available_size(hw_engine)) {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW;
+		return false;
+	}
+
+	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_READ;
+	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+	else {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
+		/* [anaumov] in DAL2, there was no "return false" */
+		return false;
+	}
+
+	request.address = (uint8_t)i2caux_request->payload.address;
+	request.length = i2caux_request->payload.length;
+	request.data = i2caux_request->payload.data;
+
+	/* obtain timeout value before submitting request */
+
+	transaction_timeout = hw_engine->funcs->get_transaction_timeout(
+		hw_engine, i2caux_request->payload.length + 1);
+
+	hw_engine->base.funcs->submit_channel_request(
+		&hw_engine->base, &request);
+
+	if ((request.status == I2C_CHANNEL_OPERATION_FAILED) ||
+		(request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY)) {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
+		return false;
+	}
+
+	/* wait until transaction proceed */
+
+	operation_result = hw_engine->funcs->wait_on_operation_result(
+		hw_engine,
+		transaction_timeout,
+		I2C_CHANNEL_OPERATION_ENGINE_BUSY);
+
+	/* update transaction status */
+
+	switch (operation_result) {
+	case I2C_CHANNEL_OPERATION_SUCCEEDED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+		result = true;
+	break;
+	case I2C_CHANNEL_OPERATION_NO_RESPONSE:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+	break;
+	case I2C_CHANNEL_OPERATION_TIMEOUT:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+	break;
+	case I2C_CHANNEL_OPERATION_FAILED:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
+	break;
+	default:
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
+	}
+
+	if (result && (i2caux_request->operation == I2CAUX_TRANSACTION_READ)) {
+		struct i2c_reply_transaction_data reply;
+
+		reply.data = i2caux_request->payload.data;
+		reply.length = i2caux_request->payload.length;
+
+		hw_engine->base.funcs->
+			process_channel_reply(&hw_engine->base, &reply);
+	}
+
+	return result;
+}
+
+bool dal_i2c_hw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc)
+{
+	enum gpio_result result;
+	uint32_t current_speed;
+
+	result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
+		GPIO_DDC_CONFIG_TYPE_MODE_I2C);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	engine->base.ddc = ddc;
+
+	current_speed = engine->funcs->get_speed(engine);
+
+	if (current_speed)
+		FROM_I2C_ENGINE(engine)->original_speed = current_speed;
+
+	return true;
+}
+/*
+ * @brief
+ * Queries in a loop for current engine status
+ * until retrieved status matches 'expected_result', or timeout occurs.
+ * Timeout given in microseconds
+ * and the status query frequency is also one per microsecond.
+ */
+enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result(
+	struct i2c_hw_engine *engine,
+	uint32_t timeout,
+	enum i2c_channel_operation_result expected_result)
+{
+	enum i2c_channel_operation_result result;
+	uint32_t i = 0;
+
+	if (!timeout)
+		return I2C_CHANNEL_OPERATION_SUCCEEDED;
+
+	do {
+		result = engine->base.funcs->get_channel_status(
+			&engine->base, NULL);
+
+		if (result != expected_result)
+			break;
+
+		dm_delay_in_microseconds(engine->base.base.ctx, 1);
+
+		++i;
+	} while (i < timeout);
+
+	return result;
+}
+
+bool dal_i2c_hw_engine_construct(
+	struct i2c_hw_engine *engine,
+	struct dc_context *ctx)
+{
+	if (!dal_i2c_engine_construct(&engine->base, ctx))
+		return false;
+	engine->original_speed = I2CAUX_DEFAULT_I2C_HW_SPEED;
+	engine->default_speed = I2CAUX_DEFAULT_I2C_HW_SPEED;
+	return true;
+}
+
+void dal_i2c_hw_engine_destruct(
+	struct i2c_hw_engine *engine)
+{
+	dal_i2c_engine_destruct(&engine->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
new file mode 100644
index 000000000000..5afbd7067a1f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_HW_ENGINE_H__
+#define __DAL_I2C_HW_ENGINE_H__
+
+enum {
+	TRANSACTION_TIMEOUT_IN_I2C_CLOCKS = 32
+};
+
+struct i2c_hw_engine;
+
+struct i2c_hw_engine_funcs {
+	uint8_t (*get_hw_buffer_available_size)(
+		const struct i2c_hw_engine *engine);
+	enum i2c_channel_operation_result (*wait_on_operation_result)(
+		struct i2c_hw_engine *engine,
+		uint32_t timeout,
+		enum i2c_channel_operation_result expected_result);
+	uint32_t (*get_transaction_timeout)(
+		const struct i2c_hw_engine *engine,
+		uint32_t length);
+};
+
+struct i2c_hw_engine {
+	struct i2c_engine base;
+	const struct i2c_hw_engine_funcs *funcs;
+
+	/* Values below are in kilohertz */
+	uint32_t original_speed;
+	uint32_t default_speed;
+};
+
+bool dal_i2c_hw_engine_construct(
+	struct i2c_hw_engine *engine,
+	struct dc_context *ctx);
+
+void dal_i2c_hw_engine_destruct(
+	struct i2c_hw_engine *engine);
+
+enum i2c_channel_operation_result dal_i2c_hw_engine_wait_on_operation_result(
+	struct i2c_hw_engine *engine,
+	uint32_t timeout,
+	enum i2c_channel_operation_result expected_result);
+
+bool dal_i2c_hw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc);
+
+bool dal_i2c_hw_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction);
+
+enum i2caux_engine_type dal_i2c_hw_engine_get_engine_type(
+	const struct engine *engine);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
new file mode 100644
index 000000000000..21e8fa2c08ee
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
@@ -0,0 +1,614 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+#include "engine.h"
+#include "i2c_engine.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2c_sw_engine.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define SCL false
+#define SDA true
+
+static inline bool read_bit_from_ddc(
+	struct ddc *ddc,
+	bool data_nor_clock)
+{
+	uint32_t value = 0;
+
+	if (data_nor_clock)
+		dal_ddc_get_data(ddc, &value);
+	else
+		dal_ddc_get_clock(ddc, &value);
+
+	return (value != 0);
+}
+
+static inline void write_bit_to_ddc(
+	struct ddc *ddc,
+	bool data_nor_clock,
+	bool bit)
+{
+	uint32_t value = bit ? 1 : 0;
+
+	if (data_nor_clock)
+		dal_ddc_set_data(ddc, value);
+	else
+		dal_ddc_set_clock(ddc, value);
+}
+
+static bool wait_for_scl_high(
+	struct dc_context *ctx,
+	struct ddc *ddc,
+	uint16_t clock_delay_div_4)
+{
+	uint32_t scl_retry = 0;
+	uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	/* 3 milliseconds delay
+	 * to wake up some displays from "low power" state.
+	 */
+
+	do {
+		if (read_bit_from_ddc(ddc, SCL))
+			return true;
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		++scl_retry;
+	} while (scl_retry <= scl_retry_max);
+
+	return false;
+}
+
+static bool start_sync(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4)
+{
+	uint32_t retry = 0;
+
+	/* The I2C communications start signal is:
+	 * the SDA going low from high, while the SCL is high. */
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	do {
+		write_bit_to_ddc(ddc_handle, SDA, true);
+
+		if (!read_bit_from_ddc(ddc_handle, SDA)) {
+			++retry;
+			continue;
+		}
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SCL, true);
+
+		if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+			break;
+
+		write_bit_to_ddc(ddc_handle, SDA, false);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SCL, false);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		return true;
+	} while (retry <= I2C_SW_RETRIES);
+
+	return false;
+}
+
+static bool stop_sync(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4)
+{
+	uint32_t retry = 0;
+
+	/* The I2C communications stop signal is:
+	 * the SDA going high from low, while the SCL is high. */
+
+	write_bit_to_ddc(ddc_handle, SCL, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SDA, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+		return false;
+
+	write_bit_to_ddc(ddc_handle, SDA, true);
+
+	do {
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		if (read_bit_from_ddc(ddc_handle, SDA))
+			return true;
+
+		++retry;
+	} while (retry <= 2);
+
+	return false;
+}
+
+static bool write_byte(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t byte)
+{
+	int32_t shift = 7;
+	bool ack;
+
+	/* bits are transmitted serially, starting from MSB */
+
+	do {
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+		write_bit_to_ddc(ddc_handle, SCL, true);
+
+		if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+			return false;
+
+		write_bit_to_ddc(ddc_handle, SCL, false);
+
+		--shift;
+	} while (shift >= 0);
+
+	/* The display sends ACK by preventing the SDA from going high
+	 * after the SCL pulse we use to send our last data bit.
+	 * If the SDA goes high after that bit, it's a NACK */
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SDA, true);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+		return false;
+
+	/* read ACK bit */
+
+	ack = !read_bit_from_ddc(ddc_handle, SDA);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4 << 1);
+
+	write_bit_to_ddc(ddc_handle, SCL, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4 << 1);
+
+	return ack;
+}
+
+static bool read_byte(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t *byte,
+	bool more)
+{
+	int32_t shift = 7;
+
+	uint8_t data = 0;
+
+	/* The data bits are read from MSB to LSB;
+	 * bit is read while SCL is high */
+
+	do {
+		write_bit_to_ddc(ddc_handle, SCL, true);
+
+		if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+			return false;
+
+		if (read_bit_from_ddc(ddc_handle, SDA))
+			data |= (1 << shift);
+
+		write_bit_to_ddc(ddc_handle, SCL, false);
+
+		dm_delay_in_microseconds(ctx, clock_delay_div_4 << 1);
+
+		--shift;
+	} while (shift >= 0);
+
+	/* read only whole byte */
+
+	*byte = data;
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	/* send the acknowledge bit:
+	 * SDA low means ACK, SDA high means NACK */
+
+	write_bit_to_ddc(ddc_handle, SDA, !more);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SCL, true);
+
+	if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
+		return false;
+
+	write_bit_to_ddc(ddc_handle, SCL, false);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	write_bit_to_ddc(ddc_handle, SDA, true);
+
+	dm_delay_in_microseconds(ctx, clock_delay_div_4);
+
+	return true;
+}
+
+static bool i2c_write(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t address,
+	uint8_t length,
+	const uint8_t *data)
+{
+	uint32_t i = 0;
+
+	if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
+		return false;
+
+	while (i < length) {
+		if (!write_byte(ctx, ddc_handle, clock_delay_div_4, data[i]))
+			return false;
+		++i;
+	}
+
+	return true;
+}
+
+static bool i2c_read(
+	struct dc_context *ctx,
+	struct ddc *ddc_handle,
+	uint16_t clock_delay_div_4,
+	uint8_t address,
+	uint8_t length,
+	uint8_t *data)
+{
+	uint32_t i = 0;
+
+	if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
+		return false;
+
+	while (i < length) {
+		if (!read_byte(ctx, ddc_handle, clock_delay_div_4, data + i,
+			i < length - 1))
+			return false;
+		++i;
+	}
+
+	return true;
+}
+
+/*
+ * @brief
+ * Cast 'struct i2c_engine *'
+ * to 'struct i2c_sw_engine *'
+ */
+#define FROM_I2C_ENGINE(ptr) \
+	container_of((ptr), struct i2c_sw_engine, base)
+
+/*
+ * @brief
+ * Cast 'struct engine *'
+ * to 'struct i2c_sw_engine *'
+ */
+#define FROM_ENGINE(ptr) \
+	FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
+
+enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type(
+	const struct engine *engine)
+{
+	return I2CAUX_ENGINE_TYPE_I2C_SW;
+}
+
+bool dal_i2c_sw_engine_submit_request(
+	struct engine *engine,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction)
+{
+	struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine);
+
+	struct i2c_engine *base = &sw_engine->base;
+
+	struct i2c_request_transaction_data request;
+	bool operation_succeeded = false;
+
+	if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_READ;
+	else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
+		request.action = middle_of_transaction ?
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
+			I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
+	else {
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
+		/* in DAL2, there was no "return false" */
+		return false;
+	}
+
+	request.address = (uint8_t)i2caux_request->payload.address;
+	request.length = i2caux_request->payload.length;
+	request.data = i2caux_request->payload.data;
+
+	base->funcs->submit_channel_request(base, &request);
+
+	if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
+		(request.status == I2C_CHANNEL_OPERATION_FAILED))
+		i2caux_request->status =
+			I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
+	else {
+		enum i2c_channel_operation_result operation_result;
+
+		do {
+			operation_result =
+				base->funcs->get_channel_status(base, NULL);
+
+			switch (operation_result) {
+			case I2C_CHANNEL_OPERATION_SUCCEEDED:
+				i2caux_request->status =
+					I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
+				operation_succeeded = true;
+			break;
+			case I2C_CHANNEL_OPERATION_NO_RESPONSE:
+				i2caux_request->status =
+					I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
+			break;
+			case I2C_CHANNEL_OPERATION_TIMEOUT:
+				i2caux_request->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
+			break;
+			case I2C_CHANNEL_OPERATION_FAILED:
+				i2caux_request->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
+			break;
+			default:
+				i2caux_request->status =
+				I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
+			break;
+			}
+		} while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY);
+	}
+
+	return operation_succeeded;
+}
+
+uint32_t dal_i2c_sw_engine_get_speed(
+	const struct i2c_engine *engine)
+{
+	return FROM_I2C_ENGINE(engine)->speed;
+}
+
+void dal_i2c_sw_engine_set_speed(
+	struct i2c_engine *engine,
+	uint32_t speed)
+{
+	struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
+
+	ASSERT(speed);
+
+	sw_engine->speed = speed ? speed : I2CAUX_DEFAULT_I2C_SW_SPEED;
+
+	sw_engine->clock_delay = 1000 / sw_engine->speed;
+
+	if (sw_engine->clock_delay < 12)
+		sw_engine->clock_delay = 12;
+}
+
+bool dal_i2caux_i2c_sw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc)
+{
+	enum gpio_result result;
+
+	result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
+		GPIO_DDC_CONFIG_TYPE_MODE_I2C);
+
+	if (result != GPIO_RESULT_OK)
+		return false;
+
+	engine->base.ddc = ddc;
+
+	return true;
+}
+
+void dal_i2c_sw_engine_submit_channel_request(
+	struct i2c_engine *engine,
+	struct i2c_request_transaction_data *req)
+{
+	struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
+
+	struct ddc *ddc = engine->base.ddc;
+	uint16_t clock_delay_div_4 = sw_engine->clock_delay >> 2;
+
+	/* send sync (start / repeated start) */
+
+	bool result = start_sync(engine->base.ctx, ddc, clock_delay_div_4);
+
+	/* process payload */
+
+	if (result) {
+		switch (req->action) {
+		case I2CAUX_TRANSACTION_ACTION_I2C_WRITE:
+		case I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT:
+			result = i2c_write(engine->base.ctx, ddc, clock_delay_div_4,
+				req->address, req->length, req->data);
+		break;
+		case I2CAUX_TRANSACTION_ACTION_I2C_READ:
+		case I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT:
+			result = i2c_read(engine->base.ctx, ddc, clock_delay_div_4,
+				req->address, req->length, req->data);
+		break;
+		default:
+			result = false;
+		break;
+		}
+	}
+
+	/* send stop if not 'mot' or operation failed */
+
+	if (!result ||
+		(req->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
+		(req->action == I2CAUX_TRANSACTION_ACTION_I2C_READ))
+		if (!stop_sync(engine->base.ctx, ddc, clock_delay_div_4))
+			result = false;
+
+	req->status = result ?
+		I2C_CHANNEL_OPERATION_SUCCEEDED :
+		I2C_CHANNEL_OPERATION_FAILED;
+}
+
+enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status(
+	struct i2c_engine *engine,
+	uint8_t *returned_bytes)
+{
+	return dal_ddc_check_line_aborted(engine->base.ddc) ?
+		I2C_CHANNEL_OPERATION_FAILED :
+		I2C_CHANNEL_OPERATION_SUCCEEDED;
+}
+
+void dal_i2c_sw_engine_destruct(
+	struct i2c_sw_engine *engine)
+{
+	dal_i2c_engine_destruct(&engine->base);
+}
+
+static void destroy(
+	struct i2c_engine **ptr)
+{
+	dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr));
+
+	dm_free((*ptr)->base.ctx, *ptr);
+	*ptr = NULL;
+}
+
+static const struct i2c_engine_funcs i2c_engine_funcs = {
+	.acquire_engine = dal_i2caux_i2c_sw_engine_acquire_engine,
+	.destroy = destroy,
+	.get_speed = dal_i2c_sw_engine_get_speed,
+	.set_speed = dal_i2c_sw_engine_set_speed,
+	.setup_engine = dal_i2c_engine_setup_i2c_engine,
+	.submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
+	.process_channel_reply = dal_i2c_engine_process_channel_reply,
+	.get_channel_status = dal_i2c_sw_engine_get_channel_status,
+};
+
+static void release_engine(
+	struct engine *engine)
+{
+
+}
+
+static const struct engine_funcs engine_funcs = {
+	.release_engine = release_engine,
+	.get_engine_type = dal_i2c_sw_engine_get_engine_type,
+	.acquire = dal_i2c_engine_acquire,
+	.submit_request = dal_i2c_sw_engine_submit_request,
+	.keep_power_up_count = dal_i2caux_keep_power_up_count,
+};
+
+bool dal_i2c_sw_engine_construct(
+	struct i2c_sw_engine *engine,
+	const struct i2c_sw_engine_create_arg *arg)
+{
+	if (!dal_i2c_engine_construct(&engine->base, arg->ctx))
+		return false;
+
+	dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed);
+	engine->base.funcs = &i2c_engine_funcs;
+	engine->base.base.funcs = &engine_funcs;
+	return true;
+}
+
+
+
+struct i2c_engine *dal_i2c_sw_engine_create(
+	const struct i2c_sw_engine_create_arg *arg)
+{
+	struct i2c_sw_engine *engine;
+
+	if (!arg) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	engine = dm_alloc(arg->ctx, sizeof(struct i2c_sw_engine));
+
+	if (!engine) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (dal_i2c_sw_engine_construct(engine, arg))
+		return &engine->base;
+
+	BREAK_TO_DEBUGGER();
+
+	dm_free(arg->ctx, engine);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
new file mode 100644
index 000000000000..e0cb4c3d483d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_SW_ENGINE_H__
+#define __DAL_I2C_SW_ENGINE_H__
+
+enum {
+	I2C_SW_RETRIES = 10,
+	I2C_SW_SCL_READ_RETRIES = 128,
+	/* following value is in microseconds */
+	I2C_SW_TIMEOUT_DELAY = 3000
+};
+
+struct i2c_sw_engine;
+
+struct i2c_sw_engine {
+	struct i2c_engine base;
+	uint32_t clock_delay;
+	/* Values below are in KHz */
+	uint32_t speed;
+	uint32_t default_speed;
+};
+
+struct i2c_sw_engine_create_arg {
+	uint32_t default_speed;
+	struct dc_context *ctx;
+};
+
+bool dal_i2c_sw_engine_construct(
+	struct i2c_sw_engine *engine,
+	const struct i2c_sw_engine_create_arg *arg);
+
+bool dal_i2caux_i2c_sw_engine_acquire_engine(
+	struct i2c_engine *engine,
+	struct ddc *ddc_handle);
+
+void dal_i2c_sw_engine_destruct(
+	struct i2c_sw_engine *engine);
+
+struct i2c_engine *dal_i2c_sw_engine_create(
+	const struct i2c_sw_engine_create_arg *arg);
+enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type(
+	const struct engine *engine);
+bool dal_i2c_sw_engine_submit_request(
+	struct engine *ptr,
+	struct i2caux_transaction_request *i2caux_request,
+	bool middle_of_transaction);
+uint32_t dal_i2c_sw_engine_get_speed(
+	const struct i2c_engine *engine);
+void dal_i2c_sw_engine_set_speed(
+	struct i2c_engine *ptr,
+	uint32_t speed);
+void dal_i2c_sw_engine_submit_channel_request(
+	struct i2c_engine *ptr,
+	struct i2c_request_transaction_data *req);
+enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status(
+	struct i2c_engine *engine,
+	uint8_t *returned_bytes);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
new file mode 100644
index 000000000000..4c2f2cb64315
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/i2caux_interface.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "i2caux.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "engine.h"
+#include "i2c_engine.h"
+#include "aux_engine.h"
+
+/*
+ * This unit
+ */
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce110/i2caux_dce110.h"
+#endif
+
+#include "diagnostics/i2caux_diag.h"
+
+/*
+ * @brief
+ * Plain API, available publicly
+ */
+
+struct i2caux *dal_i2caux_create(
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	enum dce_version dce_version;
+	enum dce_environment dce_environment;
+
+	if (!as) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	dce_version = dal_adapter_service_get_dce_version(as);
+	dce_environment = dal_adapter_service_get_dce_environment(as);
+
+	if (IS_FPGA_MAXIMUS_DC(dce_environment)) {
+		return dal_i2caux_diag_fpga_create(as, ctx);
+	}
+
+	switch (dce_version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+#endif
+	case DCE_VERSION_11_0:
+		return dal_i2caux_dce110_create(as, ctx);
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+}
+
+bool dal_i2caux_submit_i2c_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct i2c_command *cmd)
+{
+	struct i2c_engine *engine;
+	uint8_t index_of_payload = 0;
+	bool result;
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!cmd) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	switch (cmd->engine) {
+	case I2C_COMMAND_ENGINE_SW:
+		/* try to acquire SW engine first,
+		 * acquire HW engine if SW engine not available */
+		engine = i2caux->funcs->acquire_i2c_sw_engine(i2caux, ddc);
+
+		if (!engine)
+			engine = i2caux->funcs->acquire_i2c_hw_engine(
+				i2caux, ddc);
+	break;
+	case I2C_COMMAND_ENGINE_HW:
+	case I2C_COMMAND_ENGINE_DEFAULT:
+	default:
+		/* try to acquire HW engine first,
+		 * acquire SW engine if HW engine not available */
+		engine = i2caux->funcs->acquire_i2c_hw_engine(i2caux, ddc);
+
+		if (!engine)
+			engine = i2caux->funcs->acquire_i2c_sw_engine(
+				i2caux, ddc);
+	}
+
+	if (!engine)
+		return false;
+
+	engine->funcs->set_speed(engine, cmd->speed);
+
+	result = true;
+
+	while (index_of_payload < cmd->number_of_payloads) {
+		bool mot = (index_of_payload != cmd->number_of_payloads - 1);
+
+		struct i2c_payload *payload = cmd->payloads + index_of_payload;
+
+		struct i2caux_transaction_request request = { 0 };
+
+		request.operation = payload->write ?
+			I2CAUX_TRANSACTION_WRITE :
+			I2CAUX_TRANSACTION_READ;
+
+		request.payload.address_space =
+			I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C;
+		request.payload.address = (payload->address << 1) |
+			!payload->write;
+		request.payload.length = payload->length;
+		request.payload.data = payload->data;
+
+		if (!engine->base.funcs->submit_request(
+			&engine->base, &request, mot)) {
+			result = false;
+			break;
+		}
+
+		++index_of_payload;
+	}
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return result;
+}
+
+bool dal_i2caux_submit_aux_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct aux_command *cmd)
+{
+	struct aux_engine *engine;
+	uint8_t index_of_payload = 0;
+	bool result;
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!cmd) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	engine = i2caux->funcs->acquire_aux_engine(i2caux, ddc);
+
+	if (!engine)
+		return false;
+
+	engine->delay = cmd->defer_delay;
+	engine->max_defer_write_retry = cmd->max_defer_write_retry;
+
+	result = true;
+
+	while (index_of_payload < cmd->number_of_payloads) {
+		bool mot = (index_of_payload != cmd->number_of_payloads - 1);
+
+		struct aux_payload *payload = cmd->payloads + index_of_payload;
+
+		struct i2caux_transaction_request request = { 0 };
+
+		request.operation = payload->write ?
+			I2CAUX_TRANSACTION_WRITE :
+			I2CAUX_TRANSACTION_READ;
+
+		if (payload->i2c_over_aux) {
+			request.payload.address_space =
+				I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C;
+
+			request.payload.address = (payload->address << 1) |
+				!payload->write;
+		} else {
+			request.payload.address_space =
+				I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD;
+
+			request.payload.address = payload->address;
+		}
+
+		request.payload.length = payload->length;
+		request.payload.data = payload->data;
+
+		if (!engine->base.funcs->submit_request(
+			&engine->base, &request, mot)) {
+			result = false;
+			break;
+		}
+
+		++index_of_payload;
+	}
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return result;
+}
+
+static bool get_hw_supported_ddc_line(
+	struct ddc *ddc,
+	enum gpio_ddc_line *line)
+{
+	enum gpio_ddc_line line_found;
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!dal_ddc_is_hw_supported(ddc))
+		return false;
+
+	line_found = dal_ddc_get_line(ddc);
+
+	if (line_found >= GPIO_DDC_LINE_COUNT)
+		return false;
+
+	*line = line_found;
+
+	return true;
+}
+
+void dal_i2caux_keep_engine_power_up(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	bool keep_power_up)
+{
+	enum gpio_ddc_line line;
+	struct i2c_engine *engine;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return;
+
+	engine = i2caux->i2c_hw_engines[line];
+
+	engine->base.funcs->keep_power_up_count(&engine->base, keep_power_up);
+}
+
+bool dal_i2caux_start_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+
+	struct aux_engine *engine;
+
+	bool result;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return false;
+
+	engine = i2caux->aux_engines[line];
+
+	if (!engine)
+		return false;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return false;
+
+	result = engine->funcs->start_gtc_sync(engine);
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return result;
+}
+
+bool dal_i2caux_stop_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+
+	struct aux_engine *engine;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return false;
+
+	engine = i2caux->aux_engines[line];
+
+	if (!engine)
+		return false;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return false;
+
+	engine->funcs->stop_gtc_sync(engine);
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+
+	return true;
+}
+
+void dal_i2caux_configure_aux(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	union aux_config cfg)
+{
+	struct aux_engine *engine =
+		i2caux->funcs->acquire_aux_engine(i2caux, ddc);
+
+	if (!engine)
+		return;
+
+	engine->funcs->configure(engine, cfg);
+
+	i2caux->funcs->release_engine(i2caux, &engine->base);
+}
+
+void dal_i2caux_destroy(
+	struct i2caux **i2caux)
+{
+	if (!i2caux || !*i2caux) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*i2caux)->funcs->destroy(i2caux);
+
+	*i2caux = NULL;
+}
+
+/*
+ * @brief
+ * An utility function used by 'struct i2caux' and its descendants
+ */
+
+uint32_t dal_i2caux_get_reference_clock(
+	struct adapter_service *as)
+{
+	struct firmware_info info = { { 0 } };
+
+	if (!dal_adapter_service_get_firmware_info(as, &info))
+		return 0;
+
+	return info.pll_info.crystal_frequency;
+}
+
+/*
+ * @brief
+ * i2caux
+ */
+
+enum {
+	/* following are expressed in KHz */
+	DEFAULT_I2C_SW_SPEED = 50,
+	DEFAULT_I2C_HW_SPEED = 50,
+
+	/* This is the timeout as defined in DP 1.2a,
+	 * 2.3.4 "Detailed uPacket TX AUX CH State Description". */
+	AUX_TIMEOUT_PERIOD = 400,
+
+	/* Ideally, the SW timeout should be just above 550usec
+	 * which is programmed in HW.
+	 * But the SW timeout of 600usec is not reliable,
+	 * because on some systems, delay_in_microseconds()
+	 * returns faster than it should.
+	 * EPR #379763: by trial-and-error on different systems,
+	 * 700usec is the minimum reliable SW timeout for polling
+	 * the AUX_SW_STATUS.AUX_SW_DONE bit.
+	 * This timeout expires *only* when there is
+	 * AUX Error or AUX Timeout conditions - not during normal operation.
+	 * During normal operation, AUX_SW_STATUS.AUX_SW_DONE bit is set
+	 * at most within ~240usec. That means,
+	 * increasing this timeout will not affect normal operation,
+	 * and we'll timeout after
+	 * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD = 1600usec.
+	 * This timeout is especially important for
+	 * resume from S3 and CTS. */
+	SW_AUX_TIMEOUT_PERIOD_MULTIPLIER = 4
+};
+
+struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+	struct i2c_engine *engine = NULL;
+
+	if (get_hw_supported_ddc_line(ddc, &line))
+		engine = i2caux->i2c_sw_engines[line];
+
+	if (!engine)
+		engine = i2caux->i2c_generic_sw_engine;
+
+	if (!engine)
+		return NULL;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return NULL;
+
+	return engine;
+}
+
+struct aux_engine *dal_i2caux_acquire_aux_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc)
+{
+	enum gpio_ddc_line line;
+	struct aux_engine *engine;
+
+	if (!get_hw_supported_ddc_line(ddc, &line))
+		return NULL;
+
+	engine = i2caux->aux_engines[line];
+
+	if (!engine)
+		return NULL;
+
+	if (!engine->base.funcs->acquire(&engine->base, ddc))
+		return NULL;
+
+	return engine;
+}
+
+void dal_i2caux_release_engine(
+	struct i2caux *i2caux,
+	struct engine *engine)
+{
+	engine->funcs->release_engine(engine);
+
+	dal_ddc_close(engine->ddc);
+
+	engine->ddc = NULL;
+}
+
+bool dal_i2caux_construct(
+	struct i2caux *i2caux,
+	struct adapter_service *as,
+	struct dc_context *ctx)
+{
+	uint32_t i = 0;
+
+	i2caux->ctx = ctx;
+	do {
+		i2caux->i2c_sw_engines[i] = NULL;
+		i2caux->i2c_hw_engines[i] = NULL;
+		i2caux->aux_engines[i] = NULL;
+
+		++i;
+	} while (i < GPIO_DDC_LINE_COUNT);
+
+	i2caux->i2c_generic_sw_engine = NULL;
+	i2caux->i2c_generic_hw_engine = NULL;
+
+	i2caux->aux_timeout_period =
+		SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD;
+
+	i2caux->default_i2c_sw_speed = DEFAULT_I2C_SW_SPEED;
+	i2caux->default_i2c_hw_speed = DEFAULT_I2C_HW_SPEED;
+
+	return true;
+}
+
+void dal_i2caux_destruct(
+	struct i2caux *i2caux)
+{
+	uint32_t i = 0;
+
+	if (i2caux->i2c_generic_hw_engine)
+		i2caux->i2c_generic_hw_engine->funcs->destroy(
+			&i2caux->i2c_generic_hw_engine);
+
+	if (i2caux->i2c_generic_sw_engine)
+		i2caux->i2c_generic_sw_engine->funcs->destroy(
+			&i2caux->i2c_generic_sw_engine);
+
+	do {
+		if (i2caux->aux_engines[i])
+			i2caux->aux_engines[i]->funcs->destroy(
+				&i2caux->aux_engines[i]);
+
+		if (i2caux->i2c_hw_engines[i])
+			i2caux->i2c_hw_engines[i]->funcs->destroy(
+				&i2caux->i2c_hw_engines[i]);
+
+		if (i2caux->i2c_sw_engines[i])
+			i2caux->i2c_sw_engines[i]->funcs->destroy(
+				&i2caux->i2c_sw_engines[i]);
+
+		++i;
+	} while (i < GPIO_DDC_LINE_COUNT);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
new file mode 100644
index 000000000000..76f5b637ec3f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2C_AUX_H__
+#define __DAL_I2C_AUX_H__
+
+uint32_t dal_i2caux_get_reference_clock(
+	struct adapter_service *as);
+
+struct i2caux;
+
+struct engine;
+
+struct i2caux_funcs {
+	void (*destroy)(struct i2caux **ptr);
+	struct i2c_engine * (*acquire_i2c_sw_engine)(
+		struct i2caux *i2caux,
+		struct ddc *ddc);
+	struct i2c_engine * (*acquire_i2c_hw_engine)(
+		struct i2caux *i2caux,
+		struct ddc *ddc);
+	struct aux_engine * (*acquire_aux_engine)(
+		struct i2caux *i2caux,
+		struct ddc *ddc);
+	void (*release_engine)(
+		struct i2caux *i2caux,
+		struct engine *engine);
+};
+
+struct i2c_engine;
+struct aux_engine;
+
+struct i2caux {
+	struct dc_context *ctx;
+	const struct i2caux_funcs *funcs;
+	/* On ASIC we have certain amount of lines with HW DDC engine
+	 * (4, 6, or maybe more in the future).
+	 * For every such line, we create separate HW DDC engine
+	 * (since we have these engines in HW) and separate SW DDC engine
+	 * (to allow concurrent use of few lines).
+	 * In similar way we have AUX engines. */
+
+	/* I2C SW engines, per DDC line.
+	 * Only lines with HW DDC support will be initialized */
+	struct i2c_engine *i2c_sw_engines[GPIO_DDC_LINE_COUNT];
+
+	/* I2C HW engines, per DDC line.
+	 * Only lines with HW DDC support will be initialized */
+	struct i2c_engine *i2c_hw_engines[GPIO_DDC_LINE_COUNT];
+
+	/* AUX engines, per DDC line.
+	 * Only lines with HW AUX support will be initialized */
+	struct aux_engine *aux_engines[GPIO_DDC_LINE_COUNT];
+
+	/* For all other lines, we can use
+	 * single instance of generic I2C HW engine
+	 * (since in HW, there is single instance of it)
+	 * or single instance of generic I2C SW engine.
+	 * AUX is not supported for other lines. */
+
+	/* General-purpose I2C SW engine.
+	 * Can be assigned dynamically to any line per transaction */
+	struct i2c_engine *i2c_generic_sw_engine;
+
+	/* General-purpose I2C generic HW engine.
+	 * Can be assigned dynamically to almost any line per transaction */
+	struct i2c_engine *i2c_generic_hw_engine;
+
+	/* [anaumov] in DAL2, there is a Mutex */
+
+	uint32_t aux_timeout_period;
+
+	/* expressed in KHz */
+	uint32_t default_i2c_sw_speed;
+	uint32_t default_i2c_hw_speed;
+};
+
+bool dal_i2caux_construct(
+	struct i2caux *i2caux,
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+void dal_i2caux_release_engine(
+	struct i2caux *i2caux,
+	struct engine *engine);
+
+void dal_i2caux_destruct(
+	struct i2caux *i2caux);
+
+void dal_i2caux_destroy(
+	struct i2caux **ptr);
+
+struct i2c_engine *dal_i2caux_acquire_i2c_sw_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+struct aux_engine *dal_i2caux_acquire_aux_engine(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 09/26] drm/amd/dal: IRQ Service
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (7 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 08/26] drm/amd/dal: I2C Aux Manager Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 10/26] drm/amd/dal: GPU Harry Wentland
                     ` (16 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Interface to set and ack DCE interrupts.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/irq/Makefile            |  21 ++
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.c | 389 +++++++++++++++++++++
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.h |  34 ++
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c       | 177 ++++++++++
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h       |  85 +++++
 5 files changed, 706 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h

diff --git a/drivers/gpu/drm/amd/dal/dc/irq/Makefile b/drivers/gpu/drm/amd/dal/dc/irq/Makefile
new file mode 100644
index 000000000000..f1c5faf94b83
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the 'audio' sub-component of DAL.
+# It provides the control and status of HW adapter resources,
+# that are global for the ASIC and sharable between pipes.
+
+IRQ = irq_service.o
+
+AMD_DAL_IRQ = $(addprefix $(AMDDALPATH)/dc/irq/,$(IRQ))
+
+AMD_DAL_FILES += $(AMD_DAL_IRQ)
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+IRQ_DCE11 = irq_service_dce110.o
+
+AMD_DAL_IRQ_DCE11 = $(addprefix $(AMDDALPATH)/dc/irq/dce110/,$(IRQ_DCE11))
+
+AMD_DAL_FILES += $(AMD_DAL_IRQ_DCE11)
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
new file mode 100644
index 000000000000..4085b6f6e7fd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "irq_service_dce110.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "ivsrcid/ivsrcid_vislands30.h"
+
+static bool hpd_ack(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info)
+{
+	uint32_t addr = info->status_reg;
+	uint32_t value = dm_read_reg(irq_service->ctx, addr);
+	uint32_t current_status =
+		get_reg_field_value(
+			value,
+			DC_HPD_INT_STATUS,
+			DC_HPD_SENSE_DELAYED);
+
+	dal_irq_service_ack_generic(irq_service, info);
+
+	value = dm_read_reg(irq_service->ctx, info->enable_reg);
+
+	set_reg_field_value(
+		value,
+		current_status ? 0 : 1,
+		DC_HPD_INT_CONTROL,
+		DC_HPD_INT_POLARITY);
+
+	dm_write_reg(irq_service->ctx, info->enable_reg, value);
+
+	return true;
+}
+
+static const struct irq_source_info_funcs hpd_irq_info_funcs = {
+	.set = NULL,
+	.ack = hpd_ack
+};
+
+static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = {
+	.set = NULL,
+	.ack = NULL
+};
+
+static const struct irq_source_info_funcs pflip_irq_info_funcs = {
+	.set = NULL,
+	.ack = NULL
+};
+
+static const struct irq_source_info_funcs vblank_irq_info_funcs = {
+	.set = NULL,
+	.ack = NULL
+};
+
+#define hpd_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_HPD1 + reg_num] = {\
+		.enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
+		.enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
+		.enable_value = {\
+			DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
+			~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\
+		},\
+		.ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
+		.ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\
+		.ack_value = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\
+		.status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\
+		.funcs = &hpd_irq_info_funcs\
+	}
+
+#define hpd_rx_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_HPD1RX + reg_num] = {\
+		.enable_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
+		.enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
+		.enable_value = {\
+			DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
+			~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\
+		.ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
+		.ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
+		.ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
+		.status_reg = mmHPD ## reg_num ## _DC_HPD_INT_STATUS,\
+		.funcs = &hpd_rx_irq_info_funcs\
+	}
+#define pflip_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\
+		.enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\
+		.enable_mask =\
+		GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
+		.enable_value = {\
+			GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
+			~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
+		.ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\
+		.ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
+		.ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
+		.status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\
+		.funcs = &pflip_irq_info_funcs\
+	}
+
+#define vsync_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_CRTC ## reg_num ## VSYNC] = dummy_irq_entry()
+
+#define vupdate_int_entry(reg_num)\
+	[DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
+		.enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\
+		.enable_mask =\
+		CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
+		.enable_value = {\
+			CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
+			~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
+		.ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\
+		.ack_mask =\
+		CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
+		.ack_value =\
+		CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
+		.funcs = &vblank_irq_info_funcs\
+	}
+
+#define dummy_irq_entry() \
+	{\
+		.funcs = &dummy_irq_info_funcs\
+	}
+
+#define i2c_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry()
+
+#define azalia_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_AZALIA ## reg_num] = dummy_irq_entry()
+
+#define dp_sink_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry()
+
+#define gpio_pad_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry()
+
+#define dc_underflow_int_entry(reg_num) \
+	[DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry()
+
+static bool dummy_set(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info,
+	bool enable)
+{
+	dal_logger_write(
+		irq_service->ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_IRQ_SERVICE,
+		"%s: called for non-implemented irq source\n",
+		__func__);
+	return false;
+}
+
+static bool dummy_ack(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info)
+{
+	dal_logger_write(
+		irq_service->ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_IRQ_SERVICE,
+		"%s: called for non-implemented irq source\n",
+		__func__);
+	return false;
+}
+
+static const struct irq_source_info_funcs dummy_irq_info_funcs = {
+	.set = dummy_set,
+	.ack = dummy_ack
+};
+
+static const struct irq_source_info
+irq_source_info_dce110[DAL_IRQ_SOURCES_NUMBER] = {
+	[DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(),
+	hpd_int_entry(0),
+	hpd_int_entry(1),
+	hpd_int_entry(2),
+	hpd_int_entry(3),
+	hpd_int_entry(4),
+	hpd_int_entry(5),
+	hpd_rx_int_entry(0),
+	hpd_rx_int_entry(1),
+	hpd_rx_int_entry(2),
+	hpd_rx_int_entry(3),
+	hpd_rx_int_entry(4),
+	hpd_rx_int_entry(5),
+	i2c_int_entry(1),
+	i2c_int_entry(2),
+	i2c_int_entry(3),
+	i2c_int_entry(4),
+	i2c_int_entry(5),
+	i2c_int_entry(6),
+	azalia_int_entry(0),
+	azalia_int_entry(1),
+	azalia_int_entry(2),
+	azalia_int_entry(3),
+	azalia_int_entry(4),
+	azalia_int_entry(5),
+	dp_sink_int_entry(1),
+	dp_sink_int_entry(2),
+	dp_sink_int_entry(3),
+	dp_sink_int_entry(4),
+	dp_sink_int_entry(5),
+	dp_sink_int_entry(6),
+	vsync_int_entry(1),
+	vsync_int_entry(2),
+	vsync_int_entry(3),
+	vsync_int_entry(3),
+	vsync_int_entry(4),
+	vsync_int_entry(5),
+	[DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(),
+	pflip_int_entry(0),
+	pflip_int_entry(1),
+	pflip_int_entry(2),
+	pflip_int_entry(3),
+	pflip_int_entry(4),
+	pflip_int_entry(5),
+	[DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(),
+	gpio_pad_int_entry(0),
+	gpio_pad_int_entry(1),
+	gpio_pad_int_entry(2),
+	gpio_pad_int_entry(3),
+	gpio_pad_int_entry(4),
+	gpio_pad_int_entry(5),
+	gpio_pad_int_entry(6),
+	gpio_pad_int_entry(7),
+	gpio_pad_int_entry(8),
+	gpio_pad_int_entry(9),
+	gpio_pad_int_entry(10),
+	gpio_pad_int_entry(11),
+	gpio_pad_int_entry(12),
+	gpio_pad_int_entry(13),
+	gpio_pad_int_entry(14),
+	gpio_pad_int_entry(15),
+	gpio_pad_int_entry(16),
+	gpio_pad_int_entry(17),
+	gpio_pad_int_entry(18),
+	gpio_pad_int_entry(19),
+	gpio_pad_int_entry(20),
+	gpio_pad_int_entry(21),
+	gpio_pad_int_entry(22),
+	gpio_pad_int_entry(23),
+	gpio_pad_int_entry(24),
+	gpio_pad_int_entry(25),
+	gpio_pad_int_entry(26),
+	gpio_pad_int_entry(27),
+	gpio_pad_int_entry(28),
+	gpio_pad_int_entry(29),
+	gpio_pad_int_entry(30),
+	dc_underflow_int_entry(1),
+	dc_underflow_int_entry(2),
+	dc_underflow_int_entry(3),
+	dc_underflow_int_entry(4),
+	dc_underflow_int_entry(5),
+	dc_underflow_int_entry(6),
+	[DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(),
+	[DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(),
+	vupdate_int_entry(0),
+	vupdate_int_entry(1),
+	vupdate_int_entry(2),
+	vupdate_int_entry(3),
+	vupdate_int_entry(4),
+	vupdate_int_entry(5),
+};
+
+static enum dc_irq_source to_dal_irq_source(
+		struct irq_service *irq_service,
+		uint32_t src_id,
+		uint32_t ext_id)
+{
+	switch (src_id) {
+	case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE1;
+	case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE2;
+	case VISLANDS30_IV_SRCID_D3_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE3;
+	case VISLANDS30_IV_SRCID_D4_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE4;
+	case VISLANDS30_IV_SRCID_D5_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE5;
+	case VISLANDS30_IV_SRCID_D6_V_UPDATE_INT:
+		return DC_IRQ_SOURCE_VUPDATE6;
+	case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP1;
+	case VISLANDS30_IV_SRCID_D2_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP2;
+	case VISLANDS30_IV_SRCID_D3_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP3;
+	case VISLANDS30_IV_SRCID_D4_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP4;
+	case VISLANDS30_IV_SRCID_D5_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP5;
+	case VISLANDS30_IV_SRCID_D6_GRPH_PFLIP:
+		return DC_IRQ_SOURCE_PFLIP6;
+
+	case VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A:
+		/* generic src_id for all HPD and HPDRX interrupts */
+		switch (ext_id) {
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_A:
+			return DC_IRQ_SOURCE_HPD1;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_B:
+			return DC_IRQ_SOURCE_HPD2;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_C:
+			return DC_IRQ_SOURCE_HPD3;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_D:
+			return DC_IRQ_SOURCE_HPD4;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_E:
+			return DC_IRQ_SOURCE_HPD5;
+		case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_F:
+			return DC_IRQ_SOURCE_HPD6;
+		case VISLANDS30_IV_EXTID_HPD_RX_A:
+			return DC_IRQ_SOURCE_HPD1RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_B:
+			return DC_IRQ_SOURCE_HPD2RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_C:
+			return DC_IRQ_SOURCE_HPD3RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_D:
+			return DC_IRQ_SOURCE_HPD4RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_E:
+			return DC_IRQ_SOURCE_HPD5RX;
+		case VISLANDS30_IV_EXTID_HPD_RX_F:
+			return DC_IRQ_SOURCE_HPD6RX;
+		default:
+			return DC_IRQ_SOURCE_INVALID;
+		}
+		break;
+
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+static const struct irq_service_funcs irq_service_funcs_dce110 = {
+		.to_dal_irq_source = to_dal_irq_source
+};
+
+bool construct(
+	struct irq_service *irq_service,
+	struct irq_service_init_data *init_data)
+{
+	if (!dal_irq_service_construct(irq_service, init_data))
+		return false;
+
+	irq_service->info = irq_source_info_dce110;
+	irq_service->funcs = &irq_service_funcs_dce110;
+
+	return true;
+}
+
+struct irq_service *dal_irq_service_dce110_create(
+	struct irq_service_init_data *init_data)
+{
+	struct irq_service *irq_service = dm_alloc(init_data->ctx, sizeof(*irq_service));
+
+	if (!irq_service)
+		return NULL;
+
+	if (construct(irq_service, init_data))
+		return irq_service;
+
+	dm_free(init_data->ctx, irq_service);
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
new file mode 100644
index 000000000000..d6c28e940403
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_SERVICE_DCE110_H__
+#define __DAL_IRQ_SERVICE_DCE110_H__
+
+#include "../irq_service.h"
+
+struct irq_service *dal_irq_service_dce110_create(
+	struct irq_service_init_data *init_data);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
new file mode 100644
index 000000000000..137233134a53
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/irq_service_interface.h"
+#include "include/logger_interface.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/irq_service_dce110.h"
+#endif
+
+#include "irq_service.h"
+
+bool dal_irq_service_construct(
+	struct irq_service *irq_service,
+	struct irq_service_init_data *init_data)
+{
+	if (!init_data || !init_data->ctx)
+		return false;
+
+	irq_service->ctx = init_data->ctx;
+	return true;
+}
+
+struct irq_service *dal_irq_service_create(
+	enum dce_version version,
+	struct irq_service_init_data *init_data)
+{
+	switch (version) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dal_irq_service_dce110_create(init_data);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dal_irq_service_dce110_create(init_data);
+#endif
+	default:
+		return NULL;
+	}
+}
+
+void dal_irq_service_destroy(struct irq_service **irq_service)
+{
+	if (!irq_service || !*irq_service) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	dm_free((*irq_service)->ctx, *irq_service);
+
+	*irq_service = NULL;
+}
+
+const struct irq_source_info *find_irq_source_info(
+	struct irq_service *irq_service,
+	enum dc_irq_source source)
+{
+	if (source > DAL_IRQ_SOURCES_NUMBER || source < DC_IRQ_SOURCE_INVALID)
+		return NULL;
+
+	return &irq_service->info[source];
+}
+
+void dal_irq_service_set_generic(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info,
+	bool enable)
+{
+	uint32_t addr = info->enable_reg;
+	uint32_t value = dm_read_reg(irq_service->ctx, addr);
+
+	value = (value & ~info->enable_mask) |
+		(info->enable_value[enable ? 0 : 1] & info->enable_mask);
+	dm_write_reg(irq_service->ctx, addr, value);
+}
+
+bool dal_irq_service_set(
+	struct irq_service *irq_service,
+	enum dc_irq_source source,
+	bool enable)
+{
+	const struct irq_source_info *info =
+		find_irq_source_info(irq_service, source);
+
+	if (!info) {
+		dal_logger_write(
+			irq_service->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_IRQ_SERVICE,
+			"%s: cannot find irq info table entry for %d\n",
+			__func__,
+			source);
+		return false;
+	}
+
+	dal_irq_service_ack(irq_service, source);
+
+	if (info->funcs->set)
+		return info->funcs->set(irq_service, info, enable);
+
+	dal_irq_service_set_generic(irq_service, info, enable);
+
+	return true;
+}
+
+void dal_irq_service_ack_generic(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info)
+{
+	uint32_t addr = info->ack_reg;
+	uint32_t value = dm_read_reg(irq_service->ctx, addr);
+
+	value = (value & ~info->ack_mask) |
+		(info->ack_value & info->ack_mask);
+	dm_write_reg(irq_service->ctx, addr, value);
+}
+
+bool dal_irq_service_ack(
+	struct irq_service *irq_service,
+	enum dc_irq_source source)
+{
+	const struct irq_source_info *info =
+		find_irq_source_info(irq_service, source);
+
+	if (!info) {
+		dal_logger_write(
+			irq_service->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_IRQ_SERVICE,
+			"%s: cannot find irq info table entry for %d\n",
+			__func__,
+			source);
+		return false;
+	}
+
+	if (info->funcs->ack)
+		return info->funcs->ack(irq_service, info);
+
+	dal_irq_service_ack_generic(irq_service, info);
+
+	return true;
+}
+
+enum dc_irq_source dal_irq_service_to_irq_source(
+		struct irq_service *irq_service,
+		uint32_t src_id,
+		uint32_t ext_id)
+{
+	return irq_service->funcs->to_dal_irq_source(
+		irq_service,
+		src_id,
+		ext_id);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/irq/irq_service.h b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.h
new file mode 100644
index 000000000000..a2a2d6965c2f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq/irq_service.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_SERVICE_H__
+#define __DAL_IRQ_SERVICE_H__
+
+#include "include/irq_service_interface.h"
+
+#include "irq_types.h"
+
+struct irq_service;
+struct irq_source_info;
+
+struct irq_source_info_funcs {
+	bool (*set)(
+		struct irq_service *irq_service,
+		const struct irq_source_info *info,
+		bool enable);
+	bool (*ack)(
+		struct irq_service *irq_service,
+		const struct irq_source_info *info);
+};
+
+struct irq_source_info {
+	uint32_t src_id;
+	uint32_t ext_id;
+	uint32_t enable_reg;
+	uint32_t enable_mask;
+	uint32_t enable_value[2];
+	uint32_t ack_reg;
+	uint32_t ack_mask;
+	uint32_t ack_value;
+	uint32_t status_reg;
+	const struct irq_source_info_funcs *funcs;
+};
+
+struct irq_service_funcs {
+	enum dc_irq_source (*to_dal_irq_source)(
+			struct irq_service *irq_service,
+			uint32_t src_id,
+			uint32_t ext_id);
+};
+
+struct irq_service {
+	struct dc_context *ctx;
+	const struct irq_source_info *info;
+	const struct irq_service_funcs *funcs;
+};
+
+bool dal_irq_service_construct(
+	struct irq_service *irq_service,
+	struct irq_service_init_data *init_data);
+
+void dal_irq_service_ack_generic(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info);
+
+void dal_irq_service_set_generic(
+	struct irq_service *irq_service,
+	const struct irq_source_info *info,
+	bool enable);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 10/26] drm/amd/dal: GPU
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (8 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 09/26] drm/amd/dal: IRQ Service Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 11/26] drm/amd/dal: Audio Harry Wentland
                     ` (15 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Encapsulates programming for HW blocks which are shared between display
paths, such as clock sources.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/gpu/Makefile            |  22 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c    |  92 ++
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h    |  63 ++
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c |  90 ++
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h |  33 +
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.c   | 968 +++++++++++++++++++++
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.h   |  53 ++
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c     | 205 +++++
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h     |  82 ++
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c     | 127 +++
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h     |  63 ++
 11 files changed, 1798 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h

diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/Makefile b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile
new file mode 100644
index 000000000000..b481a6d5c6bb
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the 'gpu' sub-component of DAL.
+# It provides the control and status of HW adapter resources,
+# that are global for the ASIC and sharable between pipes.
+
+GPU = dc_clock_generator.o display_clock.o divider_range.o
+
+AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU))
+
+AMD_DAL_FILES += $(AMD_DAL_GPU)
+
+
+###############################################################################
+# DCE 110 family
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+GPU_DCE110 = display_clock_dce110.o dc_clock_gating_dce110.o
+
+AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_GPU_DCE110)
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
new file mode 100644
index 000000000000..b3b0f99933f7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dc_clock_generator.h"
+
+void dal_dc_clock_generator_destroy(struct dc_clock_generator **dc)
+{
+	if (dc == NULL || *dc == NULL) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*dc)->funcs->destroy(dc);
+
+	*dc = NULL;
+}
+
+void dal_dc_clock_generator_set_display_pipe_mapping(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_mapping_params *params)
+{
+	dc_clk_gen->funcs->set_display_pipe_mapping(dc_clk_gen, params);
+}
+
+bool dal_dc_clock_generator_get_dp_ref_clk_ds_params(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_dp_ref_clk_ds_params *params)
+{
+	return dc_clk_gen->funcs->get_dp_ref_clk_ds_params(dc_clk_gen, params);
+}
+
+bool dal_dc_clock_generator_enable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen,
+	uint32_t dprefclk)
+{
+	return dc_clk_gen->funcs->enable_gtc_counter(dc_clk_gen, dprefclk);
+}
+
+void dal_dc_clock_generator_disable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen)
+{
+	dc_clk_gen->funcs->disable_gtc_counter(dc_clk_gen);
+}
+
+void dal_dc_clock_generator_set_gtc_group_offset(
+	struct dc_clock_generator *dc_clk_gen,
+	enum gtc_group group_num,
+	uint32_t offset)
+{
+	dc_clk_gen->funcs->set_gtc_group_offset(dc_clk_gen, group_num, offset);
+}
+
+void dal_dc_clock_generator_base_set_display_pipe_mapping(
+	struct dc_clock_generator *base,
+	struct dccg_mapping_params *params)
+{
+
+}
+
+bool dal_dc_clock_generator_construct_base(
+	struct dc_clock_generator *base,
+	struct dc_context *ctx
+)
+{
+	base->ctx = ctx;
+	return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
new file mode 100644
index 000000000000..d1bf1af0500a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DC_CLOCK_GENERATOR_H__
+#define __DAL_DC_CLOCK_GENERATOR_H__
+
+#include "include/dc_clock_generator_interface.h"
+
+struct dc_clock_generator_funcs {
+	void (*destroy)(struct dc_clock_generator **to_destroy);
+
+	void (*set_display_pipe_mapping)(
+		struct dc_clock_generator *dc_clk_gen,
+		struct dccg_mapping_params *params);
+
+	bool (*get_dp_ref_clk_ds_params)(
+		struct dc_clock_generator *dc_clk_gen,
+		struct dccg_dp_ref_clk_ds_params *params);
+	bool (*enable_gtc_counter)(
+		struct dc_clock_generator *dc_clk_gen,
+		uint32_t dprefclk);
+	void (*disable_gtc_counter)(
+		struct dc_clock_generator *dc_clk_gen);
+	void (*set_gtc_group_offset)(
+		struct dc_clock_generator *dc_clk_gen,
+		enum gtc_group group_num,
+		uint32_t offset);
+};
+struct dc_clock_generator {
+	const struct dc_clock_generator_funcs *funcs;
+	struct dc_context *ctx;
+};
+bool dal_dc_clock_generator_construct_base(
+	struct dc_clock_generator *base,
+	struct dc_context *ctx
+);
+void dal_dc_clock_generator_base_set_display_pipe_mapping(
+	struct dc_clock_generator *base,
+	struct dccg_mapping_params *params);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
new file mode 100644
index 000000000000..4c307f6baf5a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dc_clock_gating_dce110.h"
+
+/******************************************************************************
+ * Macro definitions
+ *****************************************************************************/
+
+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_GPU, \
+		"%s:%s()\n", __FILE__, __func__)
+
+/******************************************************************************
+ * static functions
+ *****************************************************************************/
+static void force_hw_base_light_sleep(struct dc_context *ctx)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+
+	addr = mmDC_MEM_GLOBAL_PWR_REQ_CNTL;
+	/* Read the mmDC_MEM_GLOBAL_PWR_REQ_CNTL to get the currently
+	 * programmed DC_MEM_GLOBAL_PWR_REQ_DIS*/
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+			value,
+			1,
+			DC_MEM_GLOBAL_PWR_REQ_CNTL,
+			DC_MEM_GLOBAL_PWR_REQ_DIS);
+
+	dm_write_reg(ctx, addr, value);
+
+}
+
+static void enable_hw_base_light_sleep(struct dc_context *ctx)
+{
+	NOT_IMPLEMENTED();
+}
+
+static void disable_sw_manual_control_light_sleep(
+		struct dc_context *ctx)
+{
+	NOT_IMPLEMENTED();
+}
+
+/******************************************************************************
+ * public functions
+ *****************************************************************************/
+
+void dal_dc_clock_gating_dce110_power_up(
+		struct dc_context *ctx,
+		bool enable)
+{
+	if (enable) {
+		enable_hw_base_light_sleep(ctx);
+		disable_sw_manual_control_light_sleep(ctx);
+	} else {
+		force_hw_base_light_sleep(ctx);
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
new file mode 100644
index 000000000000..1bfd75a1fb51
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DC_CLOCK_GATING_DCE110_H__
+#define __DAL_DC_CLOCK_GATING_DCE110_H__
+
+void dal_dc_clock_gating_dce110_power_up(
+		struct dc_context *ctx,
+		bool enable);
+
+#endif /* __DAL_DC_CLOCK_GATING_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
new file mode 100644
index 000000000000..15243dea3290
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
@@ -0,0 +1,968 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "include/adapter_service_interface.h"
+#include "include/bios_parser_interface.h"
+#include "include/fixed32_32.h"
+#include "include/logger_interface.h"
+
+#include "../divider_range.h"
+
+#include "display_clock_dce110.h"
+
+#define FROM_DISPLAY_CLOCK(base) \
+	container_of(base, struct display_clock_dce110, disp_clk_base)
+
+static struct state_dependent_clocks max_clks_by_state[] = {
+/*ClocksStateInvalid - should not be used*/
+{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
+/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 },
+/*ClocksStateLow*/
+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 },
+/*ClocksStateNominal*/
+{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 },
+/*ClocksStatePerformance*/
+{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } };
+
+
+/* Starting point for each divider range.*/
+enum divider_range_start {
+	DIVIDER_RANGE_01_START = 200, /* 2.00*/
+	DIVIDER_RANGE_02_START = 1600, /* 16.00*/
+	DIVIDER_RANGE_03_START = 3200, /* 32.00*/
+	DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/
+};
+
+/* Array identifiers and count for the divider ranges.*/
+enum divider_range_count {
+	DIVIDER_RANGE_01 = 0,
+	DIVIDER_RANGE_02,
+	DIVIDER_RANGE_03,
+	DIVIDER_RANGE_MAX /* == 3*/
+};
+
+/* Ranges for divider identifiers (Divider ID or DID)
+ mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/
+enum divider_id_register_setting {
+	DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08,
+	DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40,
+	DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60,
+	DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80
+};
+
+/* Step size between each divider within a range.
+ Incrementing the DENTIST_DISPCLK_WDIVIDER by one
+ will increment the divider by this much.*/
+enum divider_range_step_size {
+	DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/
+	DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/
+	DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */
+};
+
+static struct divider_range divider_ranges[DIVIDER_RANGE_MAX];
+
+#define DCE110_DFS_BYPASS_THRESHOLD_KHZ 400000
+/*****************************************************************************
+ * static functions
+ *****************************************************************************/
+
+/*
+ * store_max_clocks_state
+ *
+ * @brief
+ * Cache the clock state
+ *
+ * @param
+ * struct display_clock *base - [out] cach the state in this structure
+ * enum clocks_state max_clocks_state - [in] state to be stored
+ */
+static void store_max_clocks_state(
+	struct display_clock *base,
+	enum clocks_state max_clocks_state)
+{
+	struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base);
+
+	switch (max_clocks_state) {
+	case CLOCKS_STATE_LOW:
+	case CLOCKS_STATE_NOMINAL:
+	case CLOCKS_STATE_PERFORMANCE:
+	case CLOCKS_STATE_ULTRA_LOW:
+		dc->max_clks_state = max_clocks_state;
+		break;
+
+	case CLOCKS_STATE_INVALID:
+	default:
+		/*Invalid Clocks State!*/
+		ASSERT_CRITICAL(false);
+		break;
+	}
+}
+
+static enum clocks_state get_min_clocks_state(struct display_clock *base)
+{
+	return base->cur_min_clks_state;
+}
+
+static bool set_min_clocks_state(
+	struct display_clock *base,
+	enum clocks_state clocks_state)
+{
+	struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base);
+
+	if (clocks_state > dc->max_clks_state) {
+		/*Requested state exceeds max supported state.*/
+		dal_logger_write(base->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"Requested state exceeds max supported state");
+		return false;
+	} else if (clocks_state == base->cur_min_clks_state) {
+		/*if we're trying to set the same state, we can just return
+		 * since nothing needs to be done*/
+		return true;
+	}
+
+	base->cur_min_clks_state = clocks_state;
+
+	return true;
+}
+
+static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc)
+{
+	uint32_t dispclk_cntl_value;
+	uint32_t dp_ref_clk_cntl_value;
+	uint32_t dp_ref_clk_cntl_src_sel_value;
+	uint32_t dp_ref_clk_khz = 600000;
+	uint32_t target_div = INVALID_DIVIDER;
+	struct display_clock_dce110 *disp_clk = FROM_DISPLAY_CLOCK(dc);
+
+	/* ASSERT DP Reference Clock source is from DFS*/
+	dp_ref_clk_cntl_value = dm_read_reg(dc->ctx,
+			mmDPREFCLK_CNTL);
+
+	dp_ref_clk_cntl_src_sel_value =
+			get_reg_field_value(
+				dp_ref_clk_cntl_value,
+				DPREFCLK_CNTL, DPREFCLK_SRC_SEL);
+
+	ASSERT(dp_ref_clk_cntl_src_sel_value == 0);
+
+	/* Read the mmDENTIST_DISPCLK_CNTL to get the currently
+	 * programmed DID DENTIST_DPREFCLK_WDIVIDER*/
+	dispclk_cntl_value = dm_read_reg(dc->ctx,
+			mmDENTIST_DISPCLK_CNTL);
+
+	/* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/
+	target_div = dal_divider_range_get_divider(
+		divider_ranges,
+		DIVIDER_RANGE_MAX,
+		get_reg_field_value(dispclk_cntl_value,
+			DENTIST_DISPCLK_CNTL,
+			DENTIST_DPREFCLK_WDIVIDER));
+
+
+	if (target_div != INVALID_DIVIDER) {
+		/* Calculate the current DFS clock, in kHz.*/
+		dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR
+			* disp_clk->dentist_vco_freq_khz) / target_div;
+	}
+
+	/* SW will adjust DP REF Clock average value for all purposes
+	 * (DP DTO / DP Audio DTO and DP GTC)
+	 if clock is spread for all cases:
+	 -if SS enabled on DP Ref clock and HW de-spreading enabled with SW
+	 calculations for DS_INCR/DS_MODULO (this is planned to be default case)
+	 -if SS enabled on DP Ref clock and HW de-spreading enabled with HW
+	 calculations (not planned to be used, but average clock should still
+	 be valid)
+	 -if SS enabled on DP Ref clock and HW de-spreading disabled
+	 (should not be case with CIK) then SW should program all rates
+	 generated according to average value (case as with previous ASICs)
+	  */
+	if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) {
+		struct fixed32_32 ss_percentage = dal_fixed32_32_div_int(
+				dal_fixed32_32_from_fraction(
+					disp_clk->gpu_pll_ss_percentage,
+					disp_clk->gpu_pll_ss_divider), 200);
+		struct fixed32_32 adj_dp_ref_clk_khz;
+
+		ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one,
+								ss_percentage);
+		adj_dp_ref_clk_khz =
+			dal_fixed32_32_mul_int(
+				ss_percentage,
+				dp_ref_clk_khz);
+		dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz);
+	}
+
+	return dp_ref_clk_khz;
+}
+
+
+static void destroy(struct display_clock **base)
+{
+	struct display_clock_dce110 *dc110;
+
+	dc110 = DCLCK110_FROM_BASE(*base);
+
+	dm_free((*base)->ctx, dc110);
+
+	*base = NULL;
+}
+
+static uint32_t get_validation_clock(struct display_clock *dc)
+{
+	uint32_t clk = 0;
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+
+	switch (disp_clk->max_clks_state) {
+	case CLOCKS_STATE_ULTRA_LOW:
+		/*Currently not supported, it has 0 in table entry*/
+	case CLOCKS_STATE_LOW:
+		clk = max_clks_by_state[CLOCKS_STATE_LOW].
+						display_clk_khz;
+		break;
+
+	case CLOCKS_STATE_NOMINAL:
+		clk = max_clks_by_state[CLOCKS_STATE_NOMINAL].
+						display_clk_khz;
+		break;
+
+	case CLOCKS_STATE_PERFORMANCE:
+		clk = max_clks_by_state[CLOCKS_STATE_PERFORMANCE].
+						display_clk_khz;
+		break;
+
+	case CLOCKS_STATE_INVALID:
+	default:
+		/*Invalid Clocks State*/
+		dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"Invalid clock state");
+		/* just return the display engine clock for
+		 * lowest supported state*/
+		clk = max_clks_by_state[CLOCKS_STATE_LOW].
+						display_clk_khz;
+		break;
+	}
+	return clk;
+}
+
+static struct fixed32_32 get_deep_color_factor(struct min_clock_params *params)
+{
+	/* DeepColorFactor = IF (HDMI = True, bpp / 24, 1)*/
+	struct fixed32_32 deep_color_factor = dal_fixed32_32_from_int(1);
+
+	if (params->signal_type != SIGNAL_TYPE_HDMI_TYPE_A)
+		return deep_color_factor;
+
+	switch (params->deep_color_depth) {
+	case COLOR_DEPTH_101010:
+		/*deep color ratio for 30bpp is 30/24 = 1.25*/
+		deep_color_factor = dal_fixed32_32_from_fraction(30, 24);
+		break;
+
+	case COLOR_DEPTH_121212:
+		/* deep color ratio for 36bpp is 36/24 = 1.5*/
+		deep_color_factor = dal_fixed32_32_from_fraction(36, 24);
+		break;
+
+	case COLOR_DEPTH_161616:
+		/* deep color ratio for 48bpp is 48/24 = 2.0 */
+		deep_color_factor = dal_fixed32_32_from_fraction(48, 24);
+		break;
+	default:
+		break;
+	}
+	return deep_color_factor;
+}
+
+static struct fixed32_32 get_scaler_efficiency(
+	struct dc_context *ctx,
+	struct min_clock_params *params)
+{
+	struct fixed32_32 scaler_efficiency = dal_fixed32_32_from_int(3);
+
+	if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB18BPP) {
+		scaler_efficiency =
+			dal_fixed32_32_add(
+				dal_fixed32_32_from_fraction(35555, 10000),
+				dal_fixed32_32_from_fraction(
+					55556,
+					100000 * 10000));
+	} else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB24BPP) {
+		scaler_efficiency =
+			dal_fixed32_32_add(
+				dal_fixed32_32_from_fraction(34285, 10000),
+				dal_fixed32_32_from_fraction(
+					71429,
+					100000 * 10000));
+	} else if (params->scaler_efficiency == V_SCALER_EFFICIENCY_LB30BPP)
+		scaler_efficiency = dal_fixed32_32_from_fraction(32, 10);
+
+	return scaler_efficiency;
+}
+
+static struct fixed32_32 get_lb_lines_in_per_line_out(
+		struct min_clock_params *params,
+		struct fixed32_32 v_scale_ratio)
+{
+	struct fixed32_32 two = dal_fixed32_32_from_int(2);
+	struct fixed32_32 four = dal_fixed32_32_from_int(4);
+	struct fixed32_32 f4_to_3 = dal_fixed32_32_from_fraction(4, 3);
+	struct fixed32_32 f6_to_4 = dal_fixed32_32_from_fraction(6, 4);
+
+	if (params->line_buffer_prefetch_enabled)
+		return dal_fixed32_32_max(v_scale_ratio, dal_fixed32_32_one);
+	else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_one))
+		return dal_fixed32_32_one;
+	else if (dal_fixed32_32_le(v_scale_ratio, f4_to_3))
+		return f4_to_3;
+	else if (dal_fixed32_32_le(v_scale_ratio, f6_to_4))
+		return f6_to_4;
+	else if (dal_fixed32_32_le(v_scale_ratio, two))
+		return two;
+	else if (dal_fixed32_32_le(v_scale_ratio, dal_fixed32_32_from_int(3)))
+		return four;
+	else
+		return dal_fixed32_32_zero;
+}
+
+static uint32_t get_actual_required_display_clk(
+	struct display_clock_dce110 *disp_clk,
+	uint32_t target_clk_khz)
+{
+	uint32_t disp_clk_khz = target_clk_khz;
+	uint32_t div = INVALID_DIVIDER;
+	uint32_t did = INVALID_DID;
+	uint32_t scaled_vco =
+		disp_clk->dentist_vco_freq_khz * DIVIDER_RANGE_SCALE_FACTOR;
+
+	ASSERT_CRITICAL(!!disp_clk_khz);
+
+	if (disp_clk_khz)
+		div = scaled_vco / disp_clk_khz;
+
+	did = dal_divider_range_get_did(divider_ranges, DIVIDER_RANGE_MAX, div);
+
+	if (did != INVALID_DID) {
+		div = dal_divider_range_get_divider(
+			divider_ranges, DIVIDER_RANGE_MAX, did);
+
+		if ((div != INVALID_DIVIDER) &&
+			(did > DIVIDER_RANGE_01_BASE_DIVIDER_ID))
+			if (disp_clk_khz > (scaled_vco / div))
+				div = dal_divider_range_get_divider(
+					divider_ranges, DIVIDER_RANGE_MAX,
+					did - 1);
+
+		if (div != INVALID_DIVIDER)
+			disp_clk_khz = scaled_vco / div;
+
+	}
+	/* We need to add 10KHz to this value because the accuracy in VBIOS is
+	 in 10KHz units. So we need to always round the last digit up in order
+	 to reach the next div level.*/
+	return disp_clk_khz + 10;
+}
+
+static uint32_t calc_single_display_min_clks(
+	struct display_clock *base,
+	struct min_clock_params *params,
+	bool set_clk)
+{
+	struct fixed32_32 h_scale_ratio = dal_fixed32_32_one;
+	struct fixed32_32 v_scale_ratio = dal_fixed32_32_one;
+	uint32_t pix_clk_khz = 0;
+	uint32_t lb_source_width = 0;
+	struct fixed32_32 deep_color_factor;
+	struct fixed32_32 scaler_efficiency;
+	struct fixed32_32 v_filter_init;
+	uint32_t v_filter_init_trunc;
+	uint32_t num_lines_at_frame_start = 3;
+	struct fixed32_32 v_filter_init_ceil;
+	struct fixed32_32 lines_per_lines_out_at_frame_start;
+	struct fixed32_32 lb_lines_in_per_line_out; /* in middle of the frame*/
+	uint32_t src_wdth_rnd_to_chunks;
+	struct fixed32_32 scaling_coeff;
+	struct fixed32_32 h_blank_granularity_factor =
+			dal_fixed32_32_one;
+	struct fixed32_32 fx_disp_clk_mhz;
+	struct fixed32_32 line_time;
+	struct fixed32_32 disp_pipe_pix_throughput;
+	struct fixed32_32 fx_alt_disp_clk_mhz;
+	uint32_t disp_clk_khz;
+	uint32_t alt_disp_clk_khz;
+	struct display_clock_dce110 *disp_clk_110 = DCLCK110_FROM_BASE(base);
+	uint32_t max_clk_khz = get_validation_clock(base);
+	bool panning_allowed = false; /* TODO: receive this value from AS */
+
+	if (params == NULL) {
+		dal_logger_write(base->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"Invalid input parameter in %s",
+				__func__);
+		return 0;
+	}
+
+	deep_color_factor = get_deep_color_factor(params);
+	scaler_efficiency = get_scaler_efficiency(base->ctx, params);
+	pix_clk_khz = params->requested_pixel_clock;
+	lb_source_width = params->source_view.width;
+
+	if (0 != params->dest_view.height && 0 != params->dest_view.width) {
+
+		h_scale_ratio = dal_fixed32_32_from_fraction(
+			params->source_view.width,
+			params->dest_view.width);
+		v_scale_ratio = dal_fixed32_32_from_fraction(
+			params->source_view.height,
+			params->dest_view.height);
+	} else {
+		dal_logger_write(base->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"Destination height or width is 0!\n");
+	}
+
+	v_filter_init =
+		dal_fixed32_32_add(
+			v_scale_ratio,
+			dal_fixed32_32_add_int(
+				dal_fixed32_32_div_int(
+					dal_fixed32_32_mul_int(
+						v_scale_ratio,
+						params->timing_info.INTERLACED),
+					2),
+				params->scaling_info.v_taps + 1));
+	v_filter_init = dal_fixed32_32_div_int(v_filter_init, 2);
+
+	v_filter_init_trunc = dal_fixed32_32_floor(v_filter_init);
+
+	v_filter_init_ceil = dal_fixed32_32_from_fraction(
+						v_filter_init_trunc, 2);
+	v_filter_init_ceil = dal_fixed32_32_from_int(
+		dal_fixed32_32_ceil(v_filter_init_ceil));
+	v_filter_init_ceil = dal_fixed32_32_mul_int(v_filter_init_ceil, 2);
+
+	lines_per_lines_out_at_frame_start =
+			dal_fixed32_32_div_int(v_filter_init_ceil,
+					num_lines_at_frame_start);
+	lb_lines_in_per_line_out =
+			get_lb_lines_in_per_line_out(params, v_scale_ratio);
+
+	if (panning_allowed)
+		src_wdth_rnd_to_chunks =
+			((lb_source_width - 1) / 128) * 128 + 256;
+	else
+		src_wdth_rnd_to_chunks =
+			((lb_source_width + 127) / 128) * 128;
+
+	scaling_coeff =
+		dal_fixed32_32_div(
+			dal_fixed32_32_from_int(params->scaling_info.v_taps),
+			scaler_efficiency);
+
+	if (dal_fixed32_32_le(h_scale_ratio, dal_fixed32_32_one))
+		scaling_coeff = dal_fixed32_32_max(
+			dal_fixed32_32_from_int(
+				dal_fixed32_32_ceil(
+					dal_fixed32_32_from_fraction(
+						params->scaling_info.h_taps,
+						4))),
+			dal_fixed32_32_max(
+				dal_fixed32_32_mul(
+					scaling_coeff,
+					h_scale_ratio),
+				dal_fixed32_32_one));
+
+	if (!params->line_buffer_prefetch_enabled &&
+		dal_fixed32_32_floor(lb_lines_in_per_line_out) != 2 &&
+		dal_fixed32_32_floor(lb_lines_in_per_line_out) != 4) {
+		uint32_t line_total_pixel =
+			params->timing_info.h_total + lb_source_width - 256;
+		h_blank_granularity_factor = dal_fixed32_32_div(
+			dal_fixed32_32_from_int(params->timing_info.h_total),
+			dal_fixed32_32_div(
+			dal_fixed32_32_from_fraction(
+				line_total_pixel, 2),
+				h_scale_ratio));
+	}
+
+	/* Calculate display clock with ramping. Ramping factor is 1.1*/
+	fx_disp_clk_mhz =
+		dal_fixed32_32_div_int(
+			dal_fixed32_32_mul_int(scaling_coeff, 11),
+			10);
+	line_time = dal_fixed32_32_from_fraction(
+			params->timing_info.h_total * 1000, pix_clk_khz);
+
+	disp_pipe_pix_throughput = dal_fixed32_32_mul(
+			lb_lines_in_per_line_out, h_blank_granularity_factor);
+	disp_pipe_pix_throughput = dal_fixed32_32_max(
+			disp_pipe_pix_throughput,
+			lines_per_lines_out_at_frame_start);
+	disp_pipe_pix_throughput = dal_fixed32_32_div(dal_fixed32_32_mul_int(
+			disp_pipe_pix_throughput, src_wdth_rnd_to_chunks),
+			line_time);
+
+	if (0 != params->timing_info.h_total) {
+		fx_disp_clk_mhz =
+			dal_fixed32_32_max(
+				dal_fixed32_32_div_int(
+					dal_fixed32_32_mul_int(
+						scaling_coeff, pix_clk_khz),
+						1000),
+				disp_pipe_pix_throughput);
+		fx_disp_clk_mhz =
+			dal_fixed32_32_mul(
+				fx_disp_clk_mhz,
+				dal_fixed32_32_from_fraction(11, 10));
+	}
+
+	fx_disp_clk_mhz = dal_fixed32_32_max(fx_disp_clk_mhz,
+		dal_fixed32_32_mul(deep_color_factor,
+		dal_fixed32_32_from_fraction(11, 10)));
+
+	/* Calculate display clock without ramping */
+	fx_alt_disp_clk_mhz = scaling_coeff;
+
+	if (0 != params->timing_info.h_total) {
+		fx_alt_disp_clk_mhz = dal_fixed32_32_max(
+				dal_fixed32_32_div_int(dal_fixed32_32_mul_int(
+						scaling_coeff, pix_clk_khz),
+						1000),
+				dal_fixed32_32_div_int(dal_fixed32_32_mul_int(
+						disp_pipe_pix_throughput, 105),
+						100));
+	}
+
+	if (set_clk && disp_clk_110->ss_on_gpu_pll &&
+			disp_clk_110->gpu_pll_ss_divider)
+		fx_alt_disp_clk_mhz = dal_fixed32_32_mul(fx_alt_disp_clk_mhz,
+				dal_fixed32_32_add_int(
+				dal_fixed32_32_div_int(
+				dal_fixed32_32_div_int(
+				dal_fixed32_32_from_fraction(
+				disp_clk_110->gpu_pll_ss_percentage,
+				disp_clk_110->gpu_pll_ss_divider), 100),
+				2),
+				1));
+
+	/* convert to integer */
+	disp_clk_khz = dal_fixed32_32_round(
+			dal_fixed32_32_mul_int(fx_disp_clk_mhz, 1000));
+	alt_disp_clk_khz = dal_fixed32_32_round(
+			dal_fixed32_32_mul_int(fx_alt_disp_clk_mhz, 1000));
+
+	if ((disp_clk_khz > max_clk_khz) && (alt_disp_clk_khz <= max_clk_khz))
+		disp_clk_khz = alt_disp_clk_khz;
+
+	if (set_clk) { /* only compensate clock if we are going to set it.*/
+		disp_clk_khz = get_actual_required_display_clk(
+			disp_clk_110, disp_clk_khz);
+	}
+
+	disp_clk_khz = disp_clk_khz > max_clk_khz ? max_clk_khz : disp_clk_khz;
+
+	return disp_clk_khz;
+}
+
+static uint32_t calculate_min_clock(
+	struct display_clock *base,
+	uint32_t path_num,
+	struct min_clock_params *params)
+{
+	uint32_t i;
+	uint32_t validation_clk_khz =
+			get_validation_clock(base);
+	uint32_t min_clk_khz = validation_clk_khz;
+	uint32_t max_clk_khz = 0;
+	struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base);
+
+	if (dc->use_max_disp_clk)
+		return min_clk_khz;
+
+	if (params != NULL) {
+		uint32_t disp_clk_khz = 0;
+
+		for (i = 0; i < path_num; ++i) {
+
+			disp_clk_khz = calc_single_display_min_clks(
+							base, params, true);
+
+			/* update the max required clock found*/
+			if (disp_clk_khz > max_clk_khz)
+				max_clk_khz = disp_clk_khz;
+
+			params++;
+		}
+	}
+
+	min_clk_khz = max_clk_khz;
+
+	if (min_clk_khz > validation_clk_khz)
+		min_clk_khz = validation_clk_khz;
+	else if (min_clk_khz < base->min_display_clk_threshold_khz)
+		min_clk_khz = base->min_display_clk_threshold_khz;
+
+	if (dc->use_max_disp_clk)
+		min_clk_khz = get_validation_clock(base);
+
+	return min_clk_khz;
+}
+
+static bool display_clock_integrated_info_construct(
+	struct display_clock_dce110 *disp_clk,
+	struct adapter_service *as)
+{
+	struct integrated_info info;
+	struct firmware_info fw_info;
+	uint32_t i;
+	struct display_clock *base = &disp_clk->disp_clk_base;
+	bool res;
+
+	dm_memset(&info, 0, sizeof(struct integrated_info));
+	dm_memset(&fw_info, 0, sizeof(struct firmware_info));
+
+	res = dal_adapter_service_get_integrated_info(as, &info);
+
+	disp_clk->dentist_vco_freq_khz = info.dentist_vco_freq;
+	if (disp_clk->dentist_vco_freq_khz == 0) {
+		dal_adapter_service_get_firmware_info(as, &fw_info);
+		disp_clk->dentist_vco_freq_khz =
+			fw_info.smu_gpu_pll_output_freq;
+		if (disp_clk->dentist_vco_freq_khz == 0)
+			disp_clk->dentist_vco_freq_khz = 3600000;
+	}
+
+	base->min_display_clk_threshold_khz =
+		disp_clk->dentist_vco_freq_khz / 64;
+
+	if (!res)
+		return false;
+
+	/*update the maximum display clock for each power state*/
+	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+		enum clocks_state clk_state = CLOCKS_STATE_INVALID;
+
+		switch (i) {
+		case 0:
+			clk_state = CLOCKS_STATE_ULTRA_LOW;
+			break;
+
+		case 1:
+			clk_state = CLOCKS_STATE_LOW;
+			break;
+
+		case 2:
+			clk_state = CLOCKS_STATE_NOMINAL;
+			break;
+
+		case 3:
+			clk_state = CLOCKS_STATE_PERFORMANCE;
+			break;
+
+		default:
+			clk_state = CLOCKS_STATE_INVALID;
+			break;
+		}
+
+		/*Do not allow bad VBIOS/SBIOS to override with invalid values,
+		 * check for > 100MHz*/
+		if (info.disp_clk_voltage[i].max_supported_clk >= 100000) {
+			max_clks_by_state[clk_state].display_clk_khz =
+				info.disp_clk_voltage[i].max_supported_clk;
+		}
+	}
+	disp_clk->dfs_bypass_enabled =
+		dal_adapter_service_is_dfs_bypass_enabled(as);
+	disp_clk->use_max_disp_clk =
+		dal_adapter_service_is_feature_supported(
+			FEATURE_USE_MAX_DISPLAY_CLK);
+
+	return true;
+}
+
+static uint32_t get_clock(struct display_clock *dc)
+{
+	uint32_t disp_clock = get_validation_clock(dc);
+	uint32_t target_div = INVALID_DIVIDER;
+	uint32_t addr = mmDENTIST_DISPCLK_CNTL;
+	uint32_t value = 0;
+	uint32_t field = 0;
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+
+	if (disp_clk->dfs_bypass_enabled && disp_clk->dfs_bypass_disp_clk)
+		return disp_clk->dfs_bypass_disp_clk;
+
+	/* Read the mmDENTIST_DISPCLK_CNTL to get the currently programmed
+	 DID DENTIST_DISPCLK_WDIVIDER.*/
+	value = dm_read_reg(dc->ctx, addr);
+	field = get_reg_field_value(
+			value, DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER);
+
+	/* Convert DENTIST_DISPCLK_WDIVIDER to actual divider*/
+	target_div = dal_divider_range_get_divider(
+		divider_ranges,
+		DIVIDER_RANGE_MAX,
+		field);
+
+	if (target_div != INVALID_DIVIDER)
+		/* Calculate the current DFS clock in KHz.
+		 Should be okay up to 42.9 THz before overflowing.*/
+		disp_clock = (DIVIDER_RANGE_SCALE_FACTOR
+			* disp_clk->dentist_vco_freq_khz) / target_div;
+	return disp_clock;
+}
+
+static enum clocks_state get_required_clocks_state(
+		struct display_clock *dc,
+		struct state_dependent_clocks *req_clocks)
+{
+	int32_t i;
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+	enum clocks_state low_req_clk = disp_clk->max_clks_state;
+
+	if (!req_clocks) {
+		/* NULL pointer*/
+		dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"%s: Invalid parameter",
+				__func__);
+		return CLOCKS_STATE_INVALID;
+	}
+
+	/* Iterate from highest supported to lowest valid state, and update
+	 * lowest RequiredState with the lowest state that satisfies
+	 * all required clocks
+	 */
+	for (i = disp_clk->max_clks_state; i >= CLOCKS_STATE_ULTRA_LOW; --i) {
+		if ((req_clocks->display_clk_khz <=
+			max_clks_by_state[i].display_clk_khz) &&
+			(req_clocks->pixel_clk_khz <=
+				max_clks_by_state[i].pixel_clk_khz))
+			low_req_clk = i;
+	}
+	return low_req_clk;
+}
+
+static void set_clock(
+	struct display_clock *base,
+	uint32_t requested_clk_khz)
+{
+	struct bp_pixel_clock_parameters pxl_clk_params;
+	struct display_clock_dce110 *dc = DCLCK110_FROM_BASE(base);
+	struct dc_bios *bp = dal_adapter_service_get_bios_parser(base->as);
+
+	/* Prepare to program display clock*/
+	dm_memset(&pxl_clk_params, 0, sizeof(pxl_clk_params));
+
+	pxl_clk_params.target_pixel_clock = requested_clk_khz;
+	pxl_clk_params.pll_id = base->id;
+
+	bp->funcs->program_display_engine_pll(bp, &pxl_clk_params);
+
+	if (dc->dfs_bypass_enabled) {
+
+		/* Cache the fixed display clock*/
+		dc->dfs_bypass_disp_clk =
+			pxl_clk_params.dfs_bypass_display_clock;
+	}
+
+	/* from power down, we need mark the clock state as ClocksStateNominal
+	 * from HWReset, so when resume we will call pplib voltage regulator.*/
+	if (requested_clk_khz == 0)
+		base->cur_min_clks_state = CLOCKS_STATE_NOMINAL;
+}
+
+static void set_clock_state(
+	struct display_clock *dc,
+	struct display_clock_state clk_state)
+{
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+
+	disp_clk->clock_state = clk_state;
+}
+
+static struct display_clock_state get_clock_state(
+	struct display_clock *dc)
+{
+	struct display_clock_dce110 *disp_clk = DCLCK110_FROM_BASE(dc);
+
+	return disp_clk->clock_state;
+}
+
+static uint32_t get_dfs_bypass_threshold(struct display_clock *dc)
+{
+	return DCE110_DFS_BYPASS_THRESHOLD_KHZ;
+}
+
+static const struct display_clock_funcs funcs = {
+	.destroy = destroy,
+	.calculate_min_clock = calculate_min_clock,
+	.get_clock = get_clock,
+	.get_clock_state = get_clock_state,
+	.get_dfs_bypass_threshold = get_dfs_bypass_threshold,
+	.get_dp_ref_clk_frequency = get_dp_ref_clk_frequency,
+	.get_min_clocks_state = get_min_clocks_state,
+	.get_required_clocks_state = get_required_clocks_state,
+	.get_validation_clock = get_validation_clock,
+	.set_clock = set_clock,
+	.set_clock_state = set_clock_state,
+	.set_dp_ref_clock_source = NULL,
+	.set_min_clocks_state = set_min_clocks_state,
+	.store_max_clocks_state = store_max_clocks_state,
+	.validate = NULL,
+};
+
+static bool dal_display_clock_dce110_construct(
+	struct display_clock_dce110 *dc110,
+	struct dc_context *ctx,
+	struct adapter_service *as)
+{
+	struct display_clock *dc_base = &dc110->disp_clk_base;
+
+	if (NULL == as)
+		return false;
+
+	if (!dal_display_clock_construct_base(dc_base, ctx, as))
+		return false;
+
+	dc_base->funcs = &funcs;
+
+	dc110->dfs_bypass_disp_clk = 0;
+
+	if (!display_clock_integrated_info_construct(dc110, as))
+		dal_logger_write(dc_base->ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_GPU,
+			"Cannot obtain VBIOS integrated info\n");
+
+	dc110->gpu_pll_ss_percentage = 0;
+	dc110->gpu_pll_ss_divider = 1000;
+	dc110->ss_on_gpu_pll = false;
+
+	dc_base->id = CLOCK_SOURCE_ID_DFS;
+/* Initially set max clocks state to nominal.  This should be updated by
+ * via a pplib call to DAL IRI eventually calling a
+ * DisplayEngineClock_Dce110::StoreMaxClocksState().  This call will come in
+ * on PPLIB init. This is from DCE5x. in case HW wants to use mixed method.*/
+	dc110->max_clks_state = CLOCKS_STATE_NOMINAL;
+
+	dal_divider_range_construct(
+		&divider_ranges[DIVIDER_RANGE_01],
+		DIVIDER_RANGE_01_START,
+		DIVIDER_RANGE_01_STEP_SIZE,
+		DIVIDER_RANGE_01_BASE_DIVIDER_ID,
+		DIVIDER_RANGE_02_BASE_DIVIDER_ID);
+	dal_divider_range_construct(
+		&divider_ranges[DIVIDER_RANGE_02],
+		DIVIDER_RANGE_02_START,
+		DIVIDER_RANGE_02_STEP_SIZE,
+		DIVIDER_RANGE_02_BASE_DIVIDER_ID,
+		DIVIDER_RANGE_03_BASE_DIVIDER_ID);
+	dal_divider_range_construct(
+		&divider_ranges[DIVIDER_RANGE_03],
+		DIVIDER_RANGE_03_START,
+		DIVIDER_RANGE_03_STEP_SIZE,
+		DIVIDER_RANGE_03_BASE_DIVIDER_ID,
+		DIVIDER_RANGE_MAX_DIVIDER_ID);
+
+	{
+		uint32_t ss_info_num =
+			dal_adapter_service_get_ss_info_num(
+				as,
+				AS_SIGNAL_TYPE_GPU_PLL);
+
+		if (ss_info_num) {
+			struct spread_spectrum_info info;
+			bool result;
+
+			dm_memset(&info, 0, sizeof(info));
+
+			result =
+				dal_adapter_service_get_ss_info(
+					as,
+					AS_SIGNAL_TYPE_GPU_PLL,
+					0,
+					&info);
+
+			/* Based on VBIOS, VBIOS will keep entry for GPU PLL SS
+			 * even if SS not enabled and in that case
+			 * SSInfo.spreadSpectrumPercentage !=0 would be sign
+			 * that SS is enabled
+			 */
+			if (result && info.spread_spectrum_percentage != 0) {
+				dc110->ss_on_gpu_pll = true;
+				dc110->gpu_pll_ss_divider =
+					info.spread_percentage_divider;
+
+				if (info.type.CENTER_MODE == 0) {
+					/* Currently for DP Reference clock we
+					 * need only SS percentage for
+					 * downspread */
+					dc110->gpu_pll_ss_percentage =
+						info.spread_spectrum_percentage;
+				}
+			}
+
+		}
+	}
+
+	return true;
+}
+
+/*****************************************************************************
+ * public functions
+ *****************************************************************************/
+
+struct display_clock *dal_display_clock_dce110_create(
+	struct dc_context *ctx,
+	struct adapter_service *as)
+{
+	struct display_clock_dce110 *dc110;
+
+	dc110 = dm_alloc(ctx, sizeof(struct display_clock_dce110));
+
+	if (dc110 == NULL)
+		return NULL;
+
+	if (dal_display_clock_dce110_construct(dc110, ctx, as))
+		return &dc110->disp_clk_base;
+
+	dm_free(ctx, dc110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
new file mode 100644
index 000000000000..0cdc7b52a09f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_DISPLAY_CLOCK_DCE110_H__
+#define __DAL_DISPLAY_CLOCK_DCE110_H__
+
+#include "gpu/display_clock.h"
+
+struct display_clock_dce110 {
+	struct display_clock disp_clk_base;
+	/* Max display block clocks state*/
+	enum clocks_state max_clks_state;
+	bool use_max_disp_clk;
+	uint32_t dentist_vco_freq_khz;
+	/* Cache the status of DFS-bypass feature*/
+	bool dfs_bypass_enabled;
+	/* GPU PLL SS percentage (if down-spread enabled) */
+	uint32_t gpu_pll_ss_percentage;
+	/* GPU PLL SS percentage Divider (100 or 1000) */
+	uint32_t gpu_pll_ss_divider;
+	/* Flag for Enabled SS on GPU PLL */
+	bool ss_on_gpu_pll;
+	/* Cache the display clock returned by VBIOS if DFS-bypass is enabled.
+	 * This is basically "Crystal Frequency In KHz" (XTALIN) frequency */
+	uint32_t dfs_bypass_disp_clk;
+	struct display_clock_state clock_state;
+};
+
+#define DCLCK110_FROM_BASE(dc_base) \
+	container_of(dc_base, struct display_clock_dce110, disp_clk_base)
+
+#endif /* __DAL_DISPLAY_CLOCK_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
new file mode 100644
index 000000000000..13192484a3ba
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "display_clock.h"
+
+#include "adapter_service_interface.h"
+
+void dal_display_clock_base_set_dp_ref_clock_source(
+	struct display_clock *disp_clk,
+	enum clock_source_id clk_src)
+{/*must be implemented in derived*/
+
+}
+
+void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk,
+	struct display_clock_state clk_state)
+{
+	/*Implemented only in DCE81*/
+}
+struct display_clock_state dal_display_clock_base_get_clock_state(
+	struct display_clock *disp_clk)
+{
+	/*Implemented only in DCE81*/
+	struct display_clock_state state = {0};
+	return state;
+}
+uint32_t dal_display_clock_base_get_dfs_bypass_threshold(
+	struct display_clock *disp_clk)
+{
+	/*Implemented only in DCE81*/
+	return 0;
+}
+
+bool dal_display_clock_construct_base(
+	struct display_clock *base,
+	struct dc_context *ctx,
+	struct adapter_service *as)
+{
+	base->ctx = ctx;
+	base->id = CLOCK_SOURCE_ID_DCPLL;
+	base->min_display_clk_threshold_khz = 0;
+	base->as = as;
+
+/* Initially set current min clocks state to invalid since we
+ * cannot make any assumption about PPLIB's initial state. This will be updated
+ * by HWSS via SetMinClocksState() on first mode set prior to programming
+ * state dependent clocks.*/
+	base->cur_min_clks_state = CLOCKS_STATE_INVALID;
+
+	return true;
+}
+
+void dal_display_clock_destroy(struct display_clock **disp_clk)
+{
+	if (!disp_clk || !*disp_clk) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*disp_clk)->funcs->destroy(disp_clk);
+
+	*disp_clk = NULL;
+}
+
+bool dal_display_clock_validate(
+	struct display_clock *disp_clk,
+	struct min_clock_params *params)
+{
+	return disp_clk->funcs->validate(disp_clk, params);
+}
+
+uint32_t dal_display_clock_calculate_min_clock(
+	struct display_clock *disp_clk,
+	uint32_t path_num,
+	struct min_clock_params *params)
+{
+	return disp_clk->funcs->calculate_min_clock(disp_clk, path_num, params);
+}
+
+uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_validation_clock(disp_clk);
+}
+
+void dal_display_clock_set_clock(
+	struct display_clock *disp_clk,
+	uint32_t requested_clock_khz)
+{
+	disp_clk->funcs->set_clock(disp_clk, requested_clock_khz);
+}
+
+uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_clock(disp_clk);
+}
+
+enum clocks_state dal_display_clock_get_min_clocks_state(
+	struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_min_clocks_state(disp_clk);
+}
+
+enum clocks_state dal_display_clock_get_required_clocks_state(
+	struct display_clock *disp_clk,
+	struct state_dependent_clocks *req_clocks)
+{
+	return disp_clk->funcs->get_required_clocks_state(disp_clk, req_clocks);
+}
+
+bool dal_display_clock_set_min_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state clocks_state)
+{
+	return disp_clk->funcs->set_min_clocks_state(disp_clk, clocks_state);
+}
+
+uint32_t dal_display_clock_get_dp_ref_clk_frequency(
+	struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_dp_ref_clk_frequency(disp_clk);
+}
+
+/*the second parameter of "switchreferenceclock" is
+ * a dummy argument for all pre dce 6.0 versions*/
+
+void dal_display_clock_switch_reference_clock(
+	struct display_clock *disp_clk,
+	bool use_external_ref_clk,
+	uint32_t requested_clk_khz)
+{
+	/* TODO: requires Asic Control*/
+	/*
+	struct ac_pixel_clk_params params;
+	struct asic_control *ac =
+		dal_adapter_service_get_asic_control(disp_clk->as);
+	dc_service_memset(&params, 0, sizeof(struct ac_pixel_clk_params));
+
+	params.tgt_pixel_clk_khz = requested_clk_khz;
+	params.flags.SET_EXTERNAL_REF_DIV_SRC = use_external_ref_clk;
+	params.pll_id = disp_clk->id;
+	dal_asic_control_program_display_engine_pll(ac, &params);
+	*/
+}
+
+void dal_display_clock_set_dp_ref_clock_source(
+	struct display_clock *disp_clk,
+	enum clock_source_id clk_src)
+{
+	disp_clk->funcs->set_dp_ref_clock_source(disp_clk, clk_src);
+}
+
+void dal_display_clock_store_max_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state max_clocks_state)
+{
+	disp_clk->funcs->store_max_clocks_state(disp_clk, max_clocks_state);
+}
+
+void dal_display_clock_set_clock_state(
+	struct display_clock *disp_clk,
+	struct display_clock_state clk_state)
+{
+	disp_clk->funcs->set_clock_state(disp_clk, clk_state);
+}
+
+struct display_clock_state dal_display_clock_get_clock_state(
+	struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_clock_state(disp_clk);
+}
+
+uint32_t dal_display_clock_get_dfs_bypass_threshold(
+	struct display_clock *disp_clk)
+{
+	return disp_clk->funcs->get_dfs_bypass_threshold(disp_clk);
+}
+
+void dal_display_clock_invalid_clock_state(
+	struct display_clock *disp_clk)
+{
+	disp_clk->cur_min_clks_state = CLOCKS_STATE_INVALID;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
new file mode 100644
index 000000000000..845393b7ecb6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DISPLAY_CLOCK_H__
+#define __DAL_DISPLAY_CLOCK_H__
+
+#include "include/display_clock_interface.h"
+
+struct display_clock_funcs {
+	void (*destroy)(struct display_clock **to_destroy);
+	bool (*validate)(struct display_clock *disp_clk,
+		struct min_clock_params *params);
+	uint32_t (*calculate_min_clock)(struct display_clock *disp_clk,
+		uint32_t path_num, struct min_clock_params *params);
+	uint32_t (*get_validation_clock)(struct display_clock *disp_clk);
+	void (*set_clock)(struct display_clock *disp_clk,
+		uint32_t requested_clock_khz);
+	uint32_t (*get_clock)(struct display_clock *disp_clk);
+	enum clocks_state (*get_min_clocks_state)(
+		struct display_clock *disp_clk);
+	enum clocks_state (*get_required_clocks_state)(
+		struct display_clock *disp_clk,
+		struct state_dependent_clocks *req_clocks);
+	bool (*set_min_clocks_state)(struct display_clock *disp_clk,
+		enum clocks_state clocks_state);
+	uint32_t (*get_dp_ref_clk_frequency)(struct display_clock *disp_clk);
+	void (*set_dp_ref_clock_source)(struct display_clock *disp_clk,
+		enum clock_source_id clk_src);
+	void (*store_max_clocks_state)(struct display_clock *disp_clk,
+		enum clocks_state max_clocks_state);
+	void (*set_clock_state)(struct display_clock *disp_clk,
+		struct display_clock_state clk_state);
+	struct display_clock_state (*get_clock_state)(
+		struct display_clock *disp_clk);
+	uint32_t (*get_dfs_bypass_threshold)(struct display_clock *disp_clk);
+};
+
+struct display_clock {
+	struct dc_context *ctx;
+	const struct display_clock_funcs *funcs;
+	uint32_t min_display_clk_threshold_khz;
+	enum clock_source_id id;
+	struct adapter_service *as;
+
+	enum clocks_state cur_min_clks_state;
+};
+void dal_display_clock_base_set_dp_ref_clock_source(
+	struct display_clock *disp_clk,
+	enum clock_source_id clk_src);
+struct display_clock_state dal_display_clock_base_get_clock_state(
+	struct display_clock *disp_clk);
+uint32_t dal_display_clock_base_get_dfs_bypass_threshold(
+	struct display_clock *disp_clk);
+void dal_display_clock_base_set_clock_state(struct display_clock *disp_clk,
+	struct display_clock_state clk_state);
+bool dal_display_clock_construct_base(
+	struct display_clock *base,
+	struct dc_context *ctx,
+	struct adapter_service *as);
+#endif /* __DAL_DISPLAY_CLOCK_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
new file mode 100644
index 000000000000..59d44004411b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "divider_range.h"
+
+bool dal_divider_range_construct(
+	struct divider_range *div_range,
+	uint32_t range_start,
+	uint32_t range_step,
+	uint32_t did_min,
+	uint32_t did_max)
+{
+	div_range->div_range_start = range_start;
+	div_range->div_range_step = range_step;
+	div_range->did_min = did_min;
+	div_range->did_max = did_max;
+
+	if (div_range->div_range_step == 0) {
+		div_range->div_range_step = 1;
+		/*div_range_step cannot be zero*/
+		BREAK_TO_DEBUGGER();
+	}
+	/* Calculate this based on the other inputs.*/
+	/* See DividerRange.h for explanation of */
+	/* the relationship between divider id (DID) and a divider.*/
+	/* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/
+	/* Maximum divider identified in this range =
+	 * (Number of Divider IDs)*Step size between dividers
+	 *  + The start of this range.*/
+	div_range->div_range_end = (did_max - did_min) * range_step
+		+ range_start;
+	return true;
+}
+
+static uint32_t dal_divider_range_calc_divider(
+	struct divider_range *div_range,
+	uint32_t did)
+{
+	/* Is this DID within our range?*/
+	if ((did < div_range->did_min) || (did >= div_range->did_max))
+		return INVALID_DIVIDER;
+
+	return ((did - div_range->did_min) * div_range->div_range_step)
+			+ div_range->div_range_start;
+
+}
+
+static uint32_t dal_divider_range_calc_did(
+	struct divider_range *div_range,
+	uint32_t div)
+{
+	uint32_t did;
+	/* Check before dividing.*/
+	if (div_range->div_range_step == 0) {
+		div_range->div_range_step = 1;
+		/*div_range_step cannot be zero*/
+		BREAK_TO_DEBUGGER();
+	}
+	/* Is this divider within our range?*/
+	if ((div < div_range->div_range_start)
+		|| (div >= div_range->div_range_end))
+		return INVALID_DID;
+/* did = (divider - range_start + (range_step-1)) / range_step) + did_min*/
+	did = div - div_range->div_range_start;
+	did += div_range->div_range_step - 1;
+	did /= div_range->div_range_step;
+	did += div_range->did_min;
+	return did;
+}
+
+uint32_t dal_divider_range_get_divider(
+	struct divider_range *div_range,
+	uint32_t ranges_num,
+	uint32_t did)
+{
+	uint32_t div = INVALID_DIVIDER;
+	uint32_t i;
+
+	for (i = 0; i < ranges_num; i++) {
+		/* Calculate divider with given divider ID*/
+		div = dal_divider_range_calc_divider(&div_range[i], did);
+		/* Found a valid return divider*/
+		if (div != INVALID_DIVIDER)
+			break;
+	}
+	return div;
+}
+uint32_t dal_divider_range_get_did(
+	struct divider_range *div_range,
+	uint32_t ranges_num,
+	uint32_t divider)
+{
+	uint32_t did = INVALID_DID;
+	uint32_t i;
+
+	for (i = 0; i < ranges_num; i++) {
+		/*  CalcDid returns InvalidDid if a divider ID isn't found*/
+		did = dal_divider_range_calc_did(&div_range[i], divider);
+		/* Found a valid return did*/
+		if (did != INVALID_DID)
+			break;
+	}
+	return did;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h
new file mode 100644
index 000000000000..2ec1034035ad
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DIVIDER_RANGE_H__
+#define __DAL_DIVIDER_RANGE_H__
+
+enum divider_error_types {
+	INVALID_DID = 0,
+	INVALID_DIVIDER = 1
+};
+
+struct divider_range {
+	uint32_t div_range_start;
+	/* The end of this range of dividers.*/
+	uint32_t div_range_end;
+	/* The distance between each divider in this range.*/
+	uint32_t div_range_step;
+	/* The divider id for the lowest divider.*/
+	uint32_t did_min;
+	/* The divider id for the highest divider.*/
+	uint32_t did_max;
+};
+
+bool dal_divider_range_construct(
+	struct divider_range *div_range,
+	uint32_t range_start,
+	uint32_t range_step,
+	uint32_t did_min,
+	uint32_t did_max);
+
+uint32_t dal_divider_range_get_divider(
+	struct divider_range *div_range,
+	uint32_t ranges_num,
+	uint32_t did);
+uint32_t dal_divider_range_get_did(
+	struct divider_range *div_range,
+	uint32_t ranges_num,
+	uint32_t divider);
+
+
+#endif /* __DAL_DIVIDER_RANGE_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 11/26] drm/amd/dal: Audio
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (9 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 10/26] drm/amd/dal: GPU Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 12/26] drm/amd/dal: Bandwidth calculations Harry Wentland
                     ` (14 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Responsible for programming the audio encoder in the display path.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/audio/Makefile          |   22 +
 drivers/gpu/drm/amd/dal/dc/audio/audio.h           |  195 ++
 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c      |  470 +++++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c |  453 +++++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h |   42 +
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c  | 1930 ++++++++++++++++++++
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h  |   47 +
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c    |  771 ++++++++
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h    |  285 +++
 9 files changed, 4215 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h

diff --git a/drivers/gpu/drm/amd/dal/dc/audio/Makefile b/drivers/gpu/drm/amd/dal/dc/audio/Makefile
new file mode 100644
index 000000000000..0999372cecf0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the 'audio' sub-component of DAL.
+# It provides the control and status of HW adapter resources,
+# that are global for the ASIC and sharable between pipes.
+
+AUDIO = audio_base.o hw_ctx_audio.o
+
+AMD_DAL_AUDIO = $(addprefix $(AMDDALPATH)/dc/audio/,$(AUDIO))
+
+AMD_DAL_FILES += $(AMD_DAL_AUDIO)
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+AUDIO_DCE11 = audio_dce110.o hw_ctx_audio_dce110.o
+
+AMD_DAL_AUDIO_DCE11 = $(addprefix $(AMDDALPATH)/dc/audio/dce110/,$(AUDIO_DCE11))
+
+AMD_DAL_FILES += $(AMD_DAL_AUDIO_DCE11)
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/audio.h b/drivers/gpu/drm/amd/dal/dc/audio/audio.h
new file mode 100644
index 000000000000..ad2dc18ef37b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/audio.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUDIO_H__
+#define __DAL_AUDIO_H__
+
+#include "include/audio_interface.h"
+#include "hw_ctx_audio.h"
+#include "include/link_service_types.h"
+
+/***** only for hook functions  *****/
+/**
+ *which will be overwritten by derived audio object.
+ *audio hw context object is independent object
+ */
+
+struct audio;
+
+struct audio_funcs {
+	/*
+	 *get_object_id
+	 *get_object_type
+	 *enumerate_input_signals
+	 *enumerate_output_signals
+	 *is_input_signal_supported
+	 *is_output_signal_supported
+	 *set_object_properties
+	 *get_object_properties
+	 */
+
+	void (*destroy)(struct audio **audio);
+	/*power_up
+	 *power_down
+	 *release_hw_base
+	 */
+
+	/* setup audio */
+	enum audio_result (*setup)(
+		struct audio *audio,
+		struct audio_output *output,
+		struct audio_info *info);
+
+	enum audio_result (*enable_output)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	enum audio_result (*disable_output)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	/*enable_azalia_audio_jack_presence
+	 * disable_azalia_audio_jack_presence
+	 */
+
+	enum audio_result (*unmute)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	enum audio_result (*mute)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal);
+
+	/* SW initialization that cannot be done in constructor. This will
+	 * be done is audio_power_up but is not in audio_interface. It is only
+	 * called by power_up
+	 */
+	enum audio_result (*initialize)(
+		struct audio *audio);
+
+	/* enable channel splitting mapping */
+	void (*enable_channel_splitting_mapping)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		enum signal_type signal,
+		const struct audio_channel_associate_info *audio_mapping,
+		bool enable);
+
+	/* get current multi channel split. */
+	enum audio_result (*get_channel_splitting_mapping)(
+		struct audio *audio,
+		enum engine_id engine_id,
+		struct audio_channel_associate_info *audio_mapping);
+
+	/* set payload value for the unsolicited response */
+	void (*set_unsolicited_response_payload)(
+		struct audio *audio,
+		enum audio_payload payload);
+
+	/* Update audio wall clock source */
+	void (*setup_audio_wall_dto)(
+		struct audio *audio,
+		enum signal_type signal,
+		const struct audio_crtc_info *crtc_info,
+		const struct audio_pll_info *pll_info);
+
+	/* options and features supported by Audio */
+	struct audio_feature_support (*get_supported_features)(
+		struct audio *audio);
+
+	/*
+	 *check_audio_bandwidth
+	 *write_reg
+	 *read_reg
+	 *enable_gtc_embedding_with_group
+	 *disable_gtc_embedding
+	 *register_interrupt
+	 *unregister_interrupt
+	 *process_interrupt
+	 *create_hw_ctx
+	 *getHwCtx
+	 *setHwCtx
+	 *handle_interrupt
+	 */
+};
+
+struct audio {
+	/* hook functions. they will be overwritten by specific ASIC */
+	const struct audio_funcs *funcs;
+	/* TODO: static struct audio_funcs funcs;*/
+
+	/*external structures - get service from external*/
+	struct graphics_object_id id;
+	struct adapter_service *adapter_service;
+	/* audio HW context */
+	struct hw_ctx_audio *hw_ctx;
+	struct dc_context *ctx;
+	/* audio supports input and output signals */
+	uint32_t input_signals;
+	uint32_t output_signals;
+};
+
+/* - functions defined by audio.h will be used by audio component only.
+ *   but audio.c also implements some function defined by dal\include
+ */
+
+/* graphics_object_base implemention
+ * 1.input_signals and output_signals are moved
+ * into audio object.
+ *
+ * 2.Get the Graphics Object ID
+ *
+ * Outside audio:
+ * use dal_graphics_object_id_get_audio_id
+ * Within audio:
+ *	use audio->go_base.id
+ *
+ * 3. Get the Graphics Object Type
+ *
+ *  use object_id.type
+ *  not function implemented.
+ * 4. Common Graphics Object Properties
+ * use object id ->go_properties.multi_path
+ * not function implemented.
+ */
+
+bool dal_audio_construct_base(
+	struct audio *audio,
+	const struct audio_init_data *init_data);
+
+void dal_audio_destruct_base(
+	struct audio *audio);
+
+void dal_audio_release_hw_base(
+	struct audio *audio);
+
+#endif  /* __DAL_AUDIO__ */
+
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
new file mode 100644
index 000000000000..bfd6725d9b91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "audio.h"
+#include "hw_ctx_audio.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/audio_dce110.h"
+#include "dce110/hw_ctx_audio_dce110.h"
+#endif
+
+/***** static function : only used within audio.c *****/
+
+/* stub for hook functions */
+static void destroy(
+	struct audio **audio)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+static enum audio_result setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static enum audio_result initialize(
+	struct audio *audio)
+{
+	/*DCE specific, must be implemented in derived. Implemeentaion of
+	 *initialize will create audio hw context. create_hw_ctx
+	 */
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+static void enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* get current multi channel split. */
+static enum audio_result get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return AUDIO_RESULT_OK;
+}
+
+/* set payload value for the unsolicited response */
+static void set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* update audio wall clock source */
+static void setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+static struct audio_feature_support get_supported_features(struct audio *audio)
+{
+	/*DCE specific, must be implemented in derived*/
+	struct audio_feature_support features;
+
+	dm_memset(&features, 0, sizeof(features));
+
+	features.ENGINE_DIGA = 1;
+	features.ENGINE_DIGB = 1;
+
+	return features;
+}
+
+static const struct audio_funcs audio_funcs = {
+	.destroy = destroy,
+	.setup = setup,
+	.enable_output = enable_output,
+	.disable_output = disable_output,
+	.unmute = unmute,
+	.mute = mute,
+	.initialize = initialize,
+	.enable_channel_splitting_mapping =
+		enable_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.setup_audio_wall_dto = setup_audio_wall_dto,
+	.get_supported_features = get_supported_features,
+};
+
+/***** SCOPE : declare in audio.h. use within dal-audio. *****/
+
+bool dal_audio_construct_base(
+	struct audio *audio,
+	const struct audio_init_data *init_data)
+{
+	enum signal_type signals = SIGNAL_TYPE_HDMI_TYPE_A;
+
+	ASSERT(init_data->as != NULL);
+
+	/* base hook functions */
+	audio->funcs = &audio_funcs;
+
+	/*setup pointers to get service from dal service compoenents*/
+	audio->adapter_service = init_data->as;
+
+	audio->ctx = init_data->ctx;
+
+	/* save audio endpoint number to identify object creating */
+	audio->id = init_data->audio_stream_id;
+
+	/* Fill supported signals. !!! be aware that android definition is
+	 * already shift to vector.
+	 */
+	signals |= SIGNAL_TYPE_DISPLAY_PORT;
+	signals |= SIGNAL_TYPE_DISPLAY_PORT_MST;
+	signals |= SIGNAL_TYPE_EDP;
+	signals |= SIGNAL_TYPE_DISPLAY_PORT;
+	signals |= SIGNAL_TYPE_WIRELESS;
+
+	/* Audio supports same set for input and output signals */
+	audio->input_signals = signals;
+	audio->output_signals = signals;
+
+	return true;
+}
+
+/* except hw_ctx, no other hw need reset. so do nothing */
+void dal_audio_destruct_base(
+	struct audio *audio)
+{
+}
+
+/* Enumerate Graphics Object supported Input/Output Signal Types */
+uint32_t dal_audio_enumerate_input_signals(
+	struct audio *audio)
+{
+	return audio->input_signals;
+}
+
+uint32_t dal_audio_enumerate_output_signals(
+	struct audio *audio)
+{
+	return audio->output_signals;
+}
+
+/*  Check if signal supported by GraphicsObject  */
+bool dal_audio_is_input_signal_supported(
+	struct audio *audio,
+	enum signal_type signal)
+{
+	return (signal & audio->output_signals) != 0;
+}
+
+bool dal_audio_is_output_signal_supported(
+	struct audio *audio,
+	enum signal_type signal)
+{
+	return (signal & audio->input_signals) != 0;
+}
+
+/***** SCOPE : declare in dal\include  *****/
+
+/* audio object creator triage. memory allocate and release will be
+ * done within dal_audio_create_dcexx
+ */
+struct audio *dal_audio_create(
+	const struct audio_init_data *init_data)
+{
+	struct adapter_service *as;
+
+	if (init_data->as == NULL)
+		return NULL;
+
+	as = init_data->as;
+	switch (dal_adapter_service_get_dce_version(as)) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dal_audio_create_dce110(init_data);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dal_audio_create_dce110(init_data);
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	return NULL;
+}
+
+/* audio object creator triage.
+ * memory for "struct audio   dal_audio_create_dce8x" allocate
+ * will happens within dal_audio_dce8x. memory allocate is done
+ * with dal_audio_create_dce8x. memory release is initiated by
+ * dal_audio_destroy. It will call hook function which will finially
+ * used destroy() of dal_audio_dce8x. therefore, no memroy allocate
+ *and release happen physcially at audio base object.
+ */
+void dal_audio_destroy(
+	struct audio **audio)
+{
+	if (!audio || !*audio) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	(*audio)->funcs->destroy(audio);
+
+	*audio = NULL;
+}
+
+const struct graphics_object_id dal_audio_get_graphics_object_id(
+	const struct audio *audio)
+{
+	return audio->id;
+}
+
+/* enable azalia audio endpoint. This function call hw_ctx directly
+ *not overwitten at audio level.
+ */
+enum audio_result dal_audio_enable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id)
+{
+	audio->hw_ctx->funcs->enable_azalia_audio(audio->hw_ctx, engine_id);
+	return AUDIO_RESULT_OK;
+}
+
+/* disable azalia audio endpoint. This function call hw_ctx directly
+ *not overwitten at audio level.
+ */
+enum audio_result dal_audio_disable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id)
+{
+	audio->hw_ctx->funcs->disable_azalia_audio(audio->hw_ctx, engine_id);
+	return AUDIO_RESULT_OK;
+}
+
+/* get audio bandwidth information. This function call hw_ctx directly
+ *not overwitten at audio level.
+ */
+void dal_audio_check_audio_bandwidth(
+	struct audio *audio,
+	const struct audio_crtc_info *info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates)
+{
+	dal_hw_ctx_audio_check_audio_bandwidth(
+		audio->hw_ctx, info, channel_count, signal, sample_rates);
+}
+
+/* DP Audio register write access. This function call hw_ctx directly
+ * not overwitten at audio level.
+ */
+
+/*assign GTC group and enable GTC value embedding*/
+void dal_audio_enable_gtc_embedding_with_group(
+	struct audio *audio,
+	uint32_t group_num,
+	uint32_t audio_latency)
+{
+	audio->hw_ctx->funcs->enable_gtc_embedding_with_group(
+		audio->hw_ctx, group_num, audio_latency);
+}
+
+/* disable GTC value embedding */
+void dal_audio_disable_gtc_embedding(
+	struct audio *audio)
+{
+	audio->hw_ctx->funcs->disable_gtc_embedding(audio->hw_ctx);
+}
+
+/* perform power up sequence (boot up, resume, recovery) */
+enum audio_result dal_audio_power_up(
+	struct audio *audio)
+{
+	return audio->funcs->initialize(audio);
+}
+
+/* perform power down (shut down, stand by) */
+enum audio_result dal_audio_power_down(
+	struct audio *audio)
+{
+	return AUDIO_RESULT_OK;
+}
+
+/* setup audio */
+enum audio_result dal_audio_setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info)
+{
+	return audio->funcs->setup(audio, output, info);
+}
+
+/* enable audio */
+enum audio_result dal_audio_enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->enable_output(audio, engine_id, signal);
+}
+
+/* disable audio */
+enum audio_result dal_audio_disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->disable_output(audio, engine_id, signal);
+}
+
+/* unmute audio */
+enum audio_result dal_audio_unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->unmute(audio, engine_id, signal);
+}
+
+/* mute audio */
+enum audio_result dal_audio_mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	return audio->funcs->mute(audio, engine_id, signal);
+}
+
+/* Enable multi channel split */
+void dal_audio_enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	audio->funcs->enable_channel_splitting_mapping(
+		audio, engine_id, signal, audio_mapping, enable);
+}
+
+/* get current multi channel split. */
+enum audio_result dal_audio_get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	return audio->funcs->get_channel_splitting_mapping(
+		audio, engine_id, audio_mapping);
+}
+
+/* set payload value for the unsolicited response */
+void dal_audio_set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload)
+{
+	audio->funcs->set_unsolicited_response_payload(audio, payload);
+}
+
+/* update audio wall clock source */
+void dal_audio_setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	audio->funcs->setup_audio_wall_dto(audio, signal, crtc_info, pll_info);
+}
+
+struct audio_feature_support dal_audio_get_supported_features(
+	struct audio *audio)
+{
+	return audio->funcs->get_supported_features(audio);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
new file mode 100644
index 000000000000..1aa0c1e61b32
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+
+#include "audio_dce110.h"
+
+/***** static functions  *****/
+
+static void destruct(struct audio_dce110 *audio)
+{
+	/*release memory allocated for hw_ctx -- allocated is initiated
+	 *by audio_dce110 power_up
+	 *audio->base->hw_ctx = NULL is done within hw-ctx->destroy
+	 */
+	if (audio->base.hw_ctx)
+		audio->base.hw_ctx->funcs->destroy(&(audio->base.hw_ctx));
+
+	/* reset base_audio_block */
+	dal_audio_destruct_base(&audio->base);
+}
+
+static void destroy(struct audio **ptr)
+{
+	struct audio_dce110 *audio = NULL;
+
+	audio = container_of(*ptr, struct audio_dce110, base);
+
+	destruct(audio);
+
+	/* release memory allocated for audio_dce110*/
+	dm_free((*ptr)->ctx, audio);
+	*ptr = NULL;
+}
+
+
+/* The inital call of hook function comes from audio object level.
+ *The passing object handle "struct audio *audio" point to base object
+ *already.There is not need to get base object from audio_dce110.
+ */
+
+/**
+* setup
+*
+* @brief
+*  setup Audio HW block, to be called by dal_audio_setup
+*
+*/
+static enum audio_result setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info)
+{
+	switch (output->signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		/*setup HDMI audio engine*/
+		audio->hw_ctx->funcs->enable_afmt_clock(
+			audio->hw_ctx,
+			output->engine_id,
+			true);
+		audio->hw_ctx->funcs->setup_hdmi_audio(
+			audio->hw_ctx, output->engine_id, &output->crtc_info);
+
+		audio->hw_ctx->funcs->setup_azalia(
+			audio->hw_ctx,
+			output->engine_id,
+			output->signal,
+			&output->crtc_info,
+			&output->pll_info,
+			info);
+		break;
+
+	case SIGNAL_TYPE_WIRELESS:
+		/* setup Azalia block for Wireless Display - This
+			is different than for wired
+			displays because there is no
+			DIG to program.*/
+		/*TODO:
+		audio->hw_ctx->funcs->setup_azalia_for_vce(
+			audio->hw_ctx,
+			audio->signal,
+			audio->crtc_info,
+			info);
+		*/
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		/* setup DP audio engine will be done at enable output */
+
+		/* setup Azalia block*/
+		audio->hw_ctx->funcs->setup_azalia(
+			audio->hw_ctx,
+			output->engine_id,
+			output->signal,
+			&output->crtc_info,
+			&output->pll_info,
+			info);
+
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* enable_output
+*
+* @brief
+*  enable Audio HW block, to be called by dal_audio_enable_output
+*/
+static enum audio_result enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	/* enable audio output */
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP: {
+			/* enable AFMT clock before enable audio*/
+			audio->hw_ctx->funcs->enable_afmt_clock(
+				audio->hw_ctx, engine_id, true);
+			/* setup DP audio engine */
+			audio->hw_ctx->funcs->setup_dp_audio(
+				audio->hw_ctx, engine_id);
+			/* enabl DP audio packets will be done at unblank */
+			audio->hw_ctx->funcs->enable_dp_audio(
+				audio->hw_ctx, engine_id);
+		}
+		break;
+	case SIGNAL_TYPE_WIRELESS:
+		/* route audio to VCE block */
+		audio->hw_ctx->funcs->setup_vce_audio(audio->hw_ctx);
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* disable_output
+*
+* @brief
+*  disable Audio HW block, to be called by dal_audio_disable_output
+*
+*/
+static enum audio_result disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_WIRELESS:
+		/* disable HDMI audio */
+		audio->hw_ctx->
+			funcs->disable_azalia_audio(
+					audio->hw_ctx, engine_id);
+		audio->hw_ctx->
+			funcs->enable_afmt_clock(
+					audio->hw_ctx, engine_id,
+					false);
+
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP: {
+			/* disable DP audio */
+			audio->hw_ctx->funcs->disable_dp_audio(
+				audio->hw_ctx, engine_id);
+			audio->hw_ctx->funcs->disable_azalia_audio(
+				audio->hw_ctx, engine_id);
+			audio->hw_ctx->funcs->enable_afmt_clock(
+				audio->hw_ctx, engine_id, false);
+		}
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* unmute
+*
+* @brief
+*  unmute audio, to be called by dal_audio_unmute
+*
+*/
+static enum audio_result unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		/* unmute Azalia audio */
+		audio->hw_ctx->funcs->unmute_azalia_audio(
+				audio->hw_ctx, engine_id);
+		break;
+	case SIGNAL_TYPE_WIRELESS:
+		/*Do nothing for wireless display*/
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* mute
+*
+* @brief
+*  mute audio, to be called  by dal_audio_nmute
+*
+*/
+static enum audio_result mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		/* mute Azalia audio */
+		audio->hw_ctx->funcs->mute_azalia_audio(
+				audio->hw_ctx, engine_id);
+		break;
+	case SIGNAL_TYPE_WIRELESS:
+		/*Do nothing for wireless display*/
+		break;
+	default:
+		return AUDIO_RESULT_ERROR;
+	}
+	return AUDIO_RESULT_OK;
+}
+
+/**
+* initialize
+*
+* @brief
+*  Perform SW initialization - create audio hw context. Then do HW
+*  initialization. this function is called at dal_audio_power_up.
+*
+*/
+static enum audio_result initialize(
+	struct audio *audio)
+{
+	uint8_t audio_endpoint_enum_id = 0;
+
+	audio_endpoint_enum_id = audio->id.enum_id;
+
+	/* HW CTX already create*/
+	if (audio->hw_ctx != NULL)
+		return AUDIO_RESULT_OK;
+
+	audio->hw_ctx = dal_hw_ctx_audio_dce110_create(
+			audio->ctx,
+			audio_endpoint_enum_id);
+
+	if (audio->hw_ctx == NULL)
+		return AUDIO_RESULT_ERROR;
+
+	/* override HW default settings */
+	audio->hw_ctx->funcs->hw_initialize(audio->hw_ctx);
+
+	return AUDIO_RESULT_OK;
+}
+
+/* enable multi channel split */
+static void enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	audio->hw_ctx->funcs->setup_channel_splitting_mapping(
+		audio->hw_ctx,
+		engine_id,
+		signal,
+		audio_mapping, enable);
+}
+
+/* get current multi channel split. */
+static enum audio_result get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	if (audio->hw_ctx->funcs->get_channel_splitting_mapping(
+		audio->hw_ctx, engine_id, audio_mapping)) {
+		return AUDIO_RESULT_OK;
+	} else {
+		return AUDIO_RESULT_ERROR;
+	}
+}
+
+/**
+* set_unsolicited_response_payload
+*
+* @brief
+*  Set payload value for the unsolicited response
+*/
+static void set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload)
+{
+	audio->hw_ctx->funcs->set_unsolicited_response_payload(
+			audio->hw_ctx, payload);
+}
+
+/**
+* setup_audio_wall_dto
+*
+* @brief
+*  Update audio source clock from hardware context.
+*
+*/
+static void setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	audio->hw_ctx->funcs->setup_audio_wall_dto(
+		audio->hw_ctx, signal, crtc_info, pll_info);
+}
+
+/**
+* get_supported_features
+*
+* @brief
+*  options and features supported by Audio
+*  returns supported engines, signals.
+*  features are reported for HW audio/Azalia block rather then Audio object
+*  itself the difference for DCE6.x is that MultiStream Audio is now supported
+*
+*/
+static struct audio_feature_support get_supported_features(struct audio *audio)
+{
+	struct audio_feature_support afs = {0};
+
+	afs.ENGINE_DIGA = 1;
+	afs.ENGINE_DIGB = 1;
+	afs.ENGINE_DIGC = 1;
+	afs.MULTISTREAM_AUDIO = 1;
+
+	return afs;
+}
+
+static const struct audio_funcs funcs = {
+	.destroy = destroy,
+	.setup = setup,
+	.enable_output = enable_output,
+	.disable_output = disable_output,
+	.unmute = unmute,
+	.mute = mute,
+	.initialize = initialize,
+	.enable_channel_splitting_mapping =
+		enable_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.setup_audio_wall_dto = setup_audio_wall_dto,
+	.get_supported_features = get_supported_features,
+};
+
+static bool construct(
+	struct audio_dce110 *audio,
+	const struct audio_init_data *init_data)
+{
+	struct audio *base = &audio->base;
+
+	/* base audio construct*/
+	if (!dal_audio_construct_base(base, init_data))
+		return false;
+
+	/*vtable methods*/
+	base->funcs = &funcs;
+	return true;
+}
+
+
+/* --- audio scope functions  --- */
+
+struct audio *dal_audio_create_dce110(
+	const struct audio_init_data *init_data)
+{
+	/*allocate memory for audio_dce110 */
+	struct audio_dce110 *audio = dm_alloc(init_data->ctx, sizeof(*audio));
+
+	if (audio == NULL) {
+		ASSERT_CRITICAL(audio);
+		return NULL;
+	}
+	/*pointer to base_audio_block of audio_dce110 ==> audio base object */
+	if (construct(audio, init_data))
+		return &audio->base;
+
+	dal_logger_write(
+		init_data->ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_AUDIO,
+		"Failed to create audio object for DCE11\n");
+
+	 /*release memory allocated if fail */
+	dm_free(init_data->ctx, audio);
+	return NULL;
+}
+
+/* Do not need expose construct_dce110 and destruct_dce110 becuase there is
+ *derived object after dce110
+ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
new file mode 100644
index 000000000000..e5ff823368b3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_AUDIO_DCE_110_H__
+#define __DAL_AUDIO_DCE_110_H__
+
+#include "audio/audio.h"
+#include "audio/hw_ctx_audio.h"
+#include "audio/dce110/hw_ctx_audio_dce110.h"
+
+
+
+struct audio_dce110 {
+	struct audio base;
+	/* dce-specific members are following */
+	/* none */
+};
+
+struct audio *dal_audio_create_dce110(const struct audio_init_data *init_data);
+
+#endif   /*__DAL_AUDIO_DCE_110_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
new file mode 100644
index 000000000000..f24b964bdd8d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
@@ -0,0 +1,1930 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/logger_interface.h"
+#include "../hw_ctx_audio.h"
+#include "hw_ctx_audio_dce110.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#define FROM_BASE(ptr) \
+	container_of((ptr), struct hw_ctx_audio_dce110, base)
+
+#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000
+#define DP_AUDIO_DTO_MODULE_WITHOUT_SS 360
+#define DP_AUDIO_DTO_PHASE_WITHOUT_SS 24
+
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUDIO_FRONT_END 0
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__REGISTER_PROGRAMMABLE 2
+
+#define FIRST_AUDIO_STREAM_ID 1
+
+#define NOT_IMPLEMENTED() DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_AUDIO, \
+			"Audio:%s()\n", __func__)
+
+static const uint32_t engine_offset[] = {
+	0,
+	mmDIG1_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL,
+	mmDIG2_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL,
+	mmDIG3_DIG_FE_CNTL - mmDIG0_DIG_FE_CNTL
+};
+
+static void destruct(
+	struct hw_ctx_audio_dce110 *hw_ctx_dce110)
+{
+	dal_audio_destruct_hw_ctx_audio(&hw_ctx_dce110->base);
+}
+
+static void destroy(
+	struct hw_ctx_audio **ptr)
+{
+	struct hw_ctx_audio_dce110 *hw_ctx_dce110;
+
+	hw_ctx_dce110 = container_of(
+		*ptr, struct hw_ctx_audio_dce110, base);
+
+	destruct(hw_ctx_dce110);
+	/* release memory allocated for struct hw_ctx_audio_dce110 */
+	dm_free((*ptr)->ctx, hw_ctx_dce110);
+
+	*ptr = NULL;
+}
+
+/* ---  helpers --- */
+static void write_indirect_azalia_reg(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t reg_index,
+	uint32_t reg_data)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	/* AZALIA_F0_CODEC_ENDPOINT_INDEX  endpoint index  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index;
+
+		set_reg_field_value(value, reg_index,
+			AZALIA_F0_CODEC_ENDPOINT_INDEX,
+			AZALIA_ENDPOINT_REG_INDEX);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AZALIA_F0_CODEC_ENDPOINT_DATA  endpoint data  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data;
+
+		value = 0;
+		set_reg_field_value(value, reg_data,
+			AZALIA_F0_CODEC_ENDPOINT_DATA,
+			AZALIA_ENDPOINT_REG_DATA);
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	dal_logger_write(
+		hw_ctx->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_AUDIO,
+		"AUDIO:write_indirect_azalia_reg: index: %u  data: %u\n",
+		reg_index, reg_data);
+}
+
+static uint32_t read_indirect_azalia_reg(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t reg_index)
+{
+	uint32_t ret_val = 0;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+
+	/* AZALIA_F0_CODEC_ENDPOINT_INDEX  endpoint index  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index;
+
+		set_reg_field_value(value, reg_index,
+			AZALIA_F0_CODEC_ENDPOINT_INDEX,
+			AZALIA_ENDPOINT_REG_INDEX);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AZALIA_F0_CODEC_ENDPOINT_DATA  endpoint data  */
+	{
+		addr =
+			FROM_BASE(hw_ctx)->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		ret_val = value;
+	}
+
+	dal_logger_write(
+		hw_ctx->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_AUDIO,
+		"AUDIO:read_indirect_azalia_reg: index: %u  data: %u\n",
+		reg_index, ret_val);
+
+	return ret_val;
+}
+
+/* expose/not expose HBR capability to Audio driver */
+static void set_high_bit_rate_capable(
+	const struct hw_ctx_audio *hw_ctx,
+	bool capable)
+{
+	uint32_t value = 0;
+
+	/* set high bit rate audio capable*/
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR);
+
+	set_reg_field_value(value, capable,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR,
+		HBR_CAPABLE);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR,
+		value);
+}
+
+/* set HBR channnel count *
+static void set_hbr_channel_count(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t hbr_channel_count)
+{
+	uint32_t value = 0;
+
+	if (hbr_channel_count > 7)
+		return;
+
+	value = dal_read_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL);
+
+	set_reg_field_value(value, hbr_channel_count,
+		AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL,
+		HBR_CHANNEL_COUNT);
+
+	dal_write_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL, value);
+
+}
+
+*set compressed audio channel count *
+static void set_compressed_audio_channel_count(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t compressed_audio_ch_count)
+{
+	uint32_t value = 0;
+	if (compressed_audio_ch_count > 7)
+		return;
+
+	value = dal_read_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL);
+
+	set_reg_field_value(value, compressed_audio_ch_count,
+		AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL,
+		COMPRESSED_CHANNEL_COUNT);
+
+	dal_write_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL,
+		value);
+
+}
+*/
+/* set video latency in in ms/2+1 */
+static void set_video_latency(
+	const struct hw_ctx_audio *hw_ctx,
+	int latency_in_ms)
+{
+	uint32_t value = 0;
+
+	if ((latency_in_ms < 0) || (latency_in_ms > 255))
+		return;
+
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
+
+	set_reg_field_value(value, latency_in_ms,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		VIDEO_LIPSYNC);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		value);
+
+}
+
+/* set audio latency in in ms/2+1 */
+static void set_audio_latency(
+	const struct hw_ctx_audio *hw_ctx,
+	int latency_in_ms)
+{
+	uint32_t value = 0;
+
+	if (latency_in_ms < 0)
+		latency_in_ms = 0;
+
+	if (latency_in_ms > 255)
+		latency_in_ms = 255;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
+
+	set_reg_field_value(value, latency_in_ms,
+		AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		AUDIO_LIPSYNC);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
+		value);
+
+}
+
+/* enable HW/SW Sync */
+/*static void enable_hw_sw_sync(
+	const struct hw_ctx_audio *hw_ctx)
+{
+		union AZALIA_CYCLIC_BUFFER_SYNC value;
+
+	value = dal_read_reg(mmAZALIA_CYCLIC_BUFFER_SYNC);
+	value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 1;
+	dal_write_reg(mmAZALIA_CYCLIC_BUFFER_SYNC, value);
+}*/
+
+/* disable HW/SW Sync */
+/*static void disable_hw_sw_sync(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	union AZALIA_CYCLIC_BUFFER_SYNC value;
+
+	value = dal_read_reg(
+		mmAZALIA_CYCLIC_BUFFER_SYNC);
+	value.bits.CYCLIC_BUFFER_SYNC_ENABLE = 0;
+	dal_write_reg(
+		mmAZALIA_CYCLIC_BUFFER_SYNC, value);
+}*/
+
+/* update hardware with software's current position in cyclic buffer */
+/*static void update_sw_write_ptr(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t offset)
+{
+		union AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER value;
+
+	value = dal_read_reg(
+		mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER);
+	value.bits.APPLICATION_POSITION_IN_CYCLIC_BUFFER = offset;
+	dal_write_reg(
+		mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER,
+		value);
+}*/
+
+/* update Audio/Video association */
+/*static void update_av_association(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	uint32_t displayId)
+{
+
+}*/
+
+/* ---  hook functions --- */
+static bool get_azalia_clock_info_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct azalia_clock_info *azalia_clock_info);
+
+static bool get_azalia_clock_info_dp(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t requested_pixel_clock_in_khz,
+	const struct audio_pll_info *pll_info,
+	struct azalia_clock_info *azalia_clock_info);
+
+static void setup_audio_wall_dto(
+	const struct hw_ctx_audio *hw_ctx,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	struct azalia_clock_info clock_info = { 0 };
+
+	uint32_t value = dm_read_reg(hw_ctx->ctx, mmDCCG_AUDIO_DTO_SOURCE);
+
+	/* TODO: GraphicsObject\inc\GraphicsObjectDefs.hpp(131):
+	 *inline bool isHdmiSignal(SignalType signal)
+	 *if (Signals::isHdmiSignal(signal))
+	 */
+	if (dc_is_hdmi_signal(signal)) {
+		/*DTO0 Programming goal:
+		-generate 24MHz, 128*Fs from 24MHz
+		-use DTO0 when an active HDMI port is connected
+		(optionally a DP is connected) */
+
+		/* calculate DTO settings */
+		get_azalia_clock_info_hdmi(
+			hw_ctx,
+			crtc_info->requested_pixel_clock,
+			crtc_info->calculated_pixel_clock,
+			&clock_info);
+
+		/* On TN/SI, Program DTO source select and DTO select before
+		programming DTO modulo and DTO phase. These bits must be
+		programmed first, otherwise there will be no HDMI audio at boot
+		up. This is a HW sequence change (different from old ASICs).
+		Caution when changing this programming sequence.
+
+		HDMI enabled, using DTO0
+		program master CRTC for DTO0 */
+		{
+			set_reg_field_value(value,
+				pll_info->dto_source - DTO_SOURCE_ID0,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO0_SOURCE_SEL);
+
+			set_reg_field_value(value,
+				0,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO_SEL);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO_SOURCE, value);
+		}
+
+		/* module */
+		{
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_MODULE);
+			set_reg_field_value(value,
+				clock_info.audio_dto_module,
+				DCCG_AUDIO_DTO0_MODULE,
+				DCCG_AUDIO_DTO0_MODULE);
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_MODULE, value);
+		}
+
+		/* phase */
+		{
+			value = 0;
+
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_PHASE);
+			set_reg_field_value(value,
+				clock_info.audio_dto_phase,
+				DCCG_AUDIO_DTO0_PHASE,
+				DCCG_AUDIO_DTO0_PHASE);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO0_PHASE, value);
+		}
+
+	} else {
+		/*DTO1 Programming goal:
+		-generate 24MHz, 512*Fs, 128*Fs from 24MHz
+		-default is to used DTO1, and switch to DTO0 when an audio
+		master HDMI port is connected
+		-use as default for DP
+
+		calculate DTO settings */
+		get_azalia_clock_info_dp(
+			hw_ctx,
+			crtc_info->requested_pixel_clock,
+			pll_info,
+			&clock_info);
+
+		/* Program DTO select before programming DTO modulo and DTO
+		phase. default to use DTO1 */
+
+		{
+			set_reg_field_value(value, 1,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO_SEL);
+			/*dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value)*/
+
+			/* Select 512fs for DP TODO: web register definition
+			does not match register header file
+			set_reg_field_value(value, 1,
+				DCCG_AUDIO_DTO_SOURCE,
+				DCCG_AUDIO_DTO2_USE_512FBR_DTO);
+			*/
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO_SOURCE, value);
+		}
+
+		/* module */
+		{
+			value = 0;
+
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_MODULE);
+
+			set_reg_field_value(value,
+				clock_info.audio_dto_module,
+				DCCG_AUDIO_DTO1_MODULE,
+				DCCG_AUDIO_DTO1_MODULE);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_MODULE, value);
+		}
+
+		/* phase */
+		{
+			value = 0;
+
+			value = dm_read_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_PHASE);
+
+			set_reg_field_value(value,
+				clock_info.audio_dto_phase,
+				DCCG_AUDIO_DTO1_PHASE,
+				DCCG_AUDIO_DTO1_PHASE);
+
+			dm_write_reg(hw_ctx->ctx,
+					mmDCCG_AUDIO_DTO1_PHASE, value);
+		}
+
+		/* DAL2 code separate DCCG_AUDIO_DTO_SEL and
+		DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different
+		location. merge together should not hurt */
+		/*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1;
+		dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/
+	}
+}
+
+/* setup HDMI audio */
+static void setup_hdmi_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	const struct audio_crtc_info *crtc_info)
+{
+	struct audio_clock_info audio_clock_info = {0};
+	uint32_t max_packets_per_line;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* For now still do calculation, although this field is ignored when
+	above HDMI_PACKET_GEN_VERSION set to 1 */
+	max_packets_per_line =
+		dal_audio_hw_ctx_calc_max_audio_packets_per_line(
+			hw_ctx,
+			crtc_info);
+
+	/* HDMI_AUDIO_PACKET_CONTROL */
+	{
+		addr =
+			mmHDMI_AUDIO_PACKET_CONTROL + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, max_packets_per_line,
+			HDMI_AUDIO_PACKET_CONTROL,
+			HDMI_AUDIO_PACKETS_PER_LINE);
+		/* still apply RS600's default setting which is 1. */
+		set_reg_field_value(value, 1,
+			HDMI_AUDIO_PACKET_CONTROL,
+			HDMI_AUDIO_DELAY_EN);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_AUDIO_PACKET_CONTROL */
+	{
+		addr = mmAFMT_AUDIO_PACKET_CONTROL + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 1,
+			AFMT_AUDIO_PACKET_CONTROL,
+			AFMT_60958_CS_UPDATE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_AUDIO_PACKET_CONTROL2 */
+	{
+		addr = mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 0,
+				AFMT_AUDIO_PACKET_CONTROL2,
+				AFMT_AUDIO_LAYOUT_OVRD);
+
+		/*Register field changed.*/
+		set_reg_field_value(value, 0,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_60958_OSF_OVRD);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* HDMI_ACR_PACKET_CONTROL */
+	{
+		addr = mmHDMI_ACR_PACKET_CONTROL + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 1,
+			HDMI_ACR_PACKET_CONTROL,
+			HDMI_ACR_AUTO_SEND);
+
+		/* Set HDMI_ACR_SOURCE to 0, to use hardwre
+		 *  computed CTS values.*/
+		set_reg_field_value(value, 0,
+			HDMI_ACR_PACKET_CONTROL,
+			HDMI_ACR_SOURCE);
+
+		/* For now clear HDMI_ACR_AUDIO_PRIORITY =>ACR packet has
+		higher priority over Audio Sample */
+		set_reg_field_value(value, 0,
+			HDMI_ACR_PACKET_CONTROL,
+			HDMI_ACR_AUDIO_PRIORITY);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* Program audio clock sample/regeneration parameters */
+	if (dal_audio_hw_ctx_get_audio_clock_info(
+		hw_ctx,
+		crtc_info->color_depth,
+		crtc_info->requested_pixel_clock,
+		crtc_info->calculated_pixel_clock,
+		&audio_clock_info)) {
+
+		/* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */
+		{
+			addr = mmHDMI_ACR_32_0 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+
+			set_reg_field_value(value, audio_clock_info.cts_32khz,
+				HDMI_ACR_32_0,
+				HDMI_ACR_CTS_32);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */
+		{
+			addr = mmHDMI_ACR_32_1 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.n_32khz,
+				HDMI_ACR_32_1,
+				HDMI_ACR_N_32);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */
+		{
+			addr = mmHDMI_ACR_44_0 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.cts_44khz,
+				HDMI_ACR_44_0,
+				HDMI_ACR_CTS_44);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */
+		{
+			addr = mmHDMI_ACR_44_1 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.n_44khz,
+				HDMI_ACR_44_1,
+				HDMI_ACR_N_44);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */
+		{
+			addr = mmHDMI_ACR_48_0 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.cts_48khz,
+				HDMI_ACR_48_0,
+				HDMI_ACR_CTS_48);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */
+		{
+			addr = mmHDMI_ACR_48_1 + engine_offset[engine_id];
+
+			value = dm_read_reg(hw_ctx->ctx, addr);
+			set_reg_field_value(value, audio_clock_info.n_48khz,
+				HDMI_ACR_48_1,
+				HDMI_ACR_N_48);
+
+			dm_write_reg(hw_ctx->ctx, addr, value);
+		}
+
+		/* Video driver cannot know in advance which sample rate will
+		be used by HD Audio driver
+		HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is
+		programmed below in interruppt callback */
+	} /* if */
+
+	/* AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK &
+	AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */
+	{
+		addr = mmAFMT_60958_0 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 1,
+			AFMT_60958_0,
+			AFMT_60958_CS_CHANNEL_NUMBER_L);
+
+		 /*HW default */
+		set_reg_field_value(value, 0,
+			AFMT_60958_0,
+			AFMT_60958_CS_CLOCK_ACCURACY);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_60958_1 AFMT_60958_CS_CHALNNEL_NUMBER_R */
+	{
+		addr = mmAFMT_60958_1 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 2,
+			AFMT_60958_1,
+			AFMT_60958_CS_CHANNEL_NUMBER_R);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/*AFMT_60958_2 now keep this settings until
+	 *  Programming guide comes out*/
+	{
+		addr = mmAFMT_60958_2 + engine_offset[engine_id];
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value, 3,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_2);
+
+		set_reg_field_value(value, 4,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_3);
+
+		set_reg_field_value(value, 5,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_4);
+
+		set_reg_field_value(value, 6,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_5);
+
+		set_reg_field_value(value, 7,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_6);
+
+		set_reg_field_value(value, 8,
+			AFMT_60958_2,
+			AFMT_60958_CS_CHANNEL_NUMBER_7);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+}
+
+ /* setup DP audio */
+static void setup_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/* --- DP Audio packet configurations --- */
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* ATP Configuration */
+	{
+		addr = mmDP_SEC_AUD_N + engine_offset[engine_id];
+
+		set_reg_field_value(value,
+			DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT,
+			DP_SEC_AUD_N,
+			DP_SEC_AUD_N);
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* Async/auto-calc timestamp mode */
+	{
+		addr = mmDP_SEC_TIMESTAMP +
+			engine_offset[engine_id];
+
+		value = 0;
+
+		set_reg_field_value(value,
+			DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC,
+			DP_SEC_TIMESTAMP,
+			DP_SEC_TIMESTAMP_MODE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* --- The following are the registers
+	 *  copied from the SetupHDMI --- */
+
+
+	/* AFMT_AUDIO_PACKET_CONTROL */
+	{
+		addr = mmAFMT_AUDIO_PACKET_CONTROL +
+			engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value,
+			1,
+			AFMT_AUDIO_PACKET_CONTROL,
+			AFMT_60958_CS_UPDATE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_AUDIO_PACKET_CONTROL2 */
+	{
+		addr =
+			mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value,
+			0,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_AUDIO_LAYOUT_OVRD);
+
+		set_reg_field_value(value,
+			0,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_60958_OSF_OVRD);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_INFOFRAME_CONTROL0 */
+	{
+		addr =
+			mmAFMT_INFOFRAME_CONTROL0 + engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value,
+			1,
+			AFMT_INFOFRAME_CONTROL0,
+			AFMT_AUDIO_INFO_UPDATE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK */
+	{
+		addr = mmAFMT_60958_0 + engine_offset[engine_id];
+
+		value = 0;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+		set_reg_field_value(value,
+			0,
+			AFMT_60958_0,
+			AFMT_60958_CS_CLOCK_ACCURACY);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+}
+
+ /* setup VCE audio */
+static void setup_vce_audio(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	struct dc_context *ctx = hw_ctx->ctx;
+
+	NOT_IMPLEMENTED();
+
+	/*TODO:
+	const uint32_t addr = mmDOUT_DCE_VCE_CONTROL;
+	uint32_t value = 0;
+
+	value = dal_read_reg(hw_ctx->ctx,
+			addr);
+
+	set_reg_field_value(value,
+		FROM_BASE(hw_ctx)->azalia_stream_id - 1,
+		DOUT_DCE_VCE_CONTROL,
+		DC_VCE_AUDIO_STREAM_SELECT);
+
+	dal_write_reg(hw_ctx->ctx,
+			addr, value);*/
+}
+
+static void enable_afmt_clock(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	bool enable_flag)
+{
+	uint32_t engine_offs = engine_offset[engine_id];
+	uint32_t value;
+	uint32_t count = 0;
+	uint32_t enable = enable_flag ? 1:0;
+
+	/* Enable Audio packets*/
+	value = dm_read_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs);
+
+	/*enable AFMT clock*/
+	set_reg_field_value(value, enable,
+		AFMT_CNTL, AFMT_AUDIO_CLOCK_EN);
+	dm_write_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs, value);
+
+	/*wait for AFMT clock to turn on,
+	 * the expectation is that this
+	 * should complete in 1-2 reads)
+	 */
+	do {
+		/* Wait for 1us between subsequent register reads.*/
+		dm_delay_in_microseconds(hw_ctx->ctx, 1);
+		value = dm_read_reg(hw_ctx->ctx,
+				mmAFMT_CNTL + engine_offs);
+	} while (get_reg_field_value(value,
+				AFMT_CNTL, AFMT_AUDIO_CLOCK_ON) !=
+						enable && count++ < 10);
+}
+
+/* enable Azalia audio */
+static void enable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	uint32_t value;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
+
+	if (get_reg_field_value(value,
+			AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+			AUDIO_ENABLED) != 1)
+		set_reg_field_value(value, 1,
+			AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+			AUDIO_ENABLED);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+		value);
+}
+
+/* disable Azalia audio */
+static void disable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	uint32_t value;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
+
+	set_reg_field_value(value, 0,
+		AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+		AUDIO_ENABLED);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
+		value);
+}
+
+/* enable DP audio */
+static void enable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id];
+
+	uint32_t value;
+
+	/* Enable Audio packets */
+	value = dm_read_reg(hw_ctx->ctx, addr);
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_ASP_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+
+	/* Program the ATP and AIP next */
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_ATP_ENABLE);
+
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_AIP_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+
+	/* Program STREAM_ENABLE after all the other enables. */
+	set_reg_field_value(value, 1,
+		DP_SEC_CNTL,
+		DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+/* disable DP audio */
+static void disable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id];
+
+	uint32_t value;
+
+	/* Disable Audio packets */
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_ASP_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_ATP_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_AIP_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_ACM_ENABLE);
+
+	set_reg_field_value(value, 0,
+		DP_SEC_CNTL,
+		DP_SEC_STREAM_ENABLE);
+
+	/* This register shared with encoder info frame. Therefore we need to
+	keep master enabled if at least on of the fields is not 0 */
+	if (value != 0)
+		set_reg_field_value(value, 1,
+			DP_SEC_CNTL,
+			DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+static void configure_azalia(
+	const struct hw_ctx_audio *hw_ctx,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_info *audio_info)
+{
+	uint32_t speakers = audio_info->flags.info.ALLSPEAKERS;
+	uint32_t value;
+	uint32_t field = 0;
+	enum audio_format_code audio_format_code;
+	uint32_t format_index;
+	uint32_t index;
+	bool is_ac3_supported = false;
+	bool is_audio_format_supported = false;
+	union audio_sample_rates sample_rate;
+	uint32_t strlen = 0;
+
+	/* Speaker Allocation */
+	/*
+	uint32_t value;
+	uint32_t field = 0;*/
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
+
+	set_reg_field_value(value,
+		speakers,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		SPEAKER_ALLOCATION);
+
+	/* LFE_PLAYBACK_LEVEL = LFEPBL
+	 * LFEPBL = 0 : Unknown or refer to other information
+	 * LFEPBL = 1 : 0dB playback
+	 * LFEPBL = 2 : +10dB playback
+	 * LFE_BL = 3 : Reserved
+	 */
+	set_reg_field_value(value,
+		0,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		LFE_PLAYBACK_LEVEL);
+
+	set_reg_field_value(value,
+		0,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		HDMI_CONNECTION);
+
+	set_reg_field_value(value,
+		0,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		DP_CONNECTION);
+
+	field = get_reg_field_value(value,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			EXTRA_CONNECTION_INFO);
+
+	field &= ~0x1;
+
+	set_reg_field_value(value,
+		field,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		EXTRA_CONNECTION_INFO);
+
+	/* set audio for output signal */
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		set_reg_field_value(value,
+			1,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			HDMI_CONNECTION);
+
+		break;
+	case SIGNAL_TYPE_WIRELESS: {
+		/*LSB used for "is wireless" flag */
+		field = 0;
+		field = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		EXTRA_CONNECTION_INFO);
+		field |= 0x1;
+		set_reg_field_value(value,
+			field,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			EXTRA_CONNECTION_INFO);
+
+		set_reg_field_value(value,
+			1,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			HDMI_CONNECTION);
+
+		}
+		break;
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		set_reg_field_value(value,
+			1,
+			AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+			DP_CONNECTION);
+
+		break;
+	default:
+		break;
+	}
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
+		value);
+
+	/* Wireless Display identification */
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION);
+
+	set_reg_field_value(value,
+		signal == SIGNAL_TYPE_WIRELESS ? 1 : 0,
+		AZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION,
+		WIRELESS_DISPLAY_IDENTIFICATION);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION,
+		value);
+
+	/*  Audio Descriptors   */
+	/* pass through all formats */
+	for (format_index = 0; format_index < AUDIO_FORMAT_CODE_COUNT;
+			format_index++) {
+		audio_format_code =
+			(AUDIO_FORMAT_CODE_FIRST + format_index);
+
+		/* those are unsupported, skip programming */
+		if (audio_format_code == AUDIO_FORMAT_CODE_1BITAUDIO ||
+			audio_format_code == AUDIO_FORMAT_CODE_DST)
+			continue;
+
+		value = 0;
+
+		/* check if supported */
+		is_audio_format_supported =
+			dal_audio_hw_ctx_is_audio_format_supported(
+				hw_ctx,
+				audio_info,
+				audio_format_code, &index);
+
+		if (is_audio_format_supported) {
+			const struct audio_mode *audio_mode =
+					&audio_info->modes[index];
+			union audio_sample_rates sample_rates =
+					audio_mode->sample_rates;
+			uint8_t byte2 = audio_mode->max_bit_rate;
+
+			/* adjust specific properties */
+			switch (audio_format_code) {
+			case AUDIO_FORMAT_CODE_LINEARPCM: {
+				dal_hw_ctx_audio_check_audio_bandwidth(
+					hw_ctx,
+					crtc_info,
+					audio_mode->channel_count,
+					signal,
+					&sample_rates);
+
+				byte2 = audio_mode->sample_size;
+
+				set_reg_field_value(value,
+				sample_rates.all,
+		AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+				SUPPORTED_FREQUENCIES_STEREO);
+
+				}
+				break;
+			case AUDIO_FORMAT_CODE_AC3:
+				is_ac3_supported = true;
+				break;
+			case AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS:
+			case AUDIO_FORMAT_CODE_DTS_HD:
+			case AUDIO_FORMAT_CODE_MAT_MLP:
+			case AUDIO_FORMAT_CODE_DST:
+			case AUDIO_FORMAT_CODE_WMAPRO:
+				byte2 = audio_mode->vendor_specific;
+				break;
+			default:
+				break;
+			}
+
+			/* fill audio format data */
+			set_reg_field_value(value,
+			audio_mode->channel_count - 1,
+			AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+			MAX_CHANNELS);
+
+			set_reg_field_value(value,
+			sample_rates.all,
+			AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+			SUPPORTED_FREQUENCIES);
+
+			set_reg_field_value(value,
+			byte2,
+			AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
+			DESCRIPTOR_BYTE_2);
+
+		} /* if */
+
+		write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 +
+		format_index,
+		value);
+	} /* for */
+
+	if (is_ac3_supported)
+		dm_write_reg(hw_ctx->ctx,
+		mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS,
+		0x05);
+
+	/* check for 192khz/8-Ch support for HBR requirements */
+	sample_rate.all = 0;
+	sample_rate.rate.RATE_192 = 1;
+	dal_hw_ctx_audio_check_audio_bandwidth(
+		hw_ctx,
+		crtc_info,
+		8,
+		signal,
+		&sample_rate);
+
+	set_high_bit_rate_capable(hw_ctx, sample_rate.rate.RATE_192);
+
+	/* Audio and Video Lipsync */
+	set_video_latency(hw_ctx, audio_info->video_latency);
+	set_audio_latency(hw_ctx, audio_info->audio_latency);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->manufacture_id,
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
+		MANUFACTURER_ID);
+
+	set_reg_field_value(value, audio_info->product_id,
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
+		PRODUCT_ID);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
+		value);
+
+
+	value = 0;
+
+	/*get display name string length */
+	while (audio_info->display_name[strlen++] != '\0') {
+		if (strlen >=
+		MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS)
+			break;
+		}
+	set_reg_field_value(value, strlen,
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1,
+		SINK_DESCRIPTION_LEN);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1,
+		value);
+
+
+	/*
+	*write the port ID:
+	*PORT_ID0 = display index
+	*PORT_ID1 = 16bit BDF
+	*(format MSB->LSB: 8bit Bus, 5bit Device, 3bit Function)
+	*/
+
+	value = 0;
+
+	set_reg_field_value(value, audio_info->port_id[0],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2,
+		PORT_ID0);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2,
+		value);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->port_id[1],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3,
+		PORT_ID1);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3,
+		value);
+
+	/*write the 18 char monitor string */
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[0],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION0);
+
+	set_reg_field_value(value, audio_info->display_name[1],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION1);
+
+	set_reg_field_value(value, audio_info->display_name[2],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION2);
+
+	set_reg_field_value(value, audio_info->display_name[3],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		DESCRIPTION3);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
+		value);
+
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[4],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION4);
+
+	set_reg_field_value(value, audio_info->display_name[5],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION5);
+
+	set_reg_field_value(value, audio_info->display_name[6],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION6);
+
+	set_reg_field_value(value, audio_info->display_name[7],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		DESCRIPTION7);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
+		value);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[8],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION8);
+
+	set_reg_field_value(value, audio_info->display_name[9],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION9);
+
+	set_reg_field_value(value, audio_info->display_name[10],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION10);
+
+	set_reg_field_value(value, audio_info->display_name[11],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		DESCRIPTION11);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
+		value);
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[12],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION12);
+
+	set_reg_field_value(value, audio_info->display_name[13],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION13);
+
+	set_reg_field_value(value, audio_info->display_name[14],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION14);
+
+	set_reg_field_value(value, audio_info->display_name[15],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		DESCRIPTION15);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
+		value);
+
+
+	value = 0;
+	set_reg_field_value(value, audio_info->display_name[16],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
+		DESCRIPTION16);
+
+	set_reg_field_value(value, audio_info->display_name[17],
+		AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
+		DESCRIPTION17);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
+		value);
+
+}
+
+/* setup Azalia HW block */
+static void setup_azalia(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info,
+	const struct audio_info *audio_info)
+{
+	uint32_t speakers = 0;
+	uint32_t channels = 0;
+
+	if (audio_info == NULL)
+		/* This should not happen.it does so we don't get BSOD*/
+		return;
+
+	speakers = audio_info->flags.info.ALLSPEAKERS;
+	channels = dal_audio_hw_ctx_speakers_to_channels(
+		hw_ctx,
+		audio_info->flags.speaker_flags).all;
+
+	/* setup the audio stream source select (audio -> dig mapping) */
+	{
+		const uint32_t addr =
+			mmAFMT_AUDIO_SRC_CONTROL + engine_offset[engine_id];
+
+		uint32_t value = 0;
+		/*convert one-based index to zero-based */
+		set_reg_field_value(value,
+			FROM_BASE(hw_ctx)->azalia_stream_id - 1,
+			AFMT_AUDIO_SRC_CONTROL,
+			AFMT_AUDIO_SRC_SELECT);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/* Channel allocation */
+	{
+		const uint32_t addr =
+			mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id];
+		uint32_t value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value,
+			channels,
+			AFMT_AUDIO_PACKET_CONTROL2,
+			AFMT_AUDIO_CHANNEL_ENABLE);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	configure_azalia(hw_ctx, signal, crtc_info, audio_info);
+}
+
+/* unmute audio */
+static void unmute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL +
+		engine_offset[engine_id];
+
+	uint32_t value = 0;
+
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	set_reg_field_value(value, 1,
+		AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+/* mute audio */
+static void mute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL +
+		engine_offset[engine_id];
+
+	uint32_t value = 0;
+
+	value = dm_read_reg(hw_ctx->ctx, addr);
+
+	set_reg_field_value(value, 0,
+		AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND);
+
+	dm_write_reg(hw_ctx->ctx, addr, value);
+}
+
+/* enable channel splitting mapping */
+static void setup_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	uint32_t value = 0;
+
+	if ((audio_mapping == NULL || audio_mapping->u32all == 0) && enable)
+		return;
+
+
+	value = audio_mapping->u32all;
+
+	if (enable == false)
+		/*0xFFFFFFFF;*/
+		value = MULTI_CHANNEL_SPLIT_NO_ASSO_INFO;
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO,
+		value);
+}
+
+/* get current channel spliting */
+static bool get_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	uint32_t value = 0;
+
+	if (audio_mapping == NULL)
+		return false;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO);
+
+	/*0xFFFFFFFF*/
+	if (get_reg_field_value(value,
+			AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO,
+			ASSOCIATION_INFO) !=
+			MULTI_CHANNEL_SPLIT_NO_ASSO_INFO) {
+		uint32_t multi_channel01_enable = 0;
+		uint32_t multi_channel23_enable = 0;
+		uint32_t multi_channel45_enable = 0;
+		uint32_t multi_channel67_enable = 0;
+		/* get the one we set.*/
+		audio_mapping->u32all = value;
+
+		/* check each enable status*/
+		value = read_indirect_azalia_reg(
+			hw_ctx,
+			ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE);
+
+		multi_channel01_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL01_ENABLE);
+
+		multi_channel23_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL23_ENABLE);
+
+		multi_channel45_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL45_ENABLE);
+
+		multi_channel67_enable = get_reg_field_value(value,
+		AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE,
+		MULTICHANNEL67_ENABLE);
+
+		if (multi_channel01_enable == 0 &&
+			multi_channel23_enable == 0 &&
+			multi_channel45_enable == 0 &&
+			multi_channel67_enable == 0)
+			dal_logger_write(hw_ctx->ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_COMPONENT_AUDIO,
+				"Audio driver did not enable multi-channel\n");
+
+		return true;
+	}
+
+	return false;
+}
+
+/* set the payload value for the unsolicited response */
+static void set_unsolicited_response_payload(
+	const struct hw_ctx_audio *hw_ctx,
+	enum audio_payload payload)
+{
+	/* set the payload value for the unsolicited response
+	 Jack presence is not required to be enabled */
+	uint32_t value = 0;
+
+	value = read_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE);
+
+	set_reg_field_value(value, payload,
+		AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE,
+		UNSOLICITED_RESPONSE_PAYLOAD);
+
+	set_reg_field_value(value, 1,
+		AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE,
+		UNSOLICITED_RESPONSE_FORCE);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE,
+		value);
+}
+
+/* initialize HW state */
+static void hw_initialize(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	uint32_t stream_id = FROM_BASE(hw_ctx)->azalia_stream_id;
+	uint32_t addr;
+
+	/* we only need to program the following registers once, so we only do
+	it for the first audio stream.*/
+	if (stream_id != FIRST_AUDIO_STREAM_ID)
+		return;
+
+	/* Suport R5 - 32khz
+	 * Suport R6 - 44.1khz
+	 * Suport R7 - 48khz
+	 */
+	addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES;
+	{
+		uint32_t value;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 0x70,
+		AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES,
+		AUDIO_RATE_CAPABILITIES);
+
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+
+	/*Keep alive bit to verify HW block in BU. */
+	addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES;
+	{
+		uint32_t value;
+
+		value = dm_read_reg(hw_ctx->ctx, addr);
+
+		set_reg_field_value(value, 1,
+		AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
+		CLKSTOP);
+
+		set_reg_field_value(value, 1,
+		AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
+		EPSS);
+		dm_write_reg(hw_ctx->ctx, addr, value);
+	}
+}
+
+/* Assign GTC group and enable GTC value embedding */
+static void enable_gtc_embedding_with_group(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t group_num,
+	uint32_t audio_latency)
+{
+	/*need to replace the static number with variable */
+	if (group_num <= 6) {
+		uint32_t value = read_indirect_azalia_reg(
+			hw_ctx,
+			ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING);
+
+		set_reg_field_value(
+			value,
+			group_num,
+			AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+			PRESENTATION_TIME_EMBEDDING_GROUP);
+
+		set_reg_field_value(
+			value,
+			1,
+			AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+			PRESENTATION_TIME_EMBEDDING_ENABLE);
+
+		write_indirect_azalia_reg(
+			hw_ctx,
+			ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+			value);
+
+		/*update audio latency to LIPSYNC*/
+		set_audio_latency(hw_ctx, audio_latency);
+	} else {
+		dal_logger_write(
+			hw_ctx->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_COMPONENT_AUDIO,
+			"GTC group number %d is too big",
+			group_num);
+	}
+}
+
+ /* Disable GTC value embedding */
+static void disable_gtc_embedding(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	uint32_t value = 0;
+
+	value = read_indirect_azalia_reg(
+	hw_ctx,
+	ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING);
+
+	set_reg_field_value(value, 0,
+	AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+	PRESENTATION_TIME_EMBEDDING_ENABLE);
+
+	set_reg_field_value(value, 0,
+	AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+	PRESENTATION_TIME_EMBEDDING_GROUP);
+
+	write_indirect_azalia_reg(
+		hw_ctx,
+		ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING,
+		value);
+}
+
+/* search pixel clock value for Azalia HDMI Audio */
+static bool get_azalia_clock_info_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	if (azalia_clock_info == NULL)
+		return false;
+
+	/* audio_dto_phase= 24 * 10,000;
+	 *   24MHz in [100Hz] units */
+	azalia_clock_info->audio_dto_phase =
+			24 * 10000;
+
+	/* audio_dto_module = PCLKFrequency * 10,000;
+	 *  [khz] -> [100Hz] */
+	azalia_clock_info->audio_dto_module =
+			actual_pixel_clock_in_khz * 10;
+
+	return true;
+}
+
+/* search pixel clock value for Azalia DP Audio */
+static bool get_azalia_clock_info_dp(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t requested_pixel_clock_in_khz,
+	const struct audio_pll_info *pll_info,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	if (pll_info == NULL || azalia_clock_info == NULL)
+		return false;
+
+	/* Reported dpDtoSourceClockInkhz value for
+	 * DCE8 already adjusted for SS, do not need any
+	 * adjustment here anymore
+	 */
+
+	/*audio_dto_phase = 24 * 10,000;
+	 * 24MHz in [100Hz] units */
+	azalia_clock_info->audio_dto_phase = 24 * 10000;
+
+	/*audio_dto_module = dpDtoSourceClockInkhz * 10,000;
+	 *  [khz] ->[100Hz] */
+	azalia_clock_info->audio_dto_module =
+		pll_info->dp_dto_source_clock_in_khz * 10;
+
+	return true;
+}
+
+static const struct hw_ctx_audio_funcs funcs = {
+	.destroy = destroy,
+	.setup_audio_wall_dto =
+		setup_audio_wall_dto,
+	.setup_hdmi_audio =
+		setup_hdmi_audio,
+	.setup_dp_audio = setup_dp_audio,
+	.setup_vce_audio = setup_vce_audio,
+	.enable_azalia_audio =
+		enable_azalia_audio,
+	.disable_azalia_audio =
+		disable_azalia_audio,
+	.enable_dp_audio =
+		enable_dp_audio,
+	.disable_dp_audio =
+		disable_dp_audio,
+	.setup_azalia =
+		setup_azalia,
+	.disable_az_clock_gating = NULL,
+	.unmute_azalia_audio =
+		unmute_azalia_audio,
+	.mute_azalia_audio =
+		mute_azalia_audio,
+	.setup_channel_splitting_mapping =
+		setup_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.hw_initialize =
+		hw_initialize,
+	.enable_gtc_embedding_with_group =
+		enable_gtc_embedding_with_group,
+	.disable_gtc_embedding =
+		disable_gtc_embedding,
+	.get_azalia_clock_info_hdmi =
+		get_azalia_clock_info_hdmi,
+	.get_azalia_clock_info_dp =
+		get_azalia_clock_info_dp,
+	.enable_afmt_clock = enable_afmt_clock
+};
+
+static bool construct(
+	struct hw_ctx_audio_dce110 *hw_ctx,
+	uint8_t azalia_stream_id,
+	struct dc_context *ctx)
+{
+	struct hw_ctx_audio *base = &hw_ctx->base;
+
+	if (!dal_audio_construct_hw_ctx_audio(base))
+		return false;
+
+	base->funcs = &funcs;
+
+	/* save audio endpoint or dig front for current dce110 audio object */
+	hw_ctx->azalia_stream_id = azalia_stream_id;
+	hw_ctx->base.ctx = ctx;
+
+	/* azalia audio endpoints register offsets. azalia is associated with
+	DIG front. save AUDIO register offset */
+	switch (azalia_stream_id) {
+	case 1: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	case 2: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	case 3: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	case 4: {
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_index =
+			mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX;
+			hw_ctx->az_mm_reg_offsets.
+			azf0endpointx_azalia_f0_codec_endpoint_data =
+			mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA;
+		}
+		break;
+	default:
+		dal_logger_write(
+			hw_ctx->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_AUDIO,
+			"Invalid Azalia stream ID!");
+		break;
+	}
+
+	return true;
+}
+
+/* audio_dce110 is derived from audio directly, not via dce80  */
+struct hw_ctx_audio *dal_hw_ctx_audio_dce110_create(
+	struct dc_context *ctx,
+	uint32_t azalia_stream_id)
+{
+	/* allocate memory for struc hw_ctx_audio_dce110 */
+	struct hw_ctx_audio_dce110 *hw_ctx_dce110 =
+			dm_alloc(ctx, sizeof(struct hw_ctx_audio_dce110));
+
+	if (!hw_ctx_dce110) {
+		ASSERT_CRITICAL(hw_ctx_dce110);
+		return NULL;
+	}
+
+	/*return pointer to hw_ctx_audio back to caller  -- audio object */
+	if (construct(
+			hw_ctx_dce110, azalia_stream_id, ctx))
+		return &hw_ctx_dce110->base;
+
+	dal_logger_write(
+		ctx->logger,
+		LOG_MAJOR_ERROR,
+		LOG_MINOR_COMPONENT_AUDIO,
+		"Failed to create hw_ctx_audio for DCE11\n");
+
+
+	dm_free(ctx, hw_ctx_dce110);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
new file mode 100644
index 000000000000..1ad3826aeb9f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_AUDIO_DCE110_H__
+#define __DAL_HW_CTX_AUDIO_DCE110_H__
+
+#include "audio/hw_ctx_audio.h"
+
+struct hw_ctx_audio_dce110 {
+	struct hw_ctx_audio base;
+
+	/* azalia stream id 1 based indexing, corresponding to audio GO enumId*/
+	uint32_t azalia_stream_id;
+
+	/* azalia stream endpoint register offsets */
+	struct azalia_reg_offsets az_mm_reg_offsets;
+
+	/* audio encoder block MM register offset -- associate with DIG FRONT */
+};
+
+struct hw_ctx_audio *dal_hw_ctx_audio_dce110_create(
+	struct dc_context *ctx,
+	uint32_t azalia_stream_id);
+
+#endif  /* __DAL_HW_CTX_AUDIO_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
new file mode 100644
index 000000000000..58207f53bff1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "hw_ctx_audio.h"
+
+/* 25.2MHz/1.001*/
+/* 25.2MHz/1.001*/
+/* 25.2MHz*/
+/* 27MHz */
+/* 27MHz*1.001*/
+/* 27MHz*1.001*/
+/* 54MHz*/
+/* 54MHz*1.001*/
+/* 74.25MHz/1.001*/
+/* 74.25MHz*/
+/* 148.5MHz/1.001*/
+/* 148.5MHz*/
+
+static const struct audio_clock_info audio_clock_info_table[12] = {
+	{2517, 4576, 28125, 7007, 31250, 6864, 28125},
+	{2518, 4576, 28125, 7007, 31250, 6864, 28125},
+	{2520, 4096, 25200, 6272, 28000, 6144, 25200},
+	{2700, 4096, 27000, 6272, 30000, 6144, 27000},
+	{2702, 4096, 27027, 6272, 30030, 6144, 27027},
+	{2703, 4096, 27027, 6272, 30030, 6144, 27027},
+	{5400, 4096, 54000, 6272, 60000, 6144, 54000},
+	{5405, 4096, 54054, 6272, 60060, 6144, 54054},
+	{7417, 11648, 210937, 17836, 234375, 11648, 140625},
+	{7425, 4096, 74250, 6272, 82500, 6144, 74250},
+	{14835, 11648, 421875, 8918, 234375, 5824, 140625},
+	{14850, 4096, 148500, 6272, 165000, 6144, 148500}
+};
+
+static const struct audio_clock_info audio_clock_info_table_36bpc[12] = {
+	{2517, 9152, 84375, 7007, 48875, 9152, 56250},
+	{2518, 9152, 84375, 7007, 48875, 9152, 56250},
+	{2520, 4096, 37800, 6272, 42000, 6144, 37800},
+	{2700, 4096, 40500, 6272, 45000, 6144, 40500},
+	{2702, 8192, 81081, 6272, 45045, 8192, 54054},
+	{2703, 8192, 81081, 6272, 45045, 8192, 54054},
+	{5400, 4096, 81000, 6272, 90000, 6144, 81000},
+	{5405, 4096, 81081, 6272, 90090, 6144, 81081},
+	{7417, 11648, 316406, 17836, 351562, 11648, 210937},
+	{7425, 4096, 111375, 6272, 123750, 6144, 111375},
+	{14835, 11648, 632812, 17836, 703125, 11648, 421875},
+	{14850, 4096, 222750, 6272, 247500, 6144, 222750}
+};
+
+static const struct audio_clock_info audio_clock_info_table_48bpc[12] = {
+	{2517, 4576, 56250, 7007, 62500, 6864, 56250},
+	{2518, 4576, 56250, 7007, 62500, 6864, 56250},
+	{2520, 4096, 50400, 6272, 56000, 6144, 50400},
+	{2700, 4096, 54000, 6272, 60000, 6144, 54000},
+	{2702, 4096, 54054, 6267, 60060, 8192, 54054},
+	{2703, 4096, 54054, 6272, 60060, 8192, 54054},
+	{5400, 4096, 108000, 6272, 120000, 6144, 108000},
+	{5405, 4096, 108108, 6272, 120120, 6144, 108108},
+	{7417, 11648, 421875, 17836, 468750, 11648, 281250},
+	{7425, 4096, 148500, 6272, 165000, 6144, 148500},
+	{14835, 11648, 843750, 8918, 468750, 11648, 281250},
+	{14850, 4096, 297000, 6272, 330000, 6144, 297000}
+};
+
+
+/***** static function *****/
+
+/*
+ * except of HW context create function, caller will access other functions of
+ * hw ctx via handle hw_ctx. Memory allocation for struct hw_ctx_audio_dce8x
+ * will happen in hw_ctx_audio_dce8x. Memory allocation is done with
+ * dal_audio_create_hw_ctx_audio_dce8x. Memory release is done by caller
+ * via hw_ctx->functions.destroy(). It will finally use destroy() of
+ * hw_ctx_audio_dce8x. Therefore, no memory allocate and release happen
+ * physically at hw ctx base object.
+ */
+static void destroy(
+	struct hw_ctx_audio **ptr)
+{
+	/* Attention!
+	 * You must override this method in derived class */
+}
+
+static void setup_audio_wall_dto(
+	const struct hw_ctx_audio *hw_ctx,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* setup HDMI audio */
+static void setup_hdmi_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	const struct audio_crtc_info *crtc_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+ /* setup DP audio */
+static void setup_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+ /* setup VCE audio */
+static void setup_vce_audio(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* enable Azalia audio */
+static void enable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* disable Azalia audio */
+static void disable_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* enable DP audio */
+static void enable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* disable DP audio */
+static void disable_dp_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* setup Azalia HW block */
+static void setup_azalia(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info,
+	const struct audio_info *audio_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* unmute audio */
+static void unmute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* mute audio */
+static void mute_azalia_audio(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* enable channel splitting mapping */
+static void setup_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* get current channel spliting */
+static bool get_channel_splitting_mapping(
+	const struct hw_ctx_audio *hw_ctx,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+/* set the payload value for the unsolicited response */
+static void set_unsolicited_response_payload(
+	const struct hw_ctx_audio *hw_ctx,
+	enum audio_payload payload)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* initialize HW state */
+static void hw_initialize(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* Assign GTC group and enable GTC value embedding */
+static void enable_gtc_embedding_with_group(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t groupNum,
+	uint32_t audioLatency)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* Disable GTC value embedding */
+static void disable_gtc_embedding(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* Disable Azalia Clock Gating Feature */
+static void disable_az_clock_gating(
+	const struct hw_ctx_audio *hw_ctx)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+}
+
+/* search pixel clock value for Azalia HDMI Audio */
+static bool get_azalia_clock_info_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+/* search pixel clock value for Azalia DP Audio */
+static bool get_azalia_clock_info_dp(
+	const struct hw_ctx_audio *hw_ctx,
+	uint32_t requested_pixel_clock_in_khz,
+	const struct audio_pll_info *pll_info,
+	struct azalia_clock_info *azalia_clock_info)
+{
+	/*DCE specific, must be implemented in derived*/
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+
+
+
+
+
+
+
+
+/*****SCOPE : within audio hw context dal-audio-hw-ctx *****/
+
+
+/* check whether specified sample rates can fit into a given timing */
+void dal_hw_ctx_audio_check_audio_bandwidth(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates)
+{
+	switch (signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		dal_audio_hw_ctx_check_audio_bandwidth_hdmi(
+			hw_ctx, crtc_info, channel_count, sample_rates);
+		break;
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+		dal_audio_hw_ctx_check_audio_bandwidth_dpsst(
+			hw_ctx, crtc_info, channel_count, sample_rates);
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		dal_audio_hw_ctx_check_audio_bandwidth_dpmst(
+			hw_ctx,  crtc_info, channel_count, sample_rates);
+		break;
+	default:
+		break;
+	}
+}
+
+/*For HDMI, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates)
+{
+	uint32_t samples;
+	uint32_t  h_blank;
+	bool limit_freq_to_48_khz = false;
+	bool limit_freq_to_88_2_khz = false;
+	bool limit_freq_to_96_khz = false;
+	bool limit_freq_to_174_4_khz = false;
+
+	/* For two channels supported return whatever sink support,unmodified*/
+	if (channel_count > 2) {
+
+		/* Based on HDMI spec 1.3 Table 7.5 */
+		if ((crtc_info->requested_pixel_clock <= 27000) &&
+		(crtc_info->v_active <= 576) &&
+		!(crtc_info->interlaced) &&
+		!(crtc_info->pixel_repetition == 2 ||
+		crtc_info->pixel_repetition == 4)) {
+			limit_freq_to_48_khz = true;
+
+		} else if ((crtc_info->requested_pixel_clock <= 27000) &&
+				(crtc_info->v_active <= 576) &&
+				(crtc_info->interlaced) &&
+				(crtc_info->pixel_repetition == 2)) {
+			limit_freq_to_88_2_khz = true;
+
+		} else if ((crtc_info->requested_pixel_clock <= 54000) &&
+				(crtc_info->v_active <= 576) &&
+				!(crtc_info->interlaced)) {
+			limit_freq_to_174_4_khz = true;
+		}
+	}
+
+	/* Also do some calculation for the available Audio Bandwidth for the
+	 * 8 ch (i.e. for the Layout 1 => ch > 2)
+	 */
+	h_blank = crtc_info->h_total - crtc_info->h_active;
+
+	if (crtc_info->pixel_repetition)
+		h_blank *= crtc_info->pixel_repetition;
+
+	/*based on HDMI spec 1.3 Table 7.5 */
+	h_blank -= 58;
+	/*for Control Period */
+	h_blank -= 16;
+
+	samples = h_blank * 10;
+	/* Number of Audio Packets (multiplied by 10) per Line (for 8 ch number
+	 * of Audio samples per line multiplied by 10 - Layout 1)
+	 */
+	 samples /= 32;
+	 samples *= crtc_info->v_active;
+	 /*Number of samples multiplied by 10, per second */
+	 samples *= crtc_info->refresh_rate;
+	 /*Number of Audio samples per second */
+	 samples /= 10;
+
+	 /* @todo do it after deep color is implemented
+	  * 8xx - deep color bandwidth scaling
+	  * Extra bandwidth is avaliable in deep color b/c link runs faster than
+	  * pixel rate. This has the effect of allowing more tmds characters to
+	  * be transmitted during blank
+	  */
+
+	switch (crtc_info->color_depth) {
+	case COLOR_DEPTH_888:
+		samples *= 4;
+		break;
+	case COLOR_DEPTH_101010:
+		samples *= 5;
+		break;
+	case COLOR_DEPTH_121212:
+		samples *= 6;
+		break;
+	default:
+		samples *= 4;
+		break;
+	}
+
+	samples /= 4;
+
+	/*check limitation*/
+	if (samples < 88200)
+		limit_freq_to_48_khz = true;
+	else if (samples < 96000)
+		limit_freq_to_88_2_khz = true;
+	else if (samples < 176400)
+		limit_freq_to_96_khz = true;
+	else if (samples < 192000)
+		limit_freq_to_174_4_khz = true;
+
+	if (sample_rates != NULL) {
+		/* limit frequencies */
+		if (limit_freq_to_174_4_khz)
+			sample_rates->rate.RATE_192 = 0;
+
+		if (limit_freq_to_96_khz) {
+			sample_rates->rate.RATE_192 = 0;
+			sample_rates->rate.RATE_176_4 = 0;
+		}
+		if (limit_freq_to_88_2_khz) {
+			sample_rates->rate.RATE_192 = 0;
+			sample_rates->rate.RATE_176_4 = 0;
+			sample_rates->rate.RATE_96 = 0;
+		}
+		if (limit_freq_to_48_khz) {
+			sample_rates->rate.RATE_192 = 0;
+			sample_rates->rate.RATE_176_4 = 0;
+			sample_rates->rate.RATE_96 = 0;
+			sample_rates->rate.RATE_88_2 = 0;
+		}
+	}
+}
+
+/*For DP SST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpsst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates)
+{
+	/* do nothing */
+}
+
+/*For DP MST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpmst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates)
+{
+	/* do nothing  */
+}
+
+/* calculate max number of Audio packets per line */
+uint32_t dal_audio_hw_ctx_calc_max_audio_packets_per_line(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info)
+{
+	uint32_t max_packets_per_line;
+
+	max_packets_per_line =
+		crtc_info->h_total - crtc_info->h_active;
+
+	if (crtc_info->pixel_repetition)
+		max_packets_per_line *= crtc_info->pixel_repetition;
+
+	/* for other hdmi features */
+	max_packets_per_line -= 58;
+	/* for Control Period */
+	max_packets_per_line -= 16;
+	/* Number of Audio Packets per Line */
+	max_packets_per_line /= 32;
+
+	return max_packets_per_line;
+}
+
+/**
+* speakersToChannels
+*
+* @brief
+*  translate speakers to channels
+*
+*  FL  - Front Left
+*  FR  - Front Right
+*  RL  - Rear Left
+*  RR  - Rear Right
+*  RC  - Rear Center
+*  FC  - Front Center
+*  FLC - Front Left Center
+*  FRC - Front Right Center
+*  RLC - Rear Left Center
+*  RRC - Rear Right Center
+*  LFE - Low Freq Effect
+*
+*               FC
+*          FLC      FRC
+*    FL                    FR
+*
+*                    LFE
+*              ()
+*
+*
+*    RL                    RR
+*          RLC      RRC
+*               RC
+*
+*             ch  8   7   6   5   4   3   2   1
+* 0b00000011      -   -   -   -   -   -   FR  FL
+* 0b00000111      -   -   -   -   -   LFE FR  FL
+* 0b00001011      -   -   -   -   FC  -   FR  FL
+* 0b00001111      -   -   -   -   FC  LFE FR  FL
+* 0b00010011      -   -   -   RC  -   -   FR  FL
+* 0b00010111      -   -   -   RC  -   LFE FR  FL
+* 0b00011011      -   -   -   RC  FC  -   FR  FL
+* 0b00011111      -   -   -   RC  FC  LFE FR  FL
+* 0b00110011      -   -   RR  RL  -   -   FR  FL
+* 0b00110111      -   -   RR  RL  -   LFE FR  FL
+* 0b00111011      -   -   RR  RL  FC  -   FR  FL
+* 0b00111111      -   -   RR  RL  FC  LFE FR  FL
+* 0b01110011      -   RC  RR  RL  -   -   FR  FL
+* 0b01110111      -   RC  RR  RL  -   LFE FR  FL
+* 0b01111011      -   RC  RR  RL  FC  -   FR  FL
+* 0b01111111      -   RC  RR  RL  FC  LFE FR  FL
+* 0b11110011      RRC RLC RR  RL  -   -   FR  FL
+* 0b11110111      RRC RLC RR  RL  -   LFE FR  FL
+* 0b11111011      RRC RLC RR  RL  FC  -   FR  FL
+* 0b11111111      RRC RLC RR  RL  FC  LFE FR  FL
+* 0b11000011      FRC FLC -   -   -   -   FR  FL
+* 0b11000111      FRC FLC -   -   -   LFE FR  FL
+* 0b11001011      FRC FLC -   -   FC  -   FR  FL
+* 0b11001111      FRC FLC -   -   FC  LFE FR  FL
+* 0b11010011      FRC FLC -   RC  -   -   FR  FL
+* 0b11010111      FRC FLC -   RC  -   LFE FR  FL
+* 0b11011011      FRC FLC -   RC  FC  -   FR  FL
+* 0b11011111      FRC FLC -   RC  FC  LFE FR  FL
+* 0b11110011      FRC FLC RR  RL  -   -   FR  FL
+* 0b11110111      FRC FLC RR  RL  -   LFE FR  FL
+* 0b11111011      FRC FLC RR  RL  FC  -   FR  FL
+* 0b11111111      FRC FLC RR  RL  FC  LFE FR  FL
+*
+* @param
+*  speakers - speaker information as it comes from CEA audio block
+*/
+/* translate speakers to channels */
+union audio_cea_channels dal_audio_hw_ctx_speakers_to_channels(
+	const struct hw_ctx_audio *hw_ctx,
+	struct audio_speaker_flags speaker_flags)
+{
+	union audio_cea_channels cea_channels = {0};
+
+	/* these are one to one */
+	cea_channels.channels.FL = speaker_flags.FL_FR;
+	cea_channels.channels.FR = speaker_flags.FL_FR;
+	cea_channels.channels.LFE = speaker_flags.LFE;
+	cea_channels.channels.FC = speaker_flags.FC;
+
+	/* if Rear Left and Right exist move RC speaker to channel 7
+	 * otherwise to channel 5
+	 */
+	if (speaker_flags.RL_RR) {
+		cea_channels.channels.RL_RC = speaker_flags.RL_RR;
+		cea_channels.channels.RR = speaker_flags.RL_RR;
+		cea_channels.channels.RC_RLC_FLC = speaker_flags.RC;
+	} else {
+		cea_channels.channels.RL_RC = speaker_flags.RC;
+	}
+
+	/* FRONT Left Right Center and REAR Left Right Center are exclusive */
+	if (speaker_flags.FLC_FRC) {
+		cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC;
+		cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC;
+	} else {
+		cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC;
+		cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC;
+	}
+
+	return cea_channels;
+}
+
+/* check whether specified audio format supported */
+bool dal_audio_hw_ctx_is_audio_format_supported(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_info *audio_info,
+	enum audio_format_code audio_format_code,
+	uint32_t *format_index)
+{
+	uint32_t index;
+	uint32_t max_channe_index = 0;
+	bool found = false;
+
+	if (audio_info == NULL)
+		return found;
+
+	/* pass through whole array */
+	for (index = 0; index < audio_info->mode_count; index++) {
+		if (audio_info->modes[index].format_code == audio_format_code) {
+			if (found) {
+				/* format has multiply entries, choose one with
+				 *  highst number of channels */
+				if (audio_info->modes[index].channel_count >
+		audio_info->modes[max_channe_index].channel_count) {
+					max_channe_index = index;
+				}
+			} else {
+				/* format found, save it's index */
+				found = true;
+				max_channe_index = index;
+			}
+		}
+	}
+
+	/* return index */
+	if (found && format_index != NULL)
+		*format_index = max_channe_index;
+
+	return found;
+}
+
+/* search pixel clock value for HDMI */
+bool dal_audio_hw_ctx_get_audio_clock_info(
+	const struct hw_ctx_audio *hw_ctx,
+	enum dc_color_depth color_depth,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct audio_clock_info *audio_clock_info)
+{
+	const struct audio_clock_info *clock_info;
+	uint32_t index;
+	uint32_t crtc_pixel_clock_in_10khz = crtc_pixel_clock_in_khz / 10;
+	uint32_t audio_array_size;
+
+	if (audio_clock_info == NULL)
+		return false; /* should not happen */
+
+	switch (color_depth) {
+	case COLOR_DEPTH_161616:
+		clock_info = audio_clock_info_table_48bpc;
+		audio_array_size = ARRAY_SIZE(
+				audio_clock_info_table_48bpc);
+		break;
+	case COLOR_DEPTH_121212:
+		clock_info = audio_clock_info_table_36bpc;
+		audio_array_size = ARRAY_SIZE(
+				audio_clock_info_table_36bpc);
+		break;
+	default:
+		clock_info = audio_clock_info_table;
+		audio_array_size = ARRAY_SIZE(
+				audio_clock_info_table);
+		break;
+	}
+
+	if (clock_info != NULL) {
+		/* search for exact pixel clock in table */
+		for (index = 0; index < audio_array_size; index++) {
+			if (clock_info[index].pixel_clock_in_10khz >
+				crtc_pixel_clock_in_10khz)
+				break;  /* not match */
+			else if (clock_info[index].pixel_clock_in_10khz ==
+					crtc_pixel_clock_in_10khz) {
+				/* match found */
+				if (audio_clock_info != NULL) {
+					*audio_clock_info = clock_info[index];
+					return true;
+				}
+			}
+		}
+	}
+
+
+	/* not found */
+	if (actual_pixel_clock_in_khz == 0)
+		actual_pixel_clock_in_khz = crtc_pixel_clock_in_khz;
+
+	/* See HDMI spec  the table entry under
+	 *  pixel clock of "Other". */
+	audio_clock_info->pixel_clock_in_10khz =
+			actual_pixel_clock_in_khz / 10;
+	audio_clock_info->cts_32khz = actual_pixel_clock_in_khz;
+	audio_clock_info->cts_44khz = actual_pixel_clock_in_khz;
+	audio_clock_info->cts_48khz = actual_pixel_clock_in_khz;
+
+	audio_clock_info->n_32khz = 4096;
+	audio_clock_info->n_44khz = 6272;
+	audio_clock_info->n_48khz = 6144;
+
+	return true;
+}
+
+static const struct hw_ctx_audio_funcs funcs = {
+	.destroy = destroy,
+	.setup_audio_wall_dto =
+		setup_audio_wall_dto,
+	.setup_hdmi_audio =
+		setup_hdmi_audio,
+	.setup_dp_audio = setup_dp_audio,
+	.setup_vce_audio = setup_vce_audio,
+	.enable_azalia_audio =
+		enable_azalia_audio,
+	.disable_azalia_audio =
+		disable_azalia_audio,
+	.enable_dp_audio =
+		enable_dp_audio,
+	.disable_dp_audio =
+		disable_dp_audio,
+	.setup_azalia =
+		setup_azalia,
+	.disable_az_clock_gating =
+		disable_az_clock_gating,
+	.unmute_azalia_audio =
+		unmute_azalia_audio,
+	.mute_azalia_audio =
+		mute_azalia_audio,
+	.setup_channel_splitting_mapping =
+		setup_channel_splitting_mapping,
+	.get_channel_splitting_mapping =
+		get_channel_splitting_mapping,
+	.set_unsolicited_response_payload =
+		set_unsolicited_response_payload,
+	.hw_initialize =
+		hw_initialize,
+	.enable_gtc_embedding_with_group =
+		enable_gtc_embedding_with_group,
+	.disable_gtc_embedding =
+		disable_gtc_embedding,
+	.get_azalia_clock_info_hdmi =
+		get_azalia_clock_info_hdmi,
+	.get_azalia_clock_info_dp =
+		get_azalia_clock_info_dp,
+};
+/* --- object creator, destroy, construct, destruct --- */
+
+bool dal_audio_construct_hw_ctx_audio(
+	struct hw_ctx_audio *ctx)
+{
+	ctx->funcs = &funcs;
+
+	/* internal variables */
+
+	return true;
+}
+
+void dal_audio_destruct_hw_ctx_audio(
+	struct hw_ctx_audio *ctx)
+{
+	/* nothing to do */
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
new file mode 100644
index 000000000000..8ab2e5851f91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_CTX_AUDIO_H__
+#define __DAL_HW_CTX_AUDIO_H__
+
+#include "include/audio_interface.h"
+#include "include/link_service_types.h"
+
+struct hw_ctx_audio;
+
+
+struct azalia_reg_offsets {
+	uint32_t azf0endpointx_azalia_f0_codec_endpoint_index;
+	uint32_t azf0endpointx_azalia_f0_codec_endpoint_data;
+};
+
+/***** hook functions *****/
+
+struct hw_ctx_audio_funcs {
+
+	/* functions for hw_ctx creation */
+	void (*destroy)(
+		struct hw_ctx_audio **ptr);
+
+	/***** from dal2 hwcontextaudio.hpp *****/
+
+	void (*setup_audio_wall_dto)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum signal_type signal,
+		const struct audio_crtc_info *crtc_info,
+		const struct audio_pll_info *pll_info);
+
+	/* MM register access  read_register  write_register */
+
+	/***** from dal2 hwcontextaudio_hal.hpp *****/
+
+	/* setup HDMI audio */
+	void (*setup_hdmi_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		const struct audio_crtc_info *crtc_info);
+
+	/* setup DP audio */
+	void (*setup_dp_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* setup VCE audio */
+	void (*setup_vce_audio)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* enable Azalia audio */
+	void (*enable_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* disable Azalia audio */
+	void (*disable_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* enable DP audio */
+	void (*enable_dp_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* disable DP audio */
+	void (*disable_dp_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* setup Azalia HW block */
+	void (*setup_azalia)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		enum signal_type signal,
+		const struct audio_crtc_info *crtc_info,
+		const struct audio_pll_info *pll_info,
+		const struct audio_info *audio_info);
+
+	/* unmute audio */
+	void (*unmute_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* mute audio */
+	void (*mute_azalia_audio)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id);
+
+	/* enable channel splitting mapping */
+	void (*setup_channel_splitting_mapping)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		enum signal_type signal,
+		const struct audio_channel_associate_info *audio_mapping,
+		bool enable);
+
+	/* get current channel spliting */
+	bool (*get_channel_splitting_mapping)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		struct audio_channel_associate_info *audio_mapping);
+
+	/* set the payload value for the unsolicited response */
+	void (*set_unsolicited_response_payload)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum audio_payload payload);
+
+	/* initialize HW state */
+	void (*hw_initialize)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* check_audio_bandwidth */
+
+	/* Assign GTC group and enable GTC value embedding */
+	void (*enable_gtc_embedding_with_group)(
+		const struct hw_ctx_audio *hw_ctx,
+		uint32_t groupNum,
+		uint32_t audioLatency);
+
+	/* Disable GTC value embedding */
+	void (*disable_gtc_embedding)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* Disable Azalia Clock Gating Feature */
+	void (*disable_az_clock_gating)(
+		const struct hw_ctx_audio *hw_ctx);
+
+	/* ~~~~  protected: ~~~~*/
+
+	/* calc_max_audio_packets_per_line */
+	/* speakers_to_channels */
+	/* is_audio_format_supported */
+	/* get_audio_clock_info */
+
+	/* search pixel clock value for Azalia HDMI Audio */
+	bool (*get_azalia_clock_info_hdmi)(
+		const struct hw_ctx_audio *hw_ctx,
+		uint32_t crtc_pixel_clock_in_khz,
+		uint32_t actual_pixel_clock_in_khz,
+		struct azalia_clock_info *azalia_clock_info);
+
+	/* search pixel clock value for Azalia DP Audio */
+	bool (*get_azalia_clock_info_dp)(
+		const struct hw_ctx_audio *hw_ctx,
+		uint32_t requested_pixel_clock_in_khz,
+		const struct audio_pll_info *pll_info,
+		struct azalia_clock_info *azalia_clock_info);
+
+	void (*enable_afmt_clock)(
+		const struct hw_ctx_audio *hw_ctx,
+		enum engine_id engine_id,
+		bool enable);
+
+	/* @@@@   private:  @@@@  */
+
+	/* check_audio_bandwidth_hdmi  */
+	/* check_audio_bandwidth_dpsst */
+	/* check_audio_bandwidth_dpmst */
+
+};
+
+
+struct hw_ctx_audio {
+	const struct hw_ctx_audio_funcs *funcs;
+	struct dc_context *ctx;
+
+	/*audio_clock_infoTable[12];
+	 *audio_clock_infoTable_36bpc[12];
+	 *audio_clock_infoTable_48bpc[12];
+	 *used by hw_ctx_audio.c file only. Will declare as static array
+	 *azaliaclockinfoTable[12]  -- not used
+	 *BusNumberMask;   BusNumberShift; DeviceNumberMask;
+	 *not used by dce6 and after
+	 */
+};
+
+
+
+/* --- object construct, destruct --- */
+
+/*
+ *called by derived audio object for specific ASIC. In case no derived object,
+ *these two functions do not need exposed.
+ */
+bool dal_audio_construct_hw_ctx_audio(
+	struct hw_ctx_audio *hw_ctx);
+
+void dal_audio_destruct_hw_ctx_audio(
+	struct hw_ctx_audio *hw_ctx);
+
+/*
+ *creator of audio HW context will be implemented by specific ASIC object only.
+ *Top base or interface object does not have implementation of creator.
+ */
+
+
+/* --- functions called by audio hw context itself --- */
+
+/* MM register access */
+/*read_register  - dal_read_reg */
+/*write_register - dal_write_reg*/
+
+
+/*check whether specified sample rates can fit into a given timing */
+void dal_hw_ctx_audio_check_audio_bandwidth(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates);
+
+/*For HDMI, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_hdmi(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates);
+
+/*For DPSST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpsst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates);
+
+/*For DPMST, calculate if specified sample rates can fit into a given timing */
+void dal_audio_hw_ctx_check_audio_bandwidth_dpmst(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info,
+	uint32_t channel_count,
+	union audio_sample_rates *sample_rates);
+
+/* calculate max number of Audio packets per line */
+uint32_t dal_audio_hw_ctx_calc_max_audio_packets_per_line(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_crtc_info *crtc_info);
+
+/* translate speakers to channels */
+union audio_cea_channels dal_audio_hw_ctx_speakers_to_channels(
+	const struct hw_ctx_audio *hw_ctx,
+	struct audio_speaker_flags speaker_flags);
+
+/* check whether specified audio format supported */
+bool dal_audio_hw_ctx_is_audio_format_supported(
+	const struct hw_ctx_audio *hw_ctx,
+	const struct audio_info *audio_info,
+	enum audio_format_code audio_format_code,
+	uint32_t *format_index);
+
+/* search pixel clock value for HDMI */
+bool dal_audio_hw_ctx_get_audio_clock_info(
+	const struct hw_ctx_audio *hw_ctx,
+	enum dc_color_depth color_depth,
+	uint32_t crtc_pixel_clock_in_khz,
+	uint32_t actual_pixel_clock_in_khz,
+	struct audio_clock_info *audio_clock_info);
+
+
+#endif  /* __DAL_HW_CTX_AUDIO_H__ */
+
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 12/26] drm/amd/dal: Bandwidth calculations
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (10 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 11/26] drm/amd/dal: Audio Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 13/26] drm/amd/dal: Add encoder HW programming Harry Wentland
                     ` (13 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/calcs/Makefile          |   10 +
 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 3941 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c        |  300 ++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c   | 1992 ++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h   |   74 +
 5 files changed, 6317 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h

diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/Makefile b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile
new file mode 100644
index 000000000000..7f1916b79b88
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the 'calcs' sub-component of DAL.
+# It calculates Bandwidth and Watermarks values for HW programming
+#
+
+BW_CALCS = bandwidth_calcs.o bw_fixed.o scaler_filter.o
+
+AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS))
+
+AMD_DAL_FILES += $(AMD_DAL_BW_CALCS)
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
new file mode 100644
index 000000000000..8faabbc12fd3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
@@ -0,0 +1,3941 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "bandwidth_calcs.h"
+
+/*******************************************************************************
+ * Private Functions
+ ******************************************************************************/
+
+static void calculate_bandwidth(
+	const struct bw_calcs_dceip *dceip,
+	const struct bw_calcs_vbios *vbios,
+	const struct bw_calcs_mode_data_internal *mode_data,
+	struct bw_calcs_results *results)
+
+{
+	const int32_t pixels_per_chunk = 512;
+	const int32_t max_chunks_non_fbc_mode = 16;
+	const int32_t high = 2;
+	const int32_t mid = 1;
+	const int32_t low = 0;
+
+	int32_t i, j, k;
+	struct bw_fixed yclk[3];
+	struct bw_fixed sclk[3];
+	bool d0_underlay_enable;
+	bool d1_underlay_enable;
+	enum bw_defines sclk_message;
+	enum bw_defines yclk_message;
+	enum bw_defines v_filter_init_mode[maximum_number_of_surfaces];
+	enum bw_defines tiling_mode[maximum_number_of_surfaces];
+	enum bw_defines stereo_mode[maximum_number_of_surfaces];
+	enum bw_defines surface_type[maximum_number_of_surfaces];
+	enum bw_defines voltage;
+	enum bw_defines pipe_check;
+	enum bw_defines hsr_check;
+	enum bw_defines vsr_check;
+	enum bw_defines lb_size_check;
+	enum bw_defines fbc_check;
+	enum bw_defines rotation_check;
+	enum bw_defines mode_check;
+
+	yclk[low] = vbios->low_yclk;
+	yclk[mid] = vbios->high_yclk;
+	yclk[high] = vbios->high_yclk;
+	sclk[low] = vbios->low_sclk;
+	sclk[mid] = vbios->mid_sclk;
+	sclk[high] = vbios->high_sclk;
+	/* surface assignment:*/
+	/* 0: d0 underlay or underlay luma*/
+	/* 1: d0 underlay chroma*/
+	/* 2: d1 underlay or underlay luma*/
+	/* 3: d1 underlay chroma*/
+	/* 4: d0 graphics*/
+	/* 5: d1 graphics*/
+	/* 6: d2 graphics*/
+	/* 7: d3 graphics, same mode as d2*/
+	/* 8: d4 graphics, same mode as d2*/
+	/* 9: d5 graphics, same mode as d2*/
+	/* ...*/
+	/* maximum_number_of_surfaces-2: d1 display_write_back420 luma*/
+	/* maximum_number_of_surfaces-1: d1 display_write_back420 chroma*/
+	/* underlay luma and chroma surface parameters from spreadsheet*/
+	if (mode_data->d0_underlay_mode == bw_def_none) {
+		d0_underlay_enable = 0;
+	} else {
+		d0_underlay_enable = 1;
+	}
+	if (mode_data->d1_underlay_mode == bw_def_none) {
+		d1_underlay_enable = 0;
+	} else {
+		d1_underlay_enable = 1;
+	}
+	results->number_of_underlay_surfaces = d0_underlay_enable
+		+ d1_underlay_enable;
+	switch (mode_data->underlay_surface_type) {
+	case bw_def_420:
+		surface_type[0] = bw_def_underlay420_luma;
+		surface_type[2] = bw_def_underlay420_luma;
+		results->bytes_per_pixel[0] = 1;
+		results->bytes_per_pixel[2] = 1;
+		surface_type[1] = bw_def_underlay420_chroma;
+		surface_type[3] = bw_def_underlay420_chroma;
+		results->bytes_per_pixel[1] = 2;
+		results->bytes_per_pixel[3] = 2;
+		results->lb_size_per_component[0] =
+			dceip->underlay420_luma_lb_size_per_component;
+		results->lb_size_per_component[1] =
+			dceip->underlay420_chroma_lb_size_per_component;
+		results->lb_size_per_component[2] =
+			dceip->underlay420_luma_lb_size_per_component;
+		results->lb_size_per_component[3] =
+			dceip->underlay420_chroma_lb_size_per_component;
+		break;
+	case bw_def_422:
+		surface_type[0] = bw_def_underlay422;
+		surface_type[2] = bw_def_underlay422;
+		results->bytes_per_pixel[0] = 2;
+		results->bytes_per_pixel[2] = 2;
+		results->lb_size_per_component[0] =
+			dceip->underlay422_lb_size_per_component;
+		results->lb_size_per_component[2] =
+			dceip->underlay422_lb_size_per_component;
+		break;
+	default:
+		surface_type[0] = bw_def_underlay444;
+		surface_type[2] = bw_def_underlay444;
+		results->bytes_per_pixel[0] = 4;
+		results->bytes_per_pixel[2] = 4;
+		results->lb_size_per_component[0] =
+			dceip->lb_size_per_component444;
+		results->lb_size_per_component[2] =
+			dceip->lb_size_per_component444;
+		break;
+	}
+	if (d0_underlay_enable) {
+		switch (mode_data->underlay_surface_type) {
+		case bw_def_420:
+			results->enable[0] = 1;
+			results->enable[1] = 1;
+			break;
+		default:
+			results->enable[0] = 1;
+			results->enable[1] = 0;
+			break;
+		}
+	} else {
+		results->enable[0] = 0;
+		results->enable[1] = 0;
+	}
+	if (d1_underlay_enable) {
+		switch (mode_data->underlay_surface_type) {
+		case bw_def_420:
+			results->enable[2] = 1;
+			results->enable[3] = 1;
+			break;
+		default:
+			results->enable[2] = 1;
+			results->enable[3] = 0;
+			break;
+		}
+	} else {
+		results->enable[2] = 0;
+		results->enable[3] = 0;
+	}
+	results->use_alpha[0] = 0;
+	results->use_alpha[1] = 0;
+	results->use_alpha[2] = 0;
+	results->use_alpha[3] = 0;
+	results->scatter_gather_enable_for_pipe[0] =
+		vbios->scatter_gather_enable;
+	results->scatter_gather_enable_for_pipe[1] =
+		vbios->scatter_gather_enable;
+	results->scatter_gather_enable_for_pipe[2] =
+		vbios->scatter_gather_enable;
+	results->scatter_gather_enable_for_pipe[3] =
+		vbios->scatter_gather_enable;
+	results->interlace_mode[0] = mode_data->graphics_interlace_mode;
+	results->interlace_mode[1] = mode_data->graphics_interlace_mode;
+	results->interlace_mode[2] = mode_data->graphics_interlace_mode;
+	results->interlace_mode[3] = mode_data->graphics_interlace_mode;
+	results->h_total[0] = bw_int_to_fixed(mode_data->d0_htotal);
+	results->h_total[1] = bw_int_to_fixed(mode_data->d0_htotal);
+	results->h_total[2] = bw_int_to_fixed(mode_data->d1_htotal);
+	results->h_total[3] = bw_int_to_fixed(mode_data->d1_htotal);
+	results->pixel_rate[0] = mode_data->d0_pixel_rate;
+	results->pixel_rate[1] = mode_data->d0_pixel_rate;
+	results->pixel_rate[2] = mode_data->d1_pixel_rate;
+	results->pixel_rate[3] = mode_data->d1_pixel_rate;
+	results->src_width[0] = bw_int_to_fixed(mode_data->underlay_src_width);
+	results->src_width[1] = bw_int_to_fixed(mode_data->underlay_src_width);
+	results->src_width[2] = bw_int_to_fixed(mode_data->underlay_src_width);
+	results->src_width[3] = bw_int_to_fixed(mode_data->underlay_src_width);
+	results->src_height[0] = bw_int_to_fixed(
+		mode_data->underlay_src_height);
+	results->src_height[1] = bw_int_to_fixed(
+		mode_data->underlay_src_height);
+	results->src_height[2] = bw_int_to_fixed(
+		mode_data->underlay_src_height);
+	results->src_height[3] = bw_int_to_fixed(
+		mode_data->underlay_src_height);
+	results->pitch_in_pixels[0] = bw_int_to_fixed(
+		mode_data->underlay_pitch_in_pixels);
+	results->pitch_in_pixels[1] = bw_int_to_fixed(
+		mode_data->underlay_pitch_in_pixels);
+	results->pitch_in_pixels[2] = bw_int_to_fixed(
+		mode_data->underlay_pitch_in_pixels);
+	results->pitch_in_pixels[3] = bw_int_to_fixed(
+		mode_data->underlay_pitch_in_pixels);
+	results->scale_ratio[0] = mode_data->d0_underlay_scale_ratio;
+	results->scale_ratio[1] = mode_data->d0_underlay_scale_ratio;
+	results->scale_ratio[2] = mode_data->d1_underlay_scale_ratio;
+	results->scale_ratio[3] = mode_data->d1_underlay_scale_ratio;
+	results->h_taps[0] = bw_int_to_fixed(mode_data->underlay_htaps);
+	results->h_taps[1] = bw_int_to_fixed(mode_data->underlay_htaps);
+	results->h_taps[2] = bw_int_to_fixed(mode_data->underlay_htaps);
+	results->h_taps[3] = bw_int_to_fixed(mode_data->underlay_htaps);
+	results->v_taps[0] = bw_int_to_fixed(mode_data->underlay_vtaps);
+	results->v_taps[1] = bw_int_to_fixed(mode_data->underlay_vtaps);
+	results->v_taps[2] = bw_int_to_fixed(mode_data->underlay_vtaps);
+	results->v_taps[3] = bw_int_to_fixed(mode_data->underlay_vtaps);
+	results->rotation_angle[0] = bw_int_to_fixed(
+		mode_data->underlay_rotation_angle);
+	results->rotation_angle[1] = bw_int_to_fixed(
+		mode_data->underlay_rotation_angle);
+	results->rotation_angle[2] = bw_int_to_fixed(
+		mode_data->underlay_rotation_angle);
+	results->rotation_angle[3] = bw_int_to_fixed(
+		mode_data->underlay_rotation_angle);
+	if (mode_data->underlay_tiling_mode == bw_def_linear) {
+		tiling_mode[0] = bw_def_linear;
+		tiling_mode[1] = bw_def_linear;
+		tiling_mode[2] = bw_def_linear;
+		tiling_mode[3] = bw_def_linear;
+	} else {
+		tiling_mode[0] = bw_def_landscape;
+		tiling_mode[1] = bw_def_landscape;
+		tiling_mode[2] = bw_def_landscape;
+		tiling_mode[3] = bw_def_landscape;
+	}
+	stereo_mode[0] = mode_data->underlay_stereo_mode;
+	stereo_mode[1] = mode_data->underlay_stereo_mode;
+	stereo_mode[2] = mode_data->underlay_stereo_mode;
+	stereo_mode[3] = mode_data->underlay_stereo_mode;
+	results->lb_bpc[0] = mode_data->underlay_lb_bpc;
+	results->lb_bpc[1] = mode_data->underlay_lb_bpc;
+	results->lb_bpc[2] = mode_data->underlay_lb_bpc;
+	results->lb_bpc[3] = mode_data->underlay_lb_bpc;
+	results->compression_rate[0] = bw_int_to_fixed(1);
+	results->compression_rate[1] = bw_int_to_fixed(1);
+	results->compression_rate[2] = bw_int_to_fixed(1);
+	results->compression_rate[3] = bw_int_to_fixed(1);
+	results->access_one_channel_only[0] = 0;
+	results->access_one_channel_only[1] = 0;
+	results->access_one_channel_only[2] = 0;
+	results->access_one_channel_only[3] = 0;
+	results->cursor_width_pixels[0] = bw_int_to_fixed(0);
+	results->cursor_width_pixels[1] = bw_int_to_fixed(0);
+	results->cursor_width_pixels[2] = bw_int_to_fixed(0);
+	results->cursor_width_pixels[3] = bw_int_to_fixed(0);
+	/* graphics surface parameters from spreadsheet*/
+	for (i = 4; i <= maximum_number_of_surfaces - 3; i++) {
+		if (i < mode_data->number_of_displays + 4) {
+			if (i == 4
+				&& mode_data->d0_underlay_mode
+					== bw_def_underlay_only) {
+				results->enable[i] = 0;
+				results->use_alpha[i] = 0;
+			} else if (i == 4
+				&& mode_data->d0_underlay_mode
+					== bw_def_blend) {
+				results->enable[i] = 1;
+				results->use_alpha[i] = 1;
+			} else if (i == 4) {
+				results->enable[i] = 1;
+				results->use_alpha[i] = 0;
+			} else if (i == 5
+				&& mode_data->d1_underlay_mode
+					== bw_def_underlay_only) {
+				results->enable[i] = 0;
+				results->use_alpha[i] = 0;
+			} else if (i == 5
+				&& mode_data->d1_underlay_mode
+					== bw_def_blend) {
+				results->enable[i] = 1;
+				results->use_alpha[i] = 1;
+			} else {
+				results->enable[i] = 1;
+				results->use_alpha[i] = 0;
+			}
+		} else {
+			results->enable[i] = 0;
+			results->use_alpha[i] = 0;
+		}
+		results->scatter_gather_enable_for_pipe[i] =
+			vbios->scatter_gather_enable;
+		surface_type[i] = bw_def_graphics;
+		results->lb_size_per_component[i] =
+			dceip->lb_size_per_component444;
+		results->bytes_per_pixel[i] =
+			mode_data->graphics_bytes_per_pixel;
+		results->interlace_mode[i] = mode_data->graphics_interlace_mode;
+		results->h_taps[i] = bw_int_to_fixed(mode_data->graphics_htaps);
+		results->v_taps[i] = bw_int_to_fixed(mode_data->graphics_vtaps);
+		results->rotation_angle[i] = bw_int_to_fixed(
+			mode_data->graphics_rotation_angle);
+		if (mode_data->graphics_tiling_mode == bw_def_linear) {
+			tiling_mode[i] = bw_def_linear;
+		} else if (mode_data->graphics_rotation_angle == 0
+			|| mode_data->graphics_rotation_angle == 180) {
+			tiling_mode[i] = bw_def_landscape;
+		} else {
+			tiling_mode[i] = bw_def_portrait;
+		}
+		results->lb_bpc[i] = mode_data->graphics_lb_bpc;
+		if (i == 4) {
+			if (mode_data->d0_fbc_enable
+				&& (dceip->argb_compression_support
+					|| mode_data->d0_underlay_mode
+						!= bw_def_blended)) {
+				results->compression_rate[i] = bw_int_to_fixed(
+					vbios->average_compression_rate);
+				results->access_one_channel_only[i] =
+					mode_data->d0_lpt_enable;
+			} else {
+				results->compression_rate[i] = bw_int_to_fixed(
+					1);
+				results->access_one_channel_only[i] = 0;
+			}
+			results->h_total[i] = bw_int_to_fixed(
+				mode_data->d0_htotal);
+			results->pixel_rate[i] = mode_data->d0_pixel_rate;
+			results->src_width[i] = bw_int_to_fixed(
+				mode_data->d0_graphics_src_width);
+			results->src_height[i] = bw_int_to_fixed(
+				mode_data->d0_graphics_src_height);
+			results->pitch_in_pixels[i] = bw_int_to_fixed(
+				mode_data->d0_graphics_src_width);
+			results->scale_ratio[i] =
+				mode_data->d0_graphics_scale_ratio;
+			stereo_mode[i] = mode_data->d0_graphics_stereo_mode;
+		} else if (i == 5) {
+			results->compression_rate[i] = bw_int_to_fixed(1);
+			results->access_one_channel_only[i] = 0;
+			results->h_total[i] = bw_int_to_fixed(
+				mode_data->d1_htotal);
+			results->pixel_rate[i] = mode_data->d1_pixel_rate;
+			results->src_width[i] = bw_int_to_fixed(
+				mode_data->d1_graphics_src_width);
+			results->src_height[i] = bw_int_to_fixed(
+				mode_data->d1_graphics_src_height);
+			results->pitch_in_pixels[i] = bw_int_to_fixed(
+				mode_data->d1_graphics_src_width);
+			results->scale_ratio[i] =
+				mode_data->d1_graphics_scale_ratio;
+			stereo_mode[i] = mode_data->d1_graphics_stereo_mode;
+		} else {
+			results->compression_rate[i] = bw_int_to_fixed(1);
+			results->access_one_channel_only[i] = 0;
+			results->h_total[i] = bw_int_to_fixed(
+				mode_data->d2_htotal);
+			results->pixel_rate[i] = mode_data->d2_pixel_rate;
+			results->src_width[i] = bw_int_to_fixed(
+				mode_data->d2_graphics_src_width);
+			results->src_height[i] = bw_int_to_fixed(
+				mode_data->d2_graphics_src_height);
+			results->pitch_in_pixels[i] = bw_int_to_fixed(
+				mode_data->d2_graphics_src_width);
+			results->scale_ratio[i] =
+				mode_data->d2_graphics_scale_ratio;
+			stereo_mode[i] = mode_data->d2_graphics_stereo_mode;
+		}
+		results->cursor_width_pixels[i] = bw_int_to_fixed(
+			vbios->cursor_width);
+	}
+	/* display_write_back420*/
+	results->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 2] =
+		0;
+	results->scatter_gather_enable_for_pipe[maximum_number_of_surfaces - 1] =
+		0;
+	if (mode_data->d1_display_write_back_dwb_enable == 1) {
+		results->enable[maximum_number_of_surfaces - 2] = 1;
+		results->enable[maximum_number_of_surfaces - 1] = 1;
+	} else {
+		results->enable[maximum_number_of_surfaces - 2] = 0;
+		results->enable[maximum_number_of_surfaces - 1] = 0;
+	}
+	surface_type[maximum_number_of_surfaces - 2] =
+		bw_def_display_write_back420_luma;
+	surface_type[maximum_number_of_surfaces - 1] =
+		bw_def_display_write_back420_chroma;
+	results->lb_size_per_component[maximum_number_of_surfaces - 2] =
+		dceip->underlay420_luma_lb_size_per_component;
+	results->lb_size_per_component[maximum_number_of_surfaces - 1] =
+		dceip->underlay420_chroma_lb_size_per_component;
+	results->bytes_per_pixel[maximum_number_of_surfaces - 2] = 1;
+	results->bytes_per_pixel[maximum_number_of_surfaces - 1] = 2;
+	results->interlace_mode[maximum_number_of_surfaces - 2] =
+		mode_data->graphics_interlace_mode;
+	results->interlace_mode[maximum_number_of_surfaces - 1] =
+		mode_data->graphics_interlace_mode;
+	results->h_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
+	results->h_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
+	results->v_taps[maximum_number_of_surfaces - 2] = bw_int_to_fixed(1);
+	results->v_taps[maximum_number_of_surfaces - 1] = bw_int_to_fixed(1);
+	results->rotation_angle[maximum_number_of_surfaces - 2] =
+		bw_int_to_fixed(0);
+	results->rotation_angle[maximum_number_of_surfaces - 1] =
+		bw_int_to_fixed(0);
+	tiling_mode[maximum_number_of_surfaces - 2] = bw_def_linear;
+	tiling_mode[maximum_number_of_surfaces - 1] = bw_def_linear;
+	results->lb_bpc[maximum_number_of_surfaces - 2] = 8;
+	results->lb_bpc[maximum_number_of_surfaces - 1] = 8;
+	results->compression_rate[maximum_number_of_surfaces - 2] =
+		bw_int_to_fixed(1);
+	results->compression_rate[maximum_number_of_surfaces - 1] =
+		bw_int_to_fixed(1);
+	results->access_one_channel_only[maximum_number_of_surfaces - 2] = 0;
+	results->access_one_channel_only[maximum_number_of_surfaces - 1] = 0;
+	results->h_total[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+		mode_data->d1_htotal);
+	results->h_total[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+		mode_data->d1_htotal);
+	results->pixel_rate[maximum_number_of_surfaces - 2] =
+		mode_data->d1_pixel_rate;
+	results->pixel_rate[maximum_number_of_surfaces - 1] =
+		mode_data->d1_pixel_rate;
+	results->src_width[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+		mode_data->d1_graphics_src_width);
+	results->src_width[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+		mode_data->d1_graphics_src_width);
+	results->src_height[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+		mode_data->d1_graphics_src_height);
+	results->src_height[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+		mode_data->d1_graphics_src_height);
+	results->pitch_in_pixels[maximum_number_of_surfaces - 2] =
+		bw_int_to_fixed(mode_data->d1_graphics_src_width);
+	results->pitch_in_pixels[maximum_number_of_surfaces - 1] =
+		bw_int_to_fixed(mode_data->d1_graphics_src_width);
+	results->scale_ratio[maximum_number_of_surfaces - 2] = bw_int_to_fixed(
+		1);
+	results->scale_ratio[maximum_number_of_surfaces - 1] = bw_int_to_fixed(
+		1);
+	stereo_mode[maximum_number_of_surfaces - 2] = bw_def_mono;
+	stereo_mode[maximum_number_of_surfaces - 1] = bw_def_mono;
+	results->cursor_width_pixels[maximum_number_of_surfaces - 2] =
+		bw_int_to_fixed(0);
+	results->cursor_width_pixels[maximum_number_of_surfaces - 1] =
+		bw_int_to_fixed(0);
+	results->use_alpha[maximum_number_of_surfaces - 2] = 0;
+	results->use_alpha[maximum_number_of_surfaces - 1] = 0;
+	/*mode check calculations:*/
+	/* mode within dce ip capabilities*/
+	/* fbc*/
+	/* hsr*/
+	/* vsr*/
+	/* lb size*/
+	/*effective scaling source and ratios:*/
+	/*for graphics, non-stereo, non-interlace surfaces when the size of the source and destination are the same, only one tap is used*/
+	/*420 chroma has half the width, height, horizontal and vertical scaling ratios than luma*/
+	/*rotating an underlay surface swaps the width, height, horizontal and vertical scaling ratios*/
+	/*in top-bottom stereo mode there is 2:1 vertical downscaling for each eye*/
+	/*in side-by-side stereo mode there is 2:1 horizontal downscaling for each eye*/
+	/*in interlace mode there is 2:1 vertical downscaling for each field*/
+	/*in panning or bezel adjustment mode the source width has an extra 128 pixels*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_equ(results->scale_ratio[i], bw_int_to_fixed(1))
+				&& surface_type[i] == bw_def_graphics
+				&& stereo_mode[i] == bw_def_mono
+				&& results->interlace_mode[i] == 0) {
+				results->h_taps[i] = bw_int_to_fixed(1);
+				results->v_taps[i] = bw_int_to_fixed(1);
+			}
+			if (surface_type[i]
+				== bw_def_display_write_back420_chroma
+				|| surface_type[i]
+					== bw_def_underlay420_chroma) {
+				results->pitch_in_pixels_after_surface_type[i] =
+					bw_div(
+						results->pitch_in_pixels[i],
+						bw_int_to_fixed(2));
+				results->src_width_after_surface_type = bw_div(
+					results->src_width[i],
+					bw_int_to_fixed(2));
+				results->src_height_after_surface_type = bw_div(
+					results->src_height[i],
+					bw_int_to_fixed(2));
+				results->hsr_after_surface_type = bw_div(
+					results->scale_ratio[i],
+					bw_int_to_fixed(2));
+				results->vsr_after_surface_type = bw_div(
+					results->scale_ratio[i],
+					bw_int_to_fixed(2));
+			} else {
+				results->pitch_in_pixels_after_surface_type[i] =
+					results->pitch_in_pixels[i];
+				results->src_width_after_surface_type =
+					results->src_width[i];
+				results->src_height_after_surface_type =
+					results->src_height[i];
+				results->hsr_after_surface_type =
+					results->scale_ratio[i];
+				results->vsr_after_surface_type =
+					results->scale_ratio[i];
+			}
+			if ((bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(90))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(270)))
+				&& surface_type[i] != bw_def_graphics) {
+				results->src_width_after_rotation =
+					results->src_height_after_surface_type;
+				results->src_height_after_rotation =
+					results->src_width_after_surface_type;
+				results->hsr_after_rotation =
+					results->vsr_after_surface_type;
+				results->vsr_after_rotation =
+					results->hsr_after_surface_type;
+			} else {
+				results->src_width_after_rotation =
+					results->src_width_after_surface_type;
+				results->src_height_after_rotation =
+					results->src_height_after_surface_type;
+				results->hsr_after_rotation =
+					results->hsr_after_surface_type;
+				results->vsr_after_rotation =
+					results->vsr_after_surface_type;
+			}
+			switch (stereo_mode[i]) {
+			case bw_def_top_bottom:
+				results->source_width_pixels[i] =
+					results->src_width_after_rotation;
+				results->source_height_pixels = bw_mul(
+					bw_int_to_fixed(2),
+					results->src_height_after_rotation);
+				results->hsr_after_stereo =
+					results->hsr_after_rotation;
+				results->vsr_after_stereo = bw_mul(
+					bw_int_to_fixed(1),
+					results->vsr_after_rotation);
+				break;
+			case bw_def_side_by_side:
+				results->source_width_pixels[i] = bw_mul(
+					bw_int_to_fixed(2),
+					results->src_width_after_rotation);
+				results->source_height_pixels =
+					results->src_height_after_rotation;
+				results->hsr_after_stereo = bw_mul(
+					bw_int_to_fixed(1),
+					results->hsr_after_rotation);
+				results->vsr_after_stereo =
+					results->vsr_after_rotation;
+				break;
+			default:
+				results->source_width_pixels[i] =
+					results->src_width_after_rotation;
+				results->source_height_pixels =
+					results->src_height_after_rotation;
+				results->hsr_after_stereo =
+					results->hsr_after_rotation;
+				results->vsr_after_stereo =
+					results->vsr_after_rotation;
+				break;
+			}
+			results->hsr[i] = results->hsr_after_stereo;
+			if (results->interlace_mode[i]) {
+				results->vsr[i] = bw_mul(
+					results->vsr_after_stereo,
+					bw_int_to_fixed(2));
+			} else {
+				results->vsr[i] = results->vsr_after_stereo;
+			}
+			if (mode_data->panning_and_bezel_adjustment
+				!= bw_def_none) {
+				results->source_width_rounded_up_to_chunks[i] =
+					bw_add(
+						bw_floor2(
+							bw_sub(
+								results->source_width_pixels[i],
+								bw_int_to_fixed(
+									1)),
+							bw_int_to_fixed(128)),
+						bw_int_to_fixed(256));
+			} else {
+				results->source_width_rounded_up_to_chunks[i] =
+					bw_ceil2(
+						results->source_width_pixels[i],
+						bw_int_to_fixed(128));
+			}
+			results->source_height_rounded_up_to_chunks[i] =
+				results->source_height_pixels;
+		}
+	}
+	/*mode support checks:*/
+	/*the number of graphics and underlay pipes is limited by the ip support*/
+	/*maximum horizontal and vertical scale ratio is 4, and should not exceed the number of taps*/
+	/*for downscaling with the pre-downscaler, the horizontal scale ratio must be more than the ceiling of one quarter of the number of taps*/
+	/*the pre-downscaler reduces the line buffer source by the horizontal scale ratio*/
+	/*the number of lines in the line buffer has to exceed the number of vertical taps*/
+	/*the size of the line in the line buffer is the product of the source width and the bits per component, rounded up to a multiple of 48*/
+	/*the size of the line in the line buffer in the case of 10 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/
+	/*the size of the line in the line buffer in the case of 8 bit per component is the product of the source width rounded up to multiple of 8 and 30.023438 / 3, rounded up to a multiple of 48*/
+	/*frame buffer compression is not supported with stereo mode, rotation, or non- 888 formats*/
+	/*rotation is not supported with linear of stereo modes*/
+	if (dceip->number_of_graphics_pipes >= mode_data->number_of_displays
+		&& dceip->number_of_underlay_pipes
+			>= results->number_of_underlay_surfaces
+		&& !(dceip->display_write_back_supported == 0
+			&& mode_data->d1_display_write_back_dwb_enable == 1)) {
+		pipe_check = bw_def_ok;
+	} else {
+		pipe_check = bw_def_notok;
+	}
+	hsr_check = bw_def_ok;
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_neq(results->hsr[i], bw_int_to_fixed(1))) {
+				if (bw_mtn(
+					results->hsr[i],
+					bw_int_to_fixed(4))) {
+					hsr_check = bw_def_hsr_mtn_4;
+				} else {
+					if (bw_mtn(
+						results->hsr[i],
+						results->h_taps[i])) {
+						hsr_check =
+							bw_def_hsr_mtn_h_taps;
+					} else {
+						if (dceip->pre_downscaler_enabled
+							== 1
+							&& bw_mtn(
+								results->hsr[i],
+								bw_int_to_fixed(
+									1))
+							&& bw_leq(
+								results->hsr[i],
+								bw_ceil2(
+									bw_div(
+										results->h_taps[i],
+										bw_int_to_fixed(
+											4)),
+									bw_int_to_fixed(
+										1)))) {
+							hsr_check =
+								bw_def_ceiling__h_taps_div_4___meq_hsr;
+						}
+					}
+				}
+			}
+		}
+	}
+	vsr_check = bw_def_ok;
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_neq(results->vsr[i], bw_int_to_fixed(1))) {
+				if (bw_mtn(
+					results->vsr[i],
+					bw_int_to_fixed(4))) {
+					vsr_check = bw_def_vsr_mtn_4;
+				} else {
+					if (bw_mtn(
+						results->vsr[i],
+						results->v_taps[i])) {
+						vsr_check =
+							bw_def_vsr_mtn_v_taps;
+					}
+				}
+			}
+		}
+	}
+	lb_size_check = bw_def_ok;
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if ((dceip->pre_downscaler_enabled
+				&& bw_mtn(results->hsr[i], bw_int_to_fixed(1)))) {
+				results->source_width_in_lb = bw_div(
+					results->source_width_pixels[i],
+					results->hsr[i]);
+			} else {
+				results->source_width_in_lb =
+					results->source_width_pixels[i];
+			}
+			switch (results->lb_bpc[i]) {
+			case 8:
+				results->lb_line_pitch =
+					bw_ceil2(
+						bw_mul(
+							bw_div(
+								bw_frc_to_fixed(
+									2401171875ULL,
+									100000000),
+								bw_int_to_fixed(
+									3)),
+							bw_ceil2(
+								results->source_width_in_lb,
+								bw_int_to_fixed(
+									8))),
+						bw_int_to_fixed(48));
+				break;
+			case 10:
+				results->lb_line_pitch =
+					bw_ceil2(
+						bw_mul(
+							bw_div(
+								bw_frc_to_fixed(
+									300234375,
+									10000000),
+								bw_int_to_fixed(
+									3)),
+							bw_ceil2(
+								results->source_width_in_lb,
+								bw_int_to_fixed(
+									8))),
+						bw_int_to_fixed(48));
+				break;
+			default:
+				results->lb_line_pitch = bw_ceil2(
+					bw_mul(
+						bw_int_to_fixed(
+							results->lb_bpc[i]),
+						results->source_width_in_lb),
+					bw_int_to_fixed(48));
+				break;
+			}
+			results->lb_partitions[i] = bw_floor2(
+				bw_div(
+					results->lb_size_per_component[i],
+					results->lb_line_pitch),
+				bw_int_to_fixed(1));
+			/*clamp the partitions to the maxium number supported by the lb*/
+			if ((surface_type[i] != bw_def_graphics
+				|| dceip->graphics_lb_nodownscaling_multi_line_prefetching
+					== 1)) {
+				results->lb_partitions_max[i] = bw_int_to_fixed(
+					10);
+			} else {
+				results->lb_partitions_max[i] = bw_int_to_fixed(
+					7);
+			}
+			results->lb_partitions[i] = bw_min2(
+				results->lb_partitions_max[i],
+				results->lb_partitions[i]);
+			if (bw_mtn(
+				bw_add(results->v_taps[i], bw_int_to_fixed(1)),
+				results->lb_partitions[i])) {
+				lb_size_check = bw_def_notok;
+			}
+		}
+	}
+	if (mode_data->d0_fbc_enable
+		&& (mode_data->graphics_rotation_angle == 90
+			|| mode_data->graphics_rotation_angle == 270
+			|| mode_data->d0_graphics_stereo_mode != bw_def_mono
+			|| mode_data->graphics_bytes_per_pixel != 4)) {
+		fbc_check = bw_def_invalid_rotation_or_bpp_or_stereo;
+	} else {
+		fbc_check = bw_def_ok;
+	}
+	rotation_check = bw_def_ok;
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if ((bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(90))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(270)))
+				&& (tiling_mode[i] == bw_def_linear
+					|| stereo_mode[i] != bw_def_mono)) {
+				rotation_check =
+					bw_def_invalid_linear_or_stereo_mode;
+			}
+		}
+	}
+	if (pipe_check == bw_def_ok && hsr_check == bw_def_ok
+		&& vsr_check == bw_def_ok && lb_size_check == bw_def_ok
+		&& fbc_check == bw_def_ok && rotation_check == bw_def_ok) {
+		mode_check = bw_def_ok;
+	} else {
+		mode_check = bw_def_notok;
+	}
+	/*memory request size and latency hiding:*/
+	/*request size is normally 64 byte, 2-line interleaved, with full latency hiding*/
+	/*the display write-back requests are single line*/
+	/*for tiled graphics surfaces, or undelay surfaces with width higher than the maximum size for full efficiency, request size is 32 byte in 8 and 16 bpp or if the rotation is orthogonal to the tiling grain. only half is useful of the bytes in the request size in 8 bpp or in 32 bpp if the rotation is orthogonal to the tiling grain.*/
+	/*for undelay surfaces with width lower than the maximum size for full efficiency, requests are 4-line interleaved in 16bpp if the rotation is parallel to the tiling grain, and 8-line interleaved with 4-line latency hiding in 8bpp or if the rotation is orthogonal to the tiling grain.*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if ((bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(90))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(270)))) {
+				if ((tiling_mode[i] == bw_def_portrait)) {
+					results->orthogonal_rotation[i] = 0;
+				} else {
+					results->orthogonal_rotation[i] = 1;
+				}
+			} else {
+				if ((tiling_mode[i] == bw_def_portrait)) {
+					results->orthogonal_rotation[i] = 1;
+				} else {
+					results->orthogonal_rotation[i] = 0;
+				}
+			}
+			if (bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(90))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(270))) {
+				results->underlay_maximum_source_efficient_for_tiling =
+					dceip->underlay_maximum_height_efficient_for_tiling;
+			} else {
+				results->underlay_maximum_source_efficient_for_tiling =
+					dceip->underlay_maximum_width_efficient_for_tiling;
+			}
+			if (bw_equ(
+				dceip->de_tiling_buffer,
+				bw_int_to_fixed(0))) {
+				if (surface_type[i]
+					== bw_def_display_write_back420_luma
+					|| surface_type[i]
+						== bw_def_display_write_back420_chroma) {
+					results->bytes_per_request[i] =
+						bw_int_to_fixed(64);
+					results->useful_bytes_per_request[i] =
+						bw_int_to_fixed(64);
+					results->lines_interleaved_in_mem_access[i] =
+						bw_int_to_fixed(1);
+					results->latency_hiding_lines[i] =
+						bw_int_to_fixed(1);
+				} else if (tiling_mode[i] == bw_def_linear) {
+					results->bytes_per_request[i] =
+						bw_int_to_fixed(64);
+					results->useful_bytes_per_request[i] =
+						bw_int_to_fixed(64);
+					results->lines_interleaved_in_mem_access[i] =
+						bw_int_to_fixed(2);
+					results->latency_hiding_lines[i] =
+						bw_int_to_fixed(2);
+				} else {
+					if (surface_type[i] == bw_def_graphics
+						|| (bw_mtn(
+							results->source_width_rounded_up_to_chunks[i],
+							bw_ceil2(
+								results->underlay_maximum_source_efficient_for_tiling,
+								bw_int_to_fixed(
+									256))))) {
+						switch (results->bytes_per_pixel[i]) {
+						case 8:
+							results->lines_interleaved_in_mem_access[i] =
+								bw_int_to_fixed(
+									2);
+							results->latency_hiding_lines[i] =
+								bw_int_to_fixed(
+									2);
+							if (results->orthogonal_rotation[i]) {
+								results->bytes_per_request[i] =
+									bw_int_to_fixed(
+										32);
+								results->useful_bytes_per_request[i] =
+									bw_int_to_fixed(
+										32);
+							} else {
+								results->bytes_per_request[i] =
+									bw_int_to_fixed(
+										64);
+								results->useful_bytes_per_request[i] =
+									bw_int_to_fixed(
+										64);
+							}
+							break;
+						case 4:
+							if (results->orthogonal_rotation[i]) {
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										2);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										2);
+								results->bytes_per_request[i] =
+									bw_int_to_fixed(
+										32);
+								results->useful_bytes_per_request[i] =
+									bw_int_to_fixed(
+										16);
+							} else {
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										2);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										2);
+								results->bytes_per_request[i] =
+									bw_int_to_fixed(
+										64);
+								results->useful_bytes_per_request[i] =
+									bw_int_to_fixed(
+										64);
+							}
+							break;
+						case 2:
+							results->lines_interleaved_in_mem_access[i] =
+								bw_int_to_fixed(
+									2);
+							results->latency_hiding_lines[i] =
+								bw_int_to_fixed(
+									2);
+							results->bytes_per_request[i] =
+								bw_int_to_fixed(
+									32);
+							results->useful_bytes_per_request[i] =
+								bw_int_to_fixed(
+									32);
+							break;
+						default:
+							results->lines_interleaved_in_mem_access[i] =
+								bw_int_to_fixed(
+									2);
+							results->latency_hiding_lines[i] =
+								bw_int_to_fixed(
+									2);
+							results->bytes_per_request[i] =
+								bw_int_to_fixed(
+									32);
+							results->useful_bytes_per_request[i] =
+								bw_int_to_fixed(
+									16);
+							break;
+						}
+					} else {
+						results->bytes_per_request[i] =
+							bw_int_to_fixed(64);
+						results->useful_bytes_per_request[i] =
+							bw_int_to_fixed(64);
+						if (results->orthogonal_rotation[i]) {
+							results->lines_interleaved_in_mem_access[i] =
+								bw_int_to_fixed(
+									8);
+							results->latency_hiding_lines[i] =
+								bw_int_to_fixed(
+									4);
+						} else {
+							switch (results->bytes_per_pixel[i]) {
+							case 4:
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										2);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										2);
+								break;
+							case 2:
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										4);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										4);
+								break;
+							default:
+								results->lines_interleaved_in_mem_access[i] =
+									bw_int_to_fixed(
+										8);
+								results->latency_hiding_lines[i] =
+									bw_int_to_fixed(
+										4);
+								break;
+							}
+						}
+					}
+				}
+			} else {
+				results->bytes_per_request[i] = bw_int_to_fixed(
+					256);
+				results->useful_bytes_per_request[i] =
+					bw_int_to_fixed(256);
+				results->lines_interleaved_in_mem_access[i] =
+					bw_int_to_fixed(4);
+				results->latency_hiding_lines[i] =
+					bw_int_to_fixed(4);
+			}
+		}
+	}
+	/*requested peak bandwidth:*/
+	/*the peak request-per-second bandwidth is the product of the maximum source lines in per line out in the beginning and in the middle of the frame, the ratio of the source width to the line time, the ratio of line interleaving in memory to lines of latency hiding, and the ratio of bytes per pixel to useful bytes per request.*/
+	/*the peak bandwidth is the peak request-per-second bandwidth times the request size.*/
+	/*the line buffer lines in per line out in the beginning of the frame is the vertical filter initialization value rounded up to even and divided by the line times for initialization, which is normally three.*/
+	/*the line buffer lines in per line out in the middle of the frame is at least one, or the vertical scale ratio, rounded up to line pairs if not doing line buffer prefetching.*/
+	/*the non-prefetching rounding up of the vertical scale ratio can also be done up to 1 (for a 0,2 pattern), 4/3 (for a 0,2,2 pattern), 6/4 (for a 0,2,2,2 pattern), or 3 (for a 2,4 pattern).*/
+	/*the scaler vertical filter initialization value is calculated by the hardware as the floor of the average of the vertical scale ratio and the number of vertical taps increased by one.  add one more for possible odd line panning/bezel adjustment mode.*/
+	/*for the bottom interlace field an extra 50% of the vertical scale ratio is considered for this calculation.*/
+	/*in top-bottom stereo mode software has to set the filter initialization value manually and explicitly limit it to 4.  further, there is only one line time for initialization.*/
+	/*line buffer prefetching is done when the number of lines in the line buffer exceeds the number of taps plus the ceiling of the vertical scale ratio.*/
+	/*line buffer prefetching is not done when downscaling in the graphics pipe or for possible odd line panning/bezel adjustment mode.*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->v_filter_init[i] =
+				bw_floor2(
+					bw_div(
+						(bw_add(
+							bw_add(
+								bw_add(
+									bw_int_to_fixed(
+										1),
+									results->v_taps[i]),
+								results->vsr[i]),
+							bw_mul(
+								bw_mul(
+									bw_int_to_fixed(
+										results->interlace_mode[i]),
+									bw_frc_to_fixed(
+										5,
+										10)),
+								results->vsr[i]))),
+						bw_int_to_fixed(2)),
+					bw_int_to_fixed(1));
+			if (mode_data->panning_and_bezel_adjustment
+				== bw_def_any_lines) {
+				results->v_filter_init[i] = bw_add(
+					results->v_filter_init[i],
+					bw_int_to_fixed(1));
+			}
+			if (stereo_mode[i] == bw_def_top_bottom) {
+				v_filter_init_mode[i] = bw_def_manual;
+				results->v_filter_init[i] = bw_min2(
+					results->v_filter_init[i],
+					bw_int_to_fixed(4));
+			} else {
+				v_filter_init_mode[i] = bw_def_auto;
+			}
+			if (stereo_mode[i] == bw_def_top_bottom) {
+				results->num_lines_at_frame_start =
+					bw_int_to_fixed(1);
+			} else {
+				results->num_lines_at_frame_start =
+					bw_int_to_fixed(3);
+			}
+			if ((bw_mtn(results->vsr[i], bw_int_to_fixed(1))
+				&& surface_type[i] == bw_def_graphics)
+				|| mode_data->panning_and_bezel_adjustment
+					== bw_def_any_lines) {
+				results->line_buffer_prefetch[i] = 0;
+			} else if ((((dceip->underlay_downscale_prefetch_enabled
+				== 1 && surface_type[i] != bw_def_graphics)
+				|| surface_type[i] == bw_def_graphics)
+				&& (bw_mtn(
+					results->lb_partitions[i],
+					bw_add(
+						results->v_taps[i],
+						bw_ceil2(
+							results->vsr[i],
+							bw_int_to_fixed(1))))))) {
+				results->line_buffer_prefetch[i] = 1;
+			} else {
+				results->line_buffer_prefetch[i] = 0;
+			}
+			results->lb_lines_in_per_line_out_in_beginning_of_frame[i] =
+				bw_div(
+					bw_ceil2(
+						results->v_filter_init[i],
+						bw_int_to_fixed(
+							dceip->lines_interleaved_into_lb)),
+					results->num_lines_at_frame_start);
+			if (results->line_buffer_prefetch[i] == 1) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_max2(
+						bw_int_to_fixed(1),
+						results->vsr[i]);
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(1))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_int_to_fixed(1);
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(4 / 3))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_div(
+						bw_int_to_fixed(4),
+						bw_int_to_fixed(3));
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(6 / 4))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_div(
+						bw_int_to_fixed(6),
+						bw_int_to_fixed(4));
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(2))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_int_to_fixed(2);
+			} else if (bw_leq(
+				results->vsr[i],
+				bw_int_to_fixed(3))) {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_int_to_fixed(3);
+			} else {
+				results->lb_lines_in_per_line_out_in_middle_of_frame[i] =
+					bw_int_to_fixed(4);
+			}
+			if (results->line_buffer_prefetch[i] == 1
+				|| bw_equ(
+					results->lb_lines_in_per_line_out_in_middle_of_frame[i],
+					bw_int_to_fixed(2))
+				|| bw_equ(
+					results->lb_lines_in_per_line_out_in_middle_of_frame[i],
+					bw_int_to_fixed(4))) {
+				results->horizontal_blank_and_chunk_granularity_factor[i] =
+					bw_int_to_fixed(1);
+			} else {
+				results->horizontal_blank_and_chunk_granularity_factor[i] =
+					bw_div(
+						results->h_total[i],
+						(bw_div(
+							(bw_add(
+								results->h_total[i],
+								bw_div(
+									(bw_sub(
+										results->source_width_pixels[i],
+										bw_int_to_fixed(
+											dceip->chunk_width))),
+									results->hsr[i]))),
+							bw_int_to_fixed(2))));
+			}
+			results->request_bandwidth[i] =
+				bw_div(
+					bw_mul(
+						bw_div(
+							bw_mul(
+								bw_div(
+									bw_mul(
+										bw_max2(
+											results->lb_lines_in_per_line_out_in_beginning_of_frame[i],
+											results->lb_lines_in_per_line_out_in_middle_of_frame[i]),
+										results->source_width_rounded_up_to_chunks[i]),
+									(bw_div(
+										results->h_total[i],
+										results->pixel_rate[i]))),
+								bw_int_to_fixed(
+									results->bytes_per_pixel[i])),
+							results->useful_bytes_per_request[i]),
+						results->lines_interleaved_in_mem_access[i]),
+					results->latency_hiding_lines[i]);
+			results->display_bandwidth[i] = bw_mul(
+				results->request_bandwidth[i],
+				results->bytes_per_request[i]);
+		}
+	}
+	/*outstanding chunk request limit*/
+	/*if underlay buffer sharing is enabled, the data buffer size for underlay in 422 or 444 is the sum of the luma and chroma data buffer sizes.*/
+	/*underlay buffer sharing mode is only permitted in orthogonal rotation modes.*/
+	/*if there is only one display enabled, the data buffer size for graphics is doubled.*/
+	/*the memory chunk size in bytes is 1024 for the writeback, and 256 times the memory line interleaving and the bytes per pixel for graphics*/
+	/*and underlay.*/
+	/*the pipe chunk size uses 2 for line interleaving, except for the write back, in which case it is 1.*/
+	/*graphics and underlay data buffer size is adjusted (limited) using the outstanding chunk request limit if there is more than one*/
+	/*display enabled or if the dmif request buffer is not large enough for the total data buffer size.*/
+	/*the outstanding chunk request limit is the ceiling of the adjusted data buffer size divided by the chunk size in bytes*/
+	/*the adjusted data buffer size is the product of the display bandwidth and the minimum effective data buffer size in terms of time,*/
+	/*rounded up to the chunk size in bytes, but should not exceed the original data buffer size*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			switch (surface_type[i]) {
+			case bw_def_display_write_back420_luma:
+				results->data_buffer_size[i] =
+					bw_int_to_fixed(
+						dceip->display_write_back420_luma_mcifwr_buffer_size);
+				break;
+			case bw_def_display_write_back420_chroma:
+				results->data_buffer_size[i] =
+					bw_int_to_fixed(
+						dceip->display_write_back420_chroma_mcifwr_buffer_size);
+				break;
+			case bw_def_underlay420_luma:
+				results->data_buffer_size[i] = bw_int_to_fixed(
+					dceip->underlay_luma_dmif_size);
+				break;
+			case bw_def_underlay420_chroma:
+				results->data_buffer_size[i] =
+					bw_div(
+						bw_int_to_fixed(
+							dceip->underlay_chroma_dmif_size),
+						bw_int_to_fixed(2));
+				break;
+			case bw_def_underlay422:
+			case bw_def_underlay444:
+				if (results->orthogonal_rotation[i] == 0) {
+					results->data_buffer_size[i] =
+						bw_int_to_fixed(
+							dceip->underlay_luma_dmif_size);
+				} else {
+					results->data_buffer_size[i] =
+						bw_add(
+							bw_int_to_fixed(
+								dceip->underlay_luma_dmif_size),
+							bw_int_to_fixed(
+								dceip->underlay_chroma_dmif_size));
+				}
+				break;
+			default:
+				if (mode_data->number_of_displays == 1
+					&& bw_equ(
+						dceip->de_tiling_buffer,
+						bw_int_to_fixed(0))) {
+					if (mode_data->d0_fbc_enable) {
+						results->data_buffer_size[i] =
+							bw_mul(
+								bw_int_to_fixed(
+									dceip->max_dmif_buffer_allocated),
+								bw_int_to_fixed(
+									dceip->graphics_dmif_size));
+					} else {
+						/*the effective dmif buffer size in non-fbc mode is limited by the 16 entry chunk tracker*/
+						results->data_buffer_size[i] =
+							bw_mul(
+								bw_mul(
+									bw_int_to_fixed(
+										max_chunks_non_fbc_mode),
+									bw_int_to_fixed(
+										pixels_per_chunk)),
+								bw_int_to_fixed(
+									results->bytes_per_pixel[i]));
+					}
+				} else {
+					results->data_buffer_size[i] =
+						bw_int_to_fixed(
+							dceip->graphics_dmif_size);
+				}
+				break;
+			}
+			if (surface_type[i] == bw_def_display_write_back420_luma
+				|| surface_type[i]
+					== bw_def_display_write_back420_chroma) {
+				results->memory_chunk_size_in_bytes[i] =
+					bw_int_to_fixed(1024);
+				results->pipe_chunk_size_in_bytes[i] =
+					bw_int_to_fixed(1024);
+			} else {
+				results->memory_chunk_size_in_bytes[i] =
+					bw_mul(
+						bw_mul(
+							bw_int_to_fixed(
+								dceip->chunk_width),
+							results->lines_interleaved_in_mem_access[i]),
+						bw_int_to_fixed(
+							results->bytes_per_pixel[i]));
+				results->pipe_chunk_size_in_bytes[i] =
+					bw_mul(
+						bw_mul(
+							bw_int_to_fixed(
+								dceip->chunk_width),
+							bw_int_to_fixed(
+								dceip->lines_interleaved_into_lb)),
+						bw_int_to_fixed(
+							results->bytes_per_pixel[i]));
+			}
+		}
+	}
+	results->min_dmif_size_in_time = bw_int_to_fixed(9999);
+	results->min_mcifwr_size_in_time = bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				if (bw_ltn(
+					bw_div(
+						bw_div(
+							bw_mul(
+								results->data_buffer_size[i],
+								results->bytes_per_request[i]),
+							results->useful_bytes_per_request[i]),
+						results->display_bandwidth[i]),
+					results->min_dmif_size_in_time)) {
+					results->min_dmif_size_in_time =
+						bw_div(
+							bw_div(
+								bw_mul(
+									results->data_buffer_size[i],
+									results->bytes_per_request[i]),
+								results->useful_bytes_per_request[i]),
+							results->display_bandwidth[i]);
+				}
+			} else {
+				if (bw_ltn(
+					bw_div(
+						bw_div(
+							bw_mul(
+								results->data_buffer_size[i],
+								results->bytes_per_request[i]),
+							results->useful_bytes_per_request[i]),
+						results->display_bandwidth[i]),
+					results->min_mcifwr_size_in_time)) {
+					results->min_mcifwr_size_in_time =
+						bw_div(
+							bw_div(
+								bw_mul(
+									results->data_buffer_size[i],
+									results->bytes_per_request[i]),
+								results->useful_bytes_per_request[i]),
+							results->display_bandwidth[i]);
+				}
+			}
+		}
+	}
+	results->total_requests_for_dmif_size = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]
+			&& surface_type[i] != bw_def_display_write_back420_luma
+			&& surface_type[i]
+				!= bw_def_display_write_back420_chroma) {
+			results->total_requests_for_dmif_size = bw_add(
+				results->total_requests_for_dmif_size,
+				bw_div(
+					results->data_buffer_size[i],
+					results->useful_bytes_per_request[i]));
+		}
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma
+				&& dceip->limit_excessive_outstanding_dmif_requests
+				&& (mode_data->number_of_displays > 1
+					|| bw_mtn(
+						results->total_requests_for_dmif_size,
+						dceip->dmif_request_buffer_size))) {
+				results->adjusted_data_buffer_size[i] =
+					bw_min2(
+						results->data_buffer_size[i],
+						bw_ceil2(
+							bw_mul(
+								results->min_dmif_size_in_time,
+								results->display_bandwidth[i]),
+							results->memory_chunk_size_in_bytes[i]));
+			} else {
+				results->adjusted_data_buffer_size[i] =
+					results->data_buffer_size[i];
+			}
+		}
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if ((mode_data->number_of_displays == 1
+				&& results->number_of_underlay_surfaces == 0)) {
+				/*set maximum chunk limit if only one graphic pipe is enabled*/
+				results->outstanding_chunk_request_limit[i] =
+					bw_int_to_fixed(255);
+			} else {
+				results->outstanding_chunk_request_limit[i] =
+					bw_ceil2(
+						bw_div(
+							results->adjusted_data_buffer_size[i],
+							results->pipe_chunk_size_in_bytes[i]),
+						bw_int_to_fixed(1));
+			}
+		}
+	}
+	/*outstanding pte request limit*/
+	/*in tiling mode with no rotation the sg pte requests are 8 useful pt_es, the sg row height is the page height and the sg page width x height is 64x64 for 8bpp, 64x32 for 16 bpp, 32x32 for 32 bpp*/
+	/*in tiling mode with rotation the sg pte requests are only one useful pte, and the sg row height is also the page height, but the sg page width and height are swapped*/
+	/*in linear mode the pte requests are 8 useful pt_es, the sg page width is 4096 divided by the bytes per pixel, the sg page height is 1, but there is just one row whose height is the lines of pte prefetching*/
+	/*the outstanding pte request limit is obtained by multiplying the outstanding chunk request limit by the peak pte request to eviction limiting ratio, rounding up to integer, multiplying by the pte requests per chunk, and rounding up to integer again*/
+	/*if not using peak pte request to eviction limiting, the outstanding pte request limit is the pte requests in the vblank*/
+	/*the pte requests in the vblank is the product of the number of pte request rows times the number of pte requests in a row*/
+	/*the number of pte requests in a row is the quotient of the source width divided by 256, multiplied by the pte requests per chunk, rounded up to even, multiplied by the scatter-gather row height and divided by the scatter-gather page height*/
+	/*the pte requests per chunk is 256 divided by the scatter-gather page width and the useful pt_es per pte request*/
+	if (mode_data->number_of_displays > 1
+		|| (mode_data->graphics_rotation_angle != 0
+			&& mode_data->graphics_rotation_angle != 180)) {
+		results->peak_pte_request_to_eviction_ratio_limiting =
+			dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display;
+	} else {
+		results->peak_pte_request_to_eviction_ratio_limiting =
+			dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation;
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]
+			&& results->scatter_gather_enable_for_pipe[i] == 1) {
+			if (tiling_mode[i] == bw_def_linear) {
+				results->useful_pte_per_pte_request =
+					bw_int_to_fixed(8);
+				results->scatter_gather_page_width[i] = bw_div(
+					bw_int_to_fixed(4096),
+					bw_int_to_fixed(
+						results->bytes_per_pixel[i]));
+				results->scatter_gather_page_height[i] =
+					bw_int_to_fixed(1);
+				results->scatter_gather_pte_request_rows =
+					bw_int_to_fixed(1);
+				results->scatter_gather_row_height =
+					bw_int_to_fixed(
+						dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode);
+			} else if (bw_equ(
+				results->rotation_angle[i],
+				bw_int_to_fixed(0))
+				|| bw_equ(
+					results->rotation_angle[i],
+					bw_int_to_fixed(180))) {
+				results->useful_pte_per_pte_request =
+					bw_int_to_fixed(8);
+				switch (results->bytes_per_pixel[i]) {
+				case 4:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(32);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(32);
+					break;
+				case 2:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(64);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(32);
+					break;
+				default:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(64);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(64);
+					break;
+				}
+				results->scatter_gather_pte_request_rows =
+					bw_int_to_fixed(
+						dceip->scatter_gather_pte_request_rows_in_tiling_mode);
+				results->scatter_gather_row_height =
+					results->scatter_gather_page_height[i];
+			} else {
+				results->useful_pte_per_pte_request =
+					bw_int_to_fixed(1);
+				switch (results->bytes_per_pixel[i]) {
+				case 4:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(32);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(32);
+					break;
+				case 2:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(32);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(64);
+					break;
+				default:
+					results->scatter_gather_page_width[i] =
+						bw_int_to_fixed(64);
+					results->scatter_gather_page_height[i] =
+						bw_int_to_fixed(64);
+					break;
+				}
+				results->scatter_gather_pte_request_rows =
+					bw_int_to_fixed(
+						dceip->scatter_gather_pte_request_rows_in_tiling_mode);
+				results->scatter_gather_row_height =
+					results->scatter_gather_page_height[i];
+			}
+			results->pte_request_per_chunk[i] = bw_div(
+				bw_div(
+					bw_int_to_fixed(dceip->chunk_width),
+					results->scatter_gather_page_width[i]),
+				results->useful_pte_per_pte_request);
+			results->scatter_gather_pte_requests_in_row[i] =
+				bw_div(
+					bw_mul(
+						bw_ceil2(
+							bw_mul(
+								bw_div(
+									results->source_width_rounded_up_to_chunks[i],
+									bw_int_to_fixed(
+										dceip->chunk_width)),
+								results->pte_request_per_chunk[i]),
+							bw_int_to_fixed(1)),
+						results->scatter_gather_row_height),
+					results->scatter_gather_page_height[i]);
+			results->scatter_gather_pte_requests_in_vblank = bw_mul(
+				results->scatter_gather_pte_request_rows,
+				results->scatter_gather_pte_requests_in_row[i]);
+			if (bw_equ(
+				results->peak_pte_request_to_eviction_ratio_limiting,
+				bw_int_to_fixed(0))) {
+				results->scatter_gather_pte_request_limit[i] =
+					results->scatter_gather_pte_requests_in_vblank;
+			} else {
+				results->scatter_gather_pte_request_limit[i] =
+					bw_max2(
+						dceip->minimum_outstanding_pte_request_limit,
+						bw_min2(
+							results->scatter_gather_pte_requests_in_vblank,
+							bw_ceil2(
+								bw_mul(
+									bw_mul(
+										bw_div(
+											bw_ceil2(
+												results->adjusted_data_buffer_size[i],
+												results->memory_chunk_size_in_bytes[i]),
+											results->memory_chunk_size_in_bytes[i]),
+										results->pte_request_per_chunk[i]),
+									results->peak_pte_request_to_eviction_ratio_limiting),
+								bw_int_to_fixed(
+									1))));
+			}
+		}
+	}
+	/*pitch padding recommended for efficiency in linear mode*/
+	/*in linear mode graphics or underlay with scatter gather, a pitch that is a multiple of the channel interleave (256 bytes) times the channel-bank rotation is not efficient*/
+	/*if that is the case it is recommended to pad the pitch by at least 256 pixels*/
+	results->inefficient_linear_pitch_in_bytes = bw_mul(
+		bw_mul(
+			bw_int_to_fixed(256),
+			bw_int_to_fixed(vbios->number_of_dram_banks)),
+		bw_int_to_fixed(vbios->number_of_dram_channels));
+	switch (mode_data->underlay_surface_type) {
+	case bw_def_420:
+		results->inefficient_underlay_pitch_in_pixels =
+			results->inefficient_linear_pitch_in_bytes;
+		break;
+	case bw_def_422:
+		results->inefficient_underlay_pitch_in_pixels = bw_div(
+			results->inefficient_linear_pitch_in_bytes,
+			bw_int_to_fixed(2));
+		break;
+	default:
+		results->inefficient_underlay_pitch_in_pixels = bw_div(
+			results->inefficient_linear_pitch_in_bytes,
+			bw_int_to_fixed(4));
+		break;
+	}
+	if (mode_data->underlay_tiling_mode == bw_def_linear
+		&& vbios->scatter_gather_enable == 1
+		&& bw_equ(
+			bw_mod(
+				bw_int_to_fixed(
+					mode_data->underlay_pitch_in_pixels),
+				results->inefficient_underlay_pitch_in_pixels),
+			bw_int_to_fixed(0))) {
+		results->minimum_underlay_pitch_padding_recommended_for_efficiency =
+			bw_int_to_fixed(256);
+	} else {
+		results->minimum_underlay_pitch_padding_recommended_for_efficiency =
+			bw_int_to_fixed(0);
+	}
+	/*pixel transfer time*/
+	/*the dmif and mcifwr yclk(pclk) required is the one that allows the transfer of all pipe's data buffer size in memory in the time for data transfer*/
+	/*for dmif, pte and cursor requests have to be included.*/
+	/*the dram data requirement is doubled when the data request size in bytes is less than the dram channel width times the burst size (8)*/
+	/*the dram data requirement is also multiplied by the number of channels in the case of low power tiling*/
+	/*the page close-open time is determined by trc and the number of page close-opens*/
+	/*in tiled mode graphics or underlay with scatter-gather enabled the bytes per page close-open is the product of the memory line interleave times the maximum of the scatter-gather page width and the product of the tile width (8 pixels) times the number of channels times the number of banks.*/
+	/*in linear mode graphics or underlay with scatter-gather enabled and inefficient pitch, the bytes per page close-open is the line request alternation slice, because different lines are in completely different 4k address bases.*/
+	/*otherwise, the bytes page close-open is the chunk size because that is the arbitration slice.*/
+	/*pte requests are grouped by pte requests per chunk if that is more than 1. each group costs a page close-open time for dmif reads*/
+	/*cursor requests outstanding are limited to a group of two source lines. each group costs a page close-open time for dmif reads*/
+	/*the display reads and writes time for data transfer is the minimum data or cursor buffer size in time minus the mc urgent latency*/
+	/*the mc urgent latency is experienced more than one time if the number of dmif requests in the data buffer exceeds the request buffer size plus the request slots reserved for dmif in the dram channel arbiter queues*/
+	/*the dispclk required is the maximum for all surfaces of the maximum of the source pixels for first output pixel times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, and the source pixels for last output pixel, times the throughput factor, divided by the pixels per dispclk, and divided by the minimum latency hiding minus the dram speed/p-state change latency minus the burst time, plus the active time.*/
+	/*the data burst time is the maximum of the total page close-open time, total dmif/mcifwr buffer size in memory divided by the dram bandwidth, and the total dmif/mcifwr buffer size in memory divided by the 32 byte sclk data bus bandwidth, each multiplied by its efficiency.*/
+	/*the source line transfer time is the maximum for all surfaces of the maximum of the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the fist pixel, and the burst time plus the urgent latency times the floor of the data required divided by the buffer size for the last pixel plus the active time.*/
+	/*the source pixels for the first output pixel is 512 if the scaler vertical filter initialization value is greater than 2, and it is 4 times the source width if it is greater than 4.*/
+	/*the source pixels for the last output pixel is the source width times the scaler vertical filter initialization value rounded up to even*/
+	/*the source data for these pixels is the number of pixels times the bytes per pixel times the bytes per request divided by the useful bytes per request.*/
+	results->cursor_total_data = bw_int_to_fixed(0);
+	results->cursor_total_request_groups = bw_int_to_fixed(0);
+	results->scatter_gather_total_pte_requests = bw_int_to_fixed(0);
+	results->scatter_gather_total_pte_request_groups = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->cursor_total_data =
+				bw_add(
+					results->cursor_total_data,
+					bw_mul(
+						bw_mul(
+							bw_int_to_fixed(2),
+							results->cursor_width_pixels[i]),
+						bw_int_to_fixed(4)));
+			results->cursor_total_request_groups = bw_add(
+				results->cursor_total_request_groups,
+				bw_ceil2(
+					bw_div(
+						results->cursor_width_pixels[i],
+						dceip->cursor_chunk_width),
+					bw_int_to_fixed(1)));
+			if (results->scatter_gather_enable_for_pipe[i]) {
+				results->scatter_gather_total_pte_requests =
+					bw_add(
+						results->scatter_gather_total_pte_requests,
+						results->scatter_gather_pte_request_limit[i]);
+				results->scatter_gather_total_pte_request_groups =
+					bw_add(
+						results->scatter_gather_total_pte_request_groups,
+						bw_ceil2(
+							bw_div(
+								results->scatter_gather_pte_request_limit[i],
+								bw_ceil2(
+									results->pte_request_per_chunk[i],
+									bw_int_to_fixed(
+										1))),
+							bw_int_to_fixed(1)));
+			}
+		}
+	}
+	results->tile_width_in_pixels = bw_int_to_fixed(8);
+	results->dmif_total_number_of_data_request_page_close_open =
+		bw_int_to_fixed(0);
+	results->mcifwr_total_number_of_data_request_page_close_open =
+		bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (results->scatter_gather_enable_for_pipe[i] == 1
+				&& tiling_mode[i] != bw_def_linear) {
+				results->bytes_per_page_close_open =
+					bw_mul(
+						results->lines_interleaved_in_mem_access[i],
+						bw_max2(
+							bw_mul(
+								bw_mul(
+									bw_mul(
+										bw_int_to_fixed(
+											results->bytes_per_pixel[i]),
+										results->tile_width_in_pixels),
+									bw_int_to_fixed(
+										vbios->number_of_dram_banks)),
+								bw_int_to_fixed(
+									vbios->number_of_dram_channels)),
+							bw_mul(
+								bw_int_to_fixed(
+									results->bytes_per_pixel[i]),
+								results->scatter_gather_page_width[i])));
+			} else if (results->scatter_gather_enable_for_pipe[i]
+				== 1 && tiling_mode[i] == bw_def_linear
+				&& bw_equ(
+					bw_mod(
+						(bw_mul(
+							results->pitch_in_pixels_after_surface_type[i],
+							bw_int_to_fixed(
+								results->bytes_per_pixel[i]))),
+						results->inefficient_linear_pitch_in_bytes),
+					bw_int_to_fixed(0))) {
+				results->bytes_per_page_close_open =
+					dceip->linear_mode_line_request_alternation_slice;
+			} else {
+				results->bytes_per_page_close_open =
+					results->memory_chunk_size_in_bytes[i];
+			}
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->dmif_total_number_of_data_request_page_close_open =
+					bw_add(
+						results->dmif_total_number_of_data_request_page_close_open,
+						bw_div(
+							bw_ceil2(
+								results->adjusted_data_buffer_size[i],
+								results->memory_chunk_size_in_bytes[i]),
+							results->bytes_per_page_close_open));
+			} else {
+				results->mcifwr_total_number_of_data_request_page_close_open =
+					bw_add(
+						results->mcifwr_total_number_of_data_request_page_close_open,
+						bw_div(
+							bw_ceil2(
+								results->adjusted_data_buffer_size[i],
+								results->memory_chunk_size_in_bytes[i]),
+							results->bytes_per_page_close_open));
+			}
+		}
+	}
+	results->dmif_total_page_close_open_time =
+		bw_div(
+			bw_mul(
+				(bw_add(
+					bw_add(
+						results->dmif_total_number_of_data_request_page_close_open,
+						results->scatter_gather_total_pte_request_groups),
+					results->cursor_total_request_groups)),
+				vbios->trc),
+			bw_int_to_fixed(1000));
+	results->mcifwr_total_page_close_open_time =
+		bw_div(
+			bw_mul(
+				results->mcifwr_total_number_of_data_request_page_close_open,
+				vbios->trc),
+			bw_int_to_fixed(1000));
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->adjusted_data_buffer_size_in_memory[i] =
+				bw_div(
+					bw_mul(
+						results->adjusted_data_buffer_size[i],
+						results->bytes_per_request[i]),
+					results->useful_bytes_per_request[i]);
+		}
+	}
+	results->total_requests_for_adjusted_dmif_size = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->total_requests_for_adjusted_dmif_size =
+					bw_add(
+						results->total_requests_for_adjusted_dmif_size,
+						bw_div(
+							results->adjusted_data_buffer_size[i],
+							results->useful_bytes_per_request[i]));
+			}
+		}
+	}
+	if (dceip->dcfclk_request_generation == 1) {
+		results->total_dmifmc_urgent_trips = bw_int_to_fixed(1);
+	} else {
+		results->total_dmifmc_urgent_trips =
+			bw_ceil2(
+				bw_div(
+					results->total_requests_for_adjusted_dmif_size,
+					(bw_add(
+						dceip->dmif_request_buffer_size,
+						bw_int_to_fixed(
+							vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel
+								* vbios->number_of_dram_channels)))),
+				bw_int_to_fixed(1));
+	}
+	results->total_dmifmc_urgent_latency = bw_mul(
+		vbios->dmifmc_urgent_latency,
+		results->total_dmifmc_urgent_trips);
+	results->total_display_reads_required_data = bw_int_to_fixed(0);
+	results->total_display_reads_required_dram_access_data =
+		bw_int_to_fixed(0);
+	results->total_display_writes_required_data = bw_int_to_fixed(0);
+	results->total_display_writes_required_dram_access_data =
+		bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->display_reads_required_data =
+					results->adjusted_data_buffer_size_in_memory[i];
+				results->display_reads_required_dram_access_data =
+					bw_mul(
+						results->adjusted_data_buffer_size_in_memory[i],
+						bw_ceil2(
+							bw_div(
+								bw_int_to_fixed(
+									vbios->dram_channel_width_in_bits),
+								results->bytes_per_request[i]),
+							bw_int_to_fixed(1)));
+				if (results->access_one_channel_only[i]) {
+					results->display_reads_required_dram_access_data =
+						bw_mul(
+							results->display_reads_required_dram_access_data,
+							bw_int_to_fixed(
+								vbios->number_of_dram_channels));
+				}
+				results->total_display_reads_required_data =
+					bw_add(
+						results->total_display_reads_required_data,
+						results->display_reads_required_data);
+				results->total_display_reads_required_dram_access_data =
+					bw_add(
+						results->total_display_reads_required_dram_access_data,
+						results->display_reads_required_dram_access_data);
+			} else {
+				results->total_display_writes_required_data =
+					bw_add(
+						results->total_display_writes_required_data,
+						results->adjusted_data_buffer_size_in_memory[i]);
+				results->total_display_writes_required_dram_access_data =
+					bw_add(
+						results->total_display_writes_required_dram_access_data,
+						bw_mul(
+							results->adjusted_data_buffer_size_in_memory[i],
+							bw_ceil2(
+								bw_div(
+									bw_int_to_fixed(
+										vbios->dram_channel_width_in_bits),
+									results->bytes_per_request[i]),
+								bw_int_to_fixed(
+									1))));
+			}
+		}
+	}
+	results->total_display_reads_required_data = bw_add(
+		bw_add(
+			results->total_display_reads_required_data,
+			results->cursor_total_data),
+		bw_mul(
+			results->scatter_gather_total_pte_requests,
+			bw_int_to_fixed(64)));
+	results->total_display_reads_required_dram_access_data = bw_add(
+		bw_add(
+			results->total_display_reads_required_dram_access_data,
+			results->cursor_total_data),
+		bw_mul(
+			results->scatter_gather_total_pte_requests,
+			bw_int_to_fixed(64)));
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_mtn(
+				results->v_filter_init[i],
+				bw_int_to_fixed(4))) {
+				results->src_pixels_for_first_output_pixel[i] =
+					bw_mul(
+						bw_int_to_fixed(4),
+						results->source_width_rounded_up_to_chunks[i]);
+			} else {
+				if (bw_mtn(
+					results->v_filter_init[i],
+					bw_int_to_fixed(2))) {
+					results->src_pixels_for_first_output_pixel[i] =
+						bw_int_to_fixed(512);
+				} else {
+					results->src_pixels_for_first_output_pixel[i] =
+						bw_int_to_fixed(0);
+				}
+			}
+			results->src_data_for_first_output_pixel[i] =
+				bw_div(
+					bw_mul(
+						bw_mul(
+							results->src_pixels_for_first_output_pixel[i],
+							bw_int_to_fixed(
+								results->bytes_per_pixel[i])),
+						results->bytes_per_request[i]),
+					results->useful_bytes_per_request[i]);
+			results->src_pixels_for_last_output_pixel[i] =
+				bw_mul(
+					results->source_width_rounded_up_to_chunks[i],
+					bw_max2(
+						bw_ceil2(
+							results->v_filter_init[i],
+							bw_int_to_fixed(
+								dceip->lines_interleaved_into_lb)),
+						bw_mul(
+							bw_ceil2(
+								results->vsr[i],
+								bw_int_to_fixed(
+									dceip->lines_interleaved_into_lb)),
+							results->horizontal_blank_and_chunk_granularity_factor[i])));
+			results->src_data_for_last_output_pixel[i] =
+				bw_div(
+					bw_mul(
+						bw_mul(
+							bw_mul(
+								results->source_width_rounded_up_to_chunks[i],
+								bw_max2(
+									bw_ceil2(
+										results->v_filter_init[i],
+										bw_int_to_fixed(
+											dceip->lines_interleaved_into_lb)),
+									results->lines_interleaved_in_mem_access[i])),
+							bw_int_to_fixed(
+								results->bytes_per_pixel[i])),
+						results->bytes_per_request[i]),
+					results->useful_bytes_per_request[i]);
+			results->active_time[i] =
+				bw_div(
+					bw_div(
+						results->source_width_rounded_up_to_chunks[i],
+						results->hsr[i]),
+					results->pixel_rate[i]);
+		}
+	}
+	for (i = 0; i <= 2; i++) {
+		for (j = 0; j <= 2; j++) {
+			results->dmif_burst_time[i][j] =
+				bw_max3(
+					results->dmif_total_page_close_open_time,
+					bw_div(
+						results->total_display_reads_required_dram_access_data,
+						(bw_mul(
+							bw_div(
+								bw_mul(
+									yclk[i],
+									bw_int_to_fixed(
+										vbios->dram_channel_width_in_bits)),
+								bw_int_to_fixed(
+									8)),
+							bw_int_to_fixed(
+								vbios->number_of_dram_channels)))),
+					bw_div(
+						results->total_display_reads_required_data,
+						(bw_mul(
+							sclk[j],
+							vbios->data_return_bus_width))));
+			if (mode_data->d1_display_write_back_dwb_enable == 1) {
+				results->mcifwr_burst_time[i][j] =
+					bw_max3(
+						results->mcifwr_total_page_close_open_time,
+						bw_div(
+							results->total_display_writes_required_dram_access_data,
+							(bw_mul(
+								bw_div(
+									bw_mul(
+										yclk[i],
+										bw_int_to_fixed(
+											vbios->dram_channel_width_in_bits)),
+									bw_int_to_fixed(
+										8)),
+								bw_int_to_fixed(
+									vbios->number_of_dram_channels)))),
+						bw_div(
+							results->total_display_writes_required_data,
+							(bw_mul(
+								sclk[j],
+								vbios->data_return_bus_width))));
+			}
+		}
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		for (j = 0; j <= 2; j++) {
+			for (k = 0; k <= 2; k++) {
+				if (results->enable[i]) {
+					if (surface_type[i]
+						!= bw_def_display_write_back420_luma
+						&& surface_type[i]
+							!= bw_def_display_write_back420_chroma) {
+						results->line_source_transfer_time[i][j][k] =
+							bw_max2(
+								bw_mul(
+									(bw_add(
+										results->total_dmifmc_urgent_latency,
+										results->dmif_burst_time[j][k])),
+									bw_floor2(
+										bw_div(
+											results->src_data_for_first_output_pixel[i],
+											results->adjusted_data_buffer_size_in_memory[i]),
+										bw_int_to_fixed(
+											1))),
+								bw_sub(
+									bw_mul(
+										(bw_add(
+											results->total_dmifmc_urgent_latency,
+											results->dmif_burst_time[j][k])),
+										bw_floor2(
+											bw_div(
+												results->src_data_for_last_output_pixel[i],
+												results->adjusted_data_buffer_size_in_memory[i]),
+											bw_int_to_fixed(
+												1))),
+									results->active_time[i]));
+					} else {
+						results->line_source_transfer_time[i][j][k] =
+							bw_max2(
+								bw_mul(
+									(bw_add(
+										vbios->mcifwrmc_urgent_latency,
+										results->mcifwr_burst_time[j][k])),
+									bw_floor2(
+										bw_div(
+											results->src_data_for_first_output_pixel[i],
+											results->adjusted_data_buffer_size_in_memory[i]),
+										bw_int_to_fixed(
+											1))),
+								bw_sub(
+									bw_mul(
+										(bw_add(
+											vbios->mcifwrmc_urgent_latency,
+											results->mcifwr_burst_time[j][k])),
+										bw_floor2(
+											bw_div(
+												results->src_data_for_last_output_pixel[i],
+												results->adjusted_data_buffer_size_in_memory[i]),
+											bw_int_to_fixed(
+												1))),
+									results->active_time[i]));
+					}
+				}
+			}
+		}
+	}
+	/*cpu c-state and p-state change enable*/
+	/*for cpu p-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration*/
+	/*for cpu c-state change to be possible for a yclk(pclk) and sclk level the dispclk required has to be enough for the blackout duration and recovery*/
+	/*condition for the blackout duration:*/
+	/* minimum latency hiding > blackout duration + dmif burst time + line source transfer time*/
+	/*condition for the blackout recovery:*/
+	/* recovery time >  dmif burst time + 2 * urgent latency*/
+	/* recovery time > (display bw * blackout duration  + (2 * urgent latency + dmif burst time)*dispclk - dmif size )*/
+	/*                  / (dispclk - display bw)*/
+	/*the minimum latency hiding is the minimum for all pipes of one screen line time, plus one more line time if doing lb prefetch, plus the dmif data buffer size equivalent in time, minus the urgent latency.*/
+	/*the minimum latency hiding is  further limited by the cursor.  the cursor latency hiding is the number of lines of the cursor buffer, minus one if the downscaling is less than two, or minus three if it is more*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_equ(
+				dceip->stutter_and_dram_clock_state_change_gated_before_cursor,
+				bw_int_to_fixed(0))
+				&& bw_mtn(
+					results->cursor_width_pixels[i],
+					bw_int_to_fixed(0))) {
+				if (bw_ltn(
+					results->vsr[i],
+					bw_int_to_fixed(2))) {
+					results->cursor_latency_hiding[i] =
+						bw_div(
+							bw_div(
+								bw_mul(
+									(bw_sub(
+										dceip->cursor_dcp_buffer_lines,
+										bw_int_to_fixed(
+											1))),
+									results->h_total[i]),
+								results->vsr[i]),
+							results->pixel_rate[i]);
+				} else {
+					results->cursor_latency_hiding[i] =
+						bw_div(
+							bw_div(
+								bw_mul(
+									(bw_sub(
+										dceip->cursor_dcp_buffer_lines,
+										bw_int_to_fixed(
+											3))),
+									results->h_total[i]),
+								results->vsr[i]),
+							results->pixel_rate[i]);
+				}
+			} else {
+				results->cursor_latency_hiding[i] =
+					bw_int_to_fixed(9999);
+			}
+		}
+	}
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (dceip->graphics_lb_nodownscaling_multi_line_prefetching
+				== 1
+				&& (bw_equ(results->vsr[i], bw_int_to_fixed(1))
+					|| (bw_leq(
+						results->vsr[i],
+						bw_frc_to_fixed(8, 10))
+						&& bw_leq(
+							results->v_taps[i],
+							bw_int_to_fixed(2))
+						&& results->lb_bpc[i] == 8))
+				&& surface_type[i] == bw_def_graphics) {
+				results->minimum_latency_hiding[i] =
+					bw_sub(
+						bw_div(
+							bw_mul(
+								bw_div(
+									(bw_add(
+										bw_sub(
+											results->lb_partitions[i],
+											bw_int_to_fixed(
+												1)),
+										bw_div(
+											bw_div(
+												results->data_buffer_size[i],
+												bw_int_to_fixed(
+													results->bytes_per_pixel[i])),
+											results->source_width_pixels[i]))),
+									results->vsr[i]),
+								results->h_total[i]),
+							results->pixel_rate[i]),
+						results->total_dmifmc_urgent_latency);
+			} else {
+				results->minimum_latency_hiding[i] =
+					bw_sub(
+						bw_div(
+							bw_mul(
+								(bw_add(
+									bw_int_to_fixed(
+										1
+											+ results->line_buffer_prefetch[i]),
+									bw_div(
+										bw_div(
+											bw_div(
+												results->data_buffer_size[i],
+												bw_int_to_fixed(
+													results->bytes_per_pixel[i])),
+											results->source_width_pixels[i]),
+										results->vsr[i]))),
+								results->h_total[i]),
+							results->pixel_rate[i]),
+						results->total_dmifmc_urgent_latency);
+			}
+			results->minimum_latency_hiding_with_cursor[i] =
+				bw_min2(
+					results->minimum_latency_hiding[i],
+					results->cursor_latency_hiding[i]);
+		}
+	}
+	for (i = 0; i <= 2; i++) {
+		for (j = 0; j <= 2; j++) {
+			results->blackout_duration_margin[i][j] =
+				bw_int_to_fixed(9999);
+			results->dispclk_required_for_blackout_duration[i][j] =
+				bw_int_to_fixed(0);
+			results->dispclk_required_for_blackout_recovery[i][j] =
+				bw_int_to_fixed(0);
+			for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+				if (results->enable[k]
+					&& bw_mtn(
+						vbios->blackout_duration,
+						bw_int_to_fixed(0))) {
+					if (surface_type[k]
+						!= bw_def_display_write_back420_luma
+						&& surface_type[k]
+							!= bw_def_display_write_back420_chroma) {
+						results->blackout_duration_margin[i][j] =
+							bw_min2(
+								results->blackout_duration_margin[i][j],
+								bw_sub(
+									bw_sub(
+										bw_sub(
+											results->minimum_latency_hiding_with_cursor[k],
+											vbios->blackout_duration),
+										results->dmif_burst_time[i][j]),
+									results->line_source_transfer_time[k][i][j]));
+						results->dispclk_required_for_blackout_duration[i][j] =
+							bw_max3(
+								results->dispclk_required_for_blackout_duration[i][j],
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_first_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_sub(
+										bw_sub(
+											results->minimum_latency_hiding_with_cursor[k],
+											vbios->blackout_duration),
+										results->dmif_burst_time[i][j]))),
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_last_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_add(
+										bw_sub(
+											bw_sub(
+												results->minimum_latency_hiding_with_cursor[k],
+												vbios->blackout_duration),
+											results->dmif_burst_time[i][j]),
+										results->active_time[k]))));
+						if (bw_leq(
+							vbios->maximum_blackout_recovery_time,
+							bw_add(
+								bw_mul(
+									bw_int_to_fixed(
+										2),
+									results->total_dmifmc_urgent_latency),
+								results->dmif_burst_time[i][j]))) {
+							results->dispclk_required_for_blackout_recovery[i][j] =
+								bw_int_to_fixed(
+									9999);
+						} else if (bw_ltn(
+							results->adjusted_data_buffer_size[k],
+							bw_mul(
+								bw_div(
+									bw_mul(
+										results->display_bandwidth[k],
+										results->useful_bytes_per_request[k]),
+									results->bytes_per_request[k]),
+								(bw_add(
+									vbios->blackout_duration,
+									bw_add(
+										bw_mul(
+											bw_int_to_fixed(
+												2),
+											results->total_dmifmc_urgent_latency),
+										results->dmif_burst_time[i][j])))))) {
+							results->dispclk_required_for_blackout_recovery[i][j] =
+								bw_max2(
+									results->dispclk_required_for_blackout_recovery[i][j],
+									bw_div(
+										bw_mul(
+											bw_div(
+												bw_div(
+													(bw_sub(
+														bw_mul(
+															bw_div(
+																bw_mul(
+																	results->display_bandwidth[k],
+																	results->useful_bytes_per_request[k]),
+																results->bytes_per_request[k]),
+															(bw_add(
+																vbios->blackout_duration,
+																vbios->maximum_blackout_recovery_time))),
+														results->adjusted_data_buffer_size[k])),
+													bw_int_to_fixed(
+														results->bytes_per_pixel[k])),
+												(bw_sub(
+													vbios->maximum_blackout_recovery_time,
+													bw_sub(
+														bw_mul(
+															bw_int_to_fixed(
+																2),
+															results->total_dmifmc_urgent_latency),
+														results->dmif_burst_time[i][j])))),
+											results->latency_hiding_lines[k]),
+										results->lines_interleaved_in_mem_access[k]));
+						}
+					} else {
+						results->blackout_duration_margin[i][j] =
+							bw_min2(
+								results->blackout_duration_margin[i][j],
+								bw_sub(
+									bw_sub(
+										bw_sub(
+											bw_sub(
+												results->minimum_latency_hiding_with_cursor[k],
+												vbios->blackout_duration),
+											results->dmif_burst_time[i][j]),
+										results->mcifwr_burst_time[i][j]),
+									results->line_source_transfer_time[k][i][j]));
+						results->dispclk_required_for_blackout_duration[i][j] =
+							bw_max3(
+								results->dispclk_required_for_blackout_duration[i][j],
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_first_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_sub(
+										bw_sub(
+											bw_sub(
+												results->minimum_latency_hiding_with_cursor[k],
+												vbios->blackout_duration),
+											results->dmif_burst_time[i][j]),
+										results->mcifwr_burst_time[i][j]))),
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_last_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_add(
+										bw_sub(
+											bw_sub(
+												bw_sub(
+													results->minimum_latency_hiding_with_cursor[k],
+													vbios->blackout_duration),
+												results->dmif_burst_time[i][j]),
+											results->mcifwr_burst_time[i][j]),
+										results->active_time[k]))));
+						if (bw_ltn(
+							vbios->maximum_blackout_recovery_time,
+							bw_add(
+								bw_add(
+									bw_mul(
+										bw_int_to_fixed(
+											2),
+										vbios->mcifwrmc_urgent_latency),
+									results->dmif_burst_time[i][j]),
+								results->mcifwr_burst_time[i][j]))) {
+							results->dispclk_required_for_blackout_recovery[i][j] =
+								bw_int_to_fixed(
+									9999);
+						} else if (bw_ltn(
+							results->adjusted_data_buffer_size[k],
+							bw_mul(
+								bw_div(
+									bw_mul(
+										results->display_bandwidth[k],
+										results->useful_bytes_per_request[k]),
+									results->bytes_per_request[k]),
+								(bw_add(
+									vbios->blackout_duration,
+									bw_add(
+										bw_mul(
+											bw_int_to_fixed(
+												2),
+											results->total_dmifmc_urgent_latency),
+										results->dmif_burst_time[i][j])))))) {
+							results->dispclk_required_for_blackout_recovery[i][j] =
+								bw_max2(
+									results->dispclk_required_for_blackout_recovery[i][j],
+									bw_div(
+										bw_mul(
+											bw_div(
+												bw_div(
+													(bw_sub(
+														bw_mul(
+															bw_div(
+																bw_mul(
+																	results->display_bandwidth[k],
+																	results->useful_bytes_per_request[k]),
+																results->bytes_per_request[k]),
+															(bw_add(
+																vbios->blackout_duration,
+																vbios->maximum_blackout_recovery_time))),
+														results->adjusted_data_buffer_size[k])),
+													bw_int_to_fixed(
+														results->bytes_per_pixel[k])),
+												(bw_sub(
+													vbios->maximum_blackout_recovery_time,
+													(bw_add(
+														bw_mul(
+															bw_int_to_fixed(
+																2),
+															results->total_dmifmc_urgent_latency),
+														results->dmif_burst_time[i][j]))))),
+											results->latency_hiding_lines[k]),
+										results->lines_interleaved_in_mem_access[k]));
+						}
+					}
+				}
+			}
+		}
+	}
+	if (bw_mtn(
+		results->blackout_duration_margin[high][high],
+		bw_int_to_fixed(0))
+		&& bw_ltn(
+			results->dispclk_required_for_blackout_duration[high][high],
+			vbios->high_voltage_max_dispclk)) {
+		results->cpup_state_change_enable = bw_def_yes;
+		if (bw_ltn(
+			results->dispclk_required_for_blackout_recovery[high][high],
+			vbios->high_voltage_max_dispclk)) {
+			results->cpuc_state_change_enable = bw_def_yes;
+		} else {
+			results->cpuc_state_change_enable = bw_def_no;
+		}
+	} else {
+		results->cpup_state_change_enable = bw_def_no;
+		results->cpuc_state_change_enable = bw_def_no;
+	}
+	/*nb p-state change enable*/
+	/*for dram speed/p-state change to be possible for a yclk(pclk) and sclk level there has to be positive margin and the dispclk required has to be below the maximum.*/
+	/*the dram speed/p-state change margin is the minimum for all surfaces of the maximum latency hiding minus the dram speed/p-state change latency, minus the dmif burst time, minus the source line transfer time*/
+	/*the maximum latency hiding is the minimum latency hiding plus one source line used for de-tiling in the line buffer, plus half the urgent latency*/
+	/*if stutter and dram clock state change are gated before cursor then the cursor latency hiding does not limit stutter or dram clock state change*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (mode_data->number_of_displays <= 1
+				|| mode_data->display_synchronization_enabled
+					== bw_def_yes) {
+				results->maximum_latency_hiding[i] =
+					bw_int_to_fixed(450);
+			} else {
+				results->maximum_latency_hiding[i] =
+					bw_add(
+						results->minimum_latency_hiding[i],
+						bw_add(
+							bw_div(
+								bw_mul(
+									bw_div(
+										bw_int_to_fixed(
+											1),
+										results->vsr[i]),
+									results->h_total[i]),
+								results->pixel_rate[i]),
+							bw_mul(
+								bw_frc_to_fixed(
+									5,
+									10),
+								results->total_dmifmc_urgent_latency)));
+			}
+			results->maximum_latency_hiding_with_cursor[i] =
+				bw_min2(
+					results->maximum_latency_hiding[i],
+					results->cursor_latency_hiding[i]);
+		}
+	}
+	for (i = 0; i <= 2; i++) {
+		for (j = 0; j <= 2; j++) {
+			results->dram_speed_change_margin[i][j] =
+				bw_int_to_fixed(9999);
+			results->dispclk_required_for_dram_speed_change[i][j] =
+				bw_int_to_fixed(0);
+			for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+				if (results->enable[k]) {
+					if (surface_type[k]
+						!= bw_def_display_write_back420_luma
+						&& surface_type[k]
+							!= bw_def_display_write_back420_chroma) {
+						results->dram_speed_change_margin[i][j] =
+							bw_min2(
+								results->dram_speed_change_margin[i][j],
+								bw_sub(
+									bw_sub(
+										bw_sub(
+											results->maximum_latency_hiding_with_cursor[k],
+											vbios->nbp_state_change_latency),
+										results->dmif_burst_time[i][j]),
+									results->line_source_transfer_time[k][i][j]));
+						results->dispclk_required_for_dram_speed_change[i][j] =
+							bw_max3(
+								results->dispclk_required_for_dram_speed_change[i][j],
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_first_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_sub(
+										bw_sub(
+											results->maximum_latency_hiding_with_cursor[k],
+											vbios->nbp_state_change_latency),
+										results->dmif_burst_time[i][j]))),
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_last_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_add(
+										bw_sub(
+											bw_sub(
+												results->maximum_latency_hiding_with_cursor[k],
+												vbios->nbp_state_change_latency),
+											results->dmif_burst_time[i][j]),
+										results->active_time[k]))));
+					} else {
+						results->dram_speed_change_margin[i][j] =
+							bw_min2(
+								results->dram_speed_change_margin[i][j],
+								bw_sub(
+									bw_sub(
+										bw_sub(
+											bw_sub(
+												results->maximum_latency_hiding_with_cursor[k],
+												vbios->nbp_state_change_latency),
+											results->dmif_burst_time[i][j]),
+										results->mcifwr_burst_time[i][j]),
+									results->line_source_transfer_time[k][i][j]));
+						results->dispclk_required_for_dram_speed_change[i][j] =
+							bw_max3(
+								results->dispclk_required_for_dram_speed_change[i][j],
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_first_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_sub(
+										bw_sub(
+											bw_sub(
+												results->maximum_latency_hiding_with_cursor[k],
+												vbios->nbp_state_change_latency),
+											results->dmif_burst_time[i][j]),
+										results->mcifwr_burst_time[i][j]))),
+								bw_div(
+									bw_div(
+										bw_mul(
+											results->src_pixels_for_last_output_pixel[k],
+											dceip->display_pipe_throughput_factor),
+										dceip->lb_write_pixels_per_dispclk),
+									(bw_add(
+										bw_sub(
+											bw_sub(
+												bw_sub(
+													results->maximum_latency_hiding_with_cursor[k],
+													vbios->nbp_state_change_latency),
+												results->dmif_burst_time[i][j]),
+											results->mcifwr_burst_time[i][j]),
+										results->active_time[k]))));
+					}
+				}
+			}
+		}
+	}
+	if (bw_mtn(
+		results->dram_speed_change_margin[high][high],
+		bw_int_to_fixed(0))
+		&& bw_ltn(
+			results->dispclk_required_for_dram_speed_change[high][high],
+			vbios->high_voltage_max_dispclk)) {
+		results->nbp_state_change_enable = bw_def_yes;
+	} else {
+		results->nbp_state_change_enable = bw_def_no;
+	}
+	/*required yclk(pclk)*/
+	/*yclk requirement only makes sense if the dmif and mcifwr data total page close-open time is less than the time for data transfer and the total pte requests fit in the scatter-gather saw queque size*/
+	/*if that is the case, the yclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/low yclk(pclk) is chosen accordingly*/
+	/*high yclk(pclk) has to be selected when dram speed/p-state change is not possible.*/
+	results->min_cursor_memory_interface_buffer_size_in_time =
+		bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_mtn(
+				results->cursor_width_pixels[i],
+				bw_int_to_fixed(0))) {
+				results->min_cursor_memory_interface_buffer_size_in_time =
+					bw_min2(
+						results->min_cursor_memory_interface_buffer_size_in_time,
+						bw_div(
+							bw_mul(
+								bw_div(
+									bw_div(
+										dceip->cursor_memory_interface_buffer_pixels,
+										results->cursor_width_pixels[i]),
+									results->vsr[i]),
+								results->h_total[i]),
+							results->pixel_rate[i]));
+			}
+		}
+	}
+	results->min_read_buffer_size_in_time = bw_min2(
+		results->min_cursor_memory_interface_buffer_size_in_time,
+		results->min_dmif_size_in_time);
+	results->display_reads_time_for_data_transfer = bw_sub(
+		results->min_read_buffer_size_in_time,
+		results->total_dmifmc_urgent_latency);
+	results->display_writes_time_for_data_transfer = bw_sub(
+		results->min_mcifwr_size_in_time,
+		vbios->mcifwrmc_urgent_latency);
+	results->dmif_required_dram_bandwidth = bw_div(
+		results->total_display_reads_required_dram_access_data,
+		results->display_reads_time_for_data_transfer);
+	results->mcifwr_required_dram_bandwidth = bw_div(
+		results->total_display_writes_required_dram_access_data,
+		results->display_writes_time_for_data_transfer);
+	results->required_dmifmc_urgent_latency_for_page_close_open = bw_div(
+		(bw_sub(
+			results->min_read_buffer_size_in_time,
+			results->dmif_total_page_close_open_time)),
+		results->total_dmifmc_urgent_trips);
+	results->required_mcifmcwr_urgent_latency = bw_sub(
+		results->min_mcifwr_size_in_time,
+		results->mcifwr_total_page_close_open_time);
+	if (bw_mtn(
+		results->scatter_gather_total_pte_requests,
+		dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) {
+		results->required_dram_bandwidth_gbyte_per_second =
+			bw_int_to_fixed(9999);
+		yclk_message =
+			bw_def_exceeded_allowed_outstanding_pte_req_queue_size;
+		results->y_clk_level = high;
+		results->dram_bandwidth =
+			bw_mul(
+				bw_div(
+					bw_mul(
+						yclk[high],
+						bw_int_to_fixed(
+							vbios->dram_channel_width_in_bits)),
+					bw_int_to_fixed(8)),
+				bw_int_to_fixed(
+					vbios->number_of_dram_channels));
+	} else if (bw_mtn(
+		vbios->dmifmc_urgent_latency,
+		results->required_dmifmc_urgent_latency_for_page_close_open)
+		|| bw_mtn(
+			vbios->mcifwrmc_urgent_latency,
+			results->required_mcifmcwr_urgent_latency)) {
+		results->required_dram_bandwidth_gbyte_per_second =
+			bw_int_to_fixed(9999);
+		yclk_message = bw_def_exceeded_allowed_page_close_open;
+		results->y_clk_level = high;
+		results->dram_bandwidth =
+			bw_mul(
+				bw_div(
+					bw_mul(
+						yclk[high],
+						bw_int_to_fixed(
+							vbios->dram_channel_width_in_bits)),
+					bw_int_to_fixed(8)),
+				bw_int_to_fixed(
+					vbios->number_of_dram_channels));
+	} else {
+		results->required_dram_bandwidth_gbyte_per_second = bw_div(
+			bw_max2(
+				results->dmif_required_dram_bandwidth,
+				results->mcifwr_required_dram_bandwidth),
+			bw_int_to_fixed(1000));
+		if (bw_ltn(
+			bw_mul(
+				results->required_dram_bandwidth_gbyte_per_second,
+				bw_int_to_fixed(1000)),
+			bw_mul(
+				bw_div(
+					bw_mul(
+						yclk[low],
+						bw_int_to_fixed(
+							vbios->dram_channel_width_in_bits)),
+					bw_int_to_fixed(8)),
+				bw_int_to_fixed(
+					vbios->number_of_dram_channels)))
+			&& (results->cpup_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[low][high],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[low][high],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->cpuc_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[low][high],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[low][high],
+						vbios->high_voltage_max_dispclk)
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_recovery[low][high],
+						vbios->high_voltage_max_dispclk)))
+			&& bw_mtn(
+				results->dram_speed_change_margin[low][high],
+				bw_int_to_fixed(0))
+			&& bw_ltn(
+				results->dispclk_required_for_dram_speed_change[low][high],
+				vbios->high_voltage_max_dispclk)) {
+			yclk_message = bw_def_low;
+			results->y_clk_level = low;
+			results->dram_bandwidth =
+				bw_mul(
+					bw_div(
+						bw_mul(
+							yclk[low],
+							bw_int_to_fixed(
+								vbios->dram_channel_width_in_bits)),
+						bw_int_to_fixed(8)),
+					bw_int_to_fixed(
+						vbios->number_of_dram_channels));
+		} else if (bw_ltn(
+			bw_mul(
+				results->required_dram_bandwidth_gbyte_per_second,
+				bw_int_to_fixed(1000)),
+			bw_mul(
+				bw_div(
+					bw_mul(
+						yclk[high],
+						bw_int_to_fixed(
+							vbios->dram_channel_width_in_bits)),
+					bw_int_to_fixed(8)),
+				bw_int_to_fixed(
+					vbios->number_of_dram_channels)))) {
+			yclk_message = bw_def_high;
+			results->y_clk_level = high;
+			results->dram_bandwidth =
+				bw_mul(
+					bw_div(
+						bw_mul(
+							yclk[high],
+							bw_int_to_fixed(
+								vbios->dram_channel_width_in_bits)),
+						bw_int_to_fixed(8)),
+					bw_int_to_fixed(
+						vbios->number_of_dram_channels));
+		} else {
+			yclk_message = bw_def_exceeded_allowed_maximum_bw;
+			results->y_clk_level = high;
+			results->dram_bandwidth =
+				bw_mul(
+					bw_div(
+						bw_mul(
+							yclk[high],
+							bw_int_to_fixed(
+								vbios->dram_channel_width_in_bits)),
+						bw_int_to_fixed(8)),
+					bw_int_to_fixed(
+						vbios->number_of_dram_channels));
+		}
+	}
+	/*required sclk*/
+	/*sclk requirement only makes sense if the total pte requests fit in the scatter-gather saw queque size*/
+	/*if that is the case, the sclk requirement is the maximum of the ones required by dmif and mcifwr, and the high/mid/low sclk is chosen accordingly, unless that choice results in foresaking dram speed/nb p-state change.*/
+	/*the dmif and mcifwr sclk required is the one that allows the transfer of all pipe's data buffer size through the sclk bus in the time for data transfer*/
+	/*for dmif, pte and cursor requests have to be included.*/
+	results->dmif_required_sclk = bw_div(
+		bw_div(
+			results->total_display_reads_required_data,
+			results->display_reads_time_for_data_transfer),
+		vbios->data_return_bus_width);
+	results->mcifwr_required_sclk = bw_div(
+		bw_div(
+			results->total_display_writes_required_data,
+			results->display_writes_time_for_data_transfer),
+		vbios->data_return_bus_width);
+	if (bw_mtn(
+		results->scatter_gather_total_pte_requests,
+		dceip->maximum_total_outstanding_pte_requests_allowed_by_saw)) {
+		results->required_sclk = bw_int_to_fixed(9999);
+		sclk_message =
+			bw_def_exceeded_allowed_outstanding_pte_req_queue_size;
+		results->sclk_level = high;
+	} else if (bw_mtn(
+		vbios->dmifmc_urgent_latency,
+		results->required_dmifmc_urgent_latency_for_page_close_open)
+		|| bw_mtn(
+			vbios->mcifwrmc_urgent_latency,
+			results->required_mcifmcwr_urgent_latency)) {
+		results->required_sclk = bw_int_to_fixed(9999);
+		sclk_message = bw_def_exceeded_allowed_page_close_open;
+		results->sclk_level = high;
+	} else {
+		results->required_sclk = bw_max2(
+			results->dmif_required_sclk,
+			results->mcifwr_required_sclk);
+		if (bw_ltn(results->required_sclk, sclk[low])
+			&& (results->cpup_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[results->y_clk_level][low],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[results->y_clk_level][low],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->cpuc_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[results->y_clk_level][low],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[results->y_clk_level][low],
+						vbios->high_voltage_max_dispclk)
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_recovery[results->y_clk_level][low],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->nbp_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->dram_speed_change_margin[results->y_clk_level][low],
+					bw_int_to_fixed(0))
+					&& bw_leq(
+						results->dispclk_required_for_dram_speed_change[results->y_clk_level][low],
+						vbios->high_voltage_max_dispclk)))) {
+			sclk_message = bw_def_low;
+			results->sclk_level = low;
+		} else if (bw_ltn(results->required_sclk, sclk[mid])
+			&& (results->cpup_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[results->y_clk_level][mid],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[results->y_clk_level][mid],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->cpuc_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->blackout_duration_margin[results->y_clk_level][mid],
+					bw_int_to_fixed(0))
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_duration[results->y_clk_level][mid],
+						vbios->high_voltage_max_dispclk)
+					&& bw_ltn(
+						results->dispclk_required_for_blackout_recovery[results->y_clk_level][mid],
+						vbios->high_voltage_max_dispclk)))
+			&& (results->nbp_state_change_enable == bw_def_no
+				|| (bw_mtn(
+					results->dram_speed_change_margin[results->y_clk_level][mid],
+					bw_int_to_fixed(0))
+					&& bw_leq(
+						results->dispclk_required_for_dram_speed_change[results->y_clk_level][mid],
+						vbios->high_voltage_max_dispclk)))) {
+			sclk_message = bw_def_mid;
+			results->sclk_level = mid;
+		} else if (bw_ltn(results->required_sclk, sclk[high])) {
+			sclk_message = bw_def_high;
+			results->sclk_level = high;
+		} else {
+			sclk_message = bw_def_exceeded_allowed_maximum_sclk;
+			results->sclk_level = high;
+		}
+	}
+	/*dispclk*/
+	/*if dispclk is set to the maximum, ramping is not required.  dispclk required without ramping is less than the dispclk required with ramping.*/
+	/*if dispclk required without ramping is more than the maximum dispclk, that is the dispclk required, and the mode is not supported*/
+	/*if that does not happen, but dispclk required with ramping is more than the maximum dispclk, dispclk required is just the maximum dispclk*/
+	/*if that does not happen either, dispclk required is the dispclk required with ramping.*/
+	/*dispclk required without ramping is the maximum of the one required for display pipe pixel throughput, for scaler throughput, for total read request thrrougput and for dram/np p-state change if enabled.*/
+	/*the display pipe pixel throughput is the maximum of lines in per line out in the beginning of the frame and lines in per line out in the middle of the frame multiplied by the horizontal blank and chunk granularity factor, altogether multiplied by the ratio of the source width to the line time, divided by the line buffer pixels per dispclk throughput, and multiplied by the display pipe throughput factor.*/
+	/*the horizontal blank and chunk granularity factor is the ratio of the line time divided by the line time minus half the horizontal blank and chunk time.  it applies when the lines in per line out is not 2 or 4.*/
+	/*the dispclk required for scaler throughput is the product of the pixel rate and the scaling limits factor.*/
+	/*the dispclk required for total read request throughput is the product of the peak request-per-second bandwidth and the dispclk cycles per request, divided by the request efficiency.*/
+	/*for the dispclk required with ramping, instead of multiplying just the pipe throughput by the display pipe throughput factor, we multiply the scaler and pipe throughput by the ramping factor.*/
+	/*the scaling limits factor is the product of the horizontal scale ratio, and the ratio of the vertical taps divided by the scaler efficiency clamped to at least 1.*/
+	/*the scaling limits factor itself it also clamped to at least 1*/
+	/*if doing downscaling with the pre-downscaler enabled, the horizontal scale ratio should not be considered above (use "1")*/
+	results->downspread_factor = bw_add(
+		bw_int_to_fixed(1),
+		bw_div(vbios->down_spread_percentage, bw_int_to_fixed(100)));
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] == bw_def_graphics) {
+				switch (results->lb_bpc[i]) {
+				case 6:
+					results->v_scaler_efficiency =
+						dceip->graphics_vscaler_efficiency6_bit_per_component;
+					break;
+				case 8:
+					results->v_scaler_efficiency =
+						dceip->graphics_vscaler_efficiency8_bit_per_component;
+					break;
+				case 10:
+					results->v_scaler_efficiency =
+						dceip->graphics_vscaler_efficiency10_bit_per_component;
+					break;
+				default:
+					results->v_scaler_efficiency =
+						dceip->graphics_vscaler_efficiency12_bit_per_component;
+					break;
+				}
+				if (results->use_alpha[i] == 1) {
+					results->v_scaler_efficiency =
+						bw_min2(
+							results->v_scaler_efficiency,
+							dceip->alpha_vscaler_efficiency);
+				}
+			} else {
+				switch (results->lb_bpc[i]) {
+				case 6:
+					results->v_scaler_efficiency =
+						dceip->underlay_vscaler_efficiency6_bit_per_component;
+					break;
+				case 8:
+					results->v_scaler_efficiency =
+						dceip->underlay_vscaler_efficiency8_bit_per_component;
+					break;
+				case 10:
+					results->v_scaler_efficiency =
+						dceip->underlay_vscaler_efficiency10_bit_per_component;
+					break;
+				default:
+					results->v_scaler_efficiency =
+						dceip->underlay_vscaler_efficiency12_bit_per_component;
+					break;
+				}
+			}
+			if (dceip->pre_downscaler_enabled
+				&& bw_mtn(
+					results->hsr[i],
+					bw_int_to_fixed(1))) {
+				results->scaler_limits_factor =
+					bw_max2(
+						bw_div(
+							results->v_taps[i],
+							results->v_scaler_efficiency),
+						bw_div(
+							results->source_width_rounded_up_to_chunks[i],
+							results->h_total[i]));
+			} else {
+				results->scaler_limits_factor =
+					bw_max3(
+						bw_int_to_fixed(1),
+						bw_ceil2(
+							bw_div(
+								results->h_taps[i],
+								bw_int_to_fixed(
+									4)),
+							bw_int_to_fixed(1)),
+						bw_mul(
+							results->hsr[i],
+							bw_max2(
+								bw_div(
+									results->v_taps[i],
+									results->v_scaler_efficiency),
+								bw_int_to_fixed(
+									1))));
+			}
+			results->display_pipe_pixel_throughput =
+				bw_div(
+					bw_div(
+						bw_mul(
+							bw_max2(
+								results->lb_lines_in_per_line_out_in_beginning_of_frame[i],
+								bw_mul(
+									results->lb_lines_in_per_line_out_in_middle_of_frame[i],
+									results->horizontal_blank_and_chunk_granularity_factor[i])),
+							results->source_width_rounded_up_to_chunks[i]),
+						(bw_div(
+							results->h_total[i],
+							results->pixel_rate[i]))),
+					dceip->lb_write_pixels_per_dispclk);
+			results->dispclk_required_without_ramping[i] =
+				bw_mul(
+					results->downspread_factor,
+					bw_max2(
+						bw_mul(
+							results->pixel_rate[i],
+							results->scaler_limits_factor),
+						bw_mul(
+							dceip->display_pipe_throughput_factor,
+							results->display_pipe_pixel_throughput)));
+			results->dispclk_required_with_ramping[i] =
+				bw_mul(
+					dceip->dispclk_ramping_factor,
+					bw_max2(
+						bw_mul(
+							results->pixel_rate[i],
+							results->scaler_limits_factor),
+						results->display_pipe_pixel_throughput));
+		}
+	}
+	results->total_dispclk_required_with_ramping = bw_int_to_fixed(0);
+	results->total_dispclk_required_without_ramping = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_ltn(
+				results->total_dispclk_required_with_ramping,
+				results->dispclk_required_with_ramping[i])) {
+				results->total_dispclk_required_with_ramping =
+					results->dispclk_required_with_ramping[i];
+			}
+			if (bw_ltn(
+				results->total_dispclk_required_without_ramping,
+				results->dispclk_required_without_ramping[i])) {
+				results->total_dispclk_required_without_ramping =
+					results->dispclk_required_without_ramping[i];
+			}
+		}
+	}
+	results->total_read_request_bandwidth = bw_int_to_fixed(0);
+	results->total_write_request_bandwidth = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->total_read_request_bandwidth = bw_add(
+					results->total_read_request_bandwidth,
+					results->request_bandwidth[i]);
+			} else {
+				results->total_write_request_bandwidth = bw_add(
+					results->total_write_request_bandwidth,
+					results->request_bandwidth[i]);
+			}
+		}
+	}
+	results->dispclk_required_for_total_read_request_bandwidth = bw_div(
+		bw_mul(
+			results->total_read_request_bandwidth,
+			dceip->dispclk_per_request),
+		dceip->request_efficiency);
+	if (dceip->dcfclk_request_generation == 0) {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_with_ramping,
+				results->dispclk_required_for_total_read_request_bandwidth);
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_without_ramping,
+				results->dispclk_required_for_total_read_request_bandwidth);
+	} else {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			results->total_dispclk_required_with_ramping;
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			results->total_dispclk_required_without_ramping;
+	}
+	if (results->cpuc_state_change_enable == bw_def_yes) {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			bw_max3(
+				results->total_dispclk_required_with_ramping_with_request_bandwidth,
+				results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level],
+				results->dispclk_required_for_blackout_recovery[results->y_clk_level][results->sclk_level]);
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			bw_max3(
+				results->total_dispclk_required_without_ramping_with_request_bandwidth,
+				results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level],
+				results->dispclk_required_for_blackout_recovery[results->y_clk_level][results->sclk_level]);
+	}
+	if (results->cpup_state_change_enable == bw_def_yes) {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_with_ramping_with_request_bandwidth,
+				results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level]);
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_without_ramping_with_request_bandwidth,
+				results->dispclk_required_for_blackout_duration[results->y_clk_level][results->sclk_level]);
+	}
+	if (results->nbp_state_change_enable == bw_def_yes) {
+		results->total_dispclk_required_with_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_with_ramping_with_request_bandwidth,
+				results->dispclk_required_for_dram_speed_change[results->y_clk_level][results->sclk_level]);
+		results->total_dispclk_required_without_ramping_with_request_bandwidth =
+			bw_max2(
+				results->total_dispclk_required_without_ramping_with_request_bandwidth,
+				results->dispclk_required_for_dram_speed_change[results->y_clk_level][results->sclk_level]);
+	}
+	if (bw_ltn(
+		results->total_dispclk_required_with_ramping_with_request_bandwidth,
+		vbios->high_voltage_max_dispclk)) {
+		results->dispclk =
+			results->total_dispclk_required_with_ramping_with_request_bandwidth;
+	} else if (bw_ltn(
+		results->total_dispclk_required_without_ramping_with_request_bandwidth,
+		vbios->high_voltage_max_dispclk)) {
+		results->dispclk = vbios->high_voltage_max_dispclk;
+	} else {
+		results->dispclk =
+			results->total_dispclk_required_without_ramping_with_request_bandwidth;
+	}
+	/* required core voltage*/
+	/* the core voltage required is low if sclk, yclk(pclk)and dispclk are within the low limits*/
+	/* otherwise, the core voltage required is medium if yclk (pclk) is within the low limit and sclk and dispclk are within the medium limit*/
+	/* otherwise, the core voltage required is high if the three clocks are within the high limits*/
+	/* otherwise, or if the mode is not supported, core voltage requirement is not applicable*/
+	if (pipe_check == bw_def_notok) {
+		voltage = bw_def_na;
+	} else if (mode_check == bw_def_notok) {
+		voltage = bw_def_notok;
+	} else if (yclk_message == bw_def_low && sclk_message == bw_def_low
+		&& bw_ltn(results->dispclk, vbios->low_voltage_max_dispclk)) {
+		voltage = bw_def_low;
+	} else if (yclk_message == bw_def_low
+		&& (sclk_message == bw_def_low || sclk_message == bw_def_mid)
+		&& bw_ltn(results->dispclk, vbios->mid_voltage_max_dispclk)) {
+		voltage = bw_def_mid;
+	} else if ((yclk_message == bw_def_low || yclk_message == bw_def_high)
+		&& (sclk_message == bw_def_low || sclk_message == bw_def_mid
+			|| sclk_message == bw_def_high)
+		&& bw_leq(results->dispclk, vbios->high_voltage_max_dispclk)) {
+		if (results->nbp_state_change_enable == bw_def_yes) {
+			voltage = bw_def_high;
+		} else {
+			voltage = bw_def_high_no_nbp_state_change;
+		}
+	} else {
+		voltage = bw_def_notok;
+	}
+	/*required blackout recovery time*/
+	results->blackout_recovery_time = bw_int_to_fixed(0);
+	for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
+		if (results->enable[k]
+			&& bw_mtn(vbios->blackout_duration, bw_int_to_fixed(0))
+			&& results->cpup_state_change_enable == bw_def_yes) {
+			if (surface_type[k] != bw_def_display_write_back420_luma
+				&& surface_type[k]
+					!= bw_def_display_write_back420_chroma) {
+				results->blackout_recovery_time =
+					bw_max2(
+						results->blackout_recovery_time,
+						bw_add(
+							bw_mul(
+								bw_int_to_fixed(
+									2),
+								results->total_dmifmc_urgent_latency),
+							results->dmif_burst_time[results->y_clk_level][results->sclk_level]));
+				if (bw_ltn(
+					results->adjusted_data_buffer_size[k],
+					bw_mul(
+						bw_div(
+							bw_mul(
+								results->display_bandwidth[k],
+								results->useful_bytes_per_request[k]),
+							results->bytes_per_request[k]),
+						(bw_add(
+							vbios->blackout_duration,
+							bw_add(
+								bw_mul(
+									bw_int_to_fixed(
+										2),
+									results->total_dmifmc_urgent_latency),
+								results->dmif_burst_time[results->y_clk_level][results->sclk_level])))))) {
+					results->blackout_recovery_time =
+						bw_max2(
+							results->blackout_recovery_time,
+							bw_div(
+								(bw_add(
+									bw_mul(
+										bw_div(
+											bw_mul(
+												results->display_bandwidth[k],
+												results->useful_bytes_per_request[k]),
+											results->bytes_per_request[k]),
+										vbios->blackout_duration),
+									bw_sub(
+										bw_div(
+											bw_mul(
+												bw_mul(
+													bw_mul(
+														(bw_add(
+															bw_mul(
+																bw_int_to_fixed(
+																	2),
+																results->total_dmifmc_urgent_latency),
+															results->dmif_burst_time[results->y_clk_level][results->sclk_level])),
+														results->dispclk),
+													bw_int_to_fixed(
+														results->bytes_per_pixel[k])),
+												results->lines_interleaved_in_mem_access[k]),
+											results->latency_hiding_lines[k]),
+										results->adjusted_data_buffer_size[k]))),
+								(bw_sub(
+									bw_div(
+										bw_mul(
+											bw_mul(
+												results->dispclk,
+												bw_int_to_fixed(
+													results->bytes_per_pixel[k])),
+											results->lines_interleaved_in_mem_access[k]),
+										results->latency_hiding_lines[k]),
+									bw_div(
+										bw_mul(
+											results->display_bandwidth[k],
+											results->useful_bytes_per_request[k]),
+										results->bytes_per_request[k])))));
+				}
+			} else {
+				results->blackout_recovery_time =
+					bw_max2(
+						results->blackout_recovery_time,
+						bw_add(
+							bw_mul(
+								bw_int_to_fixed(
+									2),
+								vbios->mcifwrmc_urgent_latency),
+							results->mcifwr_burst_time[results->y_clk_level][results->sclk_level]));
+				if (bw_ltn(
+					results->adjusted_data_buffer_size[k],
+					bw_mul(
+						bw_div(
+							bw_mul(
+								results->display_bandwidth[k],
+								results->useful_bytes_per_request[k]),
+							results->bytes_per_request[k]),
+						(bw_add(
+							vbios->blackout_duration,
+							bw_add(
+								bw_mul(
+									bw_int_to_fixed(
+										2),
+									vbios->mcifwrmc_urgent_latency),
+								results->mcifwr_burst_time[results->y_clk_level][results->sclk_level])))))) {
+					results->blackout_recovery_time =
+						bw_max2(
+							results->blackout_recovery_time,
+							bw_div(
+								(bw_add(
+									bw_mul(
+										bw_div(
+											bw_mul(
+												results->display_bandwidth[k],
+												results->useful_bytes_per_request[k]),
+											results->bytes_per_request[k]),
+										vbios->blackout_duration),
+									bw_sub(
+										bw_div(
+											bw_mul(
+												bw_mul(
+													bw_mul(
+														(bw_add(
+															bw_add(
+																bw_mul(
+																	bw_int_to_fixed(
+																		2),
+																	vbios->mcifwrmc_urgent_latency),
+																results->dmif_burst_time[i][j]),
+															results->mcifwr_burst_time[results->y_clk_level][results->sclk_level])),
+														results->dispclk),
+													bw_int_to_fixed(
+														results->bytes_per_pixel[k])),
+												results->lines_interleaved_in_mem_access[k]),
+											results->latency_hiding_lines[k]),
+										results->adjusted_data_buffer_size[k]))),
+								(bw_sub(
+									bw_div(
+										bw_mul(
+											bw_mul(
+												results->dispclk,
+												bw_int_to_fixed(
+													results->bytes_per_pixel[k])),
+											results->lines_interleaved_in_mem_access[k]),
+										results->latency_hiding_lines[k]),
+									bw_div(
+										bw_mul(
+											results->display_bandwidth[k],
+											results->useful_bytes_per_request[k]),
+										results->bytes_per_request[k])))));
+				}
+			}
+		}
+	}
+	/*sclk deep sleep*/
+	/*during self-refresh, sclk can be reduced to dispclk divided by the minimum pixels in the data fifo entry, with 15% margin, but shoudl not be set to less than the request bandwidth.*/
+	/*the data fifo entry is 16 pixels for the writeback, 64 bytes/bytes_per_pixel for the graphics, 16 pixels for the parallel rotation underlay,*/
+	/*and 16 bytes/bytes_per_pixel for the orthogonal rotation underlay.*/
+	/*in parallel mode (underlay pipe), the data read from the dmifv buffer is variable and based on the pixel depth (8bbp - 16 bytes, 16 bpp - 32 bytes, 32 bpp - 64 bytes)*/
+	/*in orthogonal mode (underlay pipe), the data read from the dmifv buffer is fixed at 16 bytes.*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (surface_type[i] == bw_def_display_write_back420_luma
+				|| surface_type[i]
+					== bw_def_display_write_back420_chroma) {
+				results->pixels_per_data_fifo_entry[i] =
+					bw_int_to_fixed(16);
+			} else if (surface_type[i] == bw_def_graphics) {
+				results->pixels_per_data_fifo_entry[i] = bw_div(
+					bw_int_to_fixed(64),
+					bw_int_to_fixed(
+						results->bytes_per_pixel[i]));
+			} else if (results->orthogonal_rotation[i] == 0) {
+				results->pixels_per_data_fifo_entry[i] =
+					bw_int_to_fixed(16);
+			} else {
+				results->pixels_per_data_fifo_entry[i] = bw_div(
+					bw_int_to_fixed(16),
+					bw_int_to_fixed(
+						results->bytes_per_pixel[i]));
+			}
+		}
+	}
+	results->min_pixels_per_data_fifo_entry = bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_mtn(
+				results->min_pixels_per_data_fifo_entry,
+				results->pixels_per_data_fifo_entry[i])) {
+				results->min_pixels_per_data_fifo_entry =
+					results->pixels_per_data_fifo_entry[i];
+			}
+		}
+	}
+	results->sclk_deep_sleep = bw_max2(
+		bw_div(
+			bw_mul(results->dispclk, bw_frc_to_fixed(115, 100)),
+			results->min_pixels_per_data_fifo_entry),
+		results->total_read_request_bandwidth);
+	/*urgent, stutter and nb-p_state watermark*/
+	/*the urgent watermark is the maximum of the urgent trip time plus the pixel transfer time, the urgent trip times to get data for the first pixel, and the urgent trip times to get data for the last pixel.*/
+	/*the stutter exit watermark is the self refresh exit time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel.  it does not apply to the writeback.*/
+	/*the nb p-state change watermark is the dram speed/p-state change time plus the maximum of the data burst time plus the pixel transfer time, the data burst times to get data for the first pixel, and the data burst times to get data for the last pixel.*/
+	/*the pixel transfer time is the maximum of the time to transfer the source pixels required for the first output pixel, and the time to transfer the pixels for the last output pixel minus the active line time.*/
+	/*blackout_duration is added to the urgent watermark*/
+	results->chunk_request_time = bw_int_to_fixed(0);
+	results->cursor_request_time = bw_int_to_fixed(0);
+	/*compute total time to request one chunk from each active display pipe*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->chunk_request_time =
+				bw_add(
+					results->chunk_request_time,
+					(bw_div(
+						(bw_div(
+							bw_int_to_fixed(
+								pixels_per_chunk
+									* results->bytes_per_pixel[i]),
+							results->useful_bytes_per_request[i])),
+						bw_min2(
+							sclk[results->sclk_level],
+							bw_div(
+								results->dispclk,
+								bw_int_to_fixed(
+									2))))));
+		}
+	}
+	/*compute total time to request cursor data*/
+	results->cursor_request_time = (bw_div(
+		results->cursor_total_data,
+		(bw_mul(bw_int_to_fixed(32), sclk[results->sclk_level]))));
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->line_source_pixels_transfer_time =
+				bw_max2(
+					bw_div(
+						bw_div(
+							results->src_pixels_for_first_output_pixel[i],
+							dceip->lb_write_pixels_per_dispclk),
+						(bw_div(
+							results->dispclk,
+							dceip->display_pipe_throughput_factor))),
+					bw_sub(
+						bw_div(
+							bw_div(
+								results->src_pixels_for_last_output_pixel[i],
+								dceip->lb_write_pixels_per_dispclk),
+							(bw_div(
+								results->dispclk,
+								dceip->display_pipe_throughput_factor))),
+						results->active_time[i]));
+			if (surface_type[i] != bw_def_display_write_back420_luma
+				&& surface_type[i]
+					!= bw_def_display_write_back420_chroma) {
+				results->urgent_watermark[i] =
+					bw_add(
+						bw_add(
+							bw_add(
+								bw_add(
+									bw_add(
+										results->total_dmifmc_urgent_latency,
+										results->dmif_burst_time[results->y_clk_level][results->sclk_level]),
+									bw_max2(
+										results->line_source_pixels_transfer_time,
+										results->line_source_transfer_time[i][results->y_clk_level][results->sclk_level])),
+								vbios->blackout_duration),
+							results->chunk_request_time),
+						results->cursor_request_time);
+				results->stutter_exit_watermark[i] =
+					bw_add(
+						bw_sub(
+							vbios->stutter_self_refresh_exit_latency,
+							results->total_dmifmc_urgent_latency),
+						results->urgent_watermark[i]);
+				/*unconditionally remove black out time from the nb p_state watermark*/
+				results->nbp_state_change_watermark[i] =
+					bw_sub(
+						bw_add(
+							bw_sub(
+								vbios->nbp_state_change_latency,
+								results->total_dmifmc_urgent_latency),
+							results->urgent_watermark[i]),
+						vbios->blackout_duration);
+			} else {
+				results->urgent_watermark[i] =
+					bw_add(
+						bw_add(
+							bw_add(
+								bw_add(
+									bw_add(
+										vbios->mcifwrmc_urgent_latency,
+										results->mcifwr_burst_time[results->y_clk_level][results->sclk_level]),
+									bw_max2(
+										results->line_source_pixels_transfer_time,
+										results->line_source_transfer_time[i][results->y_clk_level][results->sclk_level])),
+								vbios->blackout_duration),
+							results->chunk_request_time),
+						results->cursor_request_time);
+				results->stutter_exit_watermark[i] =
+					bw_int_to_fixed(0);
+				results->nbp_state_change_watermark[i] =
+					bw_add(
+						bw_sub(
+							bw_add(
+								vbios->nbp_state_change_latency,
+								results->dmif_burst_time[results->y_clk_level][results->sclk_level]),
+							vbios->mcifwrmc_urgent_latency),
+						results->urgent_watermark[i]);
+			}
+		}
+	}
+	/*stutter mode enable*/
+	/*in the multi-display case the stutter exit watermark cannot exceed the cursor dcp buffer size*/
+	results->stutter_mode_enable = results->cpuc_state_change_enable;
+	if (mode_data->number_of_displays > 1) {
+		for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+			if (results->enable[i]) {
+				if (bw_mtn(
+					results->stutter_exit_watermark[i],
+					results->cursor_latency_hiding[i])) {
+					results->stutter_mode_enable =
+						bw_def_no;
+				}
+			}
+		}
+	}
+	/*performance metrics*/
+	/* display read access efficiency (%)*/
+	/* display write back access efficiency (%)*/
+	/* stutter efficiency (%)*/
+	/* extra underlay pitch recommended for efficiency (pixels)*/
+	/* immediate flip time (us)*/
+	/* latency for other clients due to urgent display read (us)*/
+	/* latency for other clients due to urgent display write (us)*/
+	/* average bandwidth consumed by display (no compression) (gb/s)*/
+	/* required dram  bandwidth (gb/s)*/
+	/* required sclk (m_hz)*/
+	/* required rd urgent latency (us)*/
+	/* nb p-state change margin (us)*/
+	/*dmif and mcifwr dram access efficiency*/
+	/*is the ratio between the ideal dram access time (which is the data buffer size in memory divided by the dram bandwidth), and the actual time which is the total page close-open time.  but it cannot exceed the dram efficiency provided by the memory subsystem*/
+	results->dmifdram_access_efficiency =
+		bw_min2(
+			bw_div(
+				bw_div(
+					results->total_display_reads_required_dram_access_data,
+					results->dram_bandwidth),
+				results->dmif_total_page_close_open_time),
+			bw_int_to_fixed(1));
+	if (bw_mtn(
+		results->total_display_writes_required_dram_access_data,
+		bw_int_to_fixed(0))) {
+		results->mcifwrdram_access_efficiency =
+			bw_min2(
+				bw_div(
+					bw_div(
+						results->total_display_writes_required_dram_access_data,
+						results->dram_bandwidth),
+					results->mcifwr_total_page_close_open_time),
+				bw_int_to_fixed(1));
+	} else {
+		results->mcifwrdram_access_efficiency = bw_int_to_fixed(0);
+	}
+	/*average bandwidth*/
+	/*the average bandwidth with no compression is the vertical active time is the source width times the bytes per pixel divided by the line time, multiplied by the vertical scale ratio and the ratio of bytes per request divided by the useful bytes per request.*/
+	/*the average bandwidth with compression is the same, divided by the compression ratio*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->average_bandwidth_no_compression[i] =
+				bw_div(
+					bw_mul(
+						bw_mul(
+							bw_div(
+								bw_mul(
+									results->source_width_rounded_up_to_chunks[i],
+									bw_int_to_fixed(
+										results->bytes_per_pixel[i])),
+								(bw_div(
+									results->h_total[i],
+									results->pixel_rate[i]))),
+							results->vsr[i]),
+						results->bytes_per_request[i]),
+					results->useful_bytes_per_request[i]);
+			results->average_bandwidth[i] = bw_div(
+				results->average_bandwidth_no_compression[i],
+				results->compression_rate[i]);
+		}
+	}
+	results->total_average_bandwidth_no_compression = bw_int_to_fixed(0);
+	results->total_average_bandwidth = bw_int_to_fixed(0);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->total_average_bandwidth_no_compression =
+				bw_add(
+					results->total_average_bandwidth_no_compression,
+					results->average_bandwidth_no_compression[i]);
+			results->total_average_bandwidth = bw_add(
+				results->total_average_bandwidth,
+				results->average_bandwidth[i]);
+		}
+	}
+	/*stutter efficiency*/
+	/*the stutter efficiency is the frame-average time in self-refresh divided by the frame-average stutter cycle duration.  only applies if the display write-back is not enabled.*/
+	/*the frame-average stutter cycle used is the minimum for all pipes of the frame-average data buffer size in time, times the compression rate*/
+	/*the frame-average time in self-refresh is the stutter cycle minus the self refresh exit latency and the burst time*/
+	/*the stutter cycle is the dmif buffer size reduced by the excess of the stutter exit watermark over the lb size in time.*/
+	/*the burst time is the data needed during the stutter cycle divided by the available bandwidth*/
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->stutter_cycle_duration[i] =
+				bw_sub(
+					bw_mul(
+						bw_div(
+							bw_div(
+								bw_mul(
+									bw_div(
+										bw_div(
+											results->adjusted_data_buffer_size[i],
+											bw_int_to_fixed(
+												results->bytes_per_pixel[i])),
+										results->source_width_rounded_up_to_chunks[i]),
+									results->h_total[i]),
+								results->vsr[i]),
+							results->pixel_rate[i]),
+						results->compression_rate[i]),
+					bw_max2(
+						bw_int_to_fixed(0),
+						bw_sub(
+							results->stutter_exit_watermark[i],
+							bw_div(
+								bw_mul(
+									bw_int_to_fixed(
+										(2
+											+ results->line_buffer_prefetch[i])),
+									results->h_total[i]),
+								results->pixel_rate[i]))));
+		}
+	}
+	results->total_stutter_cycle_duration = bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			if (bw_mtn(
+				results->total_stutter_cycle_duration,
+				results->stutter_cycle_duration[i])) {
+				results->total_stutter_cycle_duration =
+					results->stutter_cycle_duration[i];
+			}
+		}
+	}
+	results->stutter_burst_time = bw_div(
+		bw_mul(
+			results->total_stutter_cycle_duration,
+			results->total_average_bandwidth),
+		bw_min2(
+			(bw_mul(
+				results->dram_bandwidth,
+				results->dmifdram_access_efficiency)),
+			bw_mul(
+				sclk[results->sclk_level],
+				vbios->data_return_bus_width)));
+	results->time_in_self_refresh = bw_sub(
+		bw_sub(
+			results->total_stutter_cycle_duration,
+			vbios->stutter_self_refresh_exit_latency),
+		results->stutter_burst_time);
+	if (mode_data->d1_display_write_back_dwb_enable == 1) {
+		results->stutter_efficiency = bw_int_to_fixed(0);
+	} else if (bw_ltn(results->time_in_self_refresh, bw_int_to_fixed(0))) {
+		results->stutter_efficiency = bw_int_to_fixed(0);
+	} else {
+		results->stutter_efficiency = bw_mul(
+			bw_div(
+				results->time_in_self_refresh,
+				results->total_stutter_cycle_duration),
+			bw_int_to_fixed(100));
+	}
+	/*immediate flip time*/
+	/*if scatter gather is enabled, the immediate flip takes a number of urgent memory trips equivalent to the pte requests in a row divided by the pte request limit.*/
+	/*otherwise, it may take just one urgenr memory trip*/
+	results->worst_number_of_trips_to_memory = bw_int_to_fixed(1);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]
+			&& results->scatter_gather_enable_for_pipe[i] == 1) {
+			results->number_of_trips_to_memory_for_getting_apte_row[i] =
+				bw_ceil2(
+					bw_div(
+						results->scatter_gather_pte_requests_in_row[i],
+						results->scatter_gather_pte_request_limit[i]),
+					bw_int_to_fixed(1));
+			if (bw_ltn(
+				results->worst_number_of_trips_to_memory,
+				results->number_of_trips_to_memory_for_getting_apte_row[i])) {
+				results->worst_number_of_trips_to_memory =
+					results->number_of_trips_to_memory_for_getting_apte_row[i];
+			}
+		}
+	}
+	results->immediate_flip_time = bw_mul(
+		results->worst_number_of_trips_to_memory,
+		results->total_dmifmc_urgent_latency);
+	/*worst latency for other clients*/
+	/*it is the urgent latency plus the urgent burst time*/
+	results->latency_for_non_dmif_clients =
+		bw_add(
+			results->total_dmifmc_urgent_latency,
+			results->dmif_burst_time[results->y_clk_level][results->sclk_level]);
+	if (mode_data->d1_display_write_back_dwb_enable == 1) {
+		results->latency_for_non_mcifwr_clients = bw_add(
+			vbios->mcifwrmc_urgent_latency,
+			dceip->mcifwr_all_surfaces_burst_time);
+	} else {
+		results->latency_for_non_mcifwr_clients = bw_int_to_fixed(0);
+	}
+	/*dmif mc urgent latency suppported in high sclk and yclk*/
+	results->dmifmc_urgent_latency_supported_in_high_sclk_and_yclk = bw_div(
+		(bw_sub(
+			results->min_read_buffer_size_in_time,
+			results->dmif_burst_time[high][high])),
+		results->total_dmifmc_urgent_trips);
+	/*dram speed/p-state change margin*/
+	/*in the multi-display case the nb p-state change watermark cannot exceed the average lb size plus the dmif size or the cursor dcp buffer size*/
+	results->nbp_state_dram_speed_change_margin = bw_int_to_fixed(9999);
+	for (i = 0; i <= maximum_number_of_surfaces - 1; i++) {
+		if (results->enable[i]) {
+			results->nbp_state_dram_speed_change_margin =
+				bw_min2(
+					results->nbp_state_dram_speed_change_margin,
+					bw_sub(
+						results->maximum_latency_hiding_with_cursor[i],
+						results->nbp_state_change_watermark[i]));
+		}
+	}
+	/*sclk required vs urgent latency*/
+	for (i = 1; i <= 5; i++) {
+		results->display_reads_time_for_data_transfer_and_urgent_latency =
+			bw_sub(
+				results->min_read_buffer_size_in_time,
+				bw_mul(
+					results->total_dmifmc_urgent_trips,
+					bw_int_to_fixed(i)));
+		if (pipe_check == bw_def_ok
+			&& (bw_mtn(
+				results->display_reads_time_for_data_transfer_and_urgent_latency,
+				results->dmif_total_page_close_open_time))) {
+			results->dmif_required_sclk_for_urgent_latency[i] =
+				bw_div(
+					bw_div(
+						results->total_display_reads_required_data,
+						results->display_reads_time_for_data_transfer_and_urgent_latency),
+					vbios->data_return_bus_width);
+		} else {
+			results->dmif_required_sclk_for_urgent_latency[i] =
+				bw_int_to_fixed(bw_def_na);
+		}
+	}
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+void bw_calcs_init(struct bw_calcs_dceip *bw_dceip,
+	struct bw_calcs_vbios *bw_vbios)
+{
+	struct bw_calcs_dceip dceip = {{ 0 }};
+	struct bw_calcs_vbios vbios = { 0 };
+
+	vbios.number_of_dram_channels = 2;
+	vbios.dram_channel_width_in_bits = 64;
+	vbios.number_of_dram_banks = 8;
+	vbios.high_yclk = bw_int_to_fixed(1600);
+	vbios.mid_yclk = bw_int_to_fixed(1600);
+	vbios.low_yclk = bw_frc_to_fixed(66666, 100);
+	vbios.low_sclk = bw_int_to_fixed(200);
+	vbios.mid_sclk = bw_int_to_fixed(300);
+	vbios.high_sclk = bw_frc_to_fixed(62609, 100);
+	vbios.low_voltage_max_dispclk = bw_int_to_fixed(352);
+	vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467);
+	vbios.high_voltage_max_dispclk = bw_int_to_fixed(643);
+	vbios.data_return_bus_width = bw_int_to_fixed(32);
+	vbios.trc = bw_int_to_fixed(50);
+	vbios.dmifmc_urgent_latency = bw_int_to_fixed(4);
+	vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(153, 10);
+	vbios.nbp_state_change_latency = bw_frc_to_fixed(19649, 1000);
+	vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10);
+	vbios.scatter_gather_enable = true;
+	vbios.down_spread_percentage = bw_frc_to_fixed(5, 10);
+	vbios.cursor_width = 32;
+	vbios.average_compression_rate = 4;
+	vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256;
+	vbios.blackout_duration = bw_int_to_fixed(18); /* us */
+	vbios.maximum_blackout_recovery_time = bw_int_to_fixed(20);
+
+
+	dceip.dmif_request_buffer_size = bw_int_to_fixed(768);
+	dceip.de_tiling_buffer = bw_int_to_fixed(0);
+	dceip.dcfclk_request_generation = 0;
+	dceip.lines_interleaved_into_lb = 2;
+	dceip.chunk_width = 256;
+	dceip.number_of_graphics_pipes = 3;
+	dceip.number_of_underlay_pipes = 1;
+	dceip.display_write_back_supported = false;
+	dceip.argb_compression_support = false;
+	dceip.underlay_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(
+		35556, 10000);
+	dceip.underlay_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(
+		34286, 10000);
+	dceip.underlay_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32,
+		10);
+	dceip.underlay_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3);
+	dceip.graphics_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35,
+		10);
+	dceip.graphics_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(
+		34286, 10000);
+	dceip.graphics_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32,
+		10);
+	dceip.graphics_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3);
+	dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3);
+	dceip.max_dmif_buffer_allocated = 2;
+	dceip.graphics_dmif_size = 12288;
+	dceip.underlay_luma_dmif_size = 19456;
+	dceip.underlay_chroma_dmif_size = 23552;
+	dceip.pre_downscaler_enabled = true;
+	dceip.underlay_downscale_prefetch_enabled = true;
+	dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1);
+	dceip.lb_size_per_component444 = bw_int_to_fixed(82176);
+	dceip.graphics_lb_nodownscaling_multi_line_prefetching = false;
+	dceip.stutter_and_dram_clock_state_change_gated_before_cursor =
+		bw_int_to_fixed(0);
+	dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed(82176);
+	dceip.underlay420_chroma_lb_size_per_component = bw_int_to_fixed(164352);
+	dceip.underlay422_lb_size_per_component = bw_int_to_fixed(82176);
+	dceip.cursor_chunk_width = bw_int_to_fixed(64);
+	dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4);
+	dceip.cursor_memory_interface_buffer_pixels = bw_int_to_fixed(64);
+	dceip.underlay_maximum_width_efficient_for_tiling = bw_int_to_fixed(1920);
+	dceip.underlay_maximum_height_efficient_for_tiling = bw_int_to_fixed(1080);
+	dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display =
+		bw_frc_to_fixed(3, 10);
+	dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation =
+		bw_int_to_fixed(25);
+	dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed(2);
+	dceip.maximum_total_outstanding_pte_requests_allowed_by_saw =
+		bw_int_to_fixed(128);
+	dceip.limit_excessive_outstanding_dmif_requests = true;
+	dceip.linear_mode_line_request_alternation_slice = bw_int_to_fixed(64);
+	dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = 32;
+	dceip.display_write_back420_luma_mcifwr_buffer_size = 12288;
+	dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192;
+	dceip.request_efficiency = bw_frc_to_fixed(8, 10);
+	dceip.dispclk_per_request = bw_int_to_fixed(2);
+	dceip.dispclk_ramping_factor = bw_frc_to_fixed(11, 10);
+	dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100);
+	dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2;
+	dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: this is a bug*/
+
+	*bw_dceip = dceip;
+	*bw_vbios = vbios;
+}
+
+/**
+ * Compare calculated (required) clocks against the clocks available at
+ * maximum voltage (max Performance Level).
+ */
+static bool is_display_configuration_supported(
+	const struct bw_calcs_vbios *vbios,
+	const struct bw_calcs_output *calcs_output)
+{
+	uint32_t int_max_clk;
+
+	int_max_clk = bw_fixed_to_int(vbios->high_voltage_max_dispclk);
+	int_max_clk *= 1000; /* MHz to kHz */
+	if (calcs_output->dispclk_khz > int_max_clk)
+		return false;
+
+	int_max_clk = bw_fixed_to_int(vbios->high_sclk);
+	int_max_clk *= 1000; /* MHz to kHz */
+	if (calcs_output->required_sclk > int_max_clk)
+		return false;
+
+	return true;
+}
+
+/**
+ * Return:
+ *	true -	Display(s) configuration supported.
+ *		In this case 'calcs_output' contains data for HW programming
+ *	false - Display(s) configuration not supported (not enough bandwidth).
+ */
+
+bool bw_calcs(struct dc_context *ctx, const struct bw_calcs_dceip *dceip,
+	const struct bw_calcs_vbios *vbios,
+	const struct bw_calcs_mode_data *mode_data,
+	struct bw_calcs_output *calcs_output)
+{
+	struct bw_calcs_results *bw_results_internal = dm_alloc(
+				ctx, sizeof(struct bw_calcs_results));
+	struct bw_calcs_mode_data_internal *bw_data_internal =
+		dm_alloc(
+			ctx, sizeof(struct bw_calcs_mode_data_internal));
+	switch (mode_data->number_of_displays) {
+	case (3):
+		bw_data_internal->d2_htotal =
+			mode_data->displays_data[2].h_total;
+		bw_data_internal->d2_pixel_rate =
+			mode_data->displays_data[2].pixel_rate;
+		bw_data_internal->d2_graphics_src_width =
+			mode_data->displays_data[2].graphics_src_width;
+		bw_data_internal->d2_graphics_src_height =
+			mode_data->displays_data[2].graphics_src_height;
+		bw_data_internal->d2_graphics_scale_ratio =
+			mode_data->displays_data[2].graphics_scale_ratio;
+		bw_data_internal->d2_graphics_stereo_mode =
+			mode_data->displays_data[2].graphics_stereo_mode;
+	case (2):
+		bw_data_internal->d1_display_write_back_dwb_enable = false;
+		bw_data_internal->d1_underlay_mode = bw_def_none;
+		bw_data_internal->d1_underlay_scale_ratio = bw_int_to_fixed(0);
+		bw_data_internal->d1_htotal =
+			mode_data->displays_data[1].h_total;
+		bw_data_internal->d1_pixel_rate =
+			mode_data->displays_data[1].pixel_rate;
+		bw_data_internal->d1_graphics_src_width =
+			mode_data->displays_data[1].graphics_src_width;
+		bw_data_internal->d1_graphics_src_height =
+			mode_data->displays_data[1].graphics_src_height;
+		bw_data_internal->d1_graphics_scale_ratio =
+			mode_data->displays_data[1].graphics_scale_ratio;
+		bw_data_internal->d1_graphics_stereo_mode =
+			mode_data->displays_data[1].graphics_stereo_mode;
+
+	case (1):
+		bw_data_internal->d0_fbc_enable =
+			mode_data->displays_data[0].fbc_enable;
+		bw_data_internal->d0_lpt_enable =
+			mode_data->displays_data[0].lpt_enable;
+		bw_data_internal->d0_underlay_mode =
+			mode_data->displays_data[0].underlay_mode;
+		bw_data_internal->d0_underlay_scale_ratio = bw_int_to_fixed(0);
+		bw_data_internal->d0_htotal =
+			mode_data->displays_data[0].h_total;
+		bw_data_internal->d0_pixel_rate =
+			mode_data->displays_data[0].pixel_rate;
+		bw_data_internal->d0_graphics_src_width =
+			mode_data->displays_data[0].graphics_src_width;
+		bw_data_internal->d0_graphics_src_height =
+			mode_data->displays_data[0].graphics_src_height;
+		bw_data_internal->d0_graphics_scale_ratio =
+			mode_data->displays_data[0].graphics_scale_ratio;
+		bw_data_internal->d0_graphics_stereo_mode =
+			mode_data->displays_data[0].graphics_stereo_mode;
+
+	default:
+		/* data for all displays */
+		bw_data_internal->number_of_displays =
+			mode_data->number_of_displays;
+		bw_data_internal->graphics_rotation_angle =
+			mode_data->displays_data[0].graphics_rotation_angle;
+		bw_data_internal->underlay_rotation_angle =
+			mode_data->displays_data[0].underlay_rotation_angle;
+		bw_data_internal->underlay_surface_type =
+			mode_data->displays_data[0].underlay_surface_type;
+		bw_data_internal->panning_and_bezel_adjustment =
+			mode_data->displays_data[0].panning_and_bezel_adjustment;
+		bw_data_internal->graphics_tiling_mode =
+			mode_data->displays_data[0].graphics_tiling_mode;
+		bw_data_internal->graphics_interlace_mode =
+			mode_data->displays_data[0].graphics_interlace_mode;
+		bw_data_internal->graphics_bytes_per_pixel =
+			mode_data->displays_data[0].graphics_bytes_per_pixel;
+		bw_data_internal->graphics_htaps =
+			mode_data->displays_data[0].graphics_h_taps;
+		bw_data_internal->graphics_vtaps =
+			mode_data->displays_data[0].graphics_v_taps;
+		bw_data_internal->graphics_lb_bpc =
+			mode_data->displays_data[0].graphics_lb_bpc;
+		bw_data_internal->underlay_lb_bpc =
+			mode_data->displays_data[0].underlay_lb_bpc;
+		bw_data_internal->underlay_tiling_mode =
+			mode_data->displays_data[0].underlay_tiling_mode;
+		bw_data_internal->underlay_htaps =
+			mode_data->displays_data[0].underlay_h_taps;
+		bw_data_internal->underlay_vtaps =
+			mode_data->displays_data[0].underlay_v_taps;
+		bw_data_internal->underlay_src_width =
+			mode_data->displays_data[0].underlay_src_width;
+		bw_data_internal->underlay_src_height =
+			mode_data->displays_data[0].underlay_src_height;
+		bw_data_internal->underlay_pitch_in_pixels =
+			mode_data->displays_data[0].underlay_pitch_in_pixels;
+		bw_data_internal->underlay_stereo_mode =
+			mode_data->displays_data[0].underlay_stereo_mode;
+		bw_data_internal->display_synchronization_enabled =
+			mode_data->display_synchronization_enabled;
+	}
+
+	if (bw_data_internal->number_of_displays != 0) {
+		uint8_t yclk_lvl, sclk_lvl;
+		struct bw_fixed high_sclk = vbios->high_sclk;
+		struct bw_fixed mid_sclk = vbios->mid_sclk;
+		struct bw_fixed low_sclk = vbios->low_sclk;
+		struct bw_fixed high_yclk = vbios->high_yclk;
+		struct bw_fixed mid_yclk = vbios->mid_yclk;
+		struct bw_fixed low_yclk = vbios->low_yclk;
+
+		calculate_bandwidth(dceip, vbios, bw_data_internal,
+							bw_results_internal);
+
+		yclk_lvl = bw_results_internal->y_clk_level;
+		sclk_lvl = bw_results_internal->sclk_level;
+
+		calcs_output->all_displays_in_sync =
+			mode_data->display_synchronization_enabled;
+		calcs_output->nbp_state_change_enable =
+			bw_results_internal->nbp_state_change_enable;
+		calcs_output->cpuc_state_change_enable =
+				bw_results_internal->cpuc_state_change_enable;
+		calcs_output->cpup_state_change_enable =
+				bw_results_internal->cpup_state_change_enable;
+		calcs_output->stutter_mode_enable =
+				bw_results_internal->stutter_mode_enable;
+		calcs_output->dispclk_khz =
+			bw_fixed_to_int(bw_mul(bw_results_internal->dispclk,
+					bw_int_to_fixed(1000)));
+		calcs_output->required_blackout_duration_us =
+			bw_fixed_to_int(bw_add(bw_results_internal->
+				blackout_duration_margin[yclk_lvl][sclk_lvl],
+				vbios->blackout_duration));
+		calcs_output->required_sclk =
+			bw_fixed_to_int(bw_mul(bw_results_internal->required_sclk,
+					bw_int_to_fixed(1000)));
+		calcs_output->required_sclk_deep_sleep =
+			bw_fixed_to_int(bw_mul(bw_results_internal->sclk_deep_sleep,
+					bw_int_to_fixed(1000)));
+		if (yclk_lvl == 0)
+			calcs_output->required_yclk = bw_fixed_to_int(
+				bw_mul(low_yclk, bw_int_to_fixed(1000)));
+		else if (yclk_lvl == 1)
+			calcs_output->required_yclk = bw_fixed_to_int(
+				bw_mul(mid_yclk, bw_int_to_fixed(1000)));
+		else
+			calcs_output->required_yclk = bw_fixed_to_int(
+				bw_mul(high_yclk, bw_int_to_fixed(1000)));
+
+		/* units: nanosecond, 16bit storage. */
+		calcs_output->nbp_state_change_wm_ns[0].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[4],bw_int_to_fixed(1000)));
+		calcs_output->nbp_state_change_wm_ns[1].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->nbp_state_change_wm_ns[2].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[6], bw_int_to_fixed(1000)));
+
+		calcs_output->stutter_exit_wm_ns[0].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->stutter_exit_wm_ns[1].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->stutter_exit_wm_ns[2].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[6], bw_int_to_fixed(1000)));
+
+		calcs_output->urgent_wm_ns[0].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->urgent_wm_ns[1].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->urgent_wm_ns[2].b_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[6], bw_int_to_fixed(1000)));
+
+		((struct bw_calcs_vbios *)vbios)->low_yclk = high_yclk;
+		((struct bw_calcs_vbios *)vbios)->mid_yclk = high_yclk;
+		((struct bw_calcs_vbios *)vbios)->low_sclk = high_sclk;
+		((struct bw_calcs_vbios *)vbios)->mid_sclk = high_sclk;
+
+		calculate_bandwidth(dceip, vbios, bw_data_internal,
+							bw_results_internal);
+
+		calcs_output->nbp_state_change_wm_ns[0].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->nbp_state_change_wm_ns[1].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->nbp_state_change_wm_ns[2].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				nbp_state_change_watermark[6], bw_int_to_fixed(1000)));
+
+		calcs_output->stutter_exit_wm_ns[0].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->stutter_exit_wm_ns[1].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->stutter_exit_wm_ns[2].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				stutter_exit_watermark[6], bw_int_to_fixed(1000)));
+
+		calcs_output->urgent_wm_ns[0].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[4], bw_int_to_fixed(1000)));
+		calcs_output->urgent_wm_ns[1].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[5], bw_int_to_fixed(1000)));
+		calcs_output->urgent_wm_ns[2].a_mark =
+			bw_fixed_to_int(bw_mul(bw_results_internal->
+				urgent_watermark[6], bw_int_to_fixed(1000)));
+
+		((struct bw_calcs_vbios *)vbios)->low_yclk = low_yclk;
+		((struct bw_calcs_vbios *)vbios)->mid_yclk = mid_yclk;
+		((struct bw_calcs_vbios *)vbios)->low_sclk = low_sclk;
+		((struct bw_calcs_vbios *)vbios)->mid_sclk = mid_sclk;
+	} else {
+		calcs_output->nbp_state_change_enable = true;
+		calcs_output->cpuc_state_change_enable = true;
+		calcs_output->cpup_state_change_enable = true;
+		calcs_output->stutter_mode_enable = true;
+		calcs_output->dispclk_khz = 0;
+		calcs_output->required_sclk = 0;
+	}
+
+	dm_free(ctx, bw_data_internal);
+	dm_free(ctx, bw_results_internal);
+
+	return is_display_configuration_supported(vbios, calcs_output);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
new file mode 100644
index 000000000000..8a7a4c99fb5b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "bw_fixed.h"
+
+
+#define BITS_PER_FRACTIONAL_PART 24
+
+#define MIN_I32 \
+	(int64_t)(-(1LL << (63 - BITS_PER_FRACTIONAL_PART)))
+
+#define MAX_I32 \
+	(int64_t)((1ULL << (63 - BITS_PER_FRACTIONAL_PART)) - 1)
+
+#define MIN_I64 \
+	(int64_t)(-(1LL << 63))
+
+#define MAX_I64 \
+	(int64_t)((1ULL << 63) - 1)
+
+
+#define FRACTIONAL_PART_MASK \
+	((1ULL << BITS_PER_FRACTIONAL_PART) - 1)
+
+#define GET_INTEGER_PART(x) \
+	((x) >> BITS_PER_FRACTIONAL_PART)
+
+#define GET_FRACTIONAL_PART(x) \
+	(FRACTIONAL_PART_MASK & (x))
+
+static uint64_t abs_i64(int64_t arg)
+{
+	if (arg >= 0)
+		return (uint64_t)(arg);
+	else
+		return (uint64_t)(-arg);
+}
+
+struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3)
+{
+	return bw_min2(bw_min2(v1, v2), v3);
+}
+
+struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3)
+{
+	return bw_max2(bw_max2(v1, v2), v3);
+}
+
+struct bw_fixed bw_int_to_fixed(int64_t value)
+{
+	struct bw_fixed res;
+	ASSERT(value < MAX_I32 && value > MIN_I32);
+	res.value = value << BITS_PER_FRACTIONAL_PART;
+	return res;
+}
+
+int32_t bw_fixed_to_int(struct bw_fixed value)
+{
+	return GET_INTEGER_PART(value.value);
+}
+
+struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator)
+{
+	struct bw_fixed res;
+	bool arg1_negative = numerator < 0;
+	bool arg2_negative = denominator < 0;
+	uint64_t arg1_value;
+	uint64_t arg2_value;
+	uint64_t remainder;
+
+	/* determine integer part */
+	uint64_t res_value;
+
+	ASSERT(denominator != 0);
+
+	arg1_value = (uint64_t)abs_i64(numerator);
+	arg2_value = (uint64_t)abs_i64(denominator);
+	res_value = div64_u64_rem(arg1_value, arg2_value, &remainder);
+
+	ASSERT(res_value <= MAX_I32);
+
+	/* determine fractional part */
+	{
+		uint32_t i = BITS_PER_FRACTIONAL_PART;
+
+		do
+		{
+			remainder <<= 1;
+
+			res_value <<= 1;
+
+			if (remainder >= arg2_value)
+			{
+				res_value |= 1;
+				remainder -= arg2_value;
+			}
+		} while (--i != 0);
+	}
+
+	/* round up LSB */
+	{
+		uint64_t summand = (remainder << 1) >= arg2_value;
+
+		ASSERT(res_value <= MAX_I64 - summand);
+
+		res_value += summand;
+	}
+
+	res.value = (int64_t)(res_value);
+
+	if (arg1_negative ^ arg2_negative)
+		res.value = -res.value;
+	return res;
+}
+
+struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return (arg1.value <= arg2.value) ? arg1 : arg2;
+}
+
+struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return (arg2.value <= arg1.value) ? arg1 : arg2;
+}
+
+struct bw_fixed bw_floor2(
+	const struct bw_fixed arg,
+	const struct bw_fixed significance)
+{
+	struct bw_fixed result;
+	int64_t multiplicand;
+	multiplicand = div64_s64(arg.value, abs_i64(significance.value));
+	result.value = abs_i64(significance.value) * multiplicand;
+	ASSERT(abs_i64(result.value) <= abs_i64(arg.value));
+	return result;
+}
+
+struct bw_fixed bw_ceil2(
+	const struct bw_fixed arg,
+	const struct bw_fixed significance)
+{
+	struct bw_fixed result;
+	int64_t multiplicand;
+
+	multiplicand = div64_s64(arg.value, abs_i64(significance.value));
+	result.value = abs_i64(significance.value) * multiplicand;
+	if (abs_i64(result.value) < abs_i64(arg.value)) {
+		if (arg.value < 0)
+			result.value -= abs_i64(significance.value);
+		else
+			result.value += abs_i64(significance.value);
+	}
+	return result;
+}
+
+struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res;
+
+	res.value = arg1.value + arg2.value;
+
+	return res;
+}
+
+struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res;
+
+	res.value = arg1.value - arg2.value;
+
+	return res;
+}
+
+struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res;
+
+	bool arg1_negative = arg1.value < 0;
+	bool arg2_negative = arg2.value < 0;
+
+	uint64_t arg1_value = abs_i64(arg1.value);
+	uint64_t arg2_value = abs_i64(arg2.value);
+
+	uint64_t arg1_int = GET_INTEGER_PART(arg1_value);
+	uint64_t arg2_int = GET_INTEGER_PART(arg2_value);
+
+	uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
+	uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
+
+	uint64_t tmp;
+
+	res.value = arg1_int * arg2_int;
+
+	ASSERT(res.value <= MAX_I32);
+
+	res.value <<= BITS_PER_FRACTIONAL_PART;
+
+	tmp = arg1_int * arg2_fra;
+
+	ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
+
+	res.value += tmp;
+
+	tmp = arg2_int * arg1_fra;
+
+	ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
+
+	res.value += tmp;
+
+	tmp = arg1_fra * arg2_fra;
+
+	tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
+		(tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value));
+
+	ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
+
+	res.value += tmp;
+
+	if (arg1_negative ^ arg2_negative)
+		res.value = -res.value;
+	return res;
+}
+
+struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res = bw_frc_to_fixed(arg1.value, arg2.value);
+	return res;
+}
+
+struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	struct bw_fixed res;
+	div64_u64_rem(arg1.value, arg2.value, &res.value);
+	return res;
+}
+struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw)
+{
+	struct bw_fixed result = { 0 };
+
+	if (raw < 0) {
+		raw = -raw;
+		result.value = -(raw >> (32 - BITS_PER_FRACTIONAL_PART));
+	} else {
+		result.value = raw >> (32 - BITS_PER_FRACTIONAL_PART);
+	}
+
+	return result;
+}
+
+bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value == arg2.value;
+}
+
+bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value != arg2.value;
+}
+
+bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value <= arg2.value;
+}
+
+bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value >= arg2.value;
+}
+
+bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value < arg2.value;
+}
+
+bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2)
+{
+	return arg1.value > arg2.value;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
new file mode 100644
index 000000000000..64ca20328315
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
@@ -0,0 +1,1992 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/fixed31_32.h"
+
+#include "scaler_filter.h"
+
+enum {
+	DOWN_DB_SCALES = 8,
+	DOWN_DB_POINTS = 11,
+
+	UP_DB_SCALES = 1,
+	UP_DB_POINTS = 7,
+
+	MIN_SHARPNESS = -50,
+	MAX_SHARPNESS = 50,
+
+	CONST_DIVIDER = 10000000,
+
+	MAX_HOR_DOWNSCALE = 1666000, /* 1:6  */
+	MAX_VER_DOWNSCALE = 1666000, /* 1:6  */
+
+	MAX_HOR_UPSCALE = 160000000, /* 16:1 */
+	MAX_VER_UPSCALE = 160000000, /* 16:1 */
+
+	THRESHOLDRATIOLOW = 8000000, /* 0.8 */
+	THRESHOLDRATIOUP = 10000000, /* 1.0 */
+
+	DOWN_DB_FUZZY = -120411996, /* -12.041200 */
+	DOWN_DB_FLAT = -60205998, /* -6.020600 */
+	DOWN_DB_SHARP = -10000000, /* -1.000000 */
+
+	UP_DB_FUZZY = -60205998, /* -6.020600 */
+	UP_DB_FLAT = 0,
+	UP_DB_SHARP = 60205998 /* 6.020600 */
+};
+
+static inline struct fixed31_32 max_hor_downscale(void)
+{
+	return dal_fixed31_32_from_fraction(MAX_HOR_DOWNSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 max_ver_downscale(void)
+{
+	return dal_fixed31_32_from_fraction(MAX_VER_DOWNSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 max_hor_upscale(void)
+{
+	return dal_fixed31_32_from_fraction(MAX_HOR_UPSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 max_ver_upscale(void)
+{
+	return dal_fixed31_32_from_fraction(MAX_VER_UPSCALE, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 threshold_ratio_low(void)
+{
+	return dal_fixed31_32_from_fraction(THRESHOLDRATIOLOW, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 threshold_ratio_up(void)
+{
+	return dal_fixed31_32_from_fraction(THRESHOLDRATIOUP, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 down_db_fuzzy(void)
+{
+	return dal_fixed31_32_from_fraction(DOWN_DB_FUZZY, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 down_db_flat(void)
+{
+	return dal_fixed31_32_from_fraction(DOWN_DB_FLAT, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 down_db_sharp(void)
+{
+	return dal_fixed31_32_from_fraction(DOWN_DB_SHARP, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 up_db_fuzzy(void)
+{
+	return dal_fixed31_32_from_fraction(UP_DB_FUZZY, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 up_db_flat(void)
+{
+	return dal_fixed31_32_from_fraction(UP_DB_FLAT, CONST_DIVIDER);
+}
+
+static inline struct fixed31_32 up_db_sharp(void)
+{
+	return dal_fixed31_32_from_fraction(UP_DB_SHARP, CONST_DIVIDER);
+}
+
+static const int32_t
+	downscaling_db_table[][DOWN_DB_SCALES + 1][DOWN_DB_POINTS] = {
+	/* 3 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			14302719,	14302719,	14302719,
+			10000000,	99999,		99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14302339,	14302339,	14302339,
+			10000000,	4452010,	99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14302760,	14302760,	14302760,
+			10000000,	7826979,	5258399,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14302819,	14302819,	14302819,
+			10000000,	8669400,	7414469,
+			4422729,	99999,		99999,
+			99999,		99999
+		},
+		{
+			14302730,	14302730,	12791190,
+			10000000,	9045640,	8180170,
+			6477950,	4599249,	2019010,
+			99999,		99999
+		},
+		{
+			14302699,	14302699,	12067849,
+			10000000,	9236029,	8541280,
+			7252740,	6021010,	4820120,
+			3511950,	1769340
+		},
+		{
+			14302710,	14302710,	11783510,
+			10000000,	9325690,	8704419,
+			7595670,	6583020,	5652850,
+			4749999,	3847680
+		},
+		{
+			14302920,	14302920,	11709250,
+			10000000,	9345560,	8754609,
+			7692559,	6738259,	5878239,
+			5057529,	4264070
+		}
+	},
+	/* 4 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			14308999,	14308999,	14308999,
+			10000000,	99999,		99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14308999,	14308999,	14308999,
+			10000000,	6311039,	99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14308999,	14308999,	14308999,
+			10000000,	8526669,	6832849,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			14308999,	14308999,	12110630,
+			10000000,	9117940,	8230940,
+			6320130,	3719770,	99999,
+			99999,		99999
+		},
+		{
+			14308999,	14308999,	11474980,
+			10000000,	9370139,	8771979,
+			7601270,	6440780,	5249999,
+			3887520,	2039040
+		},
+		{
+			14308999,	13084859,	11179579,
+			10000000,	9495180,	9016919,
+			8134520,	7311699,	6560329,
+			5845720,	5155519
+		},
+		{
+			14308999,	12576600,	11048669,
+			10000000,	9550499,	9132360,
+			8368729,	7679399,	7073119,
+			6520900,	6015530
+		},
+		{
+			14308999,	12448530,	11007410,
+			10000000,	9566799,	9165279,
+			8435800,	7785279,	7215780,
+			6701470,	6240640
+		}
+	},
+	/* 5 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			8971139,	8971139,	8971139,
+			10000000,	99999,		99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			9466379,	9466379,	9466379,
+			10000000,	5648760,	3834280,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			15000000,	15000000,	14550110,
+			10000000,	7121120,	5994579,
+			4314630,	2606149,	99999,
+			99999,		99999
+		},
+		{
+			15000000,	15000000,	13047469,
+			10000000,	8368809,	7343569,
+			5970299,	4924620,	4029389,
+			3171139,	2276369
+		},
+		{
+			15000000,	14157199,	11897679,
+			10000000,	9166659,	8444600,
+			7287240,	6374719,	5615460,
+			4949580,	4350199
+		},
+		{
+			15000000,	12877819,	11224579,
+			10000000,	9488620,	9016109,
+			8203780,	7500000,	6883730,
+			6326839,	5818459
+		},
+		{
+			14733040,	12233200,	10939040,
+			10000000,	9608929,	9250000,
+			8623390,	8076940,	7606369,
+			7177749,	6785169
+		},
+		{
+			14627330,	12046170,	10862360,
+			10000000,	9639260,	9312710,
+			8737679,	8242470,	7815709,
+			7432209,	7082970
+		}
+	},
+	/* 6 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			8231559,	8231559,	8231559,
+			10000000,	99999,		99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			8353310,	8353310,	8353310,
+			10000000,	5504879,	4310710,
+			870359,		99999,		99999,
+			99999,		99999
+		},
+		{
+			8643479,	8643479,	8643479,
+			10000000,	6483510,	5768150,
+			4630779,	3580690,	2501940,
+			1015309,	99999
+		},
+		{
+			15000000,	15000000,	13493930,
+			10000000,	7516040,	6802409,
+			5824409,	5080109,	4454280,
+			3896749,	3386510
+		},
+		{
+			15000000,	14055930,	12321079,
+			10000000,	8872389,	8090410,
+			7035570,	6281229,	5676810,
+			5165010,	4717260
+		},
+		{
+			15000000,	12915290,	11311399,
+			10000000,	9460610,	8988440,
+			8202149,	7548679,	6999999,
+			6510639,	6065719
+		},
+		{
+			14310129,	12140829,	10901659,
+			10000000,	9635019,	9307180,
+			8740929,	8263260,	7858849,
+			7499330,	7170130
+		},
+		{
+			13815449,	11911309,	10801299,
+			10000000,	9669629,	9380580,
+			8878319,	8452050,	8097199,
+			7785030,	7504299
+		}
+	},
+	/* 7 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10616660,	10616660,	10616660,
+			10000000,	2646020,	99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	4936839,	4112670,
+			2729740,	896539,		99999,
+			99999,		99999
+		},
+		{
+			8345860,	8345860,	8345860,
+			10000000,	6034079,	5371739,
+			4466759,	3763799,	3155870,
+			2588019,	2026730
+		},
+		{
+			9298499,	9298499,	13768420,
+			10000000,	7174239,	6524270,
+			5670250,	5052099,	4549089,
+			4115279,	3722150
+		},
+		{
+			15000000,	14116940,	12563209,
+			10000000,	8542140,	7782419,
+			6865050,	6239479,	5758860,
+			5351870,	4992800
+		},
+		{
+			15000000,	12913750,	11306079,
+			10000000,	9452580,	8969209,
+			8168810,	7538409,	7029479,
+			6603180,	6227809
+		},
+		{
+			14390859,	11862809,	10757420,
+			10000000,	9688709,	9404249,
+			8904439,	8472480,	8099079,
+			7765330,	7459110
+		},
+		{
+			13752900,	11554559,	10637769,
+			10000000,	9736120,	9499999,
+			9079759,	8718389,	8408790,
+			8134469,	7886120
+		}
+	},
+	/* 8 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			11277090,	11277090,	11277090,
+			10000000,	2949059,	99999,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			11196039,	11196039,	11196039,
+			10000000,	4627540,	4018869,
+			3018769,	2000000,	250770,
+			99999,		99999
+		},
+		{
+			10878369,	10878369,	10878369,
+			10000000,	5657230,	5118110,
+			4372630,	3809120,	3337709,
+			2919510,	2535369
+		},
+		{
+			9090089,	9090089,	13961290,
+			10000000,	6929969,	6334999,
+			5569829,	5019649,	4584150,
+			4208610,	3876540
+		},
+		{
+			15000000,	14173229,	12732659,
+			10000000,	8267070,	7575380,
+			6764540,	6218209,	5803539,
+			5454990,	5146239
+		},
+		{
+			15000000,	12928279,	11292259,
+			10000000,	9447429,	8954229,
+			8141599,	7516989,	7039459,
+			6649519,	6316819
+		},
+		{
+			14661350,	11638879,	10665880,
+			10000000,	9722669,	9464690,
+			9013469,	8613470,	8266339,
+			7949870,	7663450
+		},
+		{
+			13861900,	11311980,	10543940,
+			10000000,	9772019,	9565100,
+			9198870,	8881340,	8609200,
+			8365769,	8147500
+		}
+	},
+	/* 9 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{	10099999,	10099999,	10099999,
+			10000000,	2939159,	1526470,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			11726609,	11726609,	11726609,
+			10000000,	4329420,	3805609,
+			3030480,	2363760,	1732099,
+			980139,		99999
+		},
+		{
+			10949269,	10949269,	10949269,
+			10000000,	5452589,	4946640,
+			4277969,	3790729,	3392640,
+			3048950,	2750000
+		},
+		{
+			8830279,	8830279,	14084529,
+			10000000,	6743149,	6182519,
+			5482980,	5000000,	4622060,
+			4303340,	4022600
+		},
+		{
+			9709150,	14111399,	12800760,
+			10000000,	7989749,	7445629,
+			6741260,	6241980,	5857459,
+			5534989,	5255370
+		},
+		{
+			15000000,	12830289,	11489900,
+			10000000,	9302089,	8767340,
+			8025540,	7500000,	7100800,
+			6768149,	6481850
+		},
+		{
+			14873609,	11576000,	10650579,
+			10000000,	9731360,	9483649,
+			9054650,	8680559,	8358049,
+			8066400,	7802420
+		},
+		{
+			12981410,	11185950,	10491620,
+			10000000,	9795730,	9611030,
+			9286710,	9007279,	8768100,
+			8553469,	8361340
+		}
+	},
+	/* 10 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			8993279,	8993279,	8993279,
+			10000000,	2921360,	1905619,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			9064850,	9064850,	9064850,
+			10000000,	4095619,	3655839,
+			3021000,	2500000,	2031680,
+			1566990,	1055440
+		},
+		{
+			11043460,	11043460,	11043460,
+			10000000,	5287479,	4816150,
+			4208439,	3769229,	3418970,
+			3117449,	2850320
+		},
+		{
+			8651900,	8651900,	14169909,
+			10000000,	6596950,	6071490,
+			5423219,	4980779,	4644620,
+			4362219,	4114899
+		},
+		{
+			9246050,	14055370,	12832759,
+			10000000,	7831320,	7369570,
+			6731680,	6262450,	5897690,
+			5592269,	5328789
+		},
+		{
+			15000000,	12770450,	11642129,
+			10000000,	9120929,	8601920,
+			7946630,	7490440,	7140589,
+			6847490,	6593719
+		},
+		{
+			14062479,	11541219,	10644329,
+			10000000,	9736120,	9495139,
+			9080520,	8724340,	8419489,
+			8146359,	7899820
+		},
+		{
+			12507469,	11102950,	10457479,
+			10000000,	9811149,	9641249,
+			9344969,	9090980,	8875219,
+			8684499,	8513180
+		}
+	},
+	/* 11 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10099509,	10099509,	10099509,
+			10000000,	2788810,	2054850,
+			99999,		99999,		99999,
+			99999,		99999
+		},
+		{
+			8872069,	8872069,	8872069,
+			10000000,	3929649,	3522840,
+			2963230,	2527720,	2157579,
+			1823610,	1500000
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	5155599,	4712319,
+			4154500,	3759450,	3448629,
+			3183139,	2948490
+		},
+		{
+			10511649,	10511649,	14216580,
+			10000000,	6445930,	5988820,
+			5401239,	4988409,	4673399,
+			4410479,	4181599
+		},
+		{
+			9170889,	14003310,	12949769,
+			10000000,	7684900,	7250000,
+			6670129,	6255810,	5934680,
+			5664110,	5427970
+		},
+		{
+			15000000,	12763030,	11734730,
+			10000000,	8958870,	8478559,
+			7893459,	7489529,	7179200,
+			6917790,	6688359
+		},
+		{
+			14634610,	11491880,	10619130,
+			10000000,	9744859,	9509819,
+			9102900,	8760340,	8463050,
+			8202620,	7968729
+		},
+		{
+			12415319,	10980290,	10405089,
+			10000000,	9831910,	9680110,
+			9413710,	9184579,	8987190,
+			8813819,	8655819
+		}
+	},
+	/* 12 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10832400,	10832400,	10832400,
+			10000000,	2700819,	2115820,
+			750000,		99999,		99999,
+			99999,		99999
+		},
+		{
+			10747549,	10747549,	10747549,
+			10000000,	3781630,	3415020,
+			2914879,	2537429,	2221180,
+			1943199,	1688420
+		},
+		{
+			11630790,	11630790,	11630790,
+			10000000,	5047429,	4631519,
+			4113860,	3750000,	3469760,
+			3229379,	3016360
+		},
+		{
+			10780229,	10780229,	10780229,
+			10000000,	6340010,	5935009,
+			5387600,	4995940,	4695929,
+			4446829,	4231610
+		},
+		{
+			9055669,	13968739,	13037070,
+			10000000,	7556660,	7149490,
+			6625509,	6250000,	5958870,
+			5713790,	5500869
+		},
+		{
+			14614900,	12760740,	11806739,
+			10000000,	8824530,	8388419,
+			7857400,	7489010,	7206150,
+			6968010,	6759889
+		},
+		{
+			14894100,	11451840,	10598870,
+			10000000,	9750000,	9521099,
+			9122239,	8784019,	8494700,
+			8243309,	8018680
+		},
+		{
+			12298769,	10886880,	10367530,
+			10000000,	9846829,	9708030,
+			9464049,	9252949,	9072539,
+			8910980,	8766649
+		}
+	},
+	/* 13 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	2574490,	2099110,
+			1194889,	99999,		99999,
+			99999,		99999
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	3679780,	3332070,
+			2869139,	2530030,	2251899,
+			2010450,	1793050
+		},
+		{
+			9306690,	9306690,	9306690,
+			10000000,	4964010,	4573009,
+			4082309,	3742089,	3481810,
+			3262990,	3070969
+		},
+		{
+			10099999,	10099999,	10099999,
+			10000000,	6217889,	5843269,
+			5353810,	5000000,	4730190,
+			4499999,	4301390
+		},
+		{
+			8819990,	13964320,	13098440,
+			10000000,	7454770,	7075160,
+			6591439,	6250000,	5983970,
+			5760229,	5564339
+		},
+		{
+			14432849,	12727780,	11847709,
+			10000000,	8695709,	8322049,
+			7842620,	7500000,	7234820,
+			7010849,	6814730
+		},
+		{
+			15000000,	11440130,	10620100,
+			10000000,	9742270,	9508739,
+			9110010,	8782560,	8510140,
+			8276290,	8069980
+		},
+		{
+			12039999,	10825289,	10341939,
+			10000000,	9858080,	9729740,
+			9505100,	9310669,	9144560,
+			8996559,	8862569
+		}
+	},
+	/* 14 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			9289590,	9289590,	9289590,
+			10000000,	2485270,	2084970,
+			1362659,	250000,		99999,
+			99999,		99999
+		},
+		{
+			9484500,	9484500,	9484500,
+			10000000,	3593840,	3263100,
+			2833609,	2519409,	2267650,
+			2050379,	1856749
+		},
+		{
+			9237130,	9237130,	9237130,
+			10000000,	4898909,	4527629,
+			4057880,	3734529,	3490320,
+			3287230,	3111050
+		},
+		{
+			9543399,	9543399,	9543399,
+			10000000,	6110230,	5772359,
+			5328080,	5007240,	4757330,
+			4545379,	4359109
+		},
+		{
+			9032660,	9032660,	9032660,
+			10000000,	7373520,	7016940,
+			6565740,	6250000,	6002650,
+			5794939,	5610830
+		},
+		{
+			14351329,	12697319,	11875350,
+			10000000,	8606730,	8275989,
+			7833449,	7510430,	7257339,
+			7043970,	6857690
+		},
+		{
+			13286800,	11436090,	10643019,
+			10000000,	9729470,	9491149,
+			9096930,	8778640,	8519319,
+			8299450,	8104829
+		},
+		{
+			11838380,	10778709,	10322740,
+			10000000,	9866499,	9746059,
+			9535790,	9354810,	9200339,
+			9063839,	8940430
+		}
+	},
+	/* 15 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			9193199,	9193199,	9193199,
+			10000000,	2400999,	2042409,
+			1450179,	789309,		99999,
+			99999,		99999
+		},
+		{
+			10755189,	10755189,	10755189,
+			10000000,	3532319,	3212479,
+			2803660,	2510200,	2278629,
+			2078720,	1899970
+		},
+		{
+			8732669,	8732669,	8732669,
+			10000000,	4821290,	4483030,
+			4045079,	3737959,	3505080,
+			3311960,	3143329
+		},
+		{
+			9450280,	9450280,	9450280,
+			10000000,	6040880,	5718960,
+			5302609,	5004199,	4771710,
+			4575310,	4404180
+		},
+		{
+			10520930,	10520930,	10520930,
+			10000000,	7298259,	6975160,
+			6552690,	6250000,	6018469,
+			5822089,	5648869
+		},
+		{
+			14320160,	12683949,	11917040,
+			10000000,	8541300,	8228710,
+			7812070,	7509459,	7272909,
+			7072560,	6895729
+		},
+		{
+			15000000,	11434819,	10650700,
+			10000000,	9723110,	9480339,
+			9083300,	8771640,	8524850,
+			8317480,	8135899
+		},
+		{
+			11750520,	10722860,	10299190,
+			10000000,	9875990,	9763770,
+			9567070,	9397709,	9252669,
+			9124029,	9008929
+		}
+	},
+	/* 16 tap downscaling */
+	{
+		{
+			60209999,	40000000,	20000000,
+			0,		-10000000,	-20000000,
+			-40000000,	-60209999,	-80000000,
+			-100000000,	-120410003
+		},
+		{
+			10612260,	10612260,	10612260,
+			10000000,	2308720,	1999289,
+			1495770,	1009820,	315460,
+			99999,		99999
+		},
+		{
+			9394969,	9394969,	9394969,
+			10000000,	3462660,	3162190,
+			2780120,	2508420,	2295179,
+			2109449,	1943989
+		},
+		{
+			10609409,	10609409,	10609409,
+			10000000,	4749999,	4447000,
+			4039109,	3746300,	3522360,
+			3336620,	3177059
+		},
+		{
+			9435039,	9435039,	9435039,
+			10000000,	5978109,	5675160,
+			5282300,	5000000,	4782429,
+			4598149,	4438050
+		},
+		{
+			10592620,	10592620,	10592620,
+			10000000,	7244589,	6940630,
+			6537730,	6250000,	6027920,
+			5842260,	5680159
+		},
+		{
+			14282959,	12678509,	11963449,
+			10000000,	8484349,	8181620,
+			7785459,	7500000,	7281309,
+			7095699,	6932809
+		},
+		{
+			15000000,	11434919,	10673819,
+			10000000,	9708179,	9456859,
+			9060000,	8760929,	8529940,
+			8338279,	8172209
+		},
+		{
+			11690390,	10668220,	10277210,
+			10000000,	9884750,	9780330,
+			9597110,	9439319,	9304260,
+			9183580,	9075019
+		}
+	}
+};
+
+static const int32_t upscaling_db_table[][UP_DB_SCALES+1][UP_DB_POINTS] = {
+	/* 3 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			14302920,	14302920,	11709250,
+			10000000,
+			8754609,	7692559,	6738259
+		}
+	},
+	/*	4 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			14308999,	12448530,	11007410,
+			10000000,	9165279,	8435800,
+			7785279
+		}
+	},
+	/* 5 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			14627330,	12046170,	10862360,
+			10000000,
+			9312710,	8737679,	8242470
+		}
+	},
+	/* 6 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			13815449,	11911309,	10801299,
+			10000000,
+			9380580,	8878319,	8452050
+		}
+	},
+	/* 7 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			13752900,	11554559,	10637769,
+			10000000,
+			9499999,	9079759,	8718389
+		}
+	},
+	/* 8 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			13861900,	11311980,	10543940,
+			10000000,
+			9565100,	9198870,	8881340
+		}
+	},
+	/* 9 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12981410,	11185950,	10491620,
+			10000000,
+			9611030,	9286710,	9007279
+		}
+	},
+	/* 10 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12507469,	11102950,	10457479,
+			10000000,
+			9641249,	9344969,	9090980
+		}
+	},
+	/* 11 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12415319,	10980290,	10405089,
+			10000000,
+			9680110,	9413710,	9184579
+		}
+	},
+	/* 12 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12298769,	10886880,	10367530,
+			10000000,
+			9708030,	9464049,	9252949
+		}
+	},
+	/* 13 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			12039999,	10825289,	10341939,
+			10000000,
+			9729740,	9505100,	9310669
+		}
+	},
+	/* 14 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			11838380,	10778709,	10322740,
+			10000000,
+			9746059,	9535790,	9354810
+		}
+	},
+	/* 15 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			11750520,	10722860,	10299190,
+			10000000,
+			9763770,	9567070,	9397709
+		}
+	},
+	/* 16 tap upscaling */
+	{
+		{
+			60209999,	40000000,	20000000,	0,
+			-20000000,	-40000000,	-60209999
+		},
+		{
+			11690390,	10668220,	10277210,
+			10000000,
+			9780330,	9597110,	9439319
+		}
+	}
+};
+
+static bool allocate_3d_storage(
+	struct dc_context *ctx,
+	struct fixed31_32 ****ptr,
+	int32_t numberof_tables,
+	int32_t numberof_rows,
+	int32_t numberof_columns)
+{
+	int32_t indexof_table = 0;
+	int32_t indexof_row = 0;
+
+	struct fixed31_32 ***tables = dm_alloc(
+		ctx,
+		numberof_tables * sizeof(struct fixed31_32 **));
+
+	if (!tables) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	while (indexof_table != numberof_tables) {
+		struct fixed31_32 **rows = dm_alloc(
+			ctx,
+			numberof_rows * sizeof(struct fixed31_32 *));
+
+		if (!rows) {
+			BREAK_TO_DEBUGGER();
+			--indexof_table;
+			goto failure;
+		}
+
+		tables[indexof_table] = rows;
+
+		while (indexof_row != numberof_rows) {
+			struct fixed31_32 *columns = dm_alloc(
+				ctx,
+				numberof_columns * sizeof(struct fixed31_32));
+
+			if (!columns) {
+				BREAK_TO_DEBUGGER();
+				--indexof_row;
+				goto failure;
+			}
+
+			rows[indexof_row] = columns;
+
+			++indexof_row;
+		}
+
+		indexof_row = 0;
+
+		++indexof_table;
+	}
+
+	*ptr = tables;
+
+	return true;
+
+failure:
+
+	while (indexof_table >= 0) {
+		while (indexof_row >= 0) {
+			dm_free(ctx, tables[indexof_table][indexof_row]);
+
+			--indexof_row;
+		}
+
+		indexof_row = numberof_rows - 1;
+
+		dm_free(ctx, tables[indexof_table]);
+
+		--indexof_table;
+	}
+
+	dm_free(ctx, tables);
+
+	return false;
+}
+
+static void destroy_3d_storage(
+	struct dc_context *ctx,
+	struct fixed31_32 ****ptr,
+	uint32_t numberof_tables,
+	uint32_t numberof_rows)
+{
+	struct fixed31_32 ***tables = *ptr;
+
+	uint32_t indexof_table = 0;
+
+	if (!tables)
+		return;
+
+	while (indexof_table != numberof_tables) {
+		uint32_t indexof_row = 0;
+
+		while (indexof_row != numberof_rows) {
+			dm_free(
+				ctx, tables[indexof_table][indexof_row]);
+
+			++indexof_row;
+		};
+
+		dm_free(ctx, tables[indexof_table]);
+
+		++indexof_table;
+	};
+
+	dm_free(ctx, tables);
+
+	*ptr = NULL;
+}
+
+static bool create_downscaling_table(
+	struct scaler_filter *filter)
+{
+	const int32_t numberof_tables =
+		ARRAY_SIZE(downscaling_db_table);
+	const int32_t numberof_rows =
+		ARRAY_SIZE(downscaling_db_table[0]);
+	const int32_t numberof_columns =
+		ARRAY_SIZE(downscaling_db_table[0][0]);
+
+	int32_t indexof_table = 0;
+
+	if (!allocate_3d_storage(filter->ctx, &filter->downscaling_table,
+		numberof_tables, numberof_rows, numberof_columns)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	while (indexof_table != numberof_tables) {
+		struct fixed31_32 **table =
+			filter->downscaling_table[indexof_table];
+
+		int32_t indexof_row = 0;
+
+		while (indexof_row != numberof_rows) {
+			struct fixed31_32 *row = table[indexof_row];
+
+			int32_t indexof_column = 0;
+
+			while (indexof_column != numberof_columns) {
+				row[indexof_column] =
+dal_fixed31_32_from_fraction(
+	downscaling_db_table[indexof_table][indexof_row][indexof_column],
+	CONST_DIVIDER);
+
+				++indexof_column;
+			}
+
+			++indexof_row;
+		}
+
+		++indexof_table;
+	}
+
+	return true;
+}
+
+static inline void destroy_downscaling_table(
+	struct scaler_filter *filter)
+{
+	destroy_3d_storage(
+		filter->ctx,
+		&filter->downscaling_table,
+		ARRAY_SIZE(downscaling_db_table),
+		ARRAY_SIZE(downscaling_db_table[0]));
+}
+
+static bool create_upscaling_table(
+	struct scaler_filter *filter)
+{
+	const int32_t numberof_tables =
+		ARRAY_SIZE(upscaling_db_table);
+	const int32_t numberof_rows =
+		ARRAY_SIZE(upscaling_db_table[0]);
+	const int32_t numberof_columns =
+		ARRAY_SIZE(upscaling_db_table[0][0]);
+
+	int32_t indexof_table = 0;
+
+	if (!allocate_3d_storage(filter->ctx, &filter->upscaling_table,
+		numberof_tables, numberof_rows, numberof_columns)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	while (indexof_table != numberof_tables) {
+		struct fixed31_32 **table =
+			filter->upscaling_table[indexof_table];
+
+		int32_t indexof_row = 0;
+
+		while (indexof_row != numberof_rows) {
+			struct fixed31_32 *row = table[indexof_row];
+
+			int32_t indexof_column = 0;
+
+			while (indexof_column != numberof_columns) {
+				row[indexof_column] =
+dal_fixed31_32_from_fraction(
+	upscaling_db_table[indexof_table][indexof_row][indexof_column],
+	CONST_DIVIDER);
+
+				++indexof_column;
+			}
+
+			++indexof_row;
+		}
+
+		++indexof_table;
+	}
+
+	return true;
+}
+
+static inline void destroy_upscaling_table(
+	struct scaler_filter *filter)
+{
+	destroy_3d_storage(
+		filter->ctx,
+		&filter->upscaling_table,
+		ARRAY_SIZE(upscaling_db_table),
+		ARRAY_SIZE(upscaling_db_table[0]));
+}
+
+static bool same_filter_required(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	uint32_t src_size,
+	uint32_t dst_size)
+{
+	if (!filter->src_size)
+		return false;
+	if (!filter->dst_size)
+		return false;
+	if (filter->src_size != src_size)
+		return false;
+	if (filter->dst_size != dst_size)
+		return false;
+	if (filter->params.taps != params->taps)
+		return false;
+	if (filter->params.phases != params->phases)
+		return false;
+	if (filter->params.sharpness != params->sharpness)
+		return false;
+
+	return true;
+}
+
+/*
+ * @brief
+ *                                            (scale_max - scale_min)
+ * result = scale_min + (value - value_min) * -----------------------
+ *                                            (value_max - value_min)
+ */
+
+static struct fixed31_32 interpolate(
+	struct fixed31_32 value,
+	struct fixed31_32 value_min,
+	struct fixed31_32 value_max,
+	struct fixed31_32 scale_min,
+	struct fixed31_32 scale_max)
+{
+	return dal_fixed31_32_add(
+		scale_min,
+		dal_fixed31_32_div(
+			dal_fixed31_32_mul(
+				dal_fixed31_32_sub(
+					value,
+					value_min),
+				dal_fixed31_32_sub(
+					scale_max,
+					scale_min)),
+			dal_fixed31_32_sub(
+				value_max,
+				value_min)));
+}
+
+static bool map_sharpness(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	uint32_t src_size,
+	uint32_t dst_size,
+	struct fixed31_32 *attenuation,
+	struct fixed31_32 *decibels_at_nyquist)
+{
+	struct fixed31_32 ratio = dal_fixed31_32_from_fraction(
+		dst_size,
+		src_size);
+
+	const struct fixed31_32 sharp_flat =
+		dal_fixed31_32_from_fraction(MIN_SHARPNESS + MAX_SHARPNESS, 2);
+
+	struct fixed31_32 sharp_max =
+		dal_fixed31_32_from_int(MAX_SHARPNESS);
+	struct fixed31_32 sharp_min =
+		dal_fixed31_32_from_int(MIN_SHARPNESS);
+
+	uint32_t index = params->taps - 3;
+
+	struct fixed31_32 ratio_low;
+	struct fixed31_32 ratio_up;
+
+	struct fixed31_32 db_min;
+	struct fixed31_32 db_flat;
+	struct fixed31_32 db_max;
+	struct fixed31_32 db_value;
+
+	uint32_t i0;
+	uint32_t i1;
+	uint32_t row0;
+	uint32_t row1;
+
+	int32_t sharp = params->sharpness;
+
+	if (sharp < MIN_SHARPNESS)
+		sharp = MIN_SHARPNESS;
+	else if (sharp > MAX_SHARPNESS)
+		sharp = MAX_SHARPNESS;
+
+	if (params->flags.bits.HORIZONTAL) {
+		if (dal_fixed31_32_lt(ratio, max_hor_downscale())) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		} else if (dal_fixed31_32_lt(
+			max_hor_upscale(), ratio)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+	} else {
+		if (dal_fixed31_32_lt(ratio, max_ver_downscale())) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		} else if (dal_fixed31_32_lt(
+			max_ver_upscale(), ratio)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+	}
+
+	if (dst_size >= src_size) {
+		if (sharp < 0) {
+			db_max = up_db_flat();
+			db_min = up_db_fuzzy();
+
+			sharp_max = sharp_flat;
+		} else {
+			db_max = up_db_sharp();
+			db_min = up_db_flat();
+
+			sharp_min = sharp_flat;
+		}
+
+		db_value = interpolate(
+			dal_fixed31_32_from_int(sharp),
+			sharp_min, sharp_max,
+			db_min, db_max);
+
+		i0 = 0;
+
+		while (dal_fixed31_32_lt(
+			db_value, filter->upscaling_table[index][0][i0]) &&
+			(i0 < UP_DB_POINTS - 1))
+			++i0;
+
+		i1 = i0 + 1;
+
+		if (i0 == UP_DB_POINTS - 1)
+			i1 = i0--;
+
+		sharp_max = filter->upscaling_table[index][1][i0];
+		sharp_min = filter->upscaling_table[index][1][i1];
+
+		db_max = filter->upscaling_table[index][0][i0];
+		db_min = filter->upscaling_table[index][0][i1];
+
+		*attenuation = interpolate(
+			db_value,
+			db_max, db_min,
+			sharp_max, sharp_min);
+
+		*decibels_at_nyquist = db_value;
+
+		return true;
+	} else if ((5 * dst_size) < (src_size << 2)) {
+		if (sharp < 0) {
+			db_max = down_db_flat();
+			db_min = down_db_fuzzy();
+
+			sharp_max = sharp_flat;
+		} else {
+			db_max = down_db_sharp();
+			db_min = down_db_flat();
+
+			sharp_min = sharp_flat;
+		}
+
+		db_value = interpolate(
+			dal_fixed31_32_from_int(sharp),
+			sharp_min, sharp_max,
+			db_min, db_max);
+	} else {
+		struct fixed31_32 db_value_min =
+			filter->downscaling_table[index][0][0];
+
+		struct fixed31_32 db_value_max =
+			filter->downscaling_table[index][0][DOWN_DB_POINTS - 1];
+
+		db_min = interpolate(
+			ratio,
+			threshold_ratio_low(), threshold_ratio_up(),
+			down_db_fuzzy(), up_db_fuzzy());
+
+		db_flat = interpolate(
+			ratio,
+			threshold_ratio_low(), threshold_ratio_up(),
+			down_db_flat(), up_db_flat());
+
+		db_max = interpolate(
+			ratio,
+			threshold_ratio_low(), threshold_ratio_up(),
+			down_db_sharp(), up_db_sharp());
+
+		if (sharp < 0) {
+			db_max = db_flat;
+
+			db_value = interpolate(
+				dal_fixed31_32_from_int(sharp),
+				sharp_min, dal_fixed31_32_zero,
+				db_min, db_max);
+		} else {
+			db_min = db_flat;
+
+			db_value = interpolate(
+				dal_fixed31_32_from_int(sharp),
+				dal_fixed31_32_zero, sharp_max,
+				db_min, db_max);
+		}
+
+		if (dal_fixed31_32_lt(db_value_min, db_value))
+			db_value = db_value_min;
+		else if (dal_fixed31_32_lt(db_value, db_value_max))
+			db_value = db_value_max;
+	}
+
+	i1 = 0;
+
+	while (dal_fixed31_32_lt(db_value,
+		filter->downscaling_table[index][0][i1]) &&
+		(i1 < DOWN_DB_POINTS - 1))
+		++i1;
+
+	if (i1 == 0)
+		i0 = i1++;
+	else
+		i0 = i1 - 1;
+
+	row0 = dal_fixed31_32_round(
+		dal_fixed31_32_mul_int(ratio, DOWN_DB_SCALES));
+
+	if (dal_fixed31_32_lt(
+		dal_fixed31_32_from_fraction(row0, DOWN_DB_SCALES), ratio)) {
+		row1 = row0 + 1;
+
+		if (row1 > DOWN_DB_SCALES) {
+			row1 = DOWN_DB_SCALES;
+			row0 = row1 - 1;
+		}
+	} else {
+		row1 = row0--;
+
+		if (row0 < 1) {
+			row0 = 1;
+			row1 = 2;
+		}
+	}
+
+	ratio_low = dal_fixed31_32_from_fraction(row0, DOWN_DB_SCALES);
+	ratio_up = dal_fixed31_32_from_fraction(row1, DOWN_DB_SCALES);
+
+	sharp_max = interpolate(
+		ratio,
+		ratio_low, ratio_up,
+		filter->downscaling_table[index][row0][i0],
+		filter->downscaling_table[index][row1][i0]);
+
+	sharp_min = interpolate(
+		ratio,
+		ratio_low, ratio_up,
+		filter->downscaling_table[index][row0][i1],
+		filter->downscaling_table[index][row1][i1]);
+
+	db_max = filter->downscaling_table[index][0][i0];
+	db_min = filter->downscaling_table[index][0][i1];
+
+	*attenuation = interpolate(
+		db_value,
+		db_max, db_min,
+		sharp_max, sharp_min);
+
+	*decibels_at_nyquist = db_value;
+
+	return true;
+}
+
+static inline struct fixed31_32 lanczos(
+	struct fixed31_32 x,
+	struct fixed31_32 a2)
+{
+	return dal_fixed31_32_mul(
+		dal_fixed31_32_sinc(x),
+		dal_fixed31_32_sinc(
+			dal_fixed31_32_mul(x, a2)));
+}
+
+static bool generate_filter(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	struct fixed31_32 attenuation,
+	struct fixed31_32 *ringing)
+{
+	uint32_t n = params->phases * params->taps;
+
+	uint32_t coefficients_quantity = n;
+	uint32_t coefficients_sum_quantity = params->phases;
+
+	uint32_t i;
+	uint32_t i_limit;
+	uint32_t j;
+	uint32_t m;
+
+	struct fixed31_32 attenby2;
+
+	struct fixed31_32 a_max = dal_fixed31_32_zero;
+	struct fixed31_32 a_min = dal_fixed31_32_zero;
+
+	if (filter->coefficients_quantity < coefficients_quantity) {
+		if (filter->coefficients) {
+			dm_free(filter->ctx, filter->coefficients);
+
+			filter->coefficients = NULL;
+			filter->coefficients_quantity = 0;
+		}
+
+		filter->coefficients = dm_alloc(
+			filter->ctx,
+			coefficients_quantity * sizeof(struct fixed31_32));
+
+		if (!filter->coefficients) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		filter->coefficients_quantity = coefficients_quantity;
+	}
+
+	i = 0;
+
+	while (i != filter->coefficients_quantity) {
+		filter->coefficients[i] = dal_fixed31_32_zero;
+
+		++i;
+	}
+
+	if (filter->coefficients_sum_quantity < coefficients_sum_quantity) {
+		if (filter->coefficients_sum) {
+			dm_free(filter->ctx, filter->coefficients_sum);
+
+			filter->coefficients_sum = NULL;
+			filter->coefficients_sum_quantity = 0;
+		}
+
+		filter->coefficients_sum = dm_alloc(
+			filter->ctx,
+			coefficients_sum_quantity * sizeof(struct fixed31_32));
+
+		if (!filter->coefficients_sum) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		filter->coefficients_sum_quantity = coefficients_sum_quantity;
+	}
+
+	i = 0;
+
+	while (i != filter->coefficients_sum_quantity) {
+		filter->coefficients_sum[i] = dal_fixed31_32_zero;
+
+		++i;
+	}
+
+	m = 0;
+
+	attenby2 = dal_fixed31_32_div_int(
+		dal_fixed31_32_mul_int(attenuation, params->taps), 2);
+
+	i = 1;
+
+	while (i <= params->taps) {
+		j = 0;
+
+		while (j != params->phases) {
+			struct fixed31_32 x = dal_fixed31_32_mul(
+				dal_fixed31_32_pi,
+				dal_fixed31_32_from_fraction(
+					(int64_t)(m << 1) - n, n));
+
+			uint32_t index =
+				(params->taps - i) * params->phases + j;
+
+			filter->coefficients[index] = lanczos(x, attenby2);
+
+			++m;
+
+			++j;
+		}
+
+		++i;
+	}
+
+	i = 0;
+
+	while (i != params->phases) {
+		filter->coefficients_sum[i] = dal_fixed31_32_zero;
+
+		m = i;
+
+		j = 0;
+
+		while (j != params->taps) {
+			filter->coefficients_sum[i] =
+				dal_fixed31_32_add(
+					filter->coefficients_sum[i],
+					filter->coefficients[m]);
+
+			m += params->phases;
+
+			++j;
+		}
+
+		++i;
+	}
+
+	i = 0;
+
+	while (i != params->phases) {
+		m = i;
+
+		j = 0;
+
+		while (j != params->taps) {
+			filter->coefficients[m] =
+				dal_fixed31_32_div(
+					filter->coefficients[m],
+					filter->coefficients_sum[i]);
+
+			m += params->phases;
+
+			++j;
+		}
+
+		++i;
+	}
+
+	i = 0;
+	i_limit = (params->phases >> 1) + 1;
+
+	while (i != i_limit) {
+		m = i;
+
+		j = 0;
+
+		while (j != params->taps) {
+			struct fixed31_32 tmp = filter->coefficients[m];
+
+			filter->filter[i * params->taps + j] = tmp;
+
+			if (dal_fixed31_32_lt(
+				tmp, dal_fixed31_32_zero) &&
+				dal_fixed31_32_lt(tmp, a_min))
+				a_min = tmp;
+			else if (dal_fixed31_32_lt(
+				dal_fixed31_32_zero, tmp) &&
+				dal_fixed31_32_lt(a_max, tmp))
+				a_max = tmp;
+
+			m += params->phases;
+
+			++j;
+		}
+
+		++i;
+	}
+
+	if (dal_fixed31_32_eq(a_min, dal_fixed31_32_zero))
+		*ringing = dal_fixed31_32_from_int(100);
+	else
+		*ringing = dal_fixed31_32_min(
+			dal_fixed31_32_abs(
+				dal_fixed31_32_div(a_max, a_min)),
+			dal_fixed31_32_from_int(100));
+
+	return true;
+}
+
+static bool construct_scaler_filter(
+	struct dc_context *ctx,
+	struct scaler_filter *filter)
+{
+	filter->src_size = 0;
+	filter->dst_size = 0;
+	filter->filter = NULL;
+	filter->integer_filter = NULL;
+	filter->filter_size_allocated = 0;
+	filter->filter_size_effective = 0;
+	filter->coefficients = NULL;
+	filter->coefficients_quantity = 0;
+	filter->coefficients_sum = NULL;
+	filter->coefficients_sum_quantity = 0;
+	filter->downscaling_table = NULL;
+	filter->upscaling_table = NULL;
+	filter->ctx = ctx;
+
+	if (!create_downscaling_table(filter)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!create_upscaling_table(filter)) {
+		BREAK_TO_DEBUGGER();
+		destroy_downscaling_table(filter);
+		return false;
+	}
+
+	return true;
+}
+
+static void destruct_scaler_filter(
+	struct scaler_filter *filter)
+{
+	if (filter->coefficients_sum)
+		dm_free(filter->ctx, filter->coefficients_sum);
+
+	if (filter->coefficients)
+		dm_free(filter->ctx, filter->coefficients);
+
+	if (filter->integer_filter)
+		dm_free(filter->ctx, filter->integer_filter);
+
+	if (filter->filter)
+		dm_free(filter->ctx, filter->filter);
+
+	destroy_upscaling_table(filter);
+
+	destroy_downscaling_table(filter);
+}
+
+struct scaler_filter *dal_scaler_filter_create(struct dc_context *ctx)
+{
+	struct scaler_filter *filter =
+		dm_alloc(ctx, sizeof(struct scaler_filter));
+
+	if (!filter) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (construct_scaler_filter(ctx, filter))
+		return filter;
+
+	BREAK_TO_DEBUGGER();
+
+	dm_free(ctx, filter);
+
+	return NULL;
+}
+
+bool dal_scaler_filter_generate(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	uint32_t src_size,
+	uint32_t dst_size)
+{
+	uint32_t filter_size_required;
+
+	struct fixed31_32 attenuation;
+	struct fixed31_32 decibels_at_nyquist;
+	struct fixed31_32 ringing;
+
+	if (!params) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if ((params->taps < 3) || (params->taps > 16)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!src_size || !dst_size) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (same_filter_required(filter, params, src_size, dst_size))
+		return true;
+
+	filter_size_required =
+		params->taps * ((params->phases >> 1) + 1);
+
+	if (filter_size_required > filter->filter_size_allocated) {
+		if (filter->filter) {
+			dm_free(filter->ctx, filter->filter);
+
+			filter->filter = 0;
+			filter->filter_size_allocated = 0;
+		}
+
+		filter->filter = dm_alloc(
+			filter->ctx,
+			filter_size_required * sizeof(struct fixed31_32));
+
+		if (!filter->filter) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (filter->integer_filter) {
+			dm_free(filter->ctx, filter->integer_filter);
+
+			filter->integer_filter = 0;
+		}
+
+		filter->integer_filter = dm_alloc(
+			filter->ctx,
+			filter_size_required * sizeof(uint32_t));
+
+		if (!filter->integer_filter) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		filter->filter_size_allocated = filter_size_required;
+	}
+
+	filter->filter_size_effective = filter_size_required;
+
+	if (!map_sharpness(filter, params, src_size, dst_size,
+		&attenuation, &decibels_at_nyquist)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!generate_filter(filter, params, attenuation, &ringing)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	filter->params = *params;
+	filter->src_size = src_size;
+	filter->dst_size = dst_size;
+
+	return true;
+}
+
+const struct fixed31_32 *dal_scaler_filter_get(
+	const struct scaler_filter *filter,
+	uint32_t **data,
+	uint32_t *number)
+{
+	if (!number) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (!data) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	*number = filter->filter_size_effective;
+	*data = filter->integer_filter;
+
+	return filter->filter;
+}
+
+void dal_scaler_filter_destroy(
+	struct scaler_filter **filter)
+{
+	if (!filter || !*filter) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct_scaler_filter(*filter);
+
+	dm_free((*filter)->ctx, *filter);
+
+	*filter = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
new file mode 100644
index 000000000000..668691d6c6e6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
@@ -0,0 +1,74 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SCALER_FILTER_H__
+#define __DAL_SCALER_FILTER_H__
+
+struct scaler_filter_params {
+	uint32_t taps; /* 3...16 */
+	uint32_t phases;
+	int32_t sharpness; /* -50...50 */
+	union {
+		struct {
+			uint32_t HORIZONTAL:1;
+			uint32_t RESERVED:31;
+		} bits;
+		uint32_t value;
+	} flags;
+};
+
+struct q31_32;
+
+struct scaler_filter {
+	struct scaler_filter_params params;
+	uint32_t src_size;
+	uint32_t dst_size;
+	struct fixed31_32 *filter;
+	uint32_t *integer_filter;
+	uint32_t filter_size_allocated;
+	uint32_t filter_size_effective;
+	struct fixed31_32 *coefficients;
+	uint32_t coefficients_quantity;
+	struct fixed31_32 *coefficients_sum;
+	uint32_t coefficients_sum_quantity;
+	struct fixed31_32 ***downscaling_table;
+	struct fixed31_32 ***upscaling_table;
+	struct dc_context *ctx;
+};
+
+struct scaler_filter *dal_scaler_filter_create(struct dc_context *ctx);
+void dal_scaler_filter_destroy(struct scaler_filter **ptr);
+
+bool dal_scaler_filter_generate(
+	struct scaler_filter *filter,
+	const struct scaler_filter_params *params,
+	uint32_t src_size,
+	uint32_t dst_size);
+
+const struct fixed31_32 *dal_scaler_filter_get(
+	const struct scaler_filter *filter,
+	uint32_t **data,
+	uint32_t *number);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 13/26] drm/amd/dal: Add encoder HW programming
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (11 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 12/26] drm/amd/dal: Bandwidth calculations Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 14/26] drm/amd/dal: Add clock source " Harry Wentland
                     ` (12 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Responsible for programming back-end of display path, such as DIG,
UNIPHY, DP, DAC, and DVO.
Supports:
- DisplayPort (single stream)
- HDMI
- DVI
- eDP

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.c    | 1927 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.h    |  156 ++
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.c  | 1123 ++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.h  |  122 ++
 4 files changed, 3328 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
new file mode 100644
index 000000000000..f714215c0dd5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
@@ -0,0 +1,1927 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "core_types.h"
+#include "link_encoder.h"
+#include "stream_encoder.h"
+#include "dce110_link_encoder.h"
+
+#include "i2caux_interface.h"
+#include "dc_bios_types.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dce/dce_11_0_enum.h"
+
+#define LINK_REG(reg)\
+	(enc110->link_regs->reg)
+
+#define AUX_REG(reg)\
+	(enc110->aux_regs->reg)
+
+#define BL_REG(reg)\
+	(enc110->bl_regs->reg)
+
+/* For current ASICs pixel clock - 600MHz */
+#define MAX_ENCODER_CLK 600000
+
+#define DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ 600000
+
+#define DEFAULT_AUX_MAX_DATA_SIZE 16
+#define AUX_MAX_DEFER_WRITE_RETRY 20
+/*
+ * @brief
+ * Trigger Source Select
+ * ASIC-dependent, actual values for register programming
+ */
+#define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x0
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x1
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x2
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x4
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x08
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x10
+#define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20
+
+/* all values are in milliseconds */
+/* For eDP, after power-up/power/down,
+ * 300/500 msec max. delay from LCDVCC to black video generation */
+#define PANEL_POWER_UP_TIMEOUT 300
+#define PANEL_POWER_DOWN_TIMEOUT 500
+#define HPD_CHECK_INTERVAL 10
+
+/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */
+#define TMDS_MIN_PIXEL_CLOCK 25000
+/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */
+#define TMDS_MAX_PIXEL_CLOCK 165000
+/* For current ASICs pixel clock - 600MHz */
+#define MAX_ENCODER_CLOCK 600000
+
+enum {
+	DP_MST_UPDATE_MAX_RETRY = 50
+};
+
+#define DIG_REG(reg)\
+	(reg + enc110->offsets.dig)
+
+#define DP_REG(reg)\
+	(reg + enc110->offsets.dp)
+
+static struct link_encoder_funcs dce110_lnk_enc_funcs = {
+	.validate_output_with_stream =
+		dce110_link_encoder_validate_output_with_stream,
+	.hw_init = dce110_link_encoder_hw_init,
+	.setup = dce110_link_encoder_setup,
+	.enable_tmds_output = dce110_link_encoder_enable_tmds_output,
+	.enable_dp_output = dce110_link_encoder_enable_dp_output,
+	.enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,
+	.disable_output = dce110_link_encoder_disable_output,
+	.dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
+	.dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
+	.update_mst_stream_allocation_table =
+		dce110_link_encoder_update_mst_stream_allocation_table,
+	.set_lcd_backlight_level = dce110_link_encoder_set_lcd_backlight_level,
+	.backlight_control = dce110_link_encoder_edp_backlight_control,
+	.power_control = dce110_link_encoder_edp_power_control,
+	.connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe
+};
+
+static enum bp_result link_transmitter_control(
+	struct dce110_link_encoder *enc110,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result;
+	struct dc_bios *bp = dal_adapter_service_get_bios_parser(
+					enc110->base.adapter_service);
+
+	result = bp->funcs->transmitter_control(bp, cntl);
+
+	return result;
+}
+
+static void enable_phy_bypass_mode(
+	struct dce110_link_encoder *enc110,
+	bool enable)
+{
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	const uint32_t addr = LINK_REG(DP_DPHY_CNTL);
+
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, enable, DP_DPHY_CNTL, DPHY_BYPASS);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void disable_prbs_symbols(
+	struct dce110_link_encoder *enc110,
+	bool disable)
+{
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	const uint32_t addr = LINK_REG(DP_DPHY_CNTL);
+
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, disable,
+			DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0);
+
+	set_reg_field_value(value, disable,
+			DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1);
+
+	set_reg_field_value(value, disable,
+			DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2);
+
+	set_reg_field_value(value, disable,
+			DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void disable_prbs_mode(
+	struct dce110_link_encoder *enc110)
+{
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	const uint32_t addr = LINK_REG(DP_DPHY_PRBS_CNTL);
+	uint32_t value;
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, 0, DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void program_pattern_symbols(
+	struct dce110_link_encoder *enc110,
+	uint16_t pattern_symbols[8])
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+
+	addr = LINK_REG(DP_DPHY_SYM0);
+
+	value = 0;
+	set_reg_field_value(value, pattern_symbols[0],
+			DP_DPHY_SYM0, DPHY_SYM1);
+	set_reg_field_value(value, pattern_symbols[1],
+			DP_DPHY_SYM0, DPHY_SYM2);
+	set_reg_field_value(value, pattern_symbols[2],
+			DP_DPHY_SYM0, DPHY_SYM3);
+	dm_write_reg(ctx, addr, value);
+
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+
+	addr = LINK_REG(DP_DPHY_SYM1);
+
+	value = 0;
+	set_reg_field_value(value, pattern_symbols[3],
+			DP_DPHY_SYM1, DPHY_SYM4);
+	set_reg_field_value(value, pattern_symbols[4],
+			DP_DPHY_SYM1, DPHY_SYM5);
+	set_reg_field_value(value, pattern_symbols[5],
+			DP_DPHY_SYM1, DPHY_SYM6);
+	dm_write_reg(ctx, addr, value);
+
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	addr = LINK_REG(DP_DPHY_SYM2);
+	value = 0;
+	set_reg_field_value(value, pattern_symbols[6],
+			DP_DPHY_SYM2, DPHY_SYM7);
+	set_reg_field_value(value, pattern_symbols[6],
+			DP_DPHY_SYM2, DPHY_SYM8);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_dp_phy_pattern_d102(
+	struct dce110_link_encoder *enc110)
+{
+	/* Disable PHY Bypass mode to setup the test pattern */
+	enable_phy_bypass_mode(enc110, false);
+
+	/* For 10-bit PRBS or debug symbols
+	 * please use the following sequence: */
+
+	/* Enable debug symbols on the lanes */
+
+	disable_prbs_symbols(enc110, true);
+
+	/* Disable PRBS mode,
+	 * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */
+
+	disable_prbs_mode(enc110);
+
+	/* Program debug symbols to be output */
+	{
+		uint16_t pattern_symbols[8] = {
+			0x2AA, 0x2AA, 0x2AA, 0x2AA,
+			0x2AA, 0x2AA, 0x2AA, 0x2AA
+		};
+
+		program_pattern_symbols(enc110, pattern_symbols);
+	}
+
+	/* Enable phy bypass mode to enable the test pattern */
+
+	enable_phy_bypass_mode(enc110, true);
+}
+
+static void set_link_training_complete(
+	struct dce110_link_encoder *enc110,
+	bool complete)
+{
+	/* This register resides in DP back end block;
+	 * transmitter is used for the offset */
+	struct dc_context *ctx = enc110->base.ctx;
+	const uint32_t addr = LINK_REG(DP_LINK_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, complete,
+			DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_dp_phy_pattern_training_pattern(
+	struct dce110_link_encoder *enc110,
+	uint32_t index)
+{
+	/* Write Training Pattern */
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DP_DPHY_TRAINING_PATTERN_SEL);
+
+	dm_write_reg(ctx, addr, index);
+
+	/* Set HW Register Training Complete to false */
+
+	set_link_training_complete(enc110, false);
+
+	/* Disable PHY Bypass mode to output Training Pattern */
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* Disable PRBS mode,
+	 * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */
+
+	disable_prbs_mode(enc110);
+}
+
+static void set_dp_phy_pattern_symbol_error(
+	struct dce110_link_encoder *enc110)
+{
+	/* Disable PHY Bypass mode to setup the test pattern */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* program correct panel mode*/
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_INTERNAL_CTRL);
+		uint32_t value = 0x0;
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* A PRBS23 pattern is used for most DP electrical measurements. */
+
+	/* Enable PRBS symbols on the lanes */
+
+	disable_prbs_symbols(enc110, false);
+
+	/* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_PRBS_CNTL);
+		uint32_t value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(value, 1,
+				DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL);
+		set_reg_field_value(value, 1,
+				DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN);
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* Enable phy bypass mode to enable the test pattern */
+
+	enable_phy_bypass_mode(enc110, true);
+}
+
+static void set_dp_phy_pattern_prbs7(
+	struct dce110_link_encoder *enc110)
+{
+	/* Disable PHY Bypass mode to setup the test pattern */
+	struct dc_context *ctx = enc110->base.ctx;
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* A PRBS7 pattern is used for most DP electrical measurements. */
+
+	/* Enable PRBS symbols on the lanes */
+
+	disable_prbs_symbols(enc110, false);
+
+	/* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_PRBS_CNTL);
+
+		uint32_t value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(value, 0,
+				DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL);
+
+		set_reg_field_value(value, 1,
+				DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* Enable phy bypass mode to enable the test pattern */
+
+	enable_phy_bypass_mode(enc110, true);
+}
+
+static void set_dp_phy_pattern_80bit_custom(
+	struct dce110_link_encoder *enc110,
+	const uint8_t *pattern)
+{
+	/* Disable PHY Bypass mode to setup the test pattern */
+	enable_phy_bypass_mode(enc110, false);
+
+	/* Enable debug symbols on the lanes */
+
+	disable_prbs_symbols(enc110, true);
+
+	/* Enable PHY bypass mode to enable the test pattern */
+	/* TODO is it really needed ? */
+
+	enable_phy_bypass_mode(enc110, true);
+
+	/* Program 80 bit custom pattern */
+	{
+		uint16_t pattern_symbols[8];
+
+		pattern_symbols[0] =
+			((pattern[1] & 0x03) << 8) | pattern[0];
+		pattern_symbols[1] =
+			((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f);
+		pattern_symbols[2] =
+			((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f);
+		pattern_symbols[3] =
+			(pattern[4] << 2) | ((pattern[3] >> 6) & 0x03);
+		pattern_symbols[4] =
+			((pattern[6] & 0x03) << 8) | pattern[5];
+		pattern_symbols[5] =
+			((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f);
+		pattern_symbols[6] =
+			((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f);
+		pattern_symbols[7] =
+			(pattern[9] << 2) | ((pattern[8] >> 6) & 0x03);
+
+		program_pattern_symbols(enc110, pattern_symbols);
+	}
+
+	/* Enable phy bypass mode to enable the test pattern */
+
+	enable_phy_bypass_mode(enc110, true);
+}
+
+static void set_dp_phy_pattern_hbr2_compliance(
+	struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	/* previously there is a register DP_HBR2_EYE_PATTERN
+	 * that is enabled to get the pattern.
+	 * But it does not work with the latest spec change,
+	 * so we are programming the following registers manually.
+	 *
+	 * The following settings have been confirmed
+	 * by Nick Chorney and Sandra Liu */
+
+	/* Disable PHY Bypass mode to setup the test pattern */
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* Setup DIG encoder in DP SST mode */
+
+	enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);
+
+	/* program correct panel mode*/
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_INTERNAL_CTRL);
+		uint32_t value = 0x0;
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* no vbid after BS (SR)
+	 * DP_LINK_FRAMING_CNTL changed history Sandra Liu
+	 * 11000260 / 11000104 / 110000FC */
+
+	/* TODO DP_LINK_FRAMING_CNTL should always use hardware default value
+	 * output  except output hbr2_compliance pattern for physical PHY
+	 * measurement. This is not normal usage case. SW should reset this
+	 * register to hardware default value after end use of HBR2 eye
+	 */
+	BREAK_TO_DEBUGGER();
+	/* TODO: do we still need this, find out at compliance test
+	addr = mmDP_LINK_FRAMING_CNTL + fe_addr_offset;
+
+	value = (ctx, addr);
+
+	set_reg_field_value(value, 0xFC,
+			DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL);
+	set_reg_field_value(value, 1,
+			DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE);
+	set_reg_field_value(value, 1,
+			DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE);
+
+	dal_write_reg(ctx, addr, value);
+	 */
+
+	/*TODO add support for this test pattern
+	 * support_dp_hbr2_eye_pattern
+	 */
+
+	/* set link training complete */
+	set_link_training_complete(enc110, true);
+	/* do not enable video stream */
+	addr = LINK_REG(DP_VID_STREAM_CNTL);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, 0, DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* Disable PHY Bypass mode to setup the test pattern */
+
+	enable_phy_bypass_mode(enc110, false);
+}
+
+static void set_dp_phy_pattern_passthrough_mode(
+	struct dce110_link_encoder *enc110,
+	enum dp_panel_mode panel_mode)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+
+	/* program correct panel mode */
+	{
+		const uint32_t addr = LINK_REG(DP_DPHY_INTERNAL_CTRL);
+
+		uint32_t value;
+
+		value = dm_read_reg(ctx, addr);
+
+		switch (panel_mode) {
+		case DP_PANEL_MODE_EDP:
+			value = 0x1;
+		break;
+		case DP_PANEL_MODE_SPECIAL:
+			value = 0x11;
+		break;
+		default:
+			value = 0x0;
+			break;
+		}
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* set link training complete */
+
+	set_link_training_complete(enc110, true);
+
+	/* Disable PHY Bypass mode to setup the test pattern */
+
+	enable_phy_bypass_mode(enc110, false);
+
+	/* Disable PRBS mode,
+	 * make sure DPHY_PRBS_CNTL.DPHY_PRBS_EN=0 */
+
+	disable_prbs_mode(enc110);
+}
+
+/* return value is bit-vector */
+static uint8_t get_frontend_source(
+	enum engine_id engine)
+{
+	switch (engine) {
+	case ENGINE_ID_DIGA:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGA;
+	case ENGINE_ID_DIGB:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGB;
+	case ENGINE_ID_DIGC:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGC;
+	case ENGINE_ID_DIGD:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGD;
+	case ENGINE_ID_DIGE:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGE;
+	case ENGINE_ID_DIGF:
+		return DCE110_DIG_FE_SOURCE_SELECT_DIGF;
+	default:
+		ASSERT_CRITICAL(false);
+		return DCE110_DIG_FE_SOURCE_SELECT_INVALID;
+	}
+}
+
+static void configure_encoder(
+	struct dce110_link_encoder *enc110,
+	const struct link_settings *link_settings)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	/* set number of lanes */
+	addr = LINK_REG(DP_CONFIG);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, link_settings->lane_count - LANE_COUNT_ONE,
+			DP_CONFIG, DP_UDI_LANES);
+	dm_write_reg(ctx, addr, value);
+
+}
+
+static bool is_panel_powered_on(struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t value;
+	bool ret;
+
+	value = dm_read_reg(ctx,
+			BL_REG(LVTMA_PWRSEQ_STATE));
+
+	ret = get_reg_field_value(value,
+			LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R);
+
+	return ret == 1;
+}
+
+/*
+ * @brief
+ * eDP only.
+ */
+static void link_encoder_edp_wait_for_hpd_ready(
+	struct dce110_link_encoder *enc110,
+	bool power_up)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	struct adapter_service *as = enc110->base.adapter_service;
+	struct graphics_object_id connector = enc110->base.connector;
+	struct irq *hpd;
+	bool edp_hpd_high = false;
+	uint32_t time_elapsed = 0;
+	uint32_t timeout = power_up ?
+		PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
+
+	if (dal_graphics_object_id_get_connector_id(connector) !=
+		CONNECTOR_ID_EDP) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if (!power_up && dal_adapter_service_is_feature_supported(
+		FEATURE_NO_HPD_LOW_POLLING_VCC_OFF))
+		/* from KV, we will not HPD low after turning off VCC -
+		 * instead, we will check the SW timer in power_up(). */
+		return;
+
+	/* when we power on/off the eDP panel,
+	 * we need to wait until SENSE bit is high/low */
+
+	/* obtain HPD */
+
+	hpd = dal_adapter_service_obtain_hpd_irq(as, connector);
+
+	if (!hpd) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	dal_irq_open(hpd);
+
+	/* wait until timeout or panel detected */
+
+	do {
+		uint32_t detected = 0;
+
+		dal_irq_get_value(hpd, &detected);
+
+		if (!(detected ^ power_up)) {
+			edp_hpd_high = true;
+			break;
+		}
+
+		dm_sleep_in_milliseconds(ctx, HPD_CHECK_INTERVAL);
+
+		time_elapsed += HPD_CHECK_INTERVAL;
+	} while (time_elapsed < timeout);
+
+	dal_irq_close(hpd);
+
+	dal_adapter_service_release_irq(as, hpd);
+
+	if (false == edp_hpd_high) {
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: wait timed out!\n", __func__);
+	}
+}
+
+/*
+ * @brief
+ * eDP only. Control the power of the eDP panel.
+ */
+void dce110_link_encoder_edp_power_control(
+	struct link_encoder *enc,
+	bool power_up)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result bp_result;
+
+	if (dal_graphics_object_id_get_connector_id(enc110->base.connector) !=
+		CONNECTOR_ID_EDP) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if ((power_up && !is_panel_powered_on(enc110)) ||
+		(!power_up && is_panel_powered_on(enc110))) {
+
+		/* Send VBIOS command to prompt eDP panel power */
+
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: Panel Power action: %s\n",
+				__func__, (power_up ? "On":"Off"));
+
+		cntl.action = power_up ?
+			TRANSMITTER_CONTROL_POWER_ON :
+			TRANSMITTER_CONTROL_POWER_OFF;
+		cntl.transmitter = enc110->base.transmitter;
+		cntl.connector_obj_id = enc110->base.connector;
+		cntl.coherent = false;
+		cntl.lanes_number = LANE_COUNT_FOUR;
+		cntl.hpd_sel = enc110->base.hpd_source;
+
+		bp_result = link_transmitter_control(enc110, &cntl);
+
+		if (BP_RESULT_OK != bp_result) {
+
+			dal_logger_write(ctx->logger,
+					LOG_MAJOR_ERROR,
+					LOG_MINOR_HW_TRACE_RESUME_S3,
+					"%s: Panel Power bp_result: %d\n",
+					__func__, bp_result);
+		}
+	} else {
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: Skipping Panel Power action: %s\n",
+				__func__, (power_up ? "On":"Off"));
+	}
+
+	link_encoder_edp_wait_for_hpd_ready(enc110, true);
+}
+
+static void aux_initialize(
+	struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	enum hpd_source_id hpd_source = enc110->base.hpd_source;
+	uint32_t addr = AUX_REG(AUX_CONTROL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL);
+	set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN);
+	dm_write_reg(ctx, addr, value);
+
+	addr = AUX_REG(AUX_DPHY_RX_CONTROL0);
+	value = dm_read_reg(ctx, addr);
+
+	/* 1/4 window (the maximum allowed) */
+	set_reg_field_value(value, 1,
+			AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW);
+	dm_write_reg(ctx, addr, value);
+
+}
+
+/*todo: cloned in stream enc, fix*/
+static bool is_panel_backlight_on(struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t value;
+
+	value = dm_read_reg(ctx, BL_REG(LVTMA_PWRSEQ_CNTL));
+
+	return get_reg_field_value(value, LVTMA_PWRSEQ_CNTL, LVTMA_BLON);
+}
+
+/*todo: cloned in stream enc, fix*/
+/*
+ * @brief
+ * eDP only. Control the backlight of the eDP panel
+ */
+void dce110_link_encoder_edp_backlight_control(
+	struct link_encoder *enc,
+	bool enable)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+
+	if (dal_graphics_object_id_get_connector_id(enc110->base.connector)
+		!= CONNECTOR_ID_EDP) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if (enable && is_panel_backlight_on(enc110)) {
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: panel already powered up. Do nothing.\n",
+				__func__);
+		return;
+	}
+
+	if (!enable && !is_panel_powered_on(enc110)) {
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_RESUME_S3,
+				"%s: panel already powered down. Do nothing.\n",
+				__func__);
+		return;
+	}
+
+	/* Send VBIOS command to control eDP panel backlight */
+
+	dal_logger_write(ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_RESUME_S3,
+			"%s: backlight action: %s\n",
+			__func__, (enable ? "On":"Off"));
+
+	cntl.action = enable ?
+		TRANSMITTER_CONTROL_BACKLIGHT_ON :
+		TRANSMITTER_CONTROL_BACKLIGHT_OFF;
+	/*cntl.engine_id = ctx->engine;*/
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.connector_obj_id = enc110->base.connector;
+	/*todo: unhardcode*/
+	cntl.lanes_number = LANE_COUNT_FOUR;
+	cntl.hpd_sel = enc110->base.hpd_source;
+
+	/* For eDP, the following delays might need to be considered
+	 * after link training completed:
+	 * idle period - min. accounts for required BS-Idle pattern,
+	 * max. allows for source frame synchronization);
+	 * 50 msec max. delay from valid video data from source
+	 * to video on dislpay or backlight enable.
+	 *
+	 * Disable the delay for now.
+	 * Enable it in the future if necessary.
+	 */
+	/* dc_service_sleep_in_milliseconds(50); */
+	link_transmitter_control(enc110, &cntl);
+}
+
+static bool is_dig_enabled(const struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t value;
+
+	value = dm_read_reg(ctx, LINK_REG(DIG_BE_EN_CNTL));
+
+	return get_reg_field_value(value, DIG_BE_EN_CNTL, DIG_ENABLE);
+}
+
+static void link_encoder_disable(struct dce110_link_encoder *enc110)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	/* reset training pattern */
+	addr = LINK_REG(DP_DPHY_TRAINING_PATTERN_SEL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 0,
+			DP_DPHY_TRAINING_PATTERN_SEL,
+			DPHY_TRAINING_PATTERN_SEL);
+	dm_write_reg(ctx, addr, value);
+
+	/* reset training complete */
+	addr = LINK_REG(DP_LINK_CNTL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 0, DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE);
+	dm_write_reg(ctx, addr, value);
+
+	/* reset panel mode */
+	addr = LINK_REG(DP_DPHY_INTERNAL_CTRL);
+	value = 0;
+	dm_write_reg(ctx, addr, value);
+}
+
+static void hpd_initialize(
+	struct dce110_link_encoder *enc110)
+{
+	/* Associate HPD with DIG_BE */
+	struct dc_context *ctx = enc110->base.ctx;
+	enum hpd_source_id hpd_source = enc110->base.hpd_source;
+	const uint32_t addr = LINK_REG(DIG_BE_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, hpd_source, DIG_BE_CNTL, DIG_HPD_SELECT);
+	dm_write_reg(ctx, addr, value);
+}
+
+static bool validate_dvi_output(
+	const struct dce110_link_encoder *enc110,
+	enum signal_type connector_signal,
+	enum signal_type signal,
+	const struct dc_crtc_timing *crtc_timing)
+{
+	uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK;
+
+	if (enc110->base.features.max_pixel_clock < TMDS_MAX_PIXEL_CLOCK)
+		max_pixel_clock = enc110->base.features.max_pixel_clock;
+
+	if (signal == SIGNAL_TYPE_DVI_DUAL_LINK)
+		max_pixel_clock <<= 1;
+
+	/* This handles the case of HDMI downgrade to DVI we don't want to
+	 * we don't want to cap the pixel clock if the DDI is not DVI.
+	 */
+	if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK &&
+			connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
+		max_pixel_clock = enc110->base.features.max_pixel_clock;
+
+	/* DVI only support RGB pixel encoding */
+	if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB)
+		return false;
+
+	if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
+		return false;
+
+	if (crtc_timing->pix_clk_khz > max_pixel_clock)
+		return false;
+
+	/* DVI supports 6/8bpp single-link and 10/16bpp dual-link */
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_666:
+	case COLOR_DEPTH_888:
+	break;
+	case COLOR_DEPTH_101010:
+	case COLOR_DEPTH_161616:
+		if (signal != SIGNAL_TYPE_DVI_DUAL_LINK)
+			return false;
+	break;
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+static bool validate_hdmi_output(
+	const struct dce110_link_encoder *enc110,
+	const struct dc_crtc_timing *crtc_timing,
+	uint32_t max_tmds_clk_from_edid_in_mhz,
+	enum dc_color_depth max_hdmi_deep_color,
+	uint32_t max_hdmi_pixel_clock)
+{
+	enum dc_color_depth max_deep_color = max_hdmi_deep_color;
+	/* expressed in KHz */
+	uint32_t pixel_clock = 0;
+
+	/*TODO: unhardcode*/
+	max_tmds_clk_from_edid_in_mhz = 0;
+	max_hdmi_deep_color = COLOR_DEPTH_121212;
+	max_hdmi_pixel_clock = 600000;
+
+	if (max_deep_color > enc110->base.features.max_deep_color)
+		max_deep_color = enc110->base.features.max_deep_color;
+
+	if (max_deep_color < crtc_timing->display_color_depth)
+		return false;
+
+	if (crtc_timing->pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
+		return false;
+
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_666:
+		pixel_clock = (crtc_timing->pix_clk_khz * 3) >> 2;
+	break;
+	case COLOR_DEPTH_888:
+		pixel_clock = crtc_timing->pix_clk_khz;
+	break;
+	case COLOR_DEPTH_101010:
+		pixel_clock = (crtc_timing->pix_clk_khz * 10) >> 3;
+	break;
+	case COLOR_DEPTH_121212:
+		pixel_clock = (crtc_timing->pix_clk_khz * 3) >> 1;
+	break;
+	case COLOR_DEPTH_161616:
+		pixel_clock = crtc_timing->pix_clk_khz << 1;
+	break;
+	default:
+	break;
+	}
+
+	if (max_tmds_clk_from_edid_in_mhz > 0)
+		if (pixel_clock > max_tmds_clk_from_edid_in_mhz * 1000)
+			return false;
+
+	if ((pixel_clock == 0) ||
+		(pixel_clock > max_hdmi_pixel_clock) ||
+		(pixel_clock > enc110->base.features.max_pixel_clock))
+		return false;
+
+	/*
+	 * Restriction: allow non-CE mode (IT mode) to support RGB only.
+	 * When it is IT mode, the format mode will be 0,
+	 * but currently the code is broken,
+	 * VIDEO FORMAT is always 0 in validatepathMode().
+	 * Due to overscan change - need fix there and test the impact - to do.
+	 */
+	if (crtc_timing->timing_standard != TIMING_STANDARD_CEA861 &&
+		crtc_timing->timing_standard != TIMING_STANDARD_HDMI)
+		if (crtc_timing->pixel_encoding !=
+			PIXEL_ENCODING_RGB)
+			return false;
+
+	/* DCE11 HW does not support 420 */
+	if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
+		return false;
+
+	return true;
+}
+
+static bool validate_rgb_output(
+	const struct dce110_link_encoder *enc110,
+	const struct dc_crtc_timing *crtc_timing)
+{
+	if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock)
+		return false;
+
+	if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB)
+		return false;
+
+	return true;
+}
+
+static bool validate_dp_output(
+	const struct dce110_link_encoder *enc110,
+	const struct dc_crtc_timing *crtc_timing)
+{
+	if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock)
+		return false;
+
+	/* default RGB only */
+	if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
+		return true;
+
+	if (enc110->base.features.flags.bits.IS_YCBCR_CAPABLE)
+		return true;
+
+	/* for DCE 8.x or later DP Y-only feature,
+	 * we need ASIC cap + FeatureSupportDPYonly, not support 666 */
+	if (crtc_timing->flags.Y_ONLY &&
+		enc110->base.features.flags.bits.IS_YCBCR_CAPABLE &&
+		crtc_timing->display_color_depth != COLOR_DEPTH_666)
+		return true;
+
+	return false;
+}
+
+static bool validate_wireless_output(
+	const struct dce110_link_encoder *enc110,
+	const struct dc_crtc_timing *crtc_timing)
+{
+	if (crtc_timing->pix_clk_khz > enc110->base.features.max_pixel_clock)
+		return false;
+
+	/* Wireless only supports YCbCr444 */
+	if (crtc_timing->pixel_encoding ==
+			PIXEL_ENCODING_YCBCR444)
+		return true;
+
+	return false;
+}
+
+bool dce110_link_encoder_construct(
+	struct dce110_link_encoder *enc110,
+	const struct encoder_init_data *init_data,
+	const struct dce110_link_enc_registers *link_regs,
+	const struct dce110_link_enc_aux_registers *aux_regs,
+	const struct dce110_link_enc_bl_registers *bl_regs)
+{
+	struct graphics_object_encoder_cap_info enc_cap_info = {0};
+
+	enc110->base.funcs = &dce110_lnk_enc_funcs;
+	enc110->base.ctx = init_data->ctx;
+	enc110->base.id = init_data->encoder;
+
+	enc110->base.hpd_source = init_data->hpd_source;
+	enc110->base.connector = init_data->connector;
+	enc110->base.input_signals = SIGNAL_TYPE_ALL;
+
+	enc110->base.adapter_service = init_data->adapter_service;
+
+	enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
+
+	enc110->base.features.flags.raw = 0;
+
+	enc110->base.transmitter = init_data->transmitter;
+
+	enc110->base.features.flags.bits.IS_AUDIO_CAPABLE = true;
+
+	enc110->base.features.max_pixel_clock =
+		DCE11_UNIPHY_MAX_PIXEL_CLK_IN_KHZ;
+
+	/* set the flag to indicate whether driver poll the I2C data pin
+	 * while doing the DP sink detect
+	 */
+
+	if (dal_adapter_service_is_feature_supported(
+		FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
+		enc110->base.features.flags.bits.
+			DP_SINK_DETECT_POLL_DATA_PIN = true;
+
+	enc110->base.output_signals =
+		SIGNAL_TYPE_DVI_SINGLE_LINK |
+		SIGNAL_TYPE_DVI_DUAL_LINK |
+		SIGNAL_TYPE_LVDS |
+		SIGNAL_TYPE_DISPLAY_PORT |
+		SIGNAL_TYPE_DISPLAY_PORT_MST |
+		SIGNAL_TYPE_EDP |
+		SIGNAL_TYPE_HDMI_TYPE_A;
+
+	/* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.
+	 * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.
+	 * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer
+	 * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.
+	 * Prefer DIG assignment is decided by board design.
+	 * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design
+	 * and VBIOS will filter out 7 UNIPHY for DCE 8.0.
+	 * By this, adding DIGG should not hurt DCE 8.0.
+	 * This will let DCE 8.1 share DCE 8.0 as much as possible
+	 */
+
+	enc110->link_regs = link_regs;
+	enc110->aux_regs = aux_regs;
+	enc110->bl_regs = bl_regs;
+
+	switch (enc110->base.transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+		enc110->base.preferred_engine = ENGINE_ID_DIGA;
+	break;
+	case TRANSMITTER_UNIPHY_B:
+		enc110->base.preferred_engine = ENGINE_ID_DIGB;
+	break;
+	case TRANSMITTER_UNIPHY_C:
+		enc110->base.preferred_engine = ENGINE_ID_DIGC;
+	break;
+	case TRANSMITTER_UNIPHY_D:
+		enc110->base.preferred_engine = ENGINE_ID_DIGD;
+	break;
+	case TRANSMITTER_UNIPHY_E:
+		enc110->base.preferred_engine = ENGINE_ID_DIGE;
+	break;
+	case TRANSMITTER_UNIPHY_F:
+		enc110->base.preferred_engine = ENGINE_ID_DIGF;
+	break;
+	default:
+		ASSERT_CRITICAL(false);
+		enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
+	}
+
+	dal_logger_write(init_data->ctx->logger,
+			LOG_MAJOR_I2C_AUX,
+			LOG_MINOR_I2C_AUX_CFG,
+			"Using channel: %s [%d]\n",
+			DECODE_CHANNEL_ID(init_data->channel),
+			init_data->channel);
+
+	/* Override features with DCE-specific values */
+	if (dal_adapter_service_get_encoder_cap_info(
+			enc110->base.adapter_service,
+			enc110->base.id, &enc_cap_info))
+		enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
+				enc_cap_info.dp_hbr2_cap;
+
+	/* test pattern 3 support */
+	enc110->base.features.flags.bits.IS_TPS3_CAPABLE = true;
+	enc110->base.features.max_deep_color = COLOR_DEPTH_121212;
+
+	enc110->base.features.flags.bits.IS_Y_ONLY_CAPABLE =
+		dal_adapter_service_is_feature_supported(
+			FEATURE_SUPPORT_DP_Y_ONLY);
+
+	enc110->base.features.flags.bits.IS_YCBCR_CAPABLE =
+		dal_adapter_service_is_feature_supported(
+			FEATURE_SUPPORT_DP_YUV);
+	return true;
+}
+
+bool dce110_link_encoder_validate_output_with_stream(
+	struct link_encoder *enc,
+	struct core_stream *stream)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	bool is_valid;
+
+	switch (stream->signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		is_valid = validate_dvi_output(
+			enc110,
+			stream->sink->link->public.connector_signal,
+			stream->signal,
+			&stream->public.timing);
+	break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		is_valid = validate_hdmi_output(
+				enc110,
+				&stream->public.timing,
+				stream->max_tmds_clk_from_edid_in_mhz,
+				stream->max_hdmi_deep_color,
+				stream->max_hdmi_pixel_clock);
+	break;
+	case SIGNAL_TYPE_RGB:
+		is_valid = validate_rgb_output(
+			enc110, &stream->public.timing);
+	break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		is_valid = validate_dp_output(
+			enc110, &stream->public.timing);
+	break;
+	case SIGNAL_TYPE_WIRELESS:
+		is_valid = validate_wireless_output(
+			enc110, &stream->public.timing);
+	break;
+	default:
+		is_valid = true;
+	break;
+	}
+
+	return is_valid;
+}
+
+void dce110_link_encoder_hw_init(
+	struct link_encoder *enc)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	cntl.action = TRANSMITTER_CONTROL_INIT;
+	cntl.engine_id = ENGINE_ID_UNKNOWN;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.connector_obj_id = enc110->base.connector;
+	cntl.lanes_number = LANE_COUNT_FOUR;
+	cntl.coherent = false;
+	cntl.hpd_sel = enc110->base.hpd_source;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	if (enc110->base.connector.id == CONNECTOR_ID_LVDS) {
+		cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS;
+
+		result = link_transmitter_control(enc110, &cntl);
+
+		ASSERT(result == BP_RESULT_OK);
+
+	} else if (enc110->base.connector.id == CONNECTOR_ID_EDP) {
+		enc->funcs->power_control(&enc110->base, true);
+	}
+	aux_initialize(enc110);
+
+	/* reinitialize HPD.
+	 * hpd_initialize() will pass DIG_FE id to HW context.
+	 * All other routine within HW context will use fe_engine_offset
+	 * as DIG_FE id even caller pass DIG_FE id.
+	 * So this routine must be called first. */
+	hpd_initialize(enc110);
+}
+
+void dce110_link_encoder_setup(
+	struct link_encoder *enc,
+	enum signal_type signal)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	const uint32_t addr = LINK_REG(DIG_BE_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	switch (signal) {
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+		/* DP SST */
+		set_reg_field_value(value, 0, DIG_BE_CNTL, DIG_MODE);
+		break;
+	case SIGNAL_TYPE_LVDS:
+		/* LVDS */
+		set_reg_field_value(value, 1, DIG_BE_CNTL, DIG_MODE);
+		break;
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		/* TMDS-DVI */
+		set_reg_field_value(value, 2, DIG_BE_CNTL, DIG_MODE);
+		break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		/* TMDS-HDMI */
+		set_reg_field_value(value, 3, DIG_BE_CNTL, DIG_MODE);
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		/* DP MST */
+		set_reg_field_value(value, 5, DIG_BE_CNTL, DIG_MODE);
+		break;
+	default:
+		ASSERT_CRITICAL(false);
+		/* invalid mode ! */
+		break;
+	}
+
+	dm_write_reg(ctx, addr, value);
+}
+
+/* TODO: still need depth or just pass in adjusted pixel clock? */
+void dce110_link_encoder_enable_tmds_output(
+	struct link_encoder *enc,
+	enum clock_source_id clock_source,
+	enum dc_color_depth color_depth,
+	bool hdmi,
+	bool dual_link,
+	uint32_t pixel_clock)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	/* Enable the PHY */
+
+	cntl.action = TRANSMITTER_CONTROL_ENABLE;
+	cntl.engine_id = ENGINE_ID_UNKNOWN;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.pll_id = clock_source;
+	if (hdmi) {
+		cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+		cntl.lanes_number = 4;
+	} else if (dual_link) {
+		cntl.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+		cntl.lanes_number = 8;
+	} else {
+		cntl.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		cntl.lanes_number = 4;
+	}
+	cntl.hpd_sel = enc110->base.hpd_source;
+
+	cntl.pixel_clock = pixel_clock;
+	cntl.color_depth = color_depth;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+	}
+}
+
+/* enables DP PHY output */
+void dce110_link_encoder_enable_dp_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	/* Enable the PHY */
+
+	/* number_of_lanes is used for pixel clock adjust,
+	 * but it's not passed to asic_control.
+	 * We need to set number of lanes manually.
+	 */
+	configure_encoder(enc110, link_settings);
+
+	cntl.action = TRANSMITTER_CONTROL_ENABLE;
+	cntl.engine_id = enc->preferred_engine;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.pll_id = clock_source;
+	cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;
+	cntl.lanes_number = link_settings->lane_count;
+	cntl.hpd_sel = enc110->base.hpd_source;
+	cntl.pixel_clock = link_settings->link_rate
+						* LINK_RATE_REF_FREQ_IN_KHZ;
+	/* TODO: check if undefined works */
+	cntl.color_depth = COLOR_DEPTH_UNDEFINED;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+	}
+}
+
+/* enables DP PHY output in MST mode */
+void dce110_link_encoder_enable_dp_mst_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	/* Enable the PHY */
+
+	/* number_of_lanes is used for pixel clock adjust,
+	 * but it's not passed to asic_control.
+	 * We need to set number of lanes manually.
+	 */
+	configure_encoder(enc110, link_settings);
+
+	cntl.action = TRANSMITTER_CONTROL_ENABLE;
+	cntl.engine_id = enc->preferred_engine;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.pll_id = clock_source;
+	cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
+	cntl.lanes_number = link_settings->lane_count;
+	cntl.hpd_sel = enc110->base.hpd_source;
+	cntl.pixel_clock = link_settings->link_rate
+						* LINK_RATE_REF_FREQ_IN_KHZ;
+	/* TODO: check if undefined works */
+	cntl.color_depth = COLOR_DEPTH_UNDEFINED;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+	}
+}
+/*
+ * @brief
+ * Disable transmitter and its encoder
+ */
+void dce110_link_encoder_disable_output(
+	struct link_encoder *enc,
+	enum signal_type signal)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	struct bp_transmitter_control cntl = { 0 };
+	enum bp_result result;
+
+	if (!is_dig_enabled(enc110) &&
+		dal_adapter_service_should_optimize(
+			enc110->base.adapter_service,
+			OF_SKIP_POWER_DOWN_INACTIVE_ENCODER)) {
+		return;
+	}
+	/* Power-down RX and disable GPU PHY should be paired.
+	 * Disabling PHY without powering down RX may cause
+	 * symbol lock loss, on which we will get DP Sink interrupt. */
+
+	/* There is a case for the DP active dongles
+	 * where we want to disable the PHY but keep RX powered,
+	 * for those we need to ignore DP Sink interrupt
+	 * by checking lane count that has been set
+	 * on the last do_enable_output(). */
+
+	/* disable transmitter */
+	cntl.action = TRANSMITTER_CONTROL_DISABLE;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.hpd_sel = enc110->base.hpd_source;
+	cntl.signal = signal;
+	cntl.connector_obj_id = enc110->base.connector;
+
+	result = link_transmitter_control(enc110, &cntl);
+
+	if (result != BP_RESULT_OK) {
+		dal_logger_write(ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"%s: Failed to execute VBIOS command table!\n",
+			__func__);
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	/* disable encoder */
+	if (dc_is_dp_signal(signal))
+		link_encoder_disable(enc110);
+
+	if (enc110->base.connector.id == CONNECTOR_ID_EDP) {
+		/* power down eDP panel */
+		/* TODO: Power control cause regression, we should implement
+		 * it properly, for now just comment it.
+		 *
+		 * link_encoder_edp_wait_for_hpd_ready(
+			link_enc,
+			link_enc->connector,
+			false);
+
+		 * link_encoder_edp_power_control(
+				link_enc, false); */
+	}
+}
+
+void dce110_link_encoder_dp_set_lane_settings(
+	struct link_encoder *enc,
+	const struct link_training_settings *link_settings)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	union dpcd_training_lane_set training_lane_set = { { 0 } };
+	int32_t lane = 0;
+	struct bp_transmitter_control cntl = { 0 };
+
+	if (!link_settings) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
+	cntl.transmitter = enc110->base.transmitter;
+	cntl.connector_obj_id = enc110->base.connector;
+	cntl.lanes_number = link_settings->link_settings.lane_count;
+	cntl.hpd_sel = enc110->base.hpd_source;
+	cntl.pixel_clock = link_settings->link_settings.link_rate *
+						LINK_RATE_REF_FREQ_IN_KHZ;
+
+	for (lane = 0; lane < link_settings->link_settings.lane_count; ++lane) {
+		/* translate lane settings */
+
+		training_lane_set.bits.VOLTAGE_SWING_SET =
+			link_settings->lane_settings[lane].VOLTAGE_SWING;
+		training_lane_set.bits.PRE_EMPHASIS_SET =
+			link_settings->lane_settings[lane].PRE_EMPHASIS;
+
+		/* post cursor 2 setting only applies to HBR2 link rate */
+		if (link_settings->link_settings.link_rate == LINK_RATE_HIGH2) {
+			/* this is passed to VBIOS
+			 * to program post cursor 2 level */
+
+			training_lane_set.bits.POST_CURSOR2_SET =
+				link_settings->lane_settings[lane].POST_CURSOR2;
+		}
+
+		cntl.lane_select = lane;
+		cntl.lane_settings = training_lane_set.raw;
+
+		/* call VBIOS table to set voltage swing and pre-emphasis */
+		link_transmitter_control(enc110, &cntl);
+	}
+}
+
+/* set DP PHY test and training patterns */
+void dce110_link_encoder_dp_set_phy_pattern(
+	struct link_encoder *enc,
+	const struct encoder_set_dp_phy_pattern_param *param)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+
+	switch (param->dp_phy_pattern) {
+	case DP_TEST_PATTERN_TRAINING_PATTERN1:
+		set_dp_phy_pattern_training_pattern(enc110, 0);
+		break;
+	case DP_TEST_PATTERN_TRAINING_PATTERN2:
+		set_dp_phy_pattern_training_pattern(enc110, 1);
+		break;
+	case DP_TEST_PATTERN_TRAINING_PATTERN3:
+		set_dp_phy_pattern_training_pattern(enc110, 2);
+		break;
+	case DP_TEST_PATTERN_D102:
+		set_dp_phy_pattern_d102(enc110);
+		break;
+	case DP_TEST_PATTERN_SYMBOL_ERROR:
+		set_dp_phy_pattern_symbol_error(enc110);
+		break;
+	case DP_TEST_PATTERN_PRBS7:
+		set_dp_phy_pattern_prbs7(enc110);
+		break;
+	case DP_TEST_PATTERN_80BIT_CUSTOM:
+		set_dp_phy_pattern_80bit_custom(
+			enc110, param->custom_pattern);
+		break;
+	case DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE:
+		set_dp_phy_pattern_hbr2_compliance(enc110);
+		break;
+	case DP_TEST_PATTERN_VIDEO_MODE: {
+		set_dp_phy_pattern_passthrough_mode(
+			enc110, param->dp_panel_mode);
+		break;
+	}
+
+	default:
+		/* invalid phy pattern */
+		ASSERT_CRITICAL(false);
+		break;
+	}
+}
+
+static void fill_stream_allocation_row_info(
+	const struct link_mst_stream_allocation *stream_allocation,
+	uint32_t *src,
+	uint32_t *slots)
+{
+	const struct stream_encoder *stream_enc = stream_allocation->stream_enc;
+
+	if (stream_enc) {
+		*src = stream_enc->id;
+		*slots = stream_allocation->slot_count;
+	} else {
+		*src = 0;
+		*slots = 0;
+	}
+}
+
+/* programs DP MST VC payload allocation */
+void dce110_link_encoder_update_mst_stream_allocation_table(
+	struct link_encoder *enc,
+	const struct link_mst_stream_allocation_table *table)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t value0 = 0;
+	uint32_t value1 = 0;
+	uint32_t value2 = 0;
+	uint32_t slots = 0;
+	uint32_t src = 0;
+	uint32_t retries = 0;
+
+	/* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/
+
+	/* --- Set MSE Stream Attribute -
+	 * Setup VC Payload Table on Tx Side,
+	 * Issue allocation change trigger
+	 * to commit payload on both tx and rx side */
+
+	/* we should clean-up table each time */
+	value0 = dm_read_reg(ctx, LINK_REG(DP_MSE_SAT0));
+	value1 = dm_read_reg(ctx, LINK_REG(DP_MSE_SAT1));
+
+	if (table->stream_count >= 1) {
+		fill_stream_allocation_row_info(
+			&table->stream_allocations[0],
+			&src,
+			&slots);
+	} else {
+		src = 0;
+		slots = 0;
+	}
+
+	set_reg_field_value(
+		value0,
+		src,
+		DP_MSE_SAT0,
+		DP_MSE_SAT_SRC0);
+
+	set_reg_field_value(
+		value0,
+		slots,
+		DP_MSE_SAT0,
+		DP_MSE_SAT_SLOT_COUNT0);
+
+	if (table->stream_count >= 2) {
+		fill_stream_allocation_row_info(
+			&table->stream_allocations[1],
+			&src,
+			&slots);
+	} else {
+		src = 0;
+		slots = 0;
+	}
+
+	set_reg_field_value(
+		value0,
+		src,
+		DP_MSE_SAT0,
+		DP_MSE_SAT_SRC1);
+
+	set_reg_field_value(
+		value0,
+		slots,
+		DP_MSE_SAT0,
+		DP_MSE_SAT_SLOT_COUNT1);
+
+	if (table->stream_count >= 3) {
+		fill_stream_allocation_row_info(
+			&table->stream_allocations[2],
+			&src,
+			&slots);
+	} else {
+		src = 0;
+		slots = 0;
+	}
+
+	set_reg_field_value(
+		value1,
+		src,
+		DP_MSE_SAT1,
+		DP_MSE_SAT_SRC2);
+
+	set_reg_field_value(
+		value1,
+		slots,
+		DP_MSE_SAT1,
+		DP_MSE_SAT_SLOT_COUNT2);
+
+	/* update ASIC MSE stream allocation table */
+	dm_write_reg(ctx, LINK_REG(DP_MSE_SAT0), value0);
+	dm_write_reg(ctx, LINK_REG(DP_MSE_SAT1), value1);
+
+	/* --- wait for transaction finish */
+
+	/* send allocation change trigger (ACT) ?
+	 * this step first sends the ACT,
+	 * then double buffers the SAT into the hardware
+	 * making the new allocation active on the DP MST mode link */
+
+	value0 = dm_read_reg(ctx, LINK_REG(DP_MSE_SAT_UPDATE));
+
+	/* DP_MSE_SAT_UPDATE:
+	 * 0 - No Action
+	 * 1 - Update SAT with trigger
+	 * 2 - Update SAT without trigger */
+
+	set_reg_field_value(
+		value0,
+		1,
+		DP_MSE_SAT_UPDATE,
+		DP_MSE_SAT_UPDATE);
+
+	dm_write_reg(ctx, LINK_REG(DP_MSE_SAT_UPDATE), value0);
+
+	/* wait for update to complete
+	 * (i.e. DP_MSE_SAT_UPDATE field is reset to 0)
+	 * then wait for the transmission
+	 * of at least 16 MTP headers on immediate local link.
+	 * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0
+	 * a value of 1 indicates that DP MST mode
+	 * is in the 16 MTP keepout region after a VC has been added.
+	 * MST stream bandwidth (VC rate) can be configured
+	 * after this bit is cleared */
+
+	do {
+		dm_delay_in_microseconds(ctx, 10);
+
+		value0 = dm_read_reg(ctx,
+				LINK_REG(DP_MSE_SAT_UPDATE));
+
+		value1 = get_reg_field_value(
+				value0,
+				DP_MSE_SAT_UPDATE,
+				DP_MSE_SAT_UPDATE);
+		value2 = get_reg_field_value(
+				value0,
+				DP_MSE_SAT_UPDATE,
+				DP_MSE_16_MTP_KEEPOUT);
+
+		/* bit field DP_MSE_SAT_UPDATE is set to 1 already */
+		if (!value1 && !value2)
+			break;
+		++retries;
+	} while (retries < DP_MST_UPDATE_MAX_RETRY);
+}
+
+/* black light programming */
+void dce110_link_encoder_set_lcd_backlight_level(
+	struct link_encoder *enc,
+	uint32_t level)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+
+	const uint32_t backlight_update_pending_max_retry = 1000;
+
+	uint32_t backlight;
+	uint32_t backlight_period;
+	uint32_t backlight_lock;
+
+	uint32_t i;
+	uint32_t backlight_24bit;
+	uint32_t backlight_17bit;
+	uint32_t backlight_16bit;
+	uint32_t masked_pwm_period;
+	uint8_t rounding_bit;
+	uint8_t bit_count;
+	uint64_t active_duty_cycle;
+
+	backlight = dm_read_reg(ctx, BL_REG(BL_PWM_CNTL));
+	backlight_period = dm_read_reg(ctx, BL_REG(BL_PWM_PERIOD_CNTL));
+	backlight_lock = dm_read_reg(ctx, BL_REG(BL_PWM_GRP1_REG_LOCK));
+
+	/*
+	 * 1. Convert 8-bit value to 17 bit U1.16 format
+	 * (1 integer, 16 fractional bits)
+	 */
+
+	/* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value,
+	 * effectively multiplying value by 256/255
+	 * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF
+	 */
+	backlight_24bit = level * 0x10101;
+
+	/* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8
+	 * used for rounding, take most significant bit of fraction for
+	 * rounding, e.g. for 0xEFEFEF, rounding bit is 1
+	 */
+	rounding_bit = (backlight_24bit >> 7) & 1;
+
+	/* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit
+	 * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1
+	 */
+	backlight_17bit = (backlight_24bit >> 8) + rounding_bit;
+
+	/*
+	 * 2. Find  16 bit backlight active duty cycle, where 0 <= backlight
+	 * active duty cycle <= backlight period
+	 */
+
+	/* 2.1 Apply bitmask for backlight period value based on value of BITCNT
+	 */
+	{
+		uint32_t pwm_period_bitcnt = get_reg_field_value(
+			backlight_period,
+			BL_PWM_PERIOD_CNTL,
+			BL_PWM_PERIOD_BITCNT);
+		if (pwm_period_bitcnt == 0)
+			bit_count = 16;
+		else
+			bit_count = pwm_period_bitcnt;
+	}
+
+	/* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */
+	masked_pwm_period =
+	get_reg_field_value(
+		backlight_period,
+		BL_PWM_PERIOD_CNTL,
+		BL_PWM_PERIOD) & ((1 << bit_count) - 1);
+
+	/* 2.2 Calculate integer active duty cycle required upper 16 bits
+	 * contain integer component, lower 16 bits contain fractional component
+	 * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24
+	 */
+	active_duty_cycle = backlight_17bit * masked_pwm_period;
+
+	/* 2.3 Calculate 16 bit active duty cycle from integer and fractional
+	 * components shift by bitCount then mask 16 bits and add rounding bit
+	 * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0
+	 */
+	backlight_16bit = active_duty_cycle >> bit_count;
+	backlight_16bit &= 0xFFFF;
+	backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1;
+	set_reg_field_value(
+		backlight,
+		backlight_16bit,
+		BL_PWM_CNTL,
+		BL_ACTIVE_INT_FRAC_CNT);
+
+	/*
+	 * 3. Program register with updated value
+	 */
+
+	/* 3.1 Lock group 2 backlight registers */
+	set_reg_field_value(
+		backlight_lock,
+		1,
+		BL_PWM_GRP1_REG_LOCK,
+		BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN);
+	set_reg_field_value(
+		backlight_lock,
+		1,
+		BL_PWM_GRP1_REG_LOCK,
+		BL_PWM_GRP1_REG_LOCK);
+	dm_write_reg(ctx, BL_REG(BL_PWM_GRP1_REG_LOCK), backlight_lock);
+
+	/* 3.2 Write new active duty cycle */
+	dm_write_reg(ctx, BL_REG(BL_PWM_CNTL), backlight);
+
+	/* 3.3 Unlock group 2 backlight registers */
+	set_reg_field_value(
+		backlight_lock,
+		0,
+		BL_PWM_GRP1_REG_LOCK,
+		BL_PWM_GRP1_REG_LOCK);
+	dm_write_reg(ctx, BL_REG(BL_PWM_GRP1_REG_LOCK), backlight_lock);
+
+	/* 5.4.4 Wait for pending bit to be cleared */
+	for (i = 0; i < backlight_update_pending_max_retry; ++i) {
+		backlight_lock = dm_read_reg(ctx, BL_REG(BL_PWM_GRP1_REG_LOCK));
+		if (!get_reg_field_value(
+			backlight_lock,
+			BL_PWM_GRP1_REG_LOCK,
+			BL_PWM_GRP1_REG_UPDATE_PENDING))
+			break;
+
+		dm_delay_in_microseconds(ctx, 10);
+	}
+}
+
+void dce110_link_encoder_connect_dig_be_to_fe(
+	struct link_encoder *enc,
+	enum engine_id engine,
+	bool connect)
+{
+	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+	uint32_t field;
+
+	if (engine != ENGINE_ID_UNKNOWN) {
+		addr = LINK_REG(DIG_BE_CNTL);
+		value = dm_read_reg(ctx, addr);
+
+		field = get_reg_field_value(
+				value,
+				DIG_BE_CNTL,
+				DIG_FE_SOURCE_SELECT);
+
+		if (connect)
+			field |= get_frontend_source(engine);
+		else
+			field &= ~get_frontend_source(engine);
+
+		set_reg_field_value(
+			value,
+			field,
+			DIG_BE_CNTL,
+			DIG_FE_SOURCE_SELECT);
+		dm_write_reg(ctx, addr, value);
+	}
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
new file mode 100644
index 000000000000..46e297137b19
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_LINK_ENCODER__DCE110_H__
+#define __DC_LINK_ENCODER__DCE110_H__
+
+#include "inc/link_encoder.h"
+
+#define TO_DCE110_LINK_ENC(link_encoder)\
+	container_of(link_encoder, struct dce110_link_encoder, base)
+
+struct dce110_link_enc_bl_registers {
+	uint32_t BL_PWM_CNTL;
+	uint32_t BL_PWM_GRP1_REG_LOCK;
+	uint32_t BL_PWM_PERIOD_CNTL;
+	uint32_t LVTMA_PWRSEQ_CNTL;
+	uint32_t LVTMA_PWRSEQ_STATE;
+};
+
+struct dce110_link_enc_aux_registers {
+	uint32_t AUX_CONTROL;
+	uint32_t AUX_DPHY_RX_CONTROL0;
+};
+
+struct dce110_link_enc_registers {
+	uint32_t DIG_BE_CNTL;
+	uint32_t DIG_BE_EN_CNTL;
+	uint32_t DP_CONFIG;
+	uint32_t DP_DPHY_CNTL;
+	uint32_t DP_DPHY_INTERNAL_CTRL;
+	uint32_t DP_DPHY_PRBS_CNTL;
+	uint32_t DP_DPHY_SYM0;
+	uint32_t DP_DPHY_SYM1;
+	uint32_t DP_DPHY_SYM2;
+	uint32_t DP_DPHY_TRAINING_PATTERN_SEL;
+	uint32_t DP_LINK_CNTL;
+	uint32_t DP_LINK_FRAMING_CNTL;
+	uint32_t DP_MSE_SAT0;
+	uint32_t DP_MSE_SAT1;
+	uint32_t DP_MSE_SAT2;
+	uint32_t DP_MSE_SAT_UPDATE;
+	uint32_t DP_SEC_CNTL;
+	uint32_t DP_VID_STREAM_CNTL;
+};
+
+struct dce110_link_encoder {
+	struct link_encoder base;
+	const struct dce110_link_enc_registers *link_regs;
+	const struct dce110_link_enc_aux_registers *aux_regs;
+	const struct dce110_link_enc_bl_registers *bl_regs;
+};
+
+bool dce110_link_encoder_construct(
+	struct dce110_link_encoder *enc110,
+	const struct encoder_init_data *init_data,
+	const struct dce110_link_enc_registers *link_regs,
+	const struct dce110_link_enc_aux_registers *aux_regs,
+	const struct dce110_link_enc_bl_registers *bl_regs);
+
+bool dce110_link_encoder_validate_output_with_stream(
+	struct link_encoder *enc,
+	struct core_stream *stream);
+
+/****************** HW programming ************************/
+
+/* initialize HW */  /* why do we initialze aux in here? */
+void dce110_link_encoder_hw_init(struct link_encoder *enc);
+
+/* program DIG_MODE in DIG_BE */
+/* TODO can this be combined with enable_output? */
+void dce110_link_encoder_setup(
+	struct link_encoder *enc,
+	enum signal_type signal);
+
+/* enables TMDS PHY output */
+/* TODO: still need depth or just pass in adjusted pixel clock? */
+void dce110_link_encoder_enable_tmds_output(
+	struct link_encoder *enc,
+	enum clock_source_id clock_source,
+	enum dc_color_depth color_depth,
+	bool hdmi,
+	bool dual_link,
+	uint32_t pixel_clock);
+
+/* enables DP PHY output */
+void dce110_link_encoder_enable_dp_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source);
+
+/* enables DP PHY output in MST mode */
+void dce110_link_encoder_enable_dp_mst_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source);
+
+/* disable PHY output */
+void dce110_link_encoder_disable_output(
+	struct link_encoder *link_enc,
+	enum signal_type signal);
+
+/* set DP lane settings */
+void dce110_link_encoder_dp_set_lane_settings(
+	struct link_encoder *enc,
+	const struct link_training_settings *link_settings);
+
+void dce110_link_encoder_dp_set_phy_pattern(
+	struct link_encoder *enc,
+	const struct encoder_set_dp_phy_pattern_param *param);
+
+/* programs DP MST VC payload allocation */
+void dce110_link_encoder_update_mst_stream_allocation_table(
+	struct link_encoder *enc,
+	const struct link_mst_stream_allocation_table *table);
+
+void dce110_link_encoder_set_lcd_backlight_level(
+	struct link_encoder *enc,
+	uint32_t level);
+
+void dce110_link_encoder_edp_backlight_control(
+	struct link_encoder *enc,
+	bool enable);
+
+void dce110_link_encoder_edp_power_control(
+	struct link_encoder *enc,
+	bool power_up);
+
+void dce110_link_encoder_connect_dig_be_to_fe(
+	struct link_encoder *enc,
+	enum engine_id engine,
+	bool connect);
+
+
+#endif /* __DC_LINK_ENCODER__DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
new file mode 100644
index 000000000000..210730972c08
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
@@ -0,0 +1,1123 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dc_bios_types.h"
+#include "dce110_stream_encoder.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dce/dce_11_0_enum.h"
+
+#define LINK_REG(reg)\
+	(enc110->regs->reg)
+
+#define VBI_LINE_0 0
+#define DP_BLANK_MAX_RETRY 20
+#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000
+
+#ifndef HDMI_CONTROL__HDMI_DATA_SCRAMBLE_EN_MASK
+	#define HDMI_CONTROL__HDMI_DATA_SCRAMBLE_EN_MASK 0x2
+	#define HDMI_CONTROL__HDMI_DATA_SCRAMBLE_EN__SHIFT 0x1
+#endif
+
+enum {
+	DP_MST_UPDATE_MAX_RETRY = 50
+};
+
+static struct stream_encoder_funcs dce110_str_enc_funcs = {
+	.dp_set_stream_attribute =
+		dce110_stream_encoder_dp_set_stream_attribute,
+	.hdmi_set_stream_attribute =
+		dce110_stream_encoder_hdmi_set_stream_attribute,
+	.dvi_set_stream_attribute =
+		dce110_stream_encoder_dvi_set_stream_attribute,
+	.set_mst_bandwidth =
+		dce110_stream_encoder_set_mst_bandwidth,
+	.update_hdmi_info_packets =
+		dce110_stream_encoder_update_hdmi_info_packets,
+	.stop_hdmi_info_packets =
+		dce110_stream_encoder_stop_hdmi_info_packets,
+	.update_dp_info_packets =
+		dce110_stream_encoder_update_dp_info_packets,
+	.stop_dp_info_packets =
+		dce110_stream_encoder_stop_dp_info_packets,
+	.dp_blank =
+		dce110_stream_encoder_dp_blank,
+	.dp_unblank =
+		dce110_stream_encoder_dp_unblank,
+};
+
+static void dce110_update_generic_info_packet(
+	struct dce110_stream_encoder *enc110,
+	uint32_t packet_index,
+	const struct encoder_info_packet *info_packet)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t regval;
+	/* choose which generic packet to use */
+	{
+		addr = LINK_REG(AFMT_VBI_PACKET_CONTROL);
+
+		regval = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			regval,
+			packet_index,
+			AFMT_VBI_PACKET_CONTROL,
+			AFMT_GENERIC_INDEX);
+
+		dm_write_reg(ctx, addr, regval);
+	}
+
+	/* write generic packet header
+	 * (4th byte is for GENERIC0 only) */
+	{
+		addr = LINK_REG(AFMT_GENERIC_HDR);
+
+		regval = 0;
+
+		set_reg_field_value(
+			regval,
+			info_packet->hb0,
+			AFMT_GENERIC_HDR,
+			AFMT_GENERIC_HB0);
+
+		set_reg_field_value(
+			regval,
+			info_packet->hb1,
+			AFMT_GENERIC_HDR,
+			AFMT_GENERIC_HB1);
+
+		set_reg_field_value(
+			regval,
+			info_packet->hb2,
+			AFMT_GENERIC_HDR,
+			AFMT_GENERIC_HB2);
+
+		set_reg_field_value(
+			regval,
+			info_packet->hb3,
+			AFMT_GENERIC_HDR,
+			AFMT_GENERIC_HB3);
+
+		dm_write_reg(ctx, addr, regval);
+	}
+
+	/* write generic packet contents
+	 * (we never use last 4 bytes)
+	 * there are 8 (0-7) mmDIG0_AFMT_GENERIC0_x registers */
+	{
+		const uint32_t *content =
+			(const uint32_t *) &info_packet->sb[0];
+
+		uint32_t counter = 0;
+
+		addr = LINK_REG(AFMT_GENERIC_0);
+
+		do {
+			dm_write_reg(ctx, addr++, *content++);
+
+			++counter;
+		} while (counter < 7);
+	}
+
+	addr = LINK_REG(AFMT_GENERIC_7);
+
+	dm_write_reg(
+		ctx,
+		addr,
+		0);
+
+	/* force double-buffered packet update */
+	{
+		addr = LINK_REG(AFMT_VBI_PACKET_CONTROL);
+
+		regval = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			regval,
+			(packet_index == 0),
+			AFMT_VBI_PACKET_CONTROL,
+			AFMT_GENERIC0_UPDATE);
+
+		set_reg_field_value(
+			regval,
+			(packet_index == 2),
+			AFMT_VBI_PACKET_CONTROL,
+			AFMT_GENERIC2_UPDATE);
+
+		dm_write_reg(ctx, addr, regval);
+	}
+}
+
+static void dce110_update_hdmi_info_packet(
+	struct dce110_stream_encoder *enc110,
+	uint32_t packet_index,
+	const struct encoder_info_packet *info_packet)
+{
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t cont, send, line;
+	uint32_t addr;
+	uint32_t regval;
+
+	if (info_packet->valid) {
+		dce110_update_generic_info_packet(
+			enc110,
+			packet_index,
+			info_packet);
+
+		/* enable transmission of packet(s) -
+		 * packet transmission begins on the next frame */
+		cont = 1;
+		/* send packet(s) every frame */
+		send = 1;
+		/* select line number to send packets on */
+		line = 2;
+	} else {
+		cont = 0;
+		send = 0;
+		line = 0;
+	}
+
+	/* choose which generic packet control to use */
+
+	switch (packet_index) {
+	case 0:
+	case 1:
+		addr = LINK_REG(HDMI_GENERIC_PACKET_CONTROL0);
+		break;
+	case 2:
+	case 3:
+		addr = LINK_REG(HDMI_GENERIC_PACKET_CONTROL1);
+		break;
+	default:
+		/* invalid HW packet index */
+		dal_logger_write(
+			ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"Invalid HW packet index: %s()\n",
+			__func__);
+		return;
+	}
+
+	regval = dm_read_reg(ctx, addr);
+
+	switch (packet_index) {
+	case 0:
+	case 2:
+		set_reg_field_value(
+			regval,
+			cont,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC0_CONT);
+		set_reg_field_value(
+			regval,
+			send,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC0_SEND);
+		set_reg_field_value(
+			regval,
+			line,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC0_LINE);
+		break;
+	case 1:
+	case 3:
+		set_reg_field_value(
+			regval,
+			cont,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC1_CONT);
+		set_reg_field_value(
+			regval,
+			send,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC1_SEND);
+		set_reg_field_value(
+			regval,
+			line,
+			HDMI_GENERIC_PACKET_CONTROL0,
+			HDMI_GENERIC1_LINE);
+		break;
+	default:
+		/* invalid HW packet index */
+		dal_logger_write(
+			ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_ENCODER,
+			"Invalid HW packet index: %s()\n",
+			__func__);
+		return;
+	}
+
+	dm_write_reg(ctx, addr, regval);
+}
+
+bool dce110_stream_encoder_construct(
+	struct dce110_stream_encoder *enc110,
+	struct dc_context *ctx,
+	struct dc_bios *bp,
+	enum engine_id eng_id,
+	const struct dce110_stream_enc_registers *regs)
+{
+	if (!enc110)
+		return false;
+	if (!bp)
+		return false;
+
+	enc110->base.funcs = &dce110_str_enc_funcs;
+	enc110->base.ctx = ctx;
+	enc110->base.id = eng_id;
+	enc110->base.bp = bp;
+	enc110->regs = regs;
+
+	return true;
+}
+
+/* setup stream encoder in dp mode */
+void dce110_stream_encoder_dp_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	const uint32_t addr = LINK_REG(DP_PIXEL_FORMAT);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	/* set pixel encoding */
+	switch (crtc_timing->pixel_encoding) {
+	case PIXEL_ENCODING_YCBCR422:
+		set_reg_field_value(
+			value,
+			DP_PIXEL_ENCODING_YCBCR422,
+			DP_PIXEL_FORMAT,
+			DP_PIXEL_ENCODING);
+		break;
+	case PIXEL_ENCODING_YCBCR444:
+		set_reg_field_value(
+			value,
+			DP_PIXEL_ENCODING_YCBCR444,
+			DP_PIXEL_FORMAT,
+			DP_PIXEL_ENCODING);
+
+		if (crtc_timing->flags.Y_ONLY)
+			if (crtc_timing->display_color_depth != COLOR_DEPTH_666)
+				/* HW testing only, no use case yet.
+				 * Color depth of Y-only could be
+				 * 8, 10, 12, 16 bits */
+				set_reg_field_value(
+					value,
+					DP_PIXEL_ENCODING_Y_ONLY,
+					DP_PIXEL_FORMAT,
+					DP_PIXEL_ENCODING);
+		/* Note: DP_MSA_MISC1 bit 7 is the indicator
+		 * of Y-only mode.
+		 * This bit is set in HW if register
+		 * DP_PIXEL_ENCODING is programmed to 0x4 */
+		break;
+	default:
+		set_reg_field_value(
+			value,
+			DP_PIXEL_ENCODING_RGB444,
+			DP_PIXEL_FORMAT,
+			DP_PIXEL_ENCODING);
+		break;
+	}
+
+	/* set color depth */
+
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_888:
+		set_reg_field_value(
+			value,
+			DP_COMPONENT_DEPTH_8BPC,
+			DP_PIXEL_FORMAT,
+			DP_COMPONENT_DEPTH);
+		break;
+	case COLOR_DEPTH_101010:
+		set_reg_field_value(
+			value,
+			DP_COMPONENT_DEPTH_10BPC,
+			DP_PIXEL_FORMAT,
+			DP_COMPONENT_DEPTH);
+		break;
+	case COLOR_DEPTH_121212:
+		set_reg_field_value(
+			value,
+			DP_COMPONENT_DEPTH_12BPC,
+			DP_PIXEL_FORMAT,
+			DP_COMPONENT_DEPTH);
+		break;
+	default:
+		set_reg_field_value(
+			value,
+			DP_COMPONENT_DEPTH_6BPC,
+			DP_PIXEL_FORMAT,
+			DP_COMPONENT_DEPTH);
+		break;
+	}
+
+	/* set dynamic range and YCbCr range */
+	set_reg_field_value(value, 0, DP_PIXEL_FORMAT, DP_DYN_RANGE);
+	set_reg_field_value(value, 0, DP_PIXEL_FORMAT, DP_YCBCR_RANGE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+/* setup stream encoder in hdmi mode */
+void dce110_stream_encoder_hdmi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool enable_audio)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t output_pixel_clock = crtc_timing->pix_clk_khz;
+	uint32_t value;
+	uint32_t addr;
+	struct bp_encoder_control cntl = {0};
+
+	cntl.action = ENCODER_CONTROL_SETUP;
+	cntl.engine_id = enc110->base.id;
+	cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+	cntl.enable_dp_audio = enable_audio;
+	cntl.pixel_clock = crtc_timing->pix_clk_khz;
+	cntl.lanes_number = LANE_COUNT_FOUR;
+	cntl.color_depth = crtc_timing->display_color_depth;
+
+	if (enc110->base.bp->funcs->encoder_control(
+			enc110->base.bp, &cntl) != BP_RESULT_OK)
+		return;
+
+	addr = LINK_REG(DIG_FE_CNTL);
+	value = dm_read_reg(ctx, addr);
+
+	switch (crtc_timing->pixel_encoding) {
+	case PIXEL_ENCODING_YCBCR422:
+		set_reg_field_value(value, 1, DIG_FE_CNTL, TMDS_PIXEL_ENCODING);
+		break;
+	default:
+		set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_PIXEL_ENCODING);
+		break;
+	}
+	set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_COLOR_FORMAT);
+	dm_write_reg(ctx, addr, value);
+
+	/* setup HDMI engine */
+	addr = LINK_REG(HDMI_CONTROL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 1, HDMI_CONTROL, HDMI_PACKET_GEN_VERSION);
+	set_reg_field_value(value, 1, HDMI_CONTROL, HDMI_KEEPOUT_MODE);
+	set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE);
+	set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN);
+	set_reg_field_value(value, 0, HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE);
+
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_888:
+		set_reg_field_value(
+			value,
+			0,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_DEPTH);
+		break;
+	case COLOR_DEPTH_101010:
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_DEPTH);
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_ENABLE);
+		output_pixel_clock = (crtc_timing->pix_clk_khz * 30) / 24;
+		break;
+	case COLOR_DEPTH_121212:
+		set_reg_field_value(
+			value,
+			2,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_DEPTH);
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_ENABLE);
+		output_pixel_clock = (crtc_timing->pix_clk_khz * 36) / 24;
+		break;
+	case COLOR_DEPTH_161616:
+		set_reg_field_value(
+			value,
+			3,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_DEPTH);
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DEEP_COLOR_ENABLE);
+		output_pixel_clock = (crtc_timing->pix_clk_khz * 48) / 24;
+		break;
+	default:
+		break;
+	}
+
+	if (output_pixel_clock >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) {
+		/* enable HDMI data scrambler */
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DATA_SCRAMBLE_EN);
+
+		/* HDMI_CLOCK_CHANNEL_RATE_MORE_340M
+		 * Clock channel frequency is 1/4 of character rate.*/
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_CLOCK_CHANNEL_RATE);
+	} else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) {
+
+		/* TODO: New feature for DCE11, still need to implement */
+
+		/* enable HDMI data scrambler */
+		set_reg_field_value(
+			value,
+			1,
+			HDMI_CONTROL,
+			HDMI_DATA_SCRAMBLE_EN);
+
+		/* HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE
+		 * Clock channel frequency is the same
+		 * as character rate */
+		set_reg_field_value(
+			value,
+			0,
+			HDMI_CONTROL,
+			HDMI_CLOCK_CHANNEL_RATE);
+	}
+
+	dm_write_reg(ctx, addr, value);
+
+	addr = LINK_REG(HDMI_VBI_PACKET_CONTROL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT);
+	set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND);
+	set_reg_field_value(value, 1, HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* following belongs to audio */
+	addr = LINK_REG(HDMI_INFOFRAME_CONTROL0);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		HDMI_INFOFRAME_CONTROL0,
+		HDMI_AUDIO_INFO_SEND);
+	dm_write_reg(ctx, addr, value);
+
+	addr = LINK_REG(AFMT_INFOFRAME_CONTROL0);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		AFMT_INFOFRAME_CONTROL0,
+		AFMT_AUDIO_INFO_UPDATE);
+	dm_write_reg(ctx, addr, value);
+
+	addr = LINK_REG(HDMI_INFOFRAME_CONTROL1);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		VBI_LINE_0 + 2,
+		HDMI_INFOFRAME_CONTROL1,
+		HDMI_AUDIO_INFO_LINE);
+	dm_write_reg(ctx, addr, value);
+
+	addr = LINK_REG(HDMI_GC);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 0, HDMI_GC, HDMI_GC_AVMUTE);
+	dm_write_reg(ctx, addr, value);
+}
+
+/* setup stream encoder in dvi mode */
+void dce110_stream_encoder_dvi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool is_dual_link)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DIG_FE_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+	struct bp_encoder_control cntl = {0};
+
+	cntl.action = ENCODER_CONTROL_SETUP;
+	cntl.engine_id = enc110->base.id;
+	cntl.signal = is_dual_link ?
+		SIGNAL_TYPE_DVI_DUAL_LINK :
+		SIGNAL_TYPE_DVI_SINGLE_LINK;
+	cntl.enable_dp_audio = false;
+	cntl.pixel_clock = crtc_timing->pix_clk_khz;
+	cntl.lanes_number = (is_dual_link) ?
+				LANE_COUNT_EIGHT : LANE_COUNT_FOUR;
+	cntl.color_depth = crtc_timing->display_color_depth;
+
+	if (enc110->base.bp->funcs->encoder_control(
+			enc110->base.bp, &cntl) != BP_RESULT_OK)
+		return;
+
+	switch (crtc_timing->pixel_encoding) {
+	case PIXEL_ENCODING_YCBCR422:
+		set_reg_field_value(value, 1, DIG_FE_CNTL, TMDS_PIXEL_ENCODING);
+		break;
+	default:
+		set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_PIXEL_ENCODING);
+		break;
+	}
+
+	switch (crtc_timing->display_color_depth) {
+	case COLOR_DEPTH_101010:
+		if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
+			set_reg_field_value(
+				value,
+				2,
+				DIG_FE_CNTL,
+				TMDS_COLOR_FORMAT);
+		else
+			set_reg_field_value(
+				value,
+				0,
+				DIG_FE_CNTL,
+				TMDS_COLOR_FORMAT);
+		break;
+	default:
+		set_reg_field_value(value, 0, DIG_FE_CNTL, TMDS_COLOR_FORMAT);
+		break;
+	}
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_stream_encoder_set_mst_bandwidth(
+	struct stream_encoder *enc,
+	struct fixed31_32 avg_time_slots_per_mtp)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t field;
+	uint32_t value;
+	uint32_t retries = 0;
+	uint32_t x = dal_fixed31_32_floor(
+		avg_time_slots_per_mtp);
+	uint32_t y = dal_fixed31_32_ceil(
+		dal_fixed31_32_shl(
+			dal_fixed31_32_sub_int(
+				avg_time_slots_per_mtp,
+				x),
+			26));
+
+	{
+		addr = LINK_REG(DP_MSE_RATE_CNTL);
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			value,
+			x,
+			DP_MSE_RATE_CNTL,
+			DP_MSE_RATE_X);
+
+		set_reg_field_value(
+			value,
+			y,
+			DP_MSE_RATE_CNTL,
+			DP_MSE_RATE_Y);
+
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* wait for update to be completed on the link */
+	/* i.e. DP_MSE_RATE_UPDATE_PENDING field (read only) */
+	/* is reset to 0 (not pending) */
+	{
+		addr = LINK_REG(DP_MSE_RATE_UPDATE);
+
+		do {
+			value = dm_read_reg(ctx, addr);
+
+			field = get_reg_field_value(
+					value,
+					DP_MSE_RATE_UPDATE,
+					DP_MSE_RATE_UPDATE_PENDING);
+
+			if (!(field &
+			DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING_MASK))
+				break;
+
+			dm_delay_in_microseconds(ctx, 10);
+
+			++retries;
+		} while (retries < DP_MST_UPDATE_MAX_RETRY);
+	}
+}
+
+void dce110_stream_encoder_update_hdmi_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t regval;
+	uint32_t addr;
+	uint32_t control0val;
+	uint32_t control1val;
+
+	if (info_frame->avi.valid) {
+		const uint32_t *content =
+			(const uint32_t *) &info_frame->avi.sb[0];
+
+		addr = LINK_REG(AFMT_AVI_INFO0);
+		regval = content[0];
+		dm_write_reg(
+			ctx,
+			addr,
+			regval);
+		regval = content[1];
+
+		addr = LINK_REG(AFMT_AVI_INFO1);
+		dm_write_reg(
+			ctx,
+			addr,
+			regval);
+		regval = content[2];
+
+		addr = LINK_REG(AFMT_AVI_INFO2);
+		dm_write_reg(
+			ctx,
+			addr,
+			regval);
+		regval = content[3];
+
+		/* move version to AVI_INFO3 */
+		addr = LINK_REG(AFMT_AVI_INFO3);
+		set_reg_field_value(
+			regval,
+			info_frame->avi.hb1,
+			AFMT_AVI_INFO3,
+			AFMT_AVI_INFO_VERSION);
+
+		dm_write_reg(
+			ctx,
+			addr,
+			regval);
+
+		addr = LINK_REG(HDMI_INFOFRAME_CONTROL0);
+
+		control0val = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			control0val,
+			1,
+			HDMI_INFOFRAME_CONTROL0,
+			HDMI_AVI_INFO_SEND);
+
+		set_reg_field_value(
+			control0val,
+			1,
+			HDMI_INFOFRAME_CONTROL0,
+			HDMI_AVI_INFO_CONT);
+
+		dm_write_reg(ctx, addr, control0val);
+
+		addr = LINK_REG(HDMI_INFOFRAME_CONTROL1);
+
+		control1val = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			control1val,
+			VBI_LINE_0 + 2,
+			HDMI_INFOFRAME_CONTROL1,
+			HDMI_AVI_INFO_LINE);
+
+		dm_write_reg(ctx, addr, control1val);
+	} else {
+		addr = LINK_REG(HDMI_INFOFRAME_CONTROL0);
+
+		regval = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(
+			regval,
+			0,
+			HDMI_INFOFRAME_CONTROL0,
+			HDMI_AVI_INFO_SEND);
+
+		set_reg_field_value(
+			regval,
+			0,
+			HDMI_INFOFRAME_CONTROL0,
+			HDMI_AVI_INFO_CONT);
+
+		dm_write_reg(ctx, addr, regval);
+	}
+
+	dce110_update_hdmi_info_packet(enc110, 0, &info_frame->vendor);
+	dce110_update_hdmi_info_packet(enc110, 1, &info_frame->gamut);
+	dce110_update_hdmi_info_packet(enc110, 2, &info_frame->spd);
+}
+
+void dce110_stream_encoder_stop_hdmi_info_packets(
+	struct stream_encoder *enc)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* stop generic packets 0 & 1 on HDMI */
+	addr = LINK_REG(HDMI_GENERIC_PACKET_CONTROL0);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC1_CONT);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC1_LINE);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC1_SEND);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC0_CONT);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC0_LINE);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL0,
+		HDMI_GENERIC0_SEND);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* stop generic packets 2 & 3 on HDMI */
+	addr = LINK_REG(HDMI_GENERIC_PACKET_CONTROL1);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC2_CONT);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC2_LINE);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC2_SEND);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC3_CONT);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC3_LINE);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_GENERIC_PACKET_CONTROL1,
+		HDMI_GENERIC3_SEND);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* stop AVI packet on HDMI */
+	addr = LINK_REG(HDMI_INFOFRAME_CONTROL0);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_INFOFRAME_CONTROL0,
+		HDMI_AVI_INFO_SEND);
+	set_reg_field_value(
+		value,
+		0,
+		HDMI_INFOFRAME_CONTROL0,
+		HDMI_AVI_INFO_CONT);
+
+	dm_write_reg(ctx, addr, value);
+}
+void dce110_stream_encoder_update_dp_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DP_SEC_CNTL);
+	uint32_t value;
+
+	if (info_frame->vsc.valid)
+		dce110_update_generic_info_packet(
+			enc110,
+			0,
+			&info_frame->vsc);
+
+	/* enable/disable transmission of packet(s).
+	*  If enabled, packet transmission begins on the next frame
+	*/
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		info_frame->vsc.valid,
+		DP_SEC_CNTL,
+		DP_SEC_GSP0_ENABLE);
+	/* This bit is the master enable bit.
+	* When enabling secondary stream engine,
+	* this master bit must also be set.
+	* This register shared with audio info frame.
+	* Therefore we need to enable master bit
+	* if at least on of the fields is not 0
+	*/
+	if (value)
+		set_reg_field_value(
+			value,
+			1,
+			DP_SEC_CNTL,
+			DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_stream_encoder_stop_dp_info_packets(
+	struct stream_encoder *enc)
+{
+	/* stop generic packets on DP */
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DP_SEC_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP0_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP1_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP2_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP3_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_AVI_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_MPG_ENABLE);
+	set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_STREAM_ENABLE);
+
+	/* this register shared with audio info frame.
+	 * therefore we need to keep master enabled
+	 * if at least one of the fields is not 0 */
+
+	if (value)
+		set_reg_field_value(
+			value,
+			1,
+			DP_SEC_CNTL,
+			DP_SEC_STREAM_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_stream_encoder_dp_blank(
+	struct stream_encoder *enc)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr = LINK_REG(DP_VID_STREAM_CNTL);
+	uint32_t value = dm_read_reg(ctx, addr);
+	uint32_t retries = 0;
+	uint32_t max_retries = DP_BLANK_MAX_RETRY * 10;
+
+	/* Note: For CZ, we are changing driver default to disable
+	 * stream deferred to next VBLANK. If results are positive, we
+	 * will make the same change to all DCE versions. There are a
+	 * handful of panels that cannot handle disable stream at
+	 * HBLANK and will result in a white line flash across the
+	 * screen on stream disable. */
+
+	/* Specify the video stream disable point
+	 * (2 = start of the next vertical blank) */
+	set_reg_field_value(
+		value,
+		2,
+		DP_VID_STREAM_CNTL,
+		DP_VID_STREAM_DIS_DEFER);
+	/* Larger delay to wait until VBLANK - use max retry of
+	* 10us*3000=30ms. This covers 16.6ms of typical 60 Hz mode +
+	* a little more because we may not trust delay accuracy.
+	*/
+	max_retries = DP_BLANK_MAX_RETRY * 150;
+
+	/* disable DP stream */
+	set_reg_field_value(value, 0, DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE);
+	dm_write_reg(ctx, addr, value);
+
+	/* the encoder stops sending the video stream
+	* at the start of the vertical blanking.
+	* Poll for DP_VID_STREAM_STATUS == 0
+	*/
+
+	do {
+		value = dm_read_reg(ctx, addr);
+
+		if (!get_reg_field_value(
+			value,
+			DP_VID_STREAM_CNTL,
+			DP_VID_STREAM_STATUS))
+			break;
+
+		dm_delay_in_microseconds(ctx, 10);
+
+		++retries;
+	} while (retries < max_retries);
+
+	ASSERT(retries <= max_retries);
+
+	/* Tell the DP encoder to ignore timing from CRTC, must be done after
+	* the polling. If we set DP_STEER_FIFO_RESET before DP stream blank is
+	* complete, stream status will be stuck in video stream enabled state,
+	* i.e. DP_VID_STREAM_STATUS stuck at 1.
+	*/
+	addr = LINK_REG(DP_STEER_FIFO);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, true, DP_STEER_FIFO, DP_STEER_FIFO_RESET);
+	dm_write_reg(ctx, addr, value);
+}
+
+/* output video stream to link encoder */
+void dce110_stream_encoder_dp_unblank(
+	struct stream_encoder *enc,
+	const struct encoder_unblank_param *param)
+{
+	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
+	struct dc_context *ctx = enc110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
+		uint32_t n_vid = 0x8000;
+		uint32_t m_vid;
+
+		/* M / N = Fstream / Flink
+		* m_vid / n_vid = pixel rate / link rate
+		*/
+
+		uint64_t m_vid_l = n_vid;
+
+		m_vid_l *= param->crtc_timing.pixel_clock;
+		m_vid_l = div_u64(m_vid_l,
+			param->link_settings.link_rate
+				* LINK_RATE_REF_FREQ_IN_KHZ);
+
+		m_vid = (uint32_t) m_vid_l;
+
+		/* enable auto measurement */
+		addr = LINK_REG(DP_VID_TIMING);
+		value = dm_read_reg(ctx, addr);
+		set_reg_field_value(value, 0, DP_VID_TIMING, DP_VID_M_N_GEN_EN);
+		dm_write_reg(ctx, addr, value);
+
+		/* auto measurement need 1 full 0x8000 symbol cycle to kick in,
+		* therefore program initial value for Mvid and Nvid
+		*/
+		addr = LINK_REG(DP_VID_N);
+		value = dm_read_reg(ctx, addr);
+		set_reg_field_value(value, n_vid, DP_VID_N, DP_VID_N);
+		dm_write_reg(ctx, addr, value);
+
+		addr = LINK_REG(DP_VID_M);
+		value = dm_read_reg(ctx, addr);
+		set_reg_field_value(value, m_vid, DP_VID_M, DP_VID_M);
+		dm_write_reg(ctx, addr, value);
+
+		addr = LINK_REG(DP_VID_TIMING);
+		value = dm_read_reg(ctx, addr);
+		set_reg_field_value(value, 1, DP_VID_TIMING, DP_VID_M_N_GEN_EN);
+		dm_write_reg(ctx, addr, value);
+	}
+
+	/* set DIG_START to 0x1 to resync FIFO */
+	addr = LINK_REG(DIG_FE_CNTL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 1, DIG_FE_CNTL, DIG_START);
+	dm_write_reg(ctx, addr, value);
+
+	/* switch DP encoder to CRTC data */
+	addr = LINK_REG(DP_STEER_FIFO);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(value, 0, DP_STEER_FIFO, DP_STEER_FIFO_RESET);
+	dm_write_reg(ctx, addr, value);
+
+	/* wait 100us for DIG/DP logic to prime
+	* (i.e. a few video lines)
+	*/
+	dm_delay_in_microseconds(ctx, 100);
+
+	/* the hardware would start sending video at the start of the next DP
+	* frame (i.e. rising edge of the vblank).
+	* NOTE: We used to program DP_VID_STREAM_DIS_DEFER = 2 here, but this
+	* register has no effect on enable transition! HW always guarantees
+	* VID_STREAM enable at start of next frame, and this is not
+	* programmable
+	*/
+	addr = LINK_REG(DP_VID_STREAM_CNTL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		true,
+		DP_VID_STREAM_CNTL,
+		DP_VID_STREAM_ENABLE);
+	dm_write_reg(ctx, addr, value);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h
new file mode 100644
index 000000000000..5753a1b7614e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_STREAM_ENCODER_DCE110_H__
+#define __DC_STREAM_ENCODER_DCE110_H__
+
+#include "inc/stream_encoder.h"
+
+#define DCE110STRENC_FROM_STRENC(stream_encoder)\
+	container_of(stream_encoder, struct dce110_stream_encoder, base)
+
+struct dce110_stream_enc_registers {
+	uint32_t AFMT_AVI_INFO0;
+	uint32_t AFMT_AVI_INFO1;
+	uint32_t AFMT_AVI_INFO2;
+	uint32_t AFMT_AVI_INFO3;
+	uint32_t AFMT_GENERIC_0;
+	uint32_t AFMT_GENERIC_7;
+	uint32_t AFMT_GENERIC_HDR;
+	uint32_t AFMT_INFOFRAME_CONTROL0;
+	uint32_t AFMT_VBI_PACKET_CONTROL;
+	uint32_t DIG_FE_CNTL;
+	uint32_t DP_MSE_RATE_CNTL;
+	uint32_t DP_MSE_RATE_UPDATE;
+	uint32_t DP_PIXEL_FORMAT;
+	uint32_t DP_SEC_CNTL;
+	uint32_t DP_STEER_FIFO;
+	uint32_t DP_VID_M;
+	uint32_t DP_VID_N;
+	uint32_t DP_VID_STREAM_CNTL;
+	uint32_t DP_VID_TIMING;
+	uint32_t HDMI_CONTROL;
+	uint32_t HDMI_GC;
+	uint32_t HDMI_GENERIC_PACKET_CONTROL0;
+	uint32_t HDMI_GENERIC_PACKET_CONTROL1;
+	uint32_t HDMI_INFOFRAME_CONTROL0;
+	uint32_t HDMI_INFOFRAME_CONTROL1;
+	uint32_t HDMI_VBI_PACKET_CONTROL;
+	uint32_t TMDS_CNTL;
+};
+
+struct dce110_stream_encoder {
+	struct stream_encoder base;
+	const struct dce110_stream_enc_registers *regs;
+};
+
+bool dce110_stream_encoder_construct(
+	struct dce110_stream_encoder *enc110,
+	struct dc_context *ctx,
+	struct dc_bios *bp,
+	enum engine_id eng_id,
+	const struct dce110_stream_enc_registers *regs);
+
+/***** HW programming ***********/
+/* setup stream encoder in dp mode */
+void dce110_stream_encoder_dp_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing);
+
+/* setup stream encoder in hdmi mode */
+void dce110_stream_encoder_hdmi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool enable_audio);
+
+/* setup stream encoder in dvi mode */
+void dce110_stream_encoder_dvi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool is_dual_link);
+
+/* set throttling for DP MST */
+void dce110_stream_encoder_set_mst_bandwidth(
+	struct stream_encoder *enc,
+	struct fixed31_32 avg_time_slots_per_mtp);
+
+void dce110_stream_encoder_update_hdmi_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame);
+
+void dce110_stream_encoder_stop_hdmi_info_packets(
+	struct stream_encoder *enc);
+
+void dce110_stream_encoder_update_dp_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame);
+
+void dce110_stream_encoder_stop_dp_info_packets(
+	struct stream_encoder *enc);
+
+/* output blank/idle stream to link encoder */
+void dce110_stream_encoder_dp_blank(
+	struct stream_encoder *enc);
+
+/* output video stream to link encoder */
+void dce110_stream_encoder_dp_unblank(
+	struct stream_encoder *enc,
+	const struct encoder_unblank_param *param);
+
+#endif /* __DC_STREAM_ENCODER_DCE110_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 14/26] drm/amd/dal: Add clock source HW programming
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (12 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 13/26] drm/amd/dal: Add encoder HW programming Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 15/26] drm/amd/dal: Add timing generator " Harry Wentland
                     ` (11 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Adds pixel clock programming and functionality to
power down clock sources.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../drm/amd/dal/dc/dce110/dce110_clock_source.c    | 1162 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_clock_source.h    |   64 ++
 2 files changed, 1226 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
new file mode 100644
index 000000000000..e1bac1f77b79
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
@@ -0,0 +1,1162 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dc_types.h"
+#include "core_types.h"
+
+#include "include/grph_object_id.h"
+#include "include/logger_interface.h"
+
+#include "dce110_clock_source.h"
+
+#define FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM 6
+#define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1
+#define MAX_PLL_CALC_ERROR 0xFFFFFFFF
+
+static const struct spread_spectrum_data *get_ss_data_entry(
+		struct dce110_clk_src *clk_src,
+		enum signal_type signal,
+		uint32_t pix_clk_khz)
+{
+
+	uint32_t entrys_num;
+	uint32_t i;
+	struct spread_spectrum_data *ss_parm = NULL;
+	struct spread_spectrum_data *ret = NULL;
+
+	switch (signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		ss_parm = clk_src->dvi_ss_params;
+		entrys_num = clk_src->dvi_ss_params_cnt;
+		break;
+
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		ss_parm = clk_src->hdmi_ss_params;
+		entrys_num = clk_src->hdmi_ss_params_cnt;
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		ss_parm = clk_src->dp_ss_params;
+		entrys_num = clk_src->dp_ss_params_cnt;
+		break;
+
+	default:
+		ss_parm = NULL;
+		entrys_num = 0;
+		break;
+	}
+
+	if (ss_parm == NULL)
+		return ret;
+
+	for (i = 0; i < entrys_num; ++i, ++ss_parm) {
+		if (ss_parm->freq_range_khz >= pix_clk_khz) {
+			ret = ss_parm;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+* Function: calculate_fb_and_fractional_fb_divider
+*
+* * DESCRIPTION: Calculates feedback and fractional feedback dividers values
+*
+*PARAMETERS:
+* targetPixelClock             Desired frequency in 10 KHz
+* ref_divider                  Reference divider (already known)
+* postDivider                  Post Divider (already known)
+* feedback_divider_param       Pointer where to store
+*					calculated feedback divider value
+* fract_feedback_divider_param Pointer where to store
+*					calculated fract feedback divider value
+*
+*RETURNS:
+* It fills the locations pointed by feedback_divider_param
+*					and fract_feedback_divider_param
+* It returns	- true if feedback divider not 0
+*		- false should never happen)
+*/
+static bool calculate_fb_and_fractional_fb_divider(
+		struct calc_pll_clock_source *calc_pll_cs,
+		uint32_t target_pix_clk_khz,
+		uint32_t ref_divider,
+		uint32_t post_divider,
+		uint32_t *feedback_divider_param,
+		uint32_t *fract_feedback_divider_param)
+{
+	uint64_t feedback_divider;
+
+	feedback_divider =
+		(uint64_t)(target_pix_clk_khz * ref_divider * post_divider);
+	feedback_divider *= 10;
+	/* additional factor, since we divide by 10 afterwards */
+	feedback_divider *= (uint64_t)(calc_pll_cs->fract_fb_divider_factor);
+	feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz);
+
+/*Round to the number of precision
+ * The following code replace the old code (ullfeedbackDivider + 5)/10
+ * for example if the difference between the number
+ * of fractional feedback decimal point and the fractional FB Divider precision
+ * is 2 then the equation becomes (ullfeedbackDivider + 5*100) / (10*100))*/
+
+	feedback_divider += (uint64_t)
+			(5 * calc_pll_cs->fract_fb_divider_precision_factor);
+	feedback_divider =
+		div_u64(feedback_divider,
+			calc_pll_cs->fract_fb_divider_precision_factor * 10);
+	feedback_divider *= (uint64_t)
+			(calc_pll_cs->fract_fb_divider_precision_factor);
+
+	*feedback_divider_param =
+		div_u64_rem(
+			feedback_divider,
+			calc_pll_cs->fract_fb_divider_factor,
+			fract_feedback_divider_param);
+
+	if (*feedback_divider_param != 0)
+		return true;
+	return false;
+}
+
+/**
+*calc_fb_divider_checking_tolerance
+*
+*DESCRIPTION: Calculates Feedback and Fractional Feedback divider values
+*		for passed Reference and Post divider, checking for tolerance.
+*PARAMETERS:
+* pll_settings		Pointer to structure
+* ref_divider		Reference divider (already known)
+* postDivider		Post Divider (already known)
+* tolerance		Tolerance for Calculated Pixel Clock to be within
+*
+*RETURNS:
+* It fills the PLLSettings structure with PLL Dividers values
+* if calculated values are within required tolerance
+* It returns	- true if eror is within tolerance
+*		- false if eror is not within tolerance
+*/
+static bool calc_fb_divider_checking_tolerance(
+		struct calc_pll_clock_source *calc_pll_cs,
+		struct pll_settings *pll_settings,
+		uint32_t ref_divider,
+		uint32_t post_divider,
+		uint32_t tolerance)
+{
+	uint32_t feedback_divider;
+	uint32_t fract_feedback_divider;
+	uint32_t actual_calculated_clock_khz;
+	uint32_t abs_err;
+	uint64_t actual_calc_clk_khz;
+
+	calculate_fb_and_fractional_fb_divider(
+			calc_pll_cs,
+			pll_settings->adjusted_pix_clk,
+			ref_divider,
+			post_divider,
+			&feedback_divider,
+			&fract_feedback_divider);
+
+	/*Actual calculated value*/
+	actual_calc_clk_khz = (uint64_t)(feedback_divider *
+					calc_pll_cs->fract_fb_divider_factor) +
+							fract_feedback_divider;
+	actual_calc_clk_khz *= calc_pll_cs->ref_freq_khz;
+	actual_calc_clk_khz =
+		div_u64(actual_calc_clk_khz,
+			ref_divider * post_divider *
+				calc_pll_cs->fract_fb_divider_factor);
+
+	actual_calculated_clock_khz = (uint32_t)(actual_calc_clk_khz);
+
+	abs_err = (actual_calculated_clock_khz >
+					pll_settings->adjusted_pix_clk)
+			? actual_calculated_clock_khz -
+					pll_settings->adjusted_pix_clk
+			: pll_settings->adjusted_pix_clk -
+						actual_calculated_clock_khz;
+
+	if (abs_err <= tolerance) {
+		/*found good values*/
+		pll_settings->reference_freq = calc_pll_cs->ref_freq_khz;
+		pll_settings->reference_divider = ref_divider;
+		pll_settings->feedback_divider = feedback_divider;
+		pll_settings->fract_feedback_divider = fract_feedback_divider;
+		pll_settings->pix_clk_post_divider = post_divider;
+		pll_settings->calculated_pix_clk =
+			actual_calculated_clock_khz;
+		pll_settings->vco_freq =
+			actual_calculated_clock_khz * post_divider;
+		return true;
+	}
+	return false;
+}
+
+
+static bool calc_pll_dividers_in_range(
+		struct calc_pll_clock_source *calc_pll_cs,
+		struct pll_settings *pll_settings,
+		uint32_t min_ref_divider,
+		uint32_t max_ref_divider,
+		uint32_t min_post_divider,
+		uint32_t max_post_divider,
+		uint32_t err_tolerance)
+{
+	uint32_t ref_divider;
+	uint32_t post_divider;
+	uint32_t tolerance;
+
+/* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25%
+ * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/
+	tolerance = (pll_settings->adjusted_pix_clk * err_tolerance) /
+									10000;
+	if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE)
+		tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE;
+
+	for (
+			post_divider = max_post_divider;
+			post_divider >= min_post_divider;
+			--post_divider) {
+		for (
+				ref_divider = min_ref_divider;
+				ref_divider <= max_ref_divider;
+				++ref_divider) {
+			if (calc_fb_divider_checking_tolerance(
+					calc_pll_cs,
+					pll_settings,
+					ref_divider,
+					post_divider,
+					tolerance)) {
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+static uint32_t calculate_pixel_clock_pll_dividers(
+		struct calc_pll_clock_source *calc_pll_cs,
+		struct pll_settings *pll_settings)
+{
+	uint32_t err_tolerance;
+	uint32_t min_post_divider;
+	uint32_t max_post_divider;
+	uint32_t min_ref_divider;
+	uint32_t max_ref_divider;
+
+	if (pll_settings->adjusted_pix_clk == 0) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s Bad requested pixel clock", __func__);
+		return MAX_PLL_CALC_ERROR;
+	}
+
+/* 1) Find Post divider ranges */
+	if (pll_settings->pix_clk_post_divider) {
+		min_post_divider = pll_settings->pix_clk_post_divider;
+		max_post_divider = pll_settings->pix_clk_post_divider;
+	} else {
+		min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider;
+		if (min_post_divider * pll_settings->adjusted_pix_clk <
+						calc_pll_cs->min_vco_khz) {
+			min_post_divider = calc_pll_cs->min_vco_khz /
+					pll_settings->adjusted_pix_clk;
+			if ((min_post_divider *
+					pll_settings->adjusted_pix_clk) <
+						calc_pll_cs->min_vco_khz)
+				min_post_divider++;
+		}
+
+		max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider;
+		if (max_post_divider * pll_settings->adjusted_pix_clk
+				> calc_pll_cs->max_vco_khz)
+			max_post_divider = calc_pll_cs->max_vco_khz /
+					pll_settings->adjusted_pix_clk;
+	}
+
+/* 2) Find Reference divider ranges
+ * When SS is enabled, or for Display Port even without SS,
+ * pll_settings->referenceDivider is not zero.
+ * So calculate PPLL FB and fractional FB divider
+ * using the passed reference divider*/
+
+	if (pll_settings->reference_divider) {
+		min_ref_divider = pll_settings->reference_divider;
+		max_ref_divider = pll_settings->reference_divider;
+	} else {
+		min_ref_divider = ((calc_pll_cs->ref_freq_khz
+				/ calc_pll_cs->max_pll_input_freq_khz)
+				> calc_pll_cs->min_pll_ref_divider)
+			? calc_pll_cs->ref_freq_khz
+					/ calc_pll_cs->max_pll_input_freq_khz
+			: calc_pll_cs->min_pll_ref_divider;
+
+		max_ref_divider = ((calc_pll_cs->ref_freq_khz
+				/ calc_pll_cs->min_pll_input_freq_khz)
+				< calc_pll_cs->max_pll_ref_divider)
+			? calc_pll_cs->ref_freq_khz /
+					calc_pll_cs->min_pll_input_freq_khz
+			: calc_pll_cs->max_pll_ref_divider;
+	}
+
+/* If some parameters are invalid we could have scenario when  "min">"max"
+ * which produced endless loop later.
+ * We should investigate why we get the wrong parameters.
+ * But to follow the similar logic when "adjustedPixelClock" is set to be 0
+ * it is better to return here than cause system hang/watchdog timeout later.
+ *  ## SVS Wed 15 Jul 2009 */
+
+	if (min_post_divider > max_post_divider) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s Post divider range is invalid", __func__);
+		return MAX_PLL_CALC_ERROR;
+	}
+
+	if (min_ref_divider > max_ref_divider) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s Reference divider range is invalid", __func__);
+		return MAX_PLL_CALC_ERROR;
+	}
+
+/* 3) Try to find PLL dividers given ranges
+ * starting with minimal error tolerance.
+ * Increase error tolerance until PLL dividers found*/
+	err_tolerance = MAX_PLL_CALC_ERROR;
+
+	while (!calc_pll_dividers_in_range(
+			calc_pll_cs,
+			pll_settings,
+			min_ref_divider,
+			max_ref_divider,
+			min_post_divider,
+			max_post_divider,
+			err_tolerance))
+		err_tolerance += (err_tolerance > 10)
+				? (err_tolerance / 10)
+				: 1;
+
+	return err_tolerance;
+}
+
+static bool pll_adjust_pix_clk(
+		struct dce110_clk_src *clk_src,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	uint32_t actual_pix_clk_khz = 0;
+	uint32_t requested_clk_khz = 0;
+	struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = {
+							0 };
+	enum bp_result bp_result;
+
+	switch (pix_clk_params->signal_type) {
+	case SIGNAL_TYPE_HDMI_TYPE_A: {
+		requested_clk_khz = pix_clk_params->requested_pix_clk;
+
+		switch (pix_clk_params->color_depth) {
+		case COLOR_DEPTH_101010:
+			requested_clk_khz = (requested_clk_khz * 5) >> 2;
+			break; /* x1.25*/
+		case COLOR_DEPTH_121212:
+			requested_clk_khz = (requested_clk_khz * 6) >> 2;
+			break; /* x1.5*/
+		case COLOR_DEPTH_161616:
+			requested_clk_khz = requested_clk_khz * 2;
+			break; /* x2.0*/
+		default:
+			break;
+		}
+
+		actual_pix_clk_khz = requested_clk_khz;
+	}
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		requested_clk_khz = pix_clk_params->requested_sym_clk;
+		actual_pix_clk_khz = pix_clk_params->requested_pix_clk;
+		break;
+
+	default:
+		requested_clk_khz = pix_clk_params->requested_pix_clk;
+		actual_pix_clk_khz = pix_clk_params->requested_pix_clk;
+		break;
+	}
+
+	bp_adjust_pixel_clock_params.pixel_clock = requested_clk_khz;
+	bp_adjust_pixel_clock_params.
+		encoder_object_id = pix_clk_params->encoder_object_id;
+	bp_adjust_pixel_clock_params.signal_type = pix_clk_params->signal_type;
+	bp_adjust_pixel_clock_params.
+		ss_enable = pix_clk_params->flags.ENABLE_SS;
+	bp_result = clk_src->bios->funcs->adjust_pixel_clock(
+			clk_src->bios, &bp_adjust_pixel_clock_params);
+	if (bp_result == BP_RESULT_OK) {
+		pll_settings->actual_pix_clk = actual_pix_clk_khz;
+		pll_settings->adjusted_pix_clk =
+			bp_adjust_pixel_clock_params.adjusted_pixel_clock;
+		pll_settings->reference_divider =
+			bp_adjust_pixel_clock_params.reference_divider;
+		pll_settings->pix_clk_post_divider =
+			bp_adjust_pixel_clock_params.pixel_clock_post_divider;
+
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * Calculate PLL Dividers for given Clock Value.
+ * First will call VBIOS Adjust Exec table to check if requested Pixel clock
+ * will be Adjusted based on usage.
+ * Then it will calculate PLL Dividers for this Adjusted clock using preferred
+ * method (Maximum VCO frequency).
+ *
+ * \return
+ *     Calculation error in units of 0.01%
+ */
+static uint32_t dce110_get_pix_clk_dividers(
+		struct clock_source *cs,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs);
+	uint32_t pll_calc_error = MAX_PLL_CALC_ERROR;
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	uint32_t field = 0;
+
+	if (pix_clk_params == NULL || pll_settings == NULL
+			|| pix_clk_params->requested_pix_clk == 0) {
+		dal_logger_write(clk_src->base.ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Invalid parameters!!\n", __func__);
+		return pll_calc_error;
+	}
+
+	dm_memset(pll_settings, 0, sizeof(*pll_settings));
+
+	if (cs->id == CLOCK_SOURCE_ID_EXTERNAL) {
+		pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz;
+		pll_settings->calculated_pix_clk = clk_src->ext_clk_khz;
+		pll_settings->actual_pix_clk =
+					pix_clk_params->requested_pix_clk;
+		return 0;
+	}
+	/* PLL only after this point */
+
+	/* Check if reference clock is external (not pcie/xtalin)
+	* HW Dce80 spec:
+	* 00 - PCIE_REFCLK, 01 - XTALIN,    02 - GENERICA,    03 - GENERICB
+	* 04 - HSYNCA,      05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */
+	addr = clk_src->offsets.pll_cntl;
+	value = dm_read_reg(clk_src->base.ctx, addr);
+	field = get_reg_field_value(value, PLL_CNTL, PLL_REF_DIV_SRC);
+	pll_settings->use_external_clk = (field > 1);
+
+	/* VBIOS by default enables DP SS (spread on IDCLK) for DCE 8.0 always
+	 * (we do not care any more from SI for some older DP Sink which
+	 * does not report SS support, no known issues) */
+	if ((pix_clk_params->flags.ENABLE_SS) ||
+			(dc_is_dp_signal(pix_clk_params->signal_type))) {
+
+		const struct spread_spectrum_data *ss_data = get_ss_data_entry(
+					clk_src,
+					pix_clk_params->signal_type,
+					pll_settings->adjusted_pix_clk);
+
+		if (NULL != ss_data)
+			pll_settings->ss_percentage = ss_data->percentage;
+	}
+
+	/* Check VBIOS AdjustPixelClock Exec table */
+	if (!pll_adjust_pix_clk(clk_src, pix_clk_params, pll_settings)) {
+		/* Should never happen, ASSERT and fill up values to be able
+		 * to continue. */
+		dal_logger_write(clk_src->base.ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Failed to adjust pixel clock!!", __func__);
+		pll_settings->actual_pix_clk =
+				pix_clk_params->requested_pix_clk;
+		pll_settings->adjusted_pix_clk =
+				pix_clk_params->requested_pix_clk;
+
+		if (dc_is_dp_signal(pix_clk_params->signal_type))
+			pll_settings->adjusted_pix_clk = 100000;
+	}
+
+	/* Calculate Dividers */
+	if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
+		/*Calculate Dividers by HDMI object, no SS case or SS case */
+		pll_calc_error =
+			calculate_pixel_clock_pll_dividers(
+					&clk_src->calc_pll_hdmi,
+					pll_settings);
+	else
+		/*Calculate Dividers by default object, no SS case or SS case */
+		pll_calc_error =
+			calculate_pixel_clock_pll_dividers(
+					&clk_src->calc_pll,
+					pll_settings);
+
+	return pll_calc_error;
+}
+
+static bool disable_spread_spectrum(struct dce110_clk_src *clk_src)
+{
+	enum bp_result result;
+	struct bp_spread_spectrum_parameters bp_ss_params = {0};
+
+	bp_ss_params.pll_id = clk_src->base.id;
+
+	/*Call ASICControl to process ATOMBIOS Exec table*/
+	result = clk_src->bios->funcs->enable_spread_spectrum_on_ppll(
+			clk_src->bios,
+			&bp_ss_params,
+			false);
+
+	return result == BP_RESULT_OK;
+}
+
+static bool calculate_ss(
+		const struct pll_settings *pll_settings,
+		const struct spread_spectrum_data *ss_data,
+		struct delta_sigma_data *ds_data)
+{
+	struct fixed32_32 fb_div;
+	struct fixed32_32 ss_amount;
+	struct fixed32_32 ss_nslip_amount;
+	struct fixed32_32 ss_ds_frac_amount;
+	struct fixed32_32 ss_step_size;
+	struct fixed32_32 modulation_time;
+
+	if (ds_data == NULL)
+		return false;
+	if (ss_data == NULL)
+		return false;
+	if (ss_data->percentage == 0)
+		return false;
+	if (pll_settings == NULL)
+		return false;
+
+
+	dm_memset(ds_data, 0, sizeof(struct delta_sigma_data));
+
+
+
+	/* compute SS_AMOUNT_FBDIV & SS_AMOUNT_NFRAC_SLIP & SS_AMOUNT_DSFRAC*/
+	/* 6 decimal point support in fractional feedback divider */
+	fb_div  = dal_fixed32_32_from_fraction(
+		pll_settings->fract_feedback_divider, 1000000);
+	fb_div = dal_fixed32_32_add_int(fb_div, pll_settings->feedback_divider);
+
+	ds_data->ds_frac_amount = 0;
+	/*spreadSpectrumPercentage is in the unit of .01%,
+	 * so have to divided by 100 * 100*/
+	ss_amount = dal_fixed32_32_mul(
+		fb_div, dal_fixed32_32_from_fraction(ss_data->percentage,
+					100 * ss_data->percentage_divider));
+	ds_data->feedback_amount = dal_fixed32_32_floor(ss_amount);
+
+	ss_nslip_amount = dal_fixed32_32_sub(ss_amount,
+		dal_fixed32_32_from_int(ds_data->feedback_amount));
+	ss_nslip_amount = dal_fixed32_32_mul_int(ss_nslip_amount, 10);
+	ds_data->nfrac_amount = dal_fixed32_32_floor(ss_nslip_amount);
+
+	ss_ds_frac_amount = dal_fixed32_32_sub(ss_nslip_amount,
+		dal_fixed32_32_from_int(ds_data->nfrac_amount));
+	ss_ds_frac_amount = dal_fixed32_32_mul_int(ss_ds_frac_amount, 65536);
+	ds_data->ds_frac_amount = dal_fixed32_32_floor(ss_ds_frac_amount);
+
+	/* compute SS_STEP_SIZE_DSFRAC */
+	modulation_time = dal_fixed32_32_from_fraction(
+		pll_settings->reference_freq * 1000,
+		pll_settings->reference_divider * ss_data->modulation_freq_hz);
+
+
+	if (ss_data->flags.CENTER_SPREAD)
+		modulation_time = dal_fixed32_32_div_int(modulation_time, 4);
+	else
+		modulation_time = dal_fixed32_32_div_int(modulation_time, 2);
+
+	ss_step_size = dal_fixed32_32_div(ss_amount, modulation_time);
+	/* SS_STEP_SIZE_DSFRAC_DEC = Int(SS_STEP_SIZE * 2 ^ 16 * 10)*/
+	ss_step_size = dal_fixed32_32_mul_int(ss_step_size, 65536 * 10);
+	ds_data->ds_frac_size =  dal_fixed32_32_floor(ss_step_size);
+
+	return true;
+}
+
+static bool enable_spread_spectrum(
+		struct dce110_clk_src *clk_src,
+		enum signal_type signal, struct pll_settings *pll_settings)
+{
+	struct bp_spread_spectrum_parameters bp_params = {0};
+	struct delta_sigma_data d_s_data;
+	const struct spread_spectrum_data *ss_data = NULL;
+
+	ss_data = get_ss_data_entry(
+			clk_src,
+			signal,
+			pll_settings->calculated_pix_clk);
+
+/* Pixel clock PLL has been programmed to generate desired pixel clock,
+ * now enable SS on pixel clock */
+/* TODO is it OK to return true not doing anything ??*/
+	if (ss_data != NULL && pll_settings->ss_percentage != 0) {
+		if (calculate_ss(pll_settings, ss_data, &d_s_data)) {
+			bp_params.ds.feedback_amount =
+					d_s_data.feedback_amount;
+			bp_params.ds.nfrac_amount =
+					d_s_data.nfrac_amount;
+			bp_params.ds.ds_frac_size = d_s_data.ds_frac_size;
+			bp_params.ds_frac_amount =
+					d_s_data.ds_frac_amount;
+			bp_params.flags.DS_TYPE = 1;
+			bp_params.pll_id = clk_src->base.id;
+			bp_params.percentage = ss_data->percentage;
+			if (ss_data->flags.CENTER_SPREAD)
+				bp_params.flags.CENTER_SPREAD = 1;
+			if (ss_data->flags.EXTERNAL_SS)
+				bp_params.flags.EXTERNAL_SS = 1;
+
+			if (BP_RESULT_OK !=
+				clk_src->bios->funcs->
+					enable_spread_spectrum_on_ppll(
+							clk_src->bios,
+							&bp_params,
+							true))
+				return false;
+		} else
+			return false;
+	}
+	return true;
+}
+
+static void program_pixel_clk_resync(
+		struct dce110_clk_src *clk_src,
+		enum signal_type signal_type,
+		enum dc_color_depth colordepth)
+{
+	uint32_t value = 0;
+
+	value = dm_read_reg(clk_src->base.ctx, clk_src->offsets.pixclk_resync_cntl);
+
+	set_reg_field_value(
+		value,
+		0,
+		PIXCLK1_RESYNC_CNTL,
+		DCCG_DEEP_COLOR_CNTL1);
+
+	/*
+	 24 bit mode: TMDS clock = 1.0 x pixel clock  (1:1)
+	 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4)
+	 36 bit mode: TMDS clock = 1.5 x pixel clock  (3:2)
+	 48 bit mode: TMDS clock = 2 x pixel clock    (2:1)
+	 */
+	if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A)
+		return;
+
+	switch (colordepth) {
+	case COLOR_DEPTH_888:
+		set_reg_field_value(
+			value,
+			0,
+			PIXCLK1_RESYNC_CNTL,
+			DCCG_DEEP_COLOR_CNTL1);
+		break;
+	case COLOR_DEPTH_101010:
+		set_reg_field_value(
+			value,
+			1,
+			PIXCLK1_RESYNC_CNTL,
+			DCCG_DEEP_COLOR_CNTL1);
+		break;
+	case COLOR_DEPTH_121212:
+		set_reg_field_value(
+			value,
+			2,
+			PIXCLK1_RESYNC_CNTL,
+			DCCG_DEEP_COLOR_CNTL1);
+		break;
+	case COLOR_DEPTH_161616:
+		set_reg_field_value(
+			value,
+			3,
+			PIXCLK1_RESYNC_CNTL,
+			DCCG_DEEP_COLOR_CNTL1);
+		break;
+	default:
+		break;
+	}
+
+	dm_write_reg(
+		clk_src->base.ctx,
+		clk_src->offsets.pixclk_resync_cntl,
+		value);
+}
+
+static bool dce110_program_pix_clk(
+		struct clock_source *clk_src,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src);
+	struct bp_pixel_clock_parameters bp_pc_params = {0};
+
+	/* First disable SS
+	 * ATOMBIOS will enable by default SS on PLL for DP,
+	 * do not disable it here
+	 */
+	if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL &&
+			!dc_is_dp_signal(pix_clk_params->signal_type))
+		disable_spread_spectrum(dce110_clk_src);
+
+	/*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/
+	bp_pc_params.controller_id = pix_clk_params->controller_id;
+	bp_pc_params.pll_id = clk_src->id;
+	bp_pc_params.target_pixel_clock =
+			pll_settings->actual_pix_clk;
+	bp_pc_params.reference_divider = pll_settings->reference_divider;
+	bp_pc_params.feedback_divider = pll_settings->feedback_divider;
+	bp_pc_params.fractional_feedback_divider =
+			pll_settings->fract_feedback_divider;
+	bp_pc_params.pixel_clock_post_divider =
+			pll_settings->pix_clk_post_divider;
+	bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id;
+	bp_pc_params.signal_type = pix_clk_params->signal_type;
+	bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC =
+					pll_settings->use_external_clk;
+
+	if (dce110_clk_src->bios->funcs->set_pixel_clock(
+			dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK)
+		return false;
+
+/* Enable SS
+ * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock),
+ * based on HW display PLL team, SS control settings should be programmed
+ * during PLL Reset, but they do not have effect
+ * until SS_EN is asserted.*/
+	if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL
+		&& pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal(
+						pix_clk_params->signal_type))
+		if (!enable_spread_spectrum(dce110_clk_src,
+						pix_clk_params->signal_type,
+						pll_settings))
+			return false;
+
+/* Resync deep color DTO */
+	if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL)
+		program_pixel_clk_resync(dce110_clk_src,
+					pix_clk_params->signal_type,
+					pix_clk_params->color_depth);
+
+	return true;
+}
+
+static bool dce110_clock_source_power_down(
+		struct clock_source *clk_src)
+{
+	struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src);
+	enum bp_result bp_result;
+	struct bp_pixel_clock_parameters bp_pixel_clock_params = {0};
+
+	if (clk_src->id == CLOCK_SOURCE_ID_EXTERNAL)
+		return true;
+
+	/* If Pixel Clock is 0 it means Power Down Pll*/
+	bp_pixel_clock_params.controller_id = CONTROLLER_ID_UNDEFINED;
+	bp_pixel_clock_params.pll_id = clk_src->id;
+	bp_pixel_clock_params.flags.FORCE_PROGRAMMING_OF_PLL = 1;
+
+	/*Call ASICControl to process ATOMBIOS Exec table*/
+	bp_result = dce110_clk_src->bios->funcs->set_pixel_clock(
+			dce110_clk_src->bios,
+			&bp_pixel_clock_params);
+
+	return bp_result == BP_RESULT_OK;
+}
+
+/*****************************************/
+/* Constructor                           */
+/*****************************************/
+static struct clock_source_funcs dce110_clk_src_funcs = {
+	.cs_power_down = dce110_clock_source_power_down,
+	.program_pix_clk = dce110_program_pix_clk,
+	.get_pix_clk_dividers = dce110_get_pix_clk_dividers
+};
+
+
+static void get_ss_info_from_atombios(
+		struct dce110_clk_src *clk_src,
+		enum as_signal_type as_signal,
+		struct spread_spectrum_data *spread_spectrum_data[],
+		uint32_t *ss_entries_num)
+{
+	enum bp_result bp_result = BP_RESULT_FAILURE;
+	struct spread_spectrum_info *ss_info;
+	struct spread_spectrum_data *ss_data;
+	struct spread_spectrum_info *ss_info_cur;
+	struct spread_spectrum_data *ss_data_cur;
+	uint32_t i;
+
+	if (ss_entries_num == NULL) {
+		dal_logger_write(clk_src->base.ctx->logger,
+			LOG_MAJOR_SYNC,
+			LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+			"Invalid entry !!!\n");
+		return;
+	}
+	if (spread_spectrum_data == NULL) {
+		dal_logger_write(clk_src->base.ctx->logger,
+			LOG_MAJOR_SYNC,
+			LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+			"Invalid array pointer!!!\n");
+		return;
+	}
+
+	spread_spectrum_data[0] = NULL;
+	*ss_entries_num = 0;
+
+	*ss_entries_num = clk_src->bios->funcs->get_ss_entry_number(
+			clk_src->bios,
+			as_signal);
+
+	if (*ss_entries_num == 0)
+		return;
+
+	ss_info = dm_alloc(clk_src->base.ctx, sizeof(struct spread_spectrum_info)
+				* (*ss_entries_num));
+	ss_info_cur = ss_info;
+	if (ss_info == NULL)
+		return;
+
+	ss_data = dm_alloc(clk_src->base.ctx, sizeof(struct spread_spectrum_data) *
+							(*ss_entries_num));
+	if (ss_data == NULL)
+		goto out_free_info;
+
+	for (i = 0, ss_info_cur = ss_info;
+		i < (*ss_entries_num);
+		++i, ++ss_info_cur) {
+
+		bp_result = clk_src->bios->funcs->get_spread_spectrum_info(
+				clk_src->bios,
+				as_signal,
+				i,
+				ss_info_cur);
+
+		if (bp_result != BP_RESULT_OK)
+			goto out_free_data;
+	}
+
+	for (i = 0, ss_info_cur = ss_info, ss_data_cur = ss_data;
+		i < (*ss_entries_num);
+		++i, ++ss_info_cur, ++ss_data_cur) {
+
+		if (ss_info_cur->type.STEP_AND_DELAY_INFO != false) {
+			dal_logger_write(clk_src->base.ctx->logger,
+				LOG_MAJOR_SYNC,
+				LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+				"Invalid ATOMBIOS SS Table!!!\n");
+			goto out_free_data;
+		}
+
+		/* for HDMI check SS percentage,
+		 * if it is > 6 (0.06%), the ATOMBIOS table info is invalid*/
+		if (as_signal == AS_SIGNAL_TYPE_HDMI
+				&& ss_info_cur->spread_spectrum_percentage > 6){
+			/* invalid input, do nothing */
+			dal_logger_write(clk_src->base.ctx->logger,
+				LOG_MAJOR_SYNC,
+				LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+				"Invalid SS percentage ");
+			dal_logger_write(clk_src->base.ctx->logger,
+				LOG_MAJOR_SYNC,
+				LOG_MINOR_SYNC_HW_CLOCK_ADJUST,
+				"for HDMI in ATOMBIOS info Table!!!\n");
+			continue;
+		}
+		if (ss_info_cur->spread_percentage_divider == 1000) {
+			/* Keep previous precision from ATOMBIOS for these
+			* in case new precision set by ATOMBIOS for these
+			* (otherwise all code in DCE specific classes
+			* for all previous ASICs would need
+			* to be updated for SS calculations,
+			* Audio SS compensation and DP DTO SS compensation
+			* which assumes fixed SS percentage Divider = 100)*/
+			ss_info_cur->spread_spectrum_percentage /= 10;
+			ss_info_cur->spread_percentage_divider = 100;
+		}
+
+		ss_data_cur->freq_range_khz = ss_info_cur->target_clock_range;
+		ss_data_cur->percentage =
+				ss_info_cur->spread_spectrum_percentage;
+		ss_data_cur->percentage_divider =
+				ss_info_cur->spread_percentage_divider;
+		ss_data_cur->modulation_freq_hz =
+				ss_info_cur->spread_spectrum_range;
+
+		if (ss_info_cur->type.CENTER_MODE)
+			ss_data_cur->flags.CENTER_SPREAD = 1;
+
+		if (ss_info_cur->type.EXTERNAL)
+			ss_data_cur->flags.EXTERNAL_SS = 1;
+
+	}
+
+	*spread_spectrum_data = ss_data;
+	dm_free(clk_src->base.ctx, ss_info);
+	return;
+
+out_free_data:
+	dm_free(clk_src->base.ctx, ss_data);
+	*ss_entries_num = 0;
+out_free_info:
+	dm_free(clk_src->base.ctx, ss_info);
+}
+
+static void ss_info_from_atombios_create(
+	struct dce110_clk_src *clk_src)
+{
+	get_ss_info_from_atombios(
+		clk_src,
+		AS_SIGNAL_TYPE_DISPLAY_PORT,
+		&clk_src->dp_ss_params,
+		&clk_src->dp_ss_params_cnt);
+	get_ss_info_from_atombios(
+		clk_src,
+		AS_SIGNAL_TYPE_HDMI,
+		&clk_src->hdmi_ss_params,
+		&clk_src->hdmi_ss_params_cnt);
+	get_ss_info_from_atombios(
+		clk_src,
+		AS_SIGNAL_TYPE_DVI,
+		&clk_src->dvi_ss_params,
+		&clk_src->dvi_ss_params_cnt);
+}
+
+static bool calc_pll_max_vco_construct(
+			struct calc_pll_clock_source *calc_pll_cs,
+			struct calc_pll_clock_source_init_data *init_data)
+{
+	uint32_t i;
+	struct firmware_info fw_info = { { 0 } };
+	if (calc_pll_cs == NULL ||
+			init_data == NULL ||
+			init_data->bp == NULL)
+		return false;
+
+	if (init_data->bp->funcs->get_firmware_info(
+				init_data->bp,
+				&fw_info) != BP_RESULT_OK)
+		return false;
+
+	calc_pll_cs->ctx = init_data->ctx;
+	calc_pll_cs->ref_freq_khz = fw_info.pll_info.crystal_frequency;
+	calc_pll_cs->min_vco_khz =
+			fw_info.pll_info.min_output_pxl_clk_pll_frequency;
+	calc_pll_cs->max_vco_khz =
+			fw_info.pll_info.max_output_pxl_clk_pll_frequency;
+
+	if (init_data->max_override_input_pxl_clk_pll_freq_khz != 0)
+		calc_pll_cs->max_pll_input_freq_khz =
+			init_data->max_override_input_pxl_clk_pll_freq_khz;
+	else
+		calc_pll_cs->max_pll_input_freq_khz =
+			fw_info.pll_info.max_input_pxl_clk_pll_frequency;
+
+	if (init_data->min_override_input_pxl_clk_pll_freq_khz != 0)
+		calc_pll_cs->min_pll_input_freq_khz =
+			init_data->min_override_input_pxl_clk_pll_freq_khz;
+	else
+		calc_pll_cs->min_pll_input_freq_khz =
+			fw_info.pll_info.min_input_pxl_clk_pll_frequency;
+
+	calc_pll_cs->min_pix_clock_pll_post_divider =
+			init_data->min_pix_clk_pll_post_divider;
+	calc_pll_cs->max_pix_clock_pll_post_divider =
+			init_data->max_pix_clk_pll_post_divider;
+	calc_pll_cs->min_pll_ref_divider =
+			init_data->min_pll_ref_divider;
+	calc_pll_cs->max_pll_ref_divider =
+			init_data->max_pll_ref_divider;
+
+	if (init_data->num_fract_fb_divider_decimal_point == 0 ||
+		init_data->num_fract_fb_divider_decimal_point_precision >
+				init_data->num_fract_fb_divider_decimal_point) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"The dec point num or precision is incorrect!");
+		return false;
+	}
+	if (init_data->num_fract_fb_divider_decimal_point_precision == 0) {
+		dal_logger_write(calc_pll_cs->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_GPU,
+			"Incorrect fract feedback divider precision num!");
+		return false;
+	}
+
+	calc_pll_cs->fract_fb_divider_decimal_points_num =
+				init_data->num_fract_fb_divider_decimal_point;
+	calc_pll_cs->fract_fb_divider_precision =
+			init_data->num_fract_fb_divider_decimal_point_precision;
+	calc_pll_cs->fract_fb_divider_factor = 1;
+	for (i = 0; i < calc_pll_cs->fract_fb_divider_decimal_points_num; ++i)
+		calc_pll_cs->fract_fb_divider_factor *= 10;
+
+	calc_pll_cs->fract_fb_divider_precision_factor = 1;
+	for (
+		i = 0;
+		i < (calc_pll_cs->fract_fb_divider_decimal_points_num -
+				calc_pll_cs->fract_fb_divider_precision);
+		++i)
+		calc_pll_cs->fract_fb_divider_precision_factor *= 10;
+
+	return true;
+}
+
+bool dce110_clk_src_construct(
+	struct dce110_clk_src *clk_src,
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_reg_offsets *reg_offsets)
+{
+	struct firmware_info fw_info = { { 0 } };
+/* structure normally used with PLL ranges from ATOMBIOS; DS on by default */
+	struct calc_pll_clock_source_init_data calc_pll_cs_init_data = {
+		bios,
+		1, /* minPixelClockPLLPostDivider */
+		PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK,
+		/* maxPixelClockPLLPostDivider*/
+		1,/* minPLLRefDivider*/
+		PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/
+		0,
+/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+		0,
+/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+		FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM,
+/*numberOfFractFBDividerDecimalPoints*/
+		FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM,
+/*number of decimal point to round off for fractional feedback divider value*/
+		ctx
+	};
+/*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */
+	struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi = {
+		bios,
+		1, /* minPixelClockPLLPostDivider */
+		PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK,
+		/* maxPixelClockPLLPostDivider*/
+		1,/* minPLLRefDivider*/
+		PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/
+		13500,
+	/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+		27000,
+	/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+		FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM,
+		/*numberOfFractFBDividerDecimalPoints*/
+		FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM,
+/*number of decimal point to round off for fractional feedback divider value*/
+		ctx
+	};
+
+	clk_src->base.ctx = ctx;
+	clk_src->bios = bios;
+	clk_src->base.id = id;
+	clk_src->base.funcs = &dce110_clk_src_funcs;
+	clk_src->offsets = *reg_offsets;
+
+	if (clk_src->bios->funcs->get_firmware_info(
+			clk_src->bios, &fw_info) != BP_RESULT_OK) {
+		ASSERT_CRITICAL(false);
+		goto unexpected_failure;
+	}
+
+	clk_src->ext_clk_khz =
+			fw_info.external_clock_source_frequency_for_dp;
+	clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency;
+
+	if (clk_src->base.id == CLOCK_SOURCE_ID_EXTERNAL)
+		return true;
+
+	/* PLL only from here on */
+	ss_info_from_atombios_create(clk_src);
+
+	if (!calc_pll_max_vco_construct(
+			&clk_src->calc_pll,
+			&calc_pll_cs_init_data)) {
+		ASSERT_CRITICAL(false);
+		goto unexpected_failure;
+	}
+
+	if (clk_src->ref_freq_khz == 48000) {
+		calc_pll_cs_init_data_hdmi.
+			min_override_input_pxl_clk_pll_freq_khz = 24000;
+		calc_pll_cs_init_data_hdmi.
+			max_override_input_pxl_clk_pll_freq_khz = 48000;
+	} else if (clk_src->ref_freq_khz == 100000) {
+		calc_pll_cs_init_data_hdmi.
+			min_override_input_pxl_clk_pll_freq_khz = 25000;
+		calc_pll_cs_init_data_hdmi.
+			max_override_input_pxl_clk_pll_freq_khz = 50000;
+	}
+
+	if (!calc_pll_max_vco_construct(
+			&clk_src->calc_pll_hdmi, &calc_pll_cs_init_data_hdmi)) {
+		ASSERT_CRITICAL(false);
+		goto unexpected_failure;
+	}
+
+	return true;
+
+unexpected_failure:
+	return false;
+}
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h
new file mode 100644
index 000000000000..4fa82dad271f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h
@@ -0,0 +1,64 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_CLOCK_SOURCE_DCE110_H__
+#define __DC_CLOCK_SOURCE_DCE110_H__
+
+#include "../inc/clock_source.h"
+
+#define TO_DCE110_CLK_SRC(clk_src)\
+	container_of(clk_src, struct dce110_clk_src, base)
+
+struct dce110_clk_src_reg_offsets {
+	uint32_t pll_cntl;
+	uint32_t pixclk_resync_cntl;
+};
+
+struct dce110_clk_src {
+	struct clock_source base;
+	struct dce110_clk_src_reg_offsets offsets;
+	struct dc_bios *bios;
+
+	struct spread_spectrum_data *dp_ss_params;
+	uint32_t dp_ss_params_cnt;
+	struct spread_spectrum_data *hdmi_ss_params;
+	uint32_t hdmi_ss_params_cnt;
+	struct spread_spectrum_data *dvi_ss_params;
+	uint32_t dvi_ss_params_cnt;
+
+	uint32_t ext_clk_khz;
+	uint32_t ref_freq_khz;
+
+	struct calc_pll_clock_source calc_pll;
+	struct calc_pll_clock_source calc_pll_hdmi;
+};
+
+bool dce110_clk_src_construct(
+	struct dce110_clk_src *clk_src,
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id,
+	const struct dce110_clk_src_reg_offsets *reg_offsets);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 15/26] drm/amd/dal: Add timing generator HW programming
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (13 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 14/26] drm/amd/dal: Add clock source " Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 16/26] drm/amd/dal: Add surface " Harry Wentland
                     ` (10 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Adds ability to validate and program timings, enable, disable, and blank
CRTCs, and get CRTC status information.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../amd/dal/dc/dce110/dce110_timing_generator.c    | 1864 ++++++++++++++++++++
 .../amd/dal/dc/dce110/dce110_timing_generator.h    |  234 +++
 2 files changed, 2098 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
new file mode 100644
index 000000000000..6e6a7a5cac6a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
@@ -0,0 +1,1864 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dc_types.h"
+#include "dc_bios_types.h"
+
+#include "include/grph_object_id.h"
+#include "include/adapter_service_interface.h"
+#include "include/logger_interface.h"
+#include "dce110_timing_generator.h"
+
+#include "../inc/timing_generator.h"
+
+enum black_color_format {
+	BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0,	/* used as index in array */
+	BLACK_COLOR_FORMAT_RGB_LIMITED,
+	BLACK_COLOR_FORMAT_YUV_TV,
+	BLACK_COLOR_FORMAT_YUV_CV,
+	BLACK_COLOR_FORMAT_YUV_SUPER_AA,
+
+	BLACK_COLOR_FORMAT_COUNT
+};
+
+#define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10
+
+#define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1)
+#define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1)
+
+#define CRTC_REG(reg) (reg + tg110->offsets.crtc)
+#define DCP_REG(reg) (reg + tg110->offsets.dcp)
+
+
+/*******************************************************************************
+ * GSL Sync related values */
+
+/* In VSync mode, after 4 units of time, master pipe will generate
+ * flip_ready signal */
+#define VFLIP_READY_DELAY 4
+/* In HSync mode, after 2 units of time, master pipe will generate
+ * flip_ready signal */
+#define HFLIP_READY_DELAY 2
+/* 6 lines delay between forcing flip and checking all pipes ready */
+#define HFLIP_CHECK_DELAY 6
+/* 3 lines before end of frame */
+#define FLIP_READY_BACK_LOOKUP 3
+
+/* Trigger Source Select - ASIC-dependant, actual values for the
+ * register programming */
+enum trigger_source_select {
+	TRIGGER_SOURCE_SELECT_LOGIC_ZERO = 0,
+	TRIGGER_SOURCE_SELECT_CRTC_VSYNCA = 1,
+	TRIGGER_SOURCE_SELECT_CRTC_HSYNCA = 2,
+	TRIGGER_SOURCE_SELECT_CRTC_VSYNCB = 3,
+	TRIGGER_SOURCE_SELECT_CRTC_HSYNCB = 4,
+	TRIGGER_SOURCE_SELECT_GENERICF = 5,
+	TRIGGER_SOURCE_SELECT_GENERICE = 6,
+	TRIGGER_SOURCE_SELECT_VSYNCA = 7,
+	TRIGGER_SOURCE_SELECT_HSYNCA = 8,
+	TRIGGER_SOURCE_SELECT_VSYNCB = 9,
+	TRIGGER_SOURCE_SELECT_HSYNCB = 10,
+	TRIGGER_SOURCE_SELECT_HPD1 = 11,
+	TRIGGER_SOURCE_SELECT_HPD2 = 12,
+	TRIGGER_SOURCE_SELECT_GENERICD = 13,
+	TRIGGER_SOURCE_SELECT_GENERICC = 14,
+	TRIGGER_SOURCE_SELECT_VIDEO_CAPTURE = 15,
+	TRIGGER_SOURCE_SELECT_GSL_GROUP0 = 16,
+	TRIGGER_SOURCE_SELECT_GSL_GROUP1 = 17,
+	TRIGGER_SOURCE_SELECT_GSL_GROUP2 = 18,
+	TRIGGER_SOURCE_SELECT_BLONY = 19,
+	TRIGGER_SOURCE_SELECT_GENERICA = 20,
+	TRIGGER_SOURCE_SELECT_GENERICB = 21,
+	TRIGGER_SOURCE_SELECT_GSL_ALLOW_FLIP = 22,
+	TRIGGER_SOURCE_SELECT_MANUAL_TRIGGER = 23
+};
+
+/* Trigger Source Select - ASIC-dependant, actual values for the
+ * register programming */
+enum trigger_polarity_select {
+	TRIGGER_POLARITY_SELECT_LOGIC_ZERO = 0,
+	TRIGGER_POLARITY_SELECT_CRTC = 1,
+	TRIGGER_POLARITY_SELECT_GENERICA = 2,
+	TRIGGER_POLARITY_SELECT_GENERICB = 3,
+	TRIGGER_POLARITY_SELECT_HSYNCA = 4,
+	TRIGGER_POLARITY_SELECT_HSYNCB = 5,
+	TRIGGER_POLARITY_SELECT_VIDEO_CAPTURE = 6,
+	TRIGGER_POLARITY_SELECT_GENERICC = 7
+};
+
+/******************************************************************************/
+
+static struct timing_generator_funcs dce110_tg_funcs = {
+		.validate_timing = dce110_tg_validate_timing,
+		.program_timing = dce110_tg_program_timing,
+		.enable_crtc = dce110_timing_generator_enable_crtc,
+		.disable_crtc = dce110_timing_generator_disable_crtc,
+		.is_counter_moving = dce110_timing_generator_is_counter_moving,
+		.get_position = dce110_timing_generator_get_crtc_positions,
+		.get_frame_count = dce110_timing_generator_get_vblank_counter,
+		.set_early_control = dce110_timing_generator_set_early_control,
+		.wait_for_state = dce110_tg_wait_for_state,
+		.set_blank = dce110_tg_set_blank,
+		.set_colors = dce110_tg_set_colors,
+		.set_overscan_blank_color =
+				dce110_timing_generator_set_overscan_color_black,
+		.set_blank_color = dce110_timing_generator_program_blank_color,
+		.disable_vga = dce110_timing_generator_disable_vga,
+		.did_triggered_reset_occur =
+				dce110_timing_generator_did_triggered_reset_occur,
+		.setup_global_swap_lock =
+				dce110_timing_generator_setup_global_swap_lock,
+		.enable_reset_trigger = dce110_timing_generator_enable_reset_trigger,
+		.disable_reset_trigger = dce110_timing_generator_disable_reset_trigger,
+		.tear_down_global_swap_lock =
+				dce110_timing_generator_tear_down_global_swap_lock,
+		.enable_advanced_request =
+				dce110_timing_generator_enable_advanced_request
+};
+
+static const struct crtc_black_color black_color_format[] = {
+	/* BlackColorFormat_RGB_FullRange */
+	{0, 0, 0},
+	/* BlackColorFormat_RGB_Limited */
+	{CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE},
+	/* BlackColorFormat_YUV_TV */
+	{CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV},
+	/* BlackColorFormat_YUV_CV */
+	{CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4CV,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV},
+	/* BlackColorFormat_YUV_SuperAA */
+	{CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA,
+		CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA}
+};
+
+/**
+* apply_front_porch_workaround
+*
+* This is a workaround for a bug that has existed since R5xx and has not been
+* fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
+*/
+static void dce110_timing_generator_apply_front_porch_workaround(
+	struct timing_generator *tg,
+	struct dc_crtc_timing *timing)
+{
+	if (timing->flags.INTERLACE == 1) {
+		if (timing->v_front_porch < 2)
+			timing->v_front_porch = 2;
+	} else {
+		if (timing->v_front_porch < 1)
+			timing->v_front_porch = 1;
+	}
+}
+
+static void dce110_timing_generator_color_space_to_black_color(
+		enum color_space colorspace,
+	struct crtc_black_color *black_color)
+{
+	switch (colorspace) {
+	case COLOR_SPACE_YPBPR601:
+		*black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_TV];
+		break;
+
+	case COLOR_SPACE_YPBPR709:
+	case COLOR_SPACE_YCBCR601:
+	case COLOR_SPACE_YCBCR709:
+		*black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV];
+		break;
+
+	case COLOR_SPACE_N_MVPU_SUPER_AA:
+		/* In crossfire SuperAA mode, the slave overscan data is forced
+		 * to 0 in the pixel mixer on the master.  As a result, we need
+		 * to adjust the blank color so that after blending the
+		 * master+slave, it will appear black
+		 */
+		*black_color =
+			black_color_format[BLACK_COLOR_FORMAT_YUV_SUPER_AA];
+		break;
+
+	case COLOR_SPACE_SRGB_LIMITED_RANGE:
+		*black_color =
+			black_color_format[BLACK_COLOR_FORMAT_RGB_LIMITED];
+		break;
+
+	default:
+		/* fefault is sRGB black (full range). */
+		*black_color =
+			black_color_format[BLACK_COLOR_FORMAT_RGB_FULLRANGE];
+		/* default is sRGB black 0. */
+		break;
+	}
+}
+
+/**
+ *****************************************************************************
+ *  Function: is_in_vertical_blank
+ *
+ *  @brief
+ *     check the current status of CRTC to check if we are in Vertical Blank
+ *     regioneased" state
+ *
+ *  @return
+ *     true if currently in blank region, false otherwise
+ *
+ *****************************************************************************
+ */
+static bool dce110_timing_generator_is_in_vertical_blank(
+		struct timing_generator *tg)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	uint32_t field = 0;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	addr = CRTC_REG(mmCRTC_STATUS);
+	value = dm_read_reg(tg->ctx, addr);
+	field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK);
+	return field == 1;
+}
+
+void dce110_timing_generator_set_early_control(
+		struct timing_generator *tg,
+		uint32_t early_cntl)
+{
+	uint32_t regval;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t address = CRTC_REG(mmCRTC_CONTROL);
+
+	regval = dm_read_reg(tg->ctx, address);
+	set_reg_field_value(regval, early_cntl,
+			CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
+	dm_write_reg(tg->ctx, address, regval);
+}
+
+/**
+ * Enable CRTC
+ * Enable CRTC - call ASIC Control Object to enable Timing generator.
+ */
+bool dce110_timing_generator_enable_crtc(struct timing_generator *tg)
+{
+	enum bp_result result;
+
+	/* 0 value is needed by DRR and is also suggested default value for CZ
+	 */
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	value = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_MASTER_UPDATE_MODE));
+	set_reg_field_value(value, 3,
+			CRTC_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE);
+	dm_write_reg(tg->ctx,
+			CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
+
+	result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
+
+	return result == BP_RESULT_OK;
+}
+
+void dce110_timing_generator_program_blank_color(
+		struct timing_generator *tg,
+		enum color_space color_space)
+{
+	struct crtc_black_color black_color;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+
+	dce110_timing_generator_color_space_to_black_color(
+		color_space,
+		&black_color);
+
+	set_reg_field_value(
+		value,
+		black_color.black_color_b_cb,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_B_CB);
+	set_reg_field_value(
+		value,
+		black_color.black_color_g_y,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_G_Y);
+	set_reg_field_value(
+		value,
+		black_color.black_color_r_cr,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_R_CR);
+
+	dm_write_reg(tg->ctx, addr, value);
+}
+
+/**
+ * blank_crtc
+ * Call ASIC Control Object to Blank CRTC.
+ */
+
+bool dce110_timing_generator_blank_crtc(struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_BLANK_CONTROL);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+	uint8_t counter = 100;
+
+	set_reg_field_value(
+		value,
+		1,
+		CRTC_BLANK_CONTROL,
+		CRTC_BLANK_DATA_EN);
+
+	set_reg_field_value(
+		value,
+		1,
+		CRTC_BLANK_CONTROL,
+		CRTC_BLANK_DE_MODE);
+
+	dm_write_reg(tg->ctx, addr, value);
+
+	while (counter > 0) {
+		value = dm_read_reg(tg->ctx, addr);
+
+		if (get_reg_field_value(
+			value,
+			CRTC_BLANK_CONTROL,
+			CRTC_BLANK_DATA_EN) == 1 &&
+			get_reg_field_value(
+			value,
+			CRTC_BLANK_CONTROL,
+			CRTC_CURRENT_BLANK_STATE) == 1)
+			break;
+
+		dm_sleep_in_milliseconds(tg->ctx, 1);
+		counter--;
+	}
+
+	if (!counter) {
+		dal_logger_write(tg->ctx->logger, LOG_MAJOR_ERROR,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"timing generator %d blank timing out.\n",
+				tg110->controller_id);
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * unblank_crtc
+ * Call ASIC Control Object to UnBlank CRTC.
+ */
+bool dce110_timing_generator_unblank_crtc(struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_BLANK_CONTROL);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		CRTC_BLANK_CONTROL,
+		CRTC_BLANK_DATA_EN);
+
+	set_reg_field_value(
+		value,
+		0,
+		CRTC_BLANK_CONTROL,
+		CRTC_BLANK_DE_MODE);
+
+	dm_write_reg(tg->ctx, addr, value);
+
+	return true;
+}
+
+/**
+ *****************************************************************************
+ *  Function: disable_stereo
+ *
+ *  @brief
+ *     Disables active stereo on controller
+ *     Frame Packing need to be disabled in vBlank or when CRTC not running
+ *****************************************************************************
+ */
+#if 0
+@TODOSTEREO
+static void disable_stereo(struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL);
+	uint32_t value = 0;
+	uint32_t test = 0;
+	uint32_t field = 0;
+	uint32_t struc_en = 0;
+	uint32_t struc_stereo_sel_ovr = 0;
+
+	value = dm_read_reg(tg->ctx, addr);
+	struc_en = get_reg_field_value(
+			value,
+			CRTC_3D_STRUCTURE_CONTROL,
+			CRTC_3D_STRUCTURE_EN);
+
+	struc_stereo_sel_ovr = get_reg_field_value(
+			value,
+			CRTC_3D_STRUCTURE_CONTROL,
+			CRTC_3D_STRUCTURE_STEREO_SEL_OVR);
+
+	/*
+	 * When disabling Frame Packing in 2 step mode, we need to program both
+	 * registers at the same frame
+	 * Programming it in the beginning of VActive makes sure we are ok
+	 */
+
+	if (struc_en != 0 && struc_stereo_sel_ovr == 0) {
+		tg->funcs->wait_for_vblank(tg);
+		tg->funcs->wait_for_vactive(tg);
+	}
+
+	value = 0;
+	dm_write_reg(tg->ctx, addr, value);
+
+
+	addr = tg->regs[IDX_CRTC_STEREO_CONTROL];
+	dm_write_reg(tg->ctx, addr, value);
+}
+#endif
+
+/**
+ * disable_crtc - call ASIC Control Object to disable Timing generator.
+ */
+bool dce110_timing_generator_disable_crtc(struct timing_generator *tg)
+{
+	enum bp_result result;
+
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, false);
+
+	/* Need to make sure stereo is disabled according to the DCE5.0 spec */
+
+	/*
+	 * @TODOSTEREO call this when adding stereo support
+	 * tg->funcs->disable_stereo(tg);
+	 */
+
+	return result == BP_RESULT_OK;
+}
+
+/**
+* program_horz_count_by_2
+* Programs DxCRTC_HORZ_COUNT_BY2_EN - 1 for DVI 30bpp mode, 0 otherwise
+*
+*/
+static void program_horz_count_by_2(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t regval;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	regval = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_COUNT_CONTROL));
+
+	set_reg_field_value(regval, 0, CRTC_COUNT_CONTROL,
+			CRTC_HORZ_COUNT_BY2_EN);
+
+	if (timing->flags.HORZ_COUNT_BY_TWO)
+		set_reg_field_value(regval, 1, CRTC_COUNT_CONTROL,
+					CRTC_HORZ_COUNT_BY2_EN);
+
+	dm_write_reg(tg->ctx,
+			CRTC_REG(mmCRTC_COUNT_CONTROL), regval);
+}
+
+/**
+ * program_timing_generator
+ * Program CRTC Timing Registers - DxCRTC_H_*, DxCRTC_V_*, Pixel repetition.
+ * Call ASIC Control Object to program Timings.
+ */
+bool dce110_timing_generator_program_timing_generator(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *dc_crtc_timing)
+{
+	enum bp_result result;
+	struct bp_hw_crtc_timing_parameters bp_params;
+	struct dc_crtc_timing patched_crtc_timing;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	uint32_t vsync_offset = dc_crtc_timing->v_border_bottom +
+			dc_crtc_timing->v_front_porch;
+	uint32_t v_sync_start =dc_crtc_timing->v_addressable + vsync_offset;
+
+	uint32_t hsync_offset = dc_crtc_timing->h_border_right +
+			dc_crtc_timing->h_front_porch;
+	uint32_t h_sync_start = dc_crtc_timing->h_addressable + hsync_offset;
+
+	dm_memset(&bp_params, 0, sizeof(struct bp_hw_crtc_timing_parameters));
+
+	/* Due to an asic bug we need to apply the Front Porch workaround prior
+	 * to programming the timing.
+	 */
+
+	patched_crtc_timing = *dc_crtc_timing;
+
+	dce110_timing_generator_apply_front_porch_workaround(tg, &patched_crtc_timing);
+
+	bp_params.controller_id = tg110->controller_id;
+
+	bp_params.h_total = patched_crtc_timing.h_total;
+	bp_params.h_addressable =
+		patched_crtc_timing.h_addressable;
+	bp_params.v_total = patched_crtc_timing.v_total;
+	bp_params.v_addressable = patched_crtc_timing.v_addressable;
+
+	bp_params.h_sync_start = h_sync_start;
+	bp_params.h_sync_width = patched_crtc_timing.h_sync_width;
+	bp_params.v_sync_start = v_sync_start;
+	bp_params.v_sync_width = patched_crtc_timing.v_sync_width;
+
+	/* Set overscan */
+	bp_params.h_overscan_left =
+		patched_crtc_timing.h_border_left;
+	bp_params.h_overscan_right =
+		patched_crtc_timing.h_border_right;
+	bp_params.v_overscan_top = patched_crtc_timing.v_border_top;
+	bp_params.v_overscan_bottom =
+		patched_crtc_timing.v_border_bottom;
+
+	/* Set flags */
+	if (patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY == 1)
+		bp_params.flags.HSYNC_POSITIVE_POLARITY = 1;
+
+	if (patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY == 1)
+		bp_params.flags.VSYNC_POSITIVE_POLARITY = 1;
+
+	if (patched_crtc_timing.flags.INTERLACE == 1)
+		bp_params.flags.INTERLACE = 1;
+
+	if (patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1)
+		bp_params.flags.HORZ_COUNT_BY_TWO = 1;
+
+	result = tg->bp->funcs->program_crtc_timing(tg->bp, &bp_params);
+
+	program_horz_count_by_2(tg, &patched_crtc_timing);
+
+	tg110->base.funcs->enable_advanced_request(tg, true, &patched_crtc_timing);
+
+	/* Enable stereo - only when we need to pack 3D frame. Other types
+	 * of stereo handled in explicit call */
+
+	return result == BP_RESULT_OK;
+}
+
+/**
+ *****************************************************************************
+ *  Function: program_drr
+ *
+ *  @brief
+ *     Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*.
+ *
+ *  @param [in] pHwCrtcTiming: point to H
+ *  wCrtcTiming struct
+ *****************************************************************************
+ */
+void dce110_timing_generator_program_drr(
+	struct timing_generator *tg,
+	const struct hw_ranged_timing *timing)
+{
+	/* register values */
+	uint32_t v_total_min = 0;
+	uint32_t v_total_max = 0;
+	uint32_t v_total_cntl = 0;
+	uint32_t static_screen_cntl = 0;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	uint32_t addr = 0;
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
+	v_total_min = dm_read_reg(tg->ctx, addr);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
+	v_total_max = dm_read_reg(tg->ctx, addr);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
+	v_total_cntl = dm_read_reg(tg->ctx, addr);
+
+	addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
+	static_screen_cntl = dm_read_reg(tg->ctx, addr);
+
+	if (timing != NULL) {
+		/* Set Static Screen trigger events
+		 * If CRTC_SET_V_TOTAL_MIN_MASK_EN is set, use legacy event mask
+		 * register
+		 */
+		if (get_reg_field_value(
+			v_total_cntl,
+			CRTC_V_TOTAL_CONTROL,
+			CRTC_SET_V_TOTAL_MIN_MASK_EN)) {
+			set_reg_field_value(v_total_cntl,
+				/* TODO: add implementation
+				translate_to_dce_static_screen_events(
+					timing->control.event_mask.u_all),
+					*/ 0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_SET_V_TOTAL_MIN_MASK);
+		} else {
+			set_reg_field_value(static_screen_cntl,
+				/* TODO: add implementation
+				translate_to_dce_static_screen_events(
+					timing->control.event_mask.u_all),
+					*/ 0,
+				CRTC_STATIC_SCREEN_CONTROL,
+				CRTC_STATIC_SCREEN_EVENT_MASK);
+		}
+
+		/* Number of consecutive static screen frames before interrupt
+		 * is triggered. 0 is an invalid setting, which means we should
+		 * leaving HW setting unchanged. */
+		if (timing->control.static_frame_count != 0) {
+			set_reg_field_value(
+				static_screen_cntl,
+				timing->control.static_frame_count,
+				CRTC_STATIC_SCREEN_CONTROL,
+				CRTC_STATIC_SCREEN_FRAME_COUNT);
+		}
+
+		/* This value is reduced by 1 based on the register definition
+		 * of the VTOTAL value:
+		 * CRTC_V_TOTAL should be set to Vertical total minus one. (E.g.
+		 * for 525 lines, set to 524 = 0x20C)
+		 */
+		set_reg_field_value(v_total_min,
+				timing->vertical_total_min,
+				CRTC_V_TOTAL_MIN,
+				CRTC_V_TOTAL_MIN);
+		set_reg_field_value(v_total_max,
+				timing->vertical_total_max,
+				CRTC_V_TOTAL_MAX,
+				CRTC_V_TOTAL_MAX);
+
+		/* set VTotalControl value according to ranged timing control.
+		 */
+
+		if (timing->vertical_total_min != 0) {
+			set_reg_field_value(v_total_cntl,
+					1,
+					CRTC_V_TOTAL_CONTROL,
+					CRTC_V_TOTAL_MIN_SEL);
+		} else {
+			set_reg_field_value(v_total_cntl,
+					0,
+					CRTC_V_TOTAL_CONTROL,
+					CRTC_V_TOTAL_MIN_SEL);
+		}
+		if (timing->vertical_total_max != 0) {
+			set_reg_field_value(v_total_cntl,
+					1,
+					CRTC_V_TOTAL_CONTROL,
+					CRTC_V_TOTAL_MAX_SEL);
+		} else {
+			set_reg_field_value(v_total_cntl,
+					0,
+					CRTC_V_TOTAL_CONTROL,
+					CRTC_V_TOTAL_MAX_SEL);
+		}
+		set_reg_field_value(v_total_cntl,
+				timing->control.force_lock_on_event,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_FORCE_LOCK_ON_EVENT);
+		set_reg_field_value(v_total_cntl,
+				timing->control.lock_to_master_vsync,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
+	} else {
+		set_reg_field_value(v_total_cntl,
+			0,
+			CRTC_V_TOTAL_CONTROL,
+			CRTC_SET_V_TOTAL_MIN_MASK);
+		set_reg_field_value(static_screen_cntl,
+			0,
+			CRTC_STATIC_SCREEN_CONTROL,
+			CRTC_STATIC_SCREEN_EVENT_MASK);
+		set_reg_field_value(v_total_min,
+				0,
+				CRTC_V_TOTAL_MIN,
+				CRTC_V_TOTAL_MIN);
+		set_reg_field_value(v_total_max,
+				0,
+				CRTC_V_TOTAL_MAX,
+				CRTC_V_TOTAL_MAX);
+		set_reg_field_value(v_total_cntl,
+				0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_V_TOTAL_MIN_SEL);
+		set_reg_field_value(v_total_cntl,
+				0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_V_TOTAL_MAX_SEL);
+		set_reg_field_value(v_total_cntl,
+				0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_FORCE_LOCK_ON_EVENT);
+		set_reg_field_value(v_total_cntl,
+				0,
+				CRTC_V_TOTAL_CONTROL,
+				CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
+	}
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
+	dm_write_reg(tg->ctx, addr, v_total_min);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
+	dm_write_reg(tg->ctx, addr, v_total_max);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
+	dm_write_reg(tg->ctx, addr, v_total_cntl);
+
+	addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
+	dm_write_reg(tg->ctx, addr, static_screen_cntl);
+}
+
+/*
+ * get_vblank_counter
+ *
+ * @brief
+ * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
+ * holds the counter of frames.
+ *
+ * @param
+ * struct timing_generator *tg - [in] timing generator which controls the
+ * desired CRTC
+ *
+ * @return
+ * Counter of frames, which should equal to number of vblanks.
+ */
+uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_STATUS_FRAME_COUNT);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+	uint32_t field = get_reg_field_value(
+			value, CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
+
+	return field;
+}
+
+/**
+ *****************************************************************************
+ *  Function: dce110_get_crtc_positions
+ *
+ *  @brief
+ *     Returns CRTC vertical/horizontal counters
+ *
+ *  @param [out] v_position, h_position
+ *****************************************************************************
+ */
+
+void dce110_timing_generator_get_crtc_positions(
+	struct timing_generator *tg,
+	int32_t *h_position,
+	int32_t *v_position)
+{
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION));
+
+	*h_position = get_reg_field_value(
+			value,
+			CRTC_STATUS_POSITION,
+			CRTC_HORZ_COUNT);
+
+	*v_position = get_reg_field_value(
+			value,
+			CRTC_STATUS_POSITION,
+			CRTC_VERT_COUNT);
+}
+
+/**
+ *****************************************************************************
+ *  Function: get_crtc_scanoutpos
+ *
+ *  @brief
+ *     Returns CRTC vertical/horizontal counters
+ *
+ *  @param [out] vpos, hpos
+ *****************************************************************************
+ */
+uint32_t dce110_timing_generator_get_crtc_scanoutpos(
+	struct timing_generator *tg,
+	int32_t *vbl,
+	int32_t *position)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	/* TODO 1: Update the implementation once caller is updated
+	 * WARNING!! This function is returning the whole register value
+	 * because the caller is expecting it instead of proper vertical and
+	 * horizontal position. This should be a temporary implementation
+	 * until the caller is updated. */
+
+	/* TODO 2: re-use dce110_timing_generator_get_crtc_positions() */
+
+	*vbl = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_V_BLANK_START_END));
+
+	*position = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_STATUS_POSITION));
+
+	/* @TODO: return value should indicate if current
+	 * crtc is inside vblank*/
+	return 0;
+}
+
+/* TODO: is it safe to assume that mask/shift of Primary and Underlay
+ * are the same?
+ * For example: today CRTC_H_TOTAL == CRTCV_H_TOTAL but is it always
+ * guaranteed? */
+void dce110_timing_generator_program_blanking(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t vsync_offset = timing->v_border_bottom +
+			timing->v_front_porch;
+	uint32_t v_sync_start =timing->v_addressable + vsync_offset;
+
+	uint32_t hsync_offset = timing->h_border_right +
+			timing->h_front_porch;
+	uint32_t h_sync_start = timing->h_addressable + hsync_offset;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	struct dc_context *ctx = tg->ctx;
+	uint32_t value = 0;
+	uint32_t addr = 0;
+	uint32_t tmp = 0;
+
+	addr = CRTC_REG(mmCRTC_H_TOTAL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		timing->h_total - 1,
+		CRTC_H_TOTAL,
+		CRTC_H_TOTAL);
+	dm_write_reg(ctx, addr, value);
+
+	addr = CRTC_REG(mmCRTC_V_TOTAL);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		timing->v_total - 1,
+		CRTC_V_TOTAL,
+		CRTC_V_TOTAL);
+	dm_write_reg(ctx, addr, value);
+
+	addr = CRTC_REG(mmCRTC_H_BLANK_START_END);
+	value = dm_read_reg(ctx, addr);
+
+	tmp = timing->h_total -
+		(h_sync_start + timing->h_border_left);
+
+	set_reg_field_value(
+		value,
+		tmp,
+		CRTC_H_BLANK_START_END,
+		CRTC_H_BLANK_END);
+
+	tmp = tmp + timing->h_addressable +
+		timing->h_border_left + timing->h_border_right;
+
+	set_reg_field_value(
+		value,
+		tmp,
+		CRTC_H_BLANK_START_END,
+		CRTC_H_BLANK_START);
+
+	dm_write_reg(ctx, addr, value);
+
+	addr = CRTC_REG(mmCRTC_V_BLANK_START_END);
+	value = dm_read_reg(ctx, addr);
+
+	tmp = timing->v_total - (v_sync_start + timing->v_border_top);
+
+	set_reg_field_value(
+		value,
+		tmp,
+		CRTC_V_BLANK_START_END,
+		CRTC_V_BLANK_END);
+
+	tmp = tmp + timing->v_addressable + timing->v_border_top +
+		timing->v_border_bottom;
+
+	set_reg_field_value(
+		value,
+		tmp,
+		CRTC_V_BLANK_START_END,
+		CRTC_V_BLANK_START);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_timing_generator_set_test_pattern(
+	struct timing_generator *tg,
+	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
+	 * because this is not DP-specific (which is probably somewhere in DP
+	 * encoder) */
+	enum controller_dp_test_pattern test_pattern,
+	enum dc_color_depth color_depth)
+{
+	struct dc_context *ctx = tg->ctx;
+	uint32_t value;
+	uint32_t addr;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	/* TODO: add support for other test patterns */
+	switch (test_pattern) {
+	default:
+		value = 0;
+		addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
+
+		set_reg_field_value(
+			value,
+			6,
+			CRTC_TEST_PATTERN_PARAMETERS,
+			CRTC_TEST_PATTERN_VRES);
+		set_reg_field_value(
+			value,
+			6,
+			CRTC_TEST_PATTERN_PARAMETERS,
+			CRTC_TEST_PATTERN_HRES);
+
+		dm_write_reg(ctx, addr, value);
+
+		addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
+		value = 0;
+
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_TEST_PATTERN_CONTROL,
+			CRTC_TEST_PATTERN_EN);
+
+		set_reg_field_value(
+			value,
+			0,
+			CRTC_TEST_PATTERN_CONTROL,
+			CRTC_TEST_PATTERN_MODE);
+
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_TEST_PATTERN_CONTROL,
+			CRTC_TEST_PATTERN_DYNAMIC_RANGE);
+		/* add color depth translation here */
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_TEST_PATTERN_CONTROL,
+			CRTC_TEST_PATTERN_COLOR_FORMAT);
+		dm_write_reg(ctx, addr, value);
+		break;
+	} /* switch() */
+}
+
+/**
+* dce110_timing_generator_validate_timing
+* The timing generators support a maximum display size of is 8192 x 8192 pixels,
+* including both active display and blanking periods. Check H Total and V Total.
+*/
+bool dce110_timing_generator_validate_timing(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing,
+	enum signal_type signal)
+{
+	uint32_t h_blank;
+	uint32_t h_back_porch;
+	uint32_t hsync_offset = timing->h_border_right +
+			timing->h_front_porch;
+	uint32_t h_sync_start = timing->h_addressable + hsync_offset;
+
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	ASSERT(timing != NULL);
+
+	if (!timing)
+		return false;
+
+	/* Check maximum number of pixels supported by Timing Generator
+	 * (Currently will never fail, in order to fail needs display which
+	 * needs more than 8192 horizontal and
+	 * more than 8192 vertical total pixels)
+	 */
+	if (timing->h_total > tg110->max_h_total ||
+		timing->v_total > tg110->max_v_total)
+		return false;
+
+	h_blank = (timing->h_total - timing->h_addressable -
+		timing->h_border_right -
+		timing->h_border_left);
+
+	if (h_blank < tg110->min_h_blank)
+		return false;
+
+	if (timing->h_front_porch < tg110->min_h_front_porch)
+		return false;
+
+	h_back_porch = h_blank - (h_sync_start -
+		timing->h_addressable -
+		timing->h_border_right -
+		timing->h_sync_width);
+
+	if (h_back_porch < tg110->min_h_back_porch)
+		return false;
+
+	return true;
+}
+
+/**
+* Wait till we are at the beginning of VBlank.
+*/
+void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg)
+{
+	/* We want to catch beginning of VBlank here, so if the first try are
+	 * in VBlank, we might be very close to Active, in this case wait for
+	 * another frame
+	 */
+	while (dce110_timing_generator_is_in_vertical_blank(tg)) {
+		if (!dce110_timing_generator_is_counter_moving(tg)) {
+			/* error - no point to wait if counter is not moving */
+			break;
+		}
+	}
+
+	while (!dce110_timing_generator_is_in_vertical_blank(tg)) {
+		if (!dce110_timing_generator_is_counter_moving(tg)) {
+			/* error - no point to wait if counter is not moving */
+			break;
+		}
+	}
+}
+
+/**
+* Wait till we are in VActive (anywhere in VActive)
+*/
+void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg)
+{
+	while (dce110_timing_generator_is_in_vertical_blank(tg)) {
+		if (!dce110_timing_generator_is_counter_moving(tg)) {
+			/* error - no point to wait if counter is not moving */
+			break;
+		}
+	}
+}
+
+bool dce110_timing_generator_construct(
+	struct dce110_timing_generator *tg110,
+	struct adapter_service *as,
+	struct dc_context *ctx,
+	uint32_t instance,
+	const struct dce110_timing_generator_offsets *offsets)
+{
+	if (!tg110)
+		return false;
+
+	if (!as)
+		return false;
+
+	tg110->controller_id = CONTROLLER_ID_D0 + instance;
+	tg110->offsets = *offsets;
+
+	tg110->base.funcs = &dce110_tg_funcs;
+
+	tg110->base.ctx = ctx;
+	tg110->base.bp = dal_adapter_service_get_bios_parser(as);
+
+	tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
+	tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
+
+	tg110->min_h_blank = 56;
+	tg110->min_h_front_porch = 4;
+	tg110->min_h_back_porch = 4;
+
+	return true;
+}
+
+/**
+ *****************************************************************************
+ *  Function: dce110_timing_generator_setup_global_swap_lock
+ *
+ *  @brief
+ *     Setups Global Swap Lock group for current pipe
+ *     Pipe can join or leave GSL group, become a TimingServer or TimingClient
+ *
+ *  @param [in] gsl_params: setup data
+ *****************************************************************************
+ */
+
+void dce110_timing_generator_setup_global_swap_lock(
+	struct timing_generator *tg,
+	const struct dcp_gsl_params *gsl_params)
+{
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
+	uint32_t check_point = FLIP_READY_BACK_LOOKUP;
+
+	value = dm_read_reg(tg->ctx, address);
+
+	/* This pipe will belong to GSL Group zero. */
+	set_reg_field_value(value,
+			1,
+			DCP_GSL_CONTROL,
+			DCP_GSL0_EN);
+
+	set_reg_field_value(value,
+			gsl_params->timing_server,
+			DCP_GSL_CONTROL,
+			DCP_GSL_MASTER_EN);
+
+	set_reg_field_value(value,
+			HFLIP_READY_DELAY,
+			DCP_GSL_CONTROL,
+			DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
+
+        /* Keep signal low (pending high) during 6 lines.
+         * Also defines minimum interval before re-checking signal. */
+	set_reg_field_value(value,
+			HFLIP_CHECK_DELAY,
+			DCP_GSL_CONTROL,
+			DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
+
+	/* DCP_GSL_PURPOSE_SURFACE_FLIP */
+	{
+		uint32_t value_crtc_vtotal;
+
+		value_crtc_vtotal = dm_read_reg(tg->ctx,
+				CRTC_REG(mmCRTC_V_TOTAL));
+
+		set_reg_field_value(value,
+				gsl_params->gsl_purpose,
+				DCP_GSL_CONTROL,
+				DCP_GSL_SYNC_SOURCE);
+
+		/* Checkpoint relative to end of frame */
+		check_point = get_reg_field_value(value_crtc_vtotal,
+				CRTC_V_TOTAL,
+				CRTC_V_TOTAL);
+
+		dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0);
+	}
+
+	set_reg_field_value(value,
+			1,
+			DCP_GSL_CONTROL,
+			DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
+
+	dm_write_reg(tg->ctx, address, value);
+
+	/********************************************************************/
+	address = CRTC_REG(mmCRTC_GSL_CONTROL);
+
+	value = 0;
+	set_reg_field_value(value,
+			check_point - FLIP_READY_BACK_LOOKUP,
+			CRTC_GSL_CONTROL,
+			CRTC_GSL_CHECK_LINE_NUM);
+
+	set_reg_field_value(value,
+			VFLIP_READY_DELAY,
+			CRTC_GSL_CONTROL,
+			CRTC_GSL_FORCE_DELAY);
+
+	dm_write_reg(tg->ctx, address, value);
+}
+
+
+void dce110_timing_generator_tear_down_global_swap_lock(
+	struct timing_generator *tg)
+{
+	/* Clear all the register writes done by
+	 * dce110_timing_generator_setup_global_swap_lock
+	 */
+
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
+
+	value = 0;
+
+	/* This pipe will belong to GSL Group zero. */
+	/* Settig HW default values from reg specs */
+	set_reg_field_value(value,
+			0,
+			DCP_GSL_CONTROL,
+			DCP_GSL0_EN);
+
+	set_reg_field_value(value,
+			0,
+			DCP_GSL_CONTROL,
+			DCP_GSL_MASTER_EN);
+
+	set_reg_field_value(value,
+			0x2,
+			DCP_GSL_CONTROL,
+			DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
+
+
+	set_reg_field_value(value,
+			0x6,
+			DCP_GSL_CONTROL,
+			DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
+
+	/* Restore DCP_GSL_PURPOSE_SURFACE_FLIP */
+	{
+		uint32_t value_crtc_vtotal;
+
+		value_crtc_vtotal = dm_read_reg(tg->ctx,
+				CRTC_REG(mmCRTC_V_TOTAL));
+
+		set_reg_field_value(value,
+				0,
+				DCP_GSL_CONTROL,
+				DCP_GSL_SYNC_SOURCE);
+	}
+
+	set_reg_field_value(value,
+			0,
+			DCP_GSL_CONTROL,
+			DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
+
+	dm_write_reg(tg->ctx, address, value);
+
+	/********************************************************************/
+	address = CRTC_REG(mmCRTC_GSL_CONTROL);
+
+	value = 0;
+	set_reg_field_value(value,
+			0,
+			CRTC_GSL_CONTROL,
+			CRTC_GSL_CHECK_LINE_NUM);
+
+	set_reg_field_value(value,
+			0x2,
+			CRTC_GSL_CONTROL,
+			CRTC_GSL_FORCE_DELAY);
+
+	dm_write_reg(tg->ctx, address, value);
+}
+/**
+ *****************************************************************************
+ *  Function: is_counter_moving
+ *
+ *  @brief
+ *     check if the timing generator is currently going
+ *
+ *  @return
+ *     true if currently going, false if currently paused or stopped.
+ *
+ *****************************************************************************
+ */
+bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg)
+{
+	uint32_t h1 = 0;
+	uint32_t h2 = 0;
+	uint32_t v1 = 0;
+	uint32_t v2 = 0;
+
+	dce110_timing_generator_get_crtc_positions(tg, &h1, &v1);
+	dce110_timing_generator_get_crtc_positions(tg, &h2, &v2);
+
+	if (h1 == h2 && v1 == v2)
+		return false;
+	else
+		return true;
+}
+
+void dce110_timing_generator_enable_advanced_request(
+	struct timing_generator *tg,
+	bool enable,
+	const struct dc_crtc_timing *timing)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+
+	if (enable && !DCE110TG_FROM_TG(tg)->disable_advanced_request) {
+		set_reg_field_value(
+			value,
+			0,
+			CRTC_START_LINE_CONTROL,
+			CRTC_LEGACY_REQUESTOR_EN);
+	} else {
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_START_LINE_CONTROL,
+			CRTC_LEGACY_REQUESTOR_EN);
+	}
+
+	if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
+		set_reg_field_value(
+			value,
+			3,
+			CRTC_START_LINE_CONTROL,
+			CRTC_ADVANCED_START_LINE_POSITION);
+		set_reg_field_value(
+			value,
+			0,
+			CRTC_START_LINE_CONTROL,
+			CRTC_PREFETCH_EN);
+	} else {
+		set_reg_field_value(
+			value,
+			4,
+			CRTC_START_LINE_CONTROL,
+			CRTC_ADVANCED_START_LINE_POSITION);
+		set_reg_field_value(
+			value,
+			1,
+			CRTC_START_LINE_CONTROL,
+			CRTC_PREFETCH_EN);
+	}
+
+	set_reg_field_value(
+		value,
+		1,
+		CRTC_START_LINE_CONTROL,
+		CRTC_PROGRESSIVE_START_LINE_EARLY);
+
+	set_reg_field_value(
+		value,
+		1,
+		CRTC_START_LINE_CONTROL,
+		CRTC_INTERLACE_START_LINE_EARLY);
+
+	dm_write_reg(tg->ctx, addr, value);
+}
+
+/*TODO: Figure out if we need this function. */
+void dce110_timing_generator_set_lock_master(struct timing_generator *tg,
+		bool lock)
+{
+	struct dc_context *ctx = tg->ctx;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		lock ? 1 : 0,
+		CRTC_MASTER_UPDATE_LOCK,
+		MASTER_UPDATE_LOCK);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_timing_generator_enable_reset_trigger(
+	struct timing_generator *tg,
+	const struct trigger_params *trigger_params)
+{
+	uint32_t value;
+	struct dc_context *dc_ctx = tg->ctx;
+	uint32_t rising_edge = 0;
+	uint32_t falling_edge = 0;
+	enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	/* Setup trigger edge */
+	switch (trigger_params->edge) {
+	/* Default = based on current timing polarity */
+	case TRIGGER_EDGE_DEFAULT:
+		{
+			uint32_t pol_value = dm_read_reg(tg->ctx,
+					CRTC_REG(mmCRTC_V_SYNC_A_CNTL));
+
+			/* Register spec has reversed definition:
+			 *	0 for positive, 1 for negative */
+			if (get_reg_field_value(pol_value,
+					CRTC_V_SYNC_A_CNTL,
+					CRTC_V_SYNC_A_POL) == 0) {
+				rising_edge = 1;
+			} else {
+				falling_edge = 1;
+			}
+		}
+		break;
+	case TRIGGER_EDGE_RISING:
+		rising_edge = 1;
+		break;
+	case TRIGGER_EDGE_FALLING:
+		falling_edge = 1;
+		break;
+	case TRIGGER_EDGE_BOTH:
+		rising_edge = 1;
+		falling_edge = 1;
+		break;
+	default:
+		DC_ERROR("Invalid Trigger Edge!\n");
+		return;
+	}
+
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
+
+	switch(trigger_params->source) {
+	/* Currently supporting only a single group, the group zero. */
+	case SYNC_SOURCE_GSL_GROUP0:
+		trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
+		break;
+	default:
+		DC_ERROR("Unsupported GSL Group!\n");
+		return;
+	}
+
+	set_reg_field_value(value,
+			trig_src_select,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_SOURCE_SELECT);
+
+	set_reg_field_value(value,
+			TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_POLARITY_SELECT);
+
+	set_reg_field_value(value,
+			rising_edge,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
+
+	set_reg_field_value(value,
+			falling_edge,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
+
+	set_reg_field_value(value,
+			0, /* send every signal */
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_FREQUENCY_SELECT);
+
+	set_reg_field_value(value,
+			0, /* no delay */
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_DELAY);
+
+	set_reg_field_value(value,
+			1, /* clear trigger status */
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_CLEAR);
+
+	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
+
+	/**************************************************************/
+
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
+
+	set_reg_field_value(value,
+			2, /* force H count to H_TOTAL and V count to V_TOTAL */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_MODE);
+
+	set_reg_field_value(value,
+			1, /* TriggerB - we never use TriggerA */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_TRIG_SEL);
+
+	set_reg_field_value(value,
+			1, /* clear trigger status */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_CLEAR);
+
+	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
+}
+
+void dce110_timing_generator_disable_reset_trigger(
+	struct timing_generator *tg)
+{
+	uint32_t value;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
+
+	set_reg_field_value(value,
+			0, /* force counter now mode is disabled */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_MODE);
+
+	set_reg_field_value(value,
+			1, /* clear trigger status */
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_CLEAR);
+
+	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
+
+	/********************************************************************/
+	value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
+
+	set_reg_field_value(value,
+			TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_SOURCE_SELECT);
+
+	set_reg_field_value(value,
+			TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_POLARITY_SELECT);
+
+	set_reg_field_value(value,
+			1, /* clear trigger status */
+			CRTC_TRIGB_CNTL,
+			CRTC_TRIGB_CLEAR);
+
+	dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
+}
+
+/**
+ *****************************************************************************
+ *  @brief
+ *     Checks whether CRTC triggered reset occurred
+ *
+ *  @return
+ *     true if triggered reset occurred, false otherwise
+ *****************************************************************************
+ */
+bool dce110_timing_generator_did_triggered_reset_occur(
+	struct timing_generator *tg)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t value = dm_read_reg(tg->ctx,
+			CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
+
+	return get_reg_field_value(value,
+			CRTC_FORCE_COUNT_NOW_CNTL,
+			CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
+}
+
+/**
+ * dce110_timing_generator_disable_vga
+ * Turn OFF VGA Mode and Timing  - DxVGA_CONTROL
+ * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors;
+ */
+void dce110_timing_generator_disable_vga(
+	struct timing_generator *tg)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	switch (tg110->controller_id) {
+	case CONTROLLER_ID_D0:
+		addr = mmD1VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D1:
+		addr = mmD2VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D2:
+		addr = mmD3VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D3:
+		addr = mmD4VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D4:
+		addr = mmD5VGA_CONTROL;
+		break;
+	case CONTROLLER_ID_D5:
+		addr = mmD6VGA_CONTROL;
+		break;
+	default:
+		break;
+	}
+	value = dm_read_reg(tg->ctx, addr);
+
+	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
+	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
+	set_reg_field_value(
+			value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
+	set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
+
+	dm_write_reg(tg->ctx, addr, value);
+}
+
+/**
+* set_overscan_color_black
+*
+* @param :black_color is one of the color space
+*    :this routine will set overscan black color according to the color space.
+* @return none
+*/
+
+void dce110_timing_generator_set_overscan_color_black(
+	struct timing_generator *tg,
+	enum color_space black_color)
+{
+	struct dc_context *ctx = tg->ctx;
+	uint32_t value = 0;
+	uint32_t addr;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	/* Overscan Color for YUV display modes:
+	 * to achieve a black color for both the explicit and implicit overscan,
+	 * the overscan color registers should be programmed to: */
+
+	switch (black_color) {
+	case COLOR_SPACE_YPBPR601:
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_BLUE);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_GREEN);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_RED);
+		break;
+
+	case COLOR_SPACE_YPBPR709:
+	case COLOR_SPACE_YCBCR601:
+	case COLOR_SPACE_YCBCR709:
+	case COLOR_SPACE_YCBCR601_YONLY:
+	case COLOR_SPACE_YCBCR709_YONLY:
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_BLUE);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_GREEN);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_RED);
+		break;
+
+	case COLOR_SPACE_N_MVPU_SUPER_AA:
+		/* In crossfire SuperAA mode, the slave overscan data is forced
+		 * to 0 in the pixel mixer on the master.  As a result, we need
+		 * to adjust the blank color so that after blending the
+		 * master+slave, it will appear black */
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_BLUE);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_GREEN);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_RED);
+		break;
+
+	case COLOR_SPACE_SRGB_LIMITED_RANGE:
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_BLUE);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_GREEN);
+
+		set_reg_field_value(
+			value,
+			CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE,
+			CRTC_OVERSCAN_COLOR,
+			CRTC_OVERSCAN_COLOR_RED);
+		break;
+
+	default:
+		/* default is sRGB black 0. */
+		break;
+	}
+	addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
+	dm_write_reg(ctx, addr, value);
+	addr = CRTC_REG(mmCRTC_BLACK_COLOR);
+	dm_write_reg(ctx, addr, value);
+	/* This is desirable to have a constant DAC output voltage during the
+	 * blank time that is higher than the 0 volt reference level that the
+	 * DAC outputs when the NBLANK signal
+	 * is asserted low, such as for output to an analog TV. */
+	addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
+	dm_write_reg(ctx, addr, value);
+
+	/* TO DO we have to program EXT registers and we need to know LB DATA
+	 * format because it is used when more 10 , i.e. 12 bits per color
+	 *
+	 * m_mmDxCRTC_OVERSCAN_COLOR_EXT
+	 * m_mmDxCRTC_BLACK_COLOR_EXT
+	 * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
+	 */
+
+}
+
+void dce110_tg_program_blank_color(struct timing_generator *tg,
+		const struct crtc_black_color *black_color)
+{
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+	uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
+	uint32_t value = dm_read_reg(tg->ctx, addr);
+
+	set_reg_field_value(
+		value,
+		black_color->black_color_b_cb,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_B_CB);
+	set_reg_field_value(
+		value,
+		black_color->black_color_g_y,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_G_Y);
+	set_reg_field_value(
+		value,
+		black_color->black_color_r_cr,
+		CRTC_BLACK_COLOR,
+		CRTC_BLACK_COLOR_R_CR);
+
+	dm_write_reg(tg->ctx, addr, value);
+
+	addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
+	dm_write_reg(tg->ctx, addr, value);
+}
+
+void dce110_tg_set_overscan_color(struct timing_generator *tg,
+	const struct crtc_black_color *overscan_color)
+{
+	struct dc_context *ctx = tg->ctx;
+	uint32_t value = 0;
+	uint32_t addr;
+	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
+
+	set_reg_field_value(
+		value,
+		overscan_color->black_color_b_cb,
+		CRTC_OVERSCAN_COLOR,
+		CRTC_OVERSCAN_COLOR_BLUE);
+
+	set_reg_field_value(
+		value,
+		overscan_color->black_color_g_y,
+		CRTC_OVERSCAN_COLOR,
+		CRTC_OVERSCAN_COLOR_GREEN);
+
+	set_reg_field_value(
+		value,
+		overscan_color->black_color_r_cr,
+		CRTC_OVERSCAN_COLOR,
+		CRTC_OVERSCAN_COLOR_RED);
+
+	addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_tg_get_position(struct timing_generator *tg,
+	struct crtc_position *position)
+{
+	int32_t h_position;
+	int32_t v_position;
+
+	dce110_timing_generator_get_crtc_positions(tg, &h_position, &v_position);
+
+	position->horizontal_count = (uint32_t)h_position;
+	position->vertical_count = (uint32_t)v_position;
+}
+
+void dce110_tg_program_timing(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing,
+	bool use_vbios)
+{
+	if (use_vbios)
+		dce110_timing_generator_program_timing_generator(tg, timing);
+	else
+		dce110_timing_generator_program_blanking(tg, timing);
+}
+
+bool dce110_tg_set_blank(struct timing_generator *tg,
+		bool enable_blanking)
+{
+	if (enable_blanking)
+		return dce110_timing_generator_blank_crtc(tg);
+	else
+		return dce110_timing_generator_unblank_crtc(tg);
+}
+
+bool dce110_tg_validate_timing(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing)
+{
+	return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
+}
+
+
+void dce110_tg_wait_for_state(struct timing_generator *tg,
+	enum crtc_state state)
+{
+	switch (state) {
+	case CRTC_STATE_VBLANK:
+		dce110_timing_generator_wait_for_vblank(tg);
+		break;
+
+	case CRTC_STATE_VACTIVE:
+		dce110_timing_generator_wait_for_vactive(tg);
+		break;
+
+	default:
+		break;
+	}
+}
+
+void dce110_tg_set_colors(struct timing_generator *tg,
+	const struct crtc_black_color *blank_color,
+	const struct crtc_black_color *overscan_color)
+{
+	if (blank_color != NULL)
+		dce110_tg_program_blank_color(tg, blank_color);
+	if (overscan_color != NULL)
+		dce110_tg_set_overscan_color(tg, overscan_color);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
new file mode 100644
index 000000000000..163fadd1feb9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_TIMING_GENERATOR_DCE110_H__
+#define __DC_TIMING_GENERATOR_DCE110_H__
+
+
+#include "../inc/timing_generator.h"
+#include "../include/grph_object_id.h"
+#include "../include/hw_sequencer_types.h"
+
+/* overscan in blank for YUV color space. For RGB, it is zero for black. */
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4CV 0x1f4
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4CV 0x40
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4CV 0x1f4
+
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4TV 0x200
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4TV 0x40
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4TV 0x200
+
+/* overscan in blank for YUV color space when in SuperAA crossfire mode */
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_CB_YUV_4SUPERAA 0x1a2
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_Y_YUV_4SUPERAA 0x20
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_CR_YUV_4SUPERAA 0x1a2
+
+/* OVERSCAN COLOR FOR RGB LIMITED RANGE
+ * (16~253) 16*4 (Multiple over 256 code leve) =64 (0x40) */
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_B_RGB_LIMITED_RANGE 0x40
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_G_RGB_LIMITED_RANGE 0x40
+#define CRTC_OVERSCAN_COLOR_BLACK_COLOR_R_RGB_LIMITED_RANGE 0X40
+
+struct dce110_timing_generator_offsets {
+	int32_t crtc;
+	int32_t dcp;
+
+	/* DCE80 use only */
+	int32_t dmif;
+};
+
+struct dce110_timing_generator {
+	struct timing_generator base;
+	struct dce110_timing_generator_offsets offsets;
+	struct dce110_timing_generator_offsets derived_offsets;
+
+	enum controller_id controller_id;
+
+	uint32_t max_h_total;
+	uint32_t max_v_total;
+
+	uint32_t min_h_blank;
+	uint32_t min_h_front_porch;
+	uint32_t min_h_back_porch;
+
+	enum sync_source cached_gsl_group;
+	bool disable_advanced_request;
+};
+
+#define DCE110TG_FROM_TG(tg)\
+	container_of(tg, struct dce110_timing_generator, base)
+
+bool dce110_timing_generator_construct(
+	struct dce110_timing_generator *tg,
+	struct adapter_service *as,
+	struct dc_context *ctx,
+	uint32_t instance,
+	const struct dce110_timing_generator_offsets *offsets);
+
+/* determine if given timing can be supported by TG */
+bool dce110_timing_generator_validate_timing(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing,
+	enum signal_type signal);
+
+/******** HW programming ************/
+
+/* Program timing generator with given timing */
+bool dce110_timing_generator_program_timing_generator(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *dc_crtc_timing);
+
+/* Disable/Enable Timing Generator */
+bool dce110_timing_generator_enable_crtc(struct timing_generator *tg);
+bool dce110_timing_generator_disable_crtc(struct timing_generator *tg);
+
+void dce110_timing_generator_set_early_control(
+		struct timing_generator *tg,
+		uint32_t early_cntl);
+
+/**************** TG current status ******************/
+
+/* return the current frame counter. Used by Linux kernel DRM */
+uint32_t dce110_timing_generator_get_vblank_counter(
+		struct timing_generator *tg);
+
+/* Get current H and V position */
+void dce110_timing_generator_get_crtc_positions(
+	struct timing_generator *tg,
+	int32_t *h_position,
+	int32_t *v_position);
+
+/* return true if TG counter is moving. false if TG is stopped */
+bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg);
+
+/* wait until TG is in beginning of vertical blank region */
+void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg);
+
+/* wait until TG is in beginning of active region */
+void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg);
+
+
+/*********** Timing Generator Synchronization routines ****/
+
+/* Setups Global Swap Lock group, TimingServer or TimingClient*/
+void dce110_timing_generator_setup_global_swap_lock(
+	struct timing_generator *tg,
+	const struct dcp_gsl_params *gsl_params);
+
+/* Clear all the register writes done by setup_global_swap_lock */
+void dce110_timing_generator_tear_down_global_swap_lock(
+	struct timing_generator *tg);
+
+/* Reset slave controllers on master VSync */
+void dce110_timing_generator_enable_reset_trigger(
+	struct timing_generator *tg,
+	const struct trigger_params *trigger_params);
+
+/* disabling trigger-reset */
+void dce110_timing_generator_disable_reset_trigger(
+	struct timing_generator *tg);
+
+/* Checks whether CRTC triggered reset occurred */
+bool dce110_timing_generator_did_triggered_reset_occur(
+	struct timing_generator *tg);
+
+/******** Stuff to move to other virtual HW objects *****************/
+/* TODO: Should we move it to mem_input interface? */
+bool dce110_timing_generator_blank_crtc(struct timing_generator *tg);
+bool dce110_timing_generator_unblank_crtc(struct timing_generator *tg);
+/* Move to enable accelerated mode */
+void dce110_timing_generator_disable_vga(struct timing_generator *tg);
+/* TODO: Should we move it to transform */
+/* Fully program CRTC timing in timing generator */
+void dce110_timing_generator_program_blanking(
+	struct timing_generator *tg,
+	const struct dc_crtc_timing *timing);
+
+/* TODO: Should we move it to opp? */
+/* Combine with below and move YUV/RGB color conversion to SW layer */
+void dce110_timing_generator_program_blank_color(
+	struct timing_generator *tg,
+	enum color_space color_space);
+/* Combine with above and move YUV/RGB color conversion to SW layer */
+void dce110_timing_generator_set_overscan_color_black(
+	struct timing_generator *tg,
+	enum color_space black_color);
+/*************** End-of-move ********************/
+
+
+/* Not called yet */
+void dce110_timing_generator_set_test_pattern(
+	struct timing_generator *tg,
+	/* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
+	 * because this is not DP-specific (which is probably somewhere in DP
+	 * encoder) */
+	enum controller_dp_test_pattern test_pattern,
+	enum dc_color_depth color_depth);
+
+void dce110_timing_generator_program_drr(
+	struct timing_generator *tg,
+	const struct hw_ranged_timing *timing);
+
+uint32_t dce110_timing_generator_get_crtc_scanoutpos(
+	struct timing_generator *tg,
+	int32_t *vbl,
+	int32_t *position);
+
+void dce110_timing_generator_enable_advanced_request(
+	struct timing_generator *tg,
+	bool enable,
+	const struct dc_crtc_timing *timing);
+
+void dce110_timing_generator_set_lock_master(struct timing_generator *tg,
+		bool lock);
+
+void dce110_tg_program_blank_color(struct timing_generator *tg,
+	const struct crtc_black_color *black_color);
+
+void dce110_tg_set_overscan_color(struct timing_generator *tg,
+	const struct crtc_black_color *overscan_color);
+
+void dce110_tg_get_position(struct timing_generator *tg,
+	struct crtc_position *position);
+
+void dce110_tg_program_timing(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing,
+	bool use_vbios);
+
+bool dce110_tg_set_blank(struct timing_generator *tg,
+		bool enable_blanking);
+
+bool dce110_tg_validate_timing(struct timing_generator *tg,
+	const struct dc_crtc_timing *timing);
+
+
+void dce110_tg_wait_for_state(struct timing_generator *tg,
+	enum crtc_state state);
+
+void dce110_tg_set_colors(struct timing_generator *tg,
+	const struct crtc_black_color *blank_color,
+	const struct crtc_black_color *overscan_color);
+
+#endif /* __DC_TIMING_GENERATOR_DCE110_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 16/26] drm/amd/dal: Add surface HW programming
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (14 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 15/26] drm/amd/dal: Add timing generator " Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 17/26] drm/amd/dal: Add framebuffer compression " Harry Wentland
                     ` (9 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Adds watermark, DMIF, and surface programming.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c   | 965 +++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h   | 117 +++
 2 files changed, 1082 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
new file mode 100644
index 000000000000..3a928e63e647
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
@@ -0,0 +1,965 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+/* TODO: this needs to be looked at, used by Stella's workaround*/
+#include "gmc/gmc_8_2_d.h"
+#include "gmc/gmc_8_2_sh_mask.h"
+
+#include "include/logger_interface.h"
+#include "adapter_service_interface.h"
+#include "inc/bandwidth_calcs.h"
+
+#include "dce110_mem_input.h"
+
+#define MAX_WATERMARK 0xFFFF
+#define SAFE_NBP_MARK 0x7FFF
+
+#define DCP_REG(reg) (reg + mem_input110->offsets.dcp)
+#define DMIF_REG(reg) (reg + mem_input110->offsets.dmif)
+#define PIPE_REG(reg) (reg + mem_input110->offsets.pipe)
+
+static void set_flip_control(
+	struct dce110_mem_input *mem_input110,
+	bool immediate)
+{
+	uint32_t value = 0;
+
+	value = dm_read_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_FLIP_CONTROL));
+	set_reg_field_value(value, 0,
+				GRPH_FLIP_CONTROL,
+				GRPH_SURFACE_UPDATE_IMMEDIATE_EN);
+	set_reg_field_value(value, 0,
+				GRPH_FLIP_CONTROL,
+				GRPH_SURFACE_UPDATE_H_RETRACE_EN);
+	if (immediate == true)
+		set_reg_field_value(value, 1,
+			GRPH_FLIP_CONTROL,
+			GRPH_SURFACE_UPDATE_IMMEDIATE_EN);
+
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_FLIP_CONTROL),
+		value);
+}
+
+static void program_sec_addr(
+	struct dce110_mem_input *mem_input110,
+	PHYSICAL_ADDRESS_LOC address)
+{
+	uint32_t value = 0;
+	uint32_t temp = 0;
+	/*high register MUST be programmed first*/
+	temp = address.high_part &
+GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK;
+
+	set_reg_field_value(value, temp,
+		GRPH_SECONDARY_SURFACE_ADDRESS_HIGH,
+		GRPH_SECONDARY_SURFACE_ADDRESS_HIGH);
+
+	dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH),
+			value);
+
+	temp = 0;
+	value = 0;
+	temp = address.low_part >>
+	GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT;
+
+	set_reg_field_value(value, temp,
+		GRPH_SECONDARY_SURFACE_ADDRESS,
+		GRPH_SECONDARY_SURFACE_ADDRESS);
+
+	dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_SECONDARY_SURFACE_ADDRESS),
+			value);
+}
+
+static void program_pri_addr(
+	struct dce110_mem_input *mem_input110,
+	PHYSICAL_ADDRESS_LOC address)
+{
+	uint32_t value = 0;
+	uint32_t temp = 0;
+
+	/*high register MUST be programmed first*/
+	temp = address.high_part &
+GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK;
+
+	set_reg_field_value(value, temp,
+		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH,
+		GRPH_PRIMARY_SURFACE_ADDRESS_HIGH);
+
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH),
+		value);
+
+	temp = 0;
+	value = 0;
+	temp = address.low_part >>
+	GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT;
+
+	set_reg_field_value(value, temp,
+		GRPH_PRIMARY_SURFACE_ADDRESS,
+		GRPH_PRIMARY_SURFACE_ADDRESS);
+
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_PRIMARY_SURFACE_ADDRESS),
+		value);
+}
+
+static void program_addr(
+	struct dce110_mem_input *mem_input110,
+	const struct dc_plane_address *addr)
+{
+	switch (addr->type) {
+	case PLN_ADDR_TYPE_GRAPHICS:
+		program_pri_addr(
+			mem_input110,
+			addr->grph.addr);
+		break;
+	case PLN_ADDR_TYPE_GRPH_STEREO:
+		program_pri_addr(
+			mem_input110,
+			addr->grph_stereo.left_addr);
+		program_sec_addr(
+			mem_input110,
+			addr->grph_stereo.right_addr);
+		break;
+	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
+	default:
+		/* not supported */
+		BREAK_TO_DEBUGGER();
+	}
+}
+
+static void enable(struct dce110_mem_input *mem_input110)
+{
+	uint32_t value = 0;
+
+	value = dm_read_reg(mem_input110->base.ctx, DCP_REG(mmGRPH_ENABLE));
+	set_reg_field_value(value, 1, GRPH_ENABLE, GRPH_ENABLE);
+	dm_write_reg(mem_input110->base.ctx,
+		DCP_REG(mmGRPH_ENABLE),
+		value);
+}
+
+static void program_tiling(
+	struct dce110_mem_input *mem_input110,
+	const struct dc_tiling_info *info,
+	const enum surface_pixel_format pixel_format)
+{
+	uint32_t value = 0;
+
+	value = dm_read_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_CONTROL));
+
+	set_reg_field_value(value, info->num_banks,
+		GRPH_CONTROL, GRPH_NUM_BANKS);
+
+	set_reg_field_value(value, info->bank_width,
+		GRPH_CONTROL, GRPH_BANK_WIDTH);
+
+	set_reg_field_value(value, info->bank_height,
+		GRPH_CONTROL, GRPH_BANK_HEIGHT);
+
+	set_reg_field_value(value, info->tile_aspect,
+		GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT);
+
+	set_reg_field_value(value, info->tile_split,
+		GRPH_CONTROL, GRPH_TILE_SPLIT);
+
+	set_reg_field_value(value, info->tile_mode,
+		GRPH_CONTROL, GRPH_MICRO_TILE_MODE);
+
+	set_reg_field_value(value, info->pipe_config,
+		GRPH_CONTROL, GRPH_PIPE_CONFIG);
+
+	set_reg_field_value(value, info->array_mode,
+		GRPH_CONTROL, GRPH_ARRAY_MODE);
+
+	set_reg_field_value(value, 1,
+		GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE);
+
+	set_reg_field_value(value, 0,
+		GRPH_CONTROL, GRPH_Z);
+
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_CONTROL),
+		value);
+}
+
+static void program_size_and_rotation(
+	struct dce110_mem_input *mem_input110,
+	enum dc_rotation_angle rotation,
+	const union plane_size *plane_size)
+{
+	uint32_t value = 0;
+	union plane_size local_size = *plane_size;
+
+	if (rotation == ROTATION_ANGLE_90 ||
+		rotation == ROTATION_ANGLE_270) {
+
+		uint32_t swap;
+
+		swap = local_size.grph.surface_size.x;
+		local_size.grph.surface_size.x =
+			local_size.grph.surface_size.y;
+		local_size.grph.surface_size.y  = swap;
+
+		swap = local_size.grph.surface_size.width;
+		local_size.grph.surface_size.width =
+			local_size.grph.surface_size.height;
+		local_size.grph.surface_size.height = swap;
+	}
+
+	set_reg_field_value(value, local_size.grph.surface_size.x,
+			GRPH_X_START, GRPH_X_START);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_X_START),
+		value);
+
+	value = 0;
+	set_reg_field_value(value, local_size.grph.surface_size.y,
+			GRPH_Y_START, GRPH_Y_START);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_Y_START),
+		value);
+
+	value = 0;
+	set_reg_field_value(value, local_size.grph.surface_size.width,
+			GRPH_X_END, GRPH_X_END);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_X_END),
+		value);
+
+	value = 0;
+	set_reg_field_value(value, local_size.grph.surface_size.height,
+			GRPH_Y_END, GRPH_Y_END);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_Y_END),
+		value);
+
+	value = 0;
+	set_reg_field_value(value, local_size.grph.surface_pitch,
+			GRPH_PITCH, GRPH_PITCH);
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmGRPH_PITCH),
+		value);
+
+
+	value = 0;
+	switch (rotation) {
+	case ROTATION_ANGLE_90:
+		set_reg_field_value(value, 3,
+			HW_ROTATION, GRPH_ROTATION_ANGLE);
+		break;
+	case ROTATION_ANGLE_180:
+		set_reg_field_value(value, 2,
+			HW_ROTATION, GRPH_ROTATION_ANGLE);
+		break;
+	case ROTATION_ANGLE_270:
+		set_reg_field_value(value, 1,
+			HW_ROTATION, GRPH_ROTATION_ANGLE);
+		break;
+	default:
+		set_reg_field_value(value, 0,
+			HW_ROTATION, GRPH_ROTATION_ANGLE);
+		break;
+	}
+	dm_write_reg(
+		mem_input110->base.ctx,
+		DCP_REG(mmHW_ROTATION),
+		value);
+}
+
+static void program_pixel_format(
+	struct dce110_mem_input *mem_input110,
+	enum surface_pixel_format format)
+{
+	if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
+		format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
+		uint32_t value = 0;
+
+		/* handle colour twizzle formats, swapping R and B */
+		if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 ||
+			format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
+			format ==
+			SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
+			format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
+			set_reg_field_value(
+				value, 2, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR);
+			set_reg_field_value(
+				value, 2, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR);
+		}
+
+		dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_SWAP_CNTL),
+			value);
+
+
+		value =	dm_read_reg(
+				mem_input110->base.ctx,
+				DCP_REG(mmGRPH_CONTROL));
+
+		switch (format) {
+		case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
+			set_reg_field_value(
+				value, 0, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 0, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+			set_reg_field_value(
+				value, 1, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 1, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+		case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
+			set_reg_field_value(
+				value, 2, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 0, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+		case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+		case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+			set_reg_field_value(
+				value, 2, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 1, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+		case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+			set_reg_field_value(
+				value, 3, GRPH_CONTROL, GRPH_DEPTH);
+			set_reg_field_value(
+				value, 0, GRPH_CONTROL, GRPH_FORMAT);
+			break;
+		default:
+			break;
+		}
+		dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmGRPH_CONTROL),
+			value);
+
+		/*TODO [hwentlan] MOVE THIS TO CONTROLLER GAMMA!!!!!*/
+		value = dm_read_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmPRESCALE_GRPH_CONTROL));
+
+		if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
+			set_reg_field_value(
+				value, 1, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_SELECT);
+			set_reg_field_value(
+				value, 1, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_R_SIGN);
+			set_reg_field_value(
+				value, 1, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_G_SIGN);
+			set_reg_field_value(
+				value, 1, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_B_SIGN);
+		} else {
+			set_reg_field_value(
+				value, 0, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_SELECT);
+			set_reg_field_value(
+				value, 0, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_R_SIGN);
+			set_reg_field_value(
+				value, 0, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_G_SIGN);
+			set_reg_field_value(
+				value, 0, PRESCALE_GRPH_CONTROL,
+				GRPH_PRESCALE_B_SIGN);
+		}
+		dm_write_reg(
+			mem_input110->base.ctx,
+			DCP_REG(mmPRESCALE_GRPH_CONTROL),
+			value);
+	}
+}
+
+static void wait_for_no_surface_update_pending(
+				struct dce110_mem_input *mem_input110)
+{
+	uint32_t value;
+
+	do  {
+		value = dm_read_reg(mem_input110->base.ctx,
+				DCP_REG(mmGRPH_UPDATE));
+
+	} while (get_reg_field_value(value, GRPH_UPDATE,
+			GRPH_SURFACE_UPDATE_PENDING));
+}
+
+bool dce110_mem_input_program_surface_flip_and_addr(
+	struct mem_input *mem_input,
+	const struct dc_plane_address *address,
+	bool flip_immediate)
+{
+	struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input);
+
+	set_flip_control(mem_input110, flip_immediate);
+	program_addr(mem_input110,
+		address);
+
+	if (flip_immediate)
+		wait_for_no_surface_update_pending(mem_input110);
+
+	return true;
+}
+
+bool dce110_mem_input_program_surface_config(
+	struct mem_input *mem_input,
+	enum surface_pixel_format format,
+	struct dc_tiling_info *tiling_info,
+	union plane_size *plane_size,
+	enum dc_rotation_angle rotation)
+{
+	struct dce110_mem_input *mem_input110 = TO_DCE110_MEM_INPUT(mem_input);
+
+	enable(mem_input110);
+	program_tiling(mem_input110, tiling_info, format);
+	program_size_and_rotation(mem_input110, rotation, plane_size);
+	program_pixel_format(mem_input110, format);
+
+	return true;
+}
+
+static void program_urgency_watermark(
+	const struct dc_context *ctx,
+	const uint32_t offset,
+	struct bw_watermarks marks_low,
+	uint32_t total_dest_line_time_ns)
+{
+	/* register value */
+	uint32_t urgency_cntl = 0;
+	uint32_t wm_mask_cntl = 0;
+
+	uint32_t urgency_addr = offset + mmDPG_PIPE_URGENCY_CONTROL;
+	uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL;
+
+	/*Write mask to enable reading/writing of watermark set A*/
+	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
+	set_reg_field_value(wm_mask_cntl,
+			1,
+			DPG_WATERMARK_MASK_CONTROL,
+			URGENCY_WATERMARK_MASK);
+	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
+
+	urgency_cntl = dm_read_reg(ctx, urgency_addr);
+
+	set_reg_field_value(
+		urgency_cntl,
+		marks_low.a_mark,
+		DPG_PIPE_URGENCY_CONTROL,
+		URGENCY_LOW_WATERMARK);
+
+	set_reg_field_value(
+		urgency_cntl,
+		total_dest_line_time_ns,
+		DPG_PIPE_URGENCY_CONTROL,
+		URGENCY_HIGH_WATERMARK);
+	dm_write_reg(ctx, urgency_addr, urgency_cntl);
+
+
+	/*Write mask to enable reading/writing of watermark set B*/
+	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
+	set_reg_field_value(wm_mask_cntl,
+			2,
+			DPG_WATERMARK_MASK_CONTROL,
+			URGENCY_WATERMARK_MASK);
+	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
+
+	urgency_cntl = dm_read_reg(ctx, urgency_addr);
+
+	set_reg_field_value(urgency_cntl,
+		marks_low.b_mark,
+		DPG_PIPE_URGENCY_CONTROL,
+		URGENCY_LOW_WATERMARK);
+
+	set_reg_field_value(urgency_cntl,
+		total_dest_line_time_ns,
+		DPG_PIPE_URGENCY_CONTROL,
+		URGENCY_HIGH_WATERMARK);
+	dm_write_reg(ctx, urgency_addr, urgency_cntl);
+}
+
+static void program_stutter_watermark(
+	const struct dc_context *ctx,
+	const uint32_t offset,
+	struct bw_watermarks marks)
+{
+	/* register value */
+	uint32_t stutter_cntl = 0;
+	uint32_t wm_mask_cntl = 0;
+
+	uint32_t stutter_addr = offset + mmDPG_PIPE_STUTTER_CONTROL;
+	uint32_t wm_addr = offset + mmDPG_WATERMARK_MASK_CONTROL;
+
+	/*Write mask to enable reading/writing of watermark set A*/
+
+	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
+	set_reg_field_value(wm_mask_cntl,
+		1,
+		DPG_WATERMARK_MASK_CONTROL,
+		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK);
+	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
+
+	stutter_cntl = dm_read_reg(ctx, stutter_addr);
+
+	set_reg_field_value(stutter_cntl,
+		1,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_ENABLE);
+	set_reg_field_value(stutter_cntl,
+		1,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_IGNORE_FBC);
+
+	/*Write watermark set A*/
+	set_reg_field_value(stutter_cntl,
+		marks.a_mark,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_EXIT_SELF_REFRESH_WATERMARK);
+	dm_write_reg(ctx, stutter_addr, stutter_cntl);
+
+	/*Write mask to enable reading/writing of watermark set B*/
+	wm_mask_cntl = dm_read_reg(ctx, wm_addr);
+	set_reg_field_value(wm_mask_cntl,
+		2,
+		DPG_WATERMARK_MASK_CONTROL,
+		STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK);
+	dm_write_reg(ctx, wm_addr, wm_mask_cntl);
+
+	stutter_cntl = dm_read_reg(ctx, stutter_addr);
+	set_reg_field_value(stutter_cntl,
+		1,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_ENABLE);
+	set_reg_field_value(stutter_cntl,
+		1,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_IGNORE_FBC);
+
+	/*Write watermark set B*/
+	set_reg_field_value(stutter_cntl,
+		marks.b_mark,
+		DPG_PIPE_STUTTER_CONTROL,
+		STUTTER_EXIT_SELF_REFRESH_WATERMARK);
+	dm_write_reg(ctx, stutter_addr, stutter_cntl);
+}
+
+static void program_nbp_watermark(
+	const struct dc_context *ctx,
+	const uint32_t offset,
+	struct bw_watermarks marks)
+{
+	uint32_t value;
+	uint32_t addr;
+	/* Write mask to enable reading/writing of watermark set A */
+	addr = offset + mmDPG_WATERMARK_MASK_CONTROL;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_WATERMARK_MASK_CONTROL,
+		NB_PSTATE_CHANGE_WATERMARK_MASK);
+	dm_write_reg(ctx, addr, value);
+
+	addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_ENABLE);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_URGENT_DURING_REQUEST);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST);
+	dm_write_reg(ctx, addr, value);
+
+	/* Write watermark set A */
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		marks.a_mark,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_WATERMARK);
+	dm_write_reg(ctx, addr, value);
+
+	/* Write mask to enable reading/writing of watermark set B */
+	addr = offset + mmDPG_WATERMARK_MASK_CONTROL;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		2,
+		DPG_WATERMARK_MASK_CONTROL,
+		NB_PSTATE_CHANGE_WATERMARK_MASK);
+	dm_write_reg(ctx, addr, value);
+
+	addr = offset + mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_ENABLE);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_URGENT_DURING_REQUEST);
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST);
+	dm_write_reg(ctx, addr, value);
+
+	/* Write watermark set B */
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		marks.b_mark,
+		DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
+		NB_PSTATE_CHANGE_WATERMARK);
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_mem_input_program_safe_display_marks(struct mem_input *mi)
+{
+	struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi);
+	struct bw_watermarks max_marks = { MAX_WATERMARK, MAX_WATERMARK };
+	struct bw_watermarks nbp_marks = { SAFE_NBP_MARK, SAFE_NBP_MARK };
+
+	program_urgency_watermark(
+		mi->ctx, bm_dce110->offsets.dmif, max_marks, MAX_WATERMARK);
+	program_stutter_watermark(mi->ctx, bm_dce110->offsets.dmif, max_marks);
+	program_nbp_watermark(mi->ctx, bm_dce110->offsets.dmif, nbp_marks);
+}
+
+void dce110_mem_input_program_display_marks(
+	struct mem_input *mem_input,
+	struct bw_watermarks nbp,
+	struct bw_watermarks stutter,
+	struct bw_watermarks urgent,
+	uint32_t h_total,
+	uint32_t pixel_clk_in_khz,
+	uint32_t pstate_blackout_duration_ns)
+{
+	struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mem_input);
+	uint32_t total_dest_line_time_ns = 1000000UL * h_total
+		/ pixel_clk_in_khz + pstate_blackout_duration_ns;
+
+	program_urgency_watermark(
+		mem_input->ctx,
+		bm_dce110->offsets.dmif,
+		urgent,
+		total_dest_line_time_ns);
+	program_nbp_watermark(
+		mem_input->ctx,
+		bm_dce110->offsets.dmif,
+		nbp);
+	program_stutter_watermark(
+		mem_input->ctx,
+		bm_dce110->offsets.dmif,
+		stutter);
+}
+
+static uint32_t get_dmif_switch_time_us(struct dc_crtc_timing *timing)
+{
+	uint32_t frame_time;
+	uint32_t pixels_per_second;
+	uint32_t pixels_per_frame;
+	uint32_t refresh_rate;
+	const uint32_t us_in_sec = 1000000;
+	const uint32_t min_single_frame_time_us = 30000;
+	/*return double of frame time*/
+	const uint32_t single_frame_time_multiplier = 2;
+
+	if (timing == NULL)
+		return single_frame_time_multiplier * min_single_frame_time_us;
+
+	/*TODO: should we use pixel format normalized pixel clock here?*/
+	pixels_per_second = timing->pix_clk_khz * 1000;
+	pixels_per_frame = timing->h_total * timing->v_total;
+
+	if (!pixels_per_second || !pixels_per_frame) {
+		/* avoid division by zero */
+		ASSERT(pixels_per_frame);
+		ASSERT(pixels_per_second);
+		return single_frame_time_multiplier * min_single_frame_time_us;
+	}
+
+	refresh_rate = pixels_per_second / pixels_per_frame;
+
+	if (!refresh_rate) {
+		/* avoid division by zero*/
+		ASSERT(refresh_rate);
+		return single_frame_time_multiplier * min_single_frame_time_us;
+	}
+
+	frame_time = us_in_sec / refresh_rate;
+
+	if (frame_time < min_single_frame_time_us)
+		frame_time = min_single_frame_time_us;
+
+	frame_time *= single_frame_time_multiplier;
+
+	return frame_time;
+}
+
+void dce110_mem_input_allocate_dmif_buffer(
+		struct mem_input *mi,
+		struct dc_crtc_timing *timing,
+		uint32_t paths_num)
+{
+	const uint32_t retry_delay = 10;
+	uint32_t retry_count = get_dmif_switch_time_us(timing) / retry_delay;
+
+	struct dce110_mem_input *bm110 = TO_DCE110_MEM_INPUT(mi);
+	uint32_t addr = bm110->offsets.pipe + mmPIPE0_DMIF_BUFFER_CONTROL;
+	uint32_t value;
+	uint32_t field;
+	uint32_t pix_dur;
+
+	if (bm110->supported_stutter_mode
+			& STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION)
+		goto register_underflow_int;
+
+	/*Allocate DMIF buffer*/
+	value = dm_read_reg(mi->ctx, addr);
+	field = get_reg_field_value(
+		value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED);
+	if (field == 2)
+		goto register_underflow_int;
+
+	set_reg_field_value(
+			value,
+			2,
+			PIPE0_DMIF_BUFFER_CONTROL,
+			DMIF_BUFFERS_ALLOCATED);
+
+	dm_write_reg(mi->ctx, addr, value);
+
+	do {
+		value = dm_read_reg(mi->ctx, addr);
+		field = get_reg_field_value(
+			value,
+			PIPE0_DMIF_BUFFER_CONTROL,
+			DMIF_BUFFERS_ALLOCATION_COMPLETED);
+
+		if (field)
+			break;
+
+		dm_delay_in_microseconds(mi->ctx, retry_delay);
+		retry_count--;
+
+	} while (retry_count > 0);
+
+	if (field == 0)
+		dal_logger_write(mi->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_COMPONENT_GPU,
+				"%s: DMIF allocation failed",
+				__func__);
+
+
+	if (timing->pix_clk_khz != 0) {
+		addr = mmDPG_PIPE_ARBITRATION_CONTROL1 + bm110->offsets.dmif;
+		value = dm_read_reg(mi->ctx, addr);
+		pix_dur = 1000000000ULL / timing->pix_clk_khz;
+
+		set_reg_field_value(
+			value,
+			pix_dur,
+			DPG_PIPE_ARBITRATION_CONTROL1,
+			PIXEL_DURATION);
+
+		dm_write_reg(mi->ctx, addr, value);
+	}
+
+	/*
+	 * Stella Wong proposed the following change
+	 *
+	 * Value of mcHubRdReqDmifLimit.ENABLE:
+	 * 00 - disable DMIF rdreq limit
+	 * 01 - enable DMIF rdreq limit, disabled by DMIF stall = 1 || urg != 0
+	 * 02 - enable DMIF rdreq limit, disable by DMIF stall = 1
+	 * 03 - force enable DMIF rdreq limit, ignore DMIF stall / urgent
+	 */
+	if (!IS_FPGA_MAXIMUS_DC(mi->ctx->dce_environment)) {
+		addr = mmMC_HUB_RDREQ_DMIF_LIMIT;
+		value = dm_read_reg(mi->ctx, addr);
+
+		if (paths_num > 1)
+			set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE);
+		else
+			set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE);
+		dm_write_reg(mi->ctx, addr, value);
+	}
+
+register_underflow_int:
+	/*todo*/;
+	/*register_interrupt(bm110, irq_source, ctrl_id);*/
+}
+
+static void deallocate_dmif_buffer_helper(
+				struct dc_context *ctx, uint32_t offset)
+{
+	uint32_t value;
+	uint32_t count = 0xBB8; /* max retry count */
+
+	value = dm_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset);
+
+	if (!get_reg_field_value(
+		value, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED))
+		return;
+
+	set_reg_field_value(
+		value, 0, PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED);
+
+	dm_write_reg(
+		ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset, value);
+
+	do {
+		value = dm_read_reg(ctx, mmPIPE0_DMIF_BUFFER_CONTROL + offset);
+		dm_delay_in_microseconds(ctx, 10);
+		count--;
+	} while (count > 0 &&
+		!get_reg_field_value(
+			value,
+			PIPE0_DMIF_BUFFER_CONTROL,
+			DMIF_BUFFERS_ALLOCATION_COMPLETED));
+}
+
+void dce110_mem_input_deallocate_dmif_buffer(
+	struct mem_input *mi, uint32_t paths_num)
+{
+	struct dce110_mem_input *bm_dce110 = TO_DCE110_MEM_INPUT(mi);
+	uint32_t value;
+
+	if (!(bm_dce110->supported_stutter_mode &
+		STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION)) {
+
+		/* De-allocate DMIF buffer first */
+		if (mmPIPE0_DMIF_BUFFER_CONTROL + bm_dce110->offsets.pipe != 0)
+			deallocate_dmif_buffer_helper(
+					mi->ctx, bm_dce110->offsets.pipe);
+	}
+
+	/* TODO: unregister underflow interrupt
+	unregisterInterrupt();
+	*/
+
+	/* Value of mcHubRdReqDmifLimit.ENABLE.
+	 * 00 - disable dmif rdreq limit
+	 * 01 - enable dmif rdreq limit, disable by dmif stall=1||urg!=0
+	 * 02 - enable dmif rdreq limit, disable by dmif stall=1
+	 * 03 - force enable dmif rdreq limit, ignore dmif stall/urgent
+	 * Stella Wong proposed this change. */
+	if (!IS_FPGA_MAXIMUS_DC(mi->ctx->dce_environment)) {
+		value = dm_read_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT);
+		if (paths_num > 1)
+			set_reg_field_value(value, 0, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE);
+		else
+			set_reg_field_value(value, 3, MC_HUB_RDREQ_DMIF_LIMIT, ENABLE);
+
+		dm_write_reg(mi->ctx, mmMC_HUB_RDREQ_DMIF_LIMIT, value);
+	}
+}
+
+static struct mem_input_funcs dce110_mem_input_funcs = {
+	.mem_input_program_safe_display_marks =
+			dce110_mem_input_program_safe_display_marks,
+	.mem_input_program_display_marks =
+			dce110_mem_input_program_display_marks,
+	.mem_input_allocate_dmif_buffer = dce110_mem_input_allocate_dmif_buffer,
+	.mem_input_deallocate_dmif_buffer =
+			dce110_mem_input_deallocate_dmif_buffer,
+	.mem_input_program_surface_flip_and_addr =
+			dce110_mem_input_program_surface_flip_and_addr,
+	.mem_input_program_surface_config =
+			dce110_mem_input_program_surface_config,
+};
+/*****************************************/
+/* Constructor, Destructor               */
+/*****************************************/
+
+bool dce110_mem_input_construct(
+	struct dce110_mem_input *mem_input110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_mem_input_reg_offsets *offsets)
+{
+	mem_input110->base.funcs = &dce110_mem_input_funcs;
+	mem_input110->base.ctx = ctx;
+
+	mem_input110->base.inst = inst;
+
+	mem_input110->offsets = *offsets;
+
+	mem_input110->supported_stutter_mode = 0;
+	dal_adapter_service_get_feature_value(FEATURE_STUTTER_MODE,
+			&(mem_input110->supported_stutter_mode),
+			sizeof(mem_input110->supported_stutter_mode));
+
+	return true;
+}
+
+void dce110_mem_input_destroy(struct mem_input **mem_input)
+{
+	dm_free((*mem_input)->ctx, TO_DCE110_MEM_INPUT(*mem_input));
+	*mem_input = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h
new file mode 100644
index 000000000000..5a4e5fe33a79
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h
@@ -0,0 +1,117 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_MEM_INPUT_DCE110_H__
+#define __DC_MEM_INPUT_DCE110_H__
+
+#include "inc/mem_input.h"
+
+#define TO_DCE110_MEM_INPUT(mi)\
+	container_of(mi, struct dce110_mem_input, base)
+
+struct dce110_mem_input_reg_offsets {
+	uint32_t dcp;
+	uint32_t dmif;
+	uint32_t pipe;
+};
+
+struct dce110_mem_input {
+	struct mem_input base;
+	struct dce110_mem_input_reg_offsets offsets;
+	uint32_t supported_stutter_mode;
+};
+
+bool dce110_mem_input_construct(
+	struct dce110_mem_input *mem_input110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_mem_input_reg_offsets *offsets);
+
+/*
+ * dce110_mem_input_program_display_marks
+ *
+ * This function will program nbp stutter and urgency watermarks to maximum
+ * safe values
+ */
+void dce110_mem_input_program_safe_display_marks(struct mem_input *mi);
+
+/*
+ * dce110_mem_input_program_display_marks
+ *
+ * This function will program nbp stutter and urgency watermarks to minimum
+ * allowable values
+ */
+void dce110_mem_input_program_display_marks(
+	struct mem_input *mem_input,
+	struct bw_watermarks nbp,
+	struct bw_watermarks stutter,
+	struct bw_watermarks urgent,
+	uint32_t h_total,
+	uint32_t pixel_clk_in_khz,
+	uint32_t pstate_blackout_duration_ns);
+
+/*
+ * dce110_mem_input_allocate_dmif_buffer
+ *
+ * This function will allocate a dmif buffer and program required
+ * pixel duration for pipe
+ */
+void dce110_mem_input_allocate_dmif_buffer(
+		struct mem_input *mem_input,
+		struct dc_crtc_timing *timing,
+		uint32_t paths_num);
+
+/*
+ * dce110_mem_input_deallocate_dmif_buffer
+ *
+ * This function will deallocate a dmif buffer from pipe
+ */
+void dce110_mem_input_deallocate_dmif_buffer(
+	struct mem_input *mem_input, uint32_t paths_num);
+
+/*
+ * dce110_mem_input_program_surface_flip_and_addr
+ *
+ * This function programs hsync/vsync mode and surface address
+ */
+bool dce110_mem_input_program_surface_flip_and_addr(
+	struct mem_input *mem_input,
+	const struct dc_plane_address *address,
+	bool flip_immediate);
+
+/*
+ * dce110_mem_input_program_surface_config
+ *
+ * This function will program surface tiling, size, rotation and pixel format
+ * to corresponding dcp registers.
+ */
+bool  dce110_mem_input_program_surface_config(
+	struct mem_input *mem_input,
+	enum surface_pixel_format format,
+	struct dc_tiling_info *tiling_info,
+	union plane_size *plane_size,
+	enum dc_rotation_angle rotation);
+
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 17/26] drm/amd/dal: Add framebuffer compression HW programming
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (15 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 16/26] drm/amd/dal: Add surface " Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 18/26] drm/amd/dal: Add input pixel processing " Harry Wentland
                     ` (8 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Adds framebuffer compression programming. Currently unused.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.c  | 886 +++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.h  |  84 ++
 2 files changed, 970 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
new file mode 100644
index 000000000000..285d54439f4c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
@@ -0,0 +1,886 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "gmc/gmc_8_2_sh_mask.h"
+#include "gmc/gmc_8_2_d.h"
+
+#include "include/logger_interface.h"
+#include "include/adapter_service_interface.h"
+
+#include "dce110_compressor.h"
+
+#define DCP_REG(reg)\
+	(reg + cp110->offsets.dcp_offset)
+#define DMIF_REG(reg)\
+	(reg + cp110->offsets.dmif_offset)
+
+static const struct dce110_compressor_reg_offsets reg_offsets[] = {
+{
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+	.dmif_offset =
+		(mmDMIF_PG0_DPG_PIPE_DPM_CONTROL
+			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+	.dmif_offset =
+		(mmDMIF_PG1_DPG_PIPE_DPM_CONTROL
+			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+	.dmif_offset =
+		(mmDMIF_PG2_DPG_PIPE_DPM_CONTROL
+			- mmDMIF_PG0_DPG_PIPE_DPM_CONTROL),
+}
+};
+
+static const uint32_t dce11_one_lpt_channel_max_resolution = 2560 * 1600;
+
+enum fbc_idle_force {
+	/* Bit 0 - Display registers updated */
+	FBC_IDLE_FORCE_DISPLAY_REGISTER_UPDATE = 0x00000001,
+
+	/* Bit 2 - FBC_GRPH_COMP_EN register updated */
+	FBC_IDLE_FORCE_GRPH_COMP_EN = 0x00000002,
+	/* Bit 3 - FBC_SRC_SEL register updated */
+	FBC_IDLE_FORCE_SRC_SEL_CHANGE = 0x00000004,
+	/* Bit 4 - FBC_MIN_COMPRESSION register updated */
+	FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE = 0x00000008,
+	/* Bit 5 - FBC_ALPHA_COMP_EN register updated */
+	FBC_IDLE_FORCE_ALPHA_COMP_EN = 0x00000010,
+	/* Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated */
+	FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN = 0x00000020,
+	/* Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */
+	FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF = 0x00000040,
+
+	/* Bit 24 - Memory write to region 0 defined by MC registers. */
+	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION0 = 0x01000000,
+	/* Bit 25 - Memory write to region 1 defined by MC registers */
+	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION1 = 0x02000000,
+	/* Bit 26 - Memory write to region 2 defined by MC registers */
+	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION2 = 0x04000000,
+	/* Bit 27 - Memory write to region 3 defined by MC registers. */
+	FBC_IDLE_FORCE_MEMORY_WRITE_TO_REGION3 = 0x08000000,
+
+	/* Bit 28 - Memory write from any client other than MCIF */
+	FBC_IDLE_FORCE_MEMORY_WRITE_OTHER_THAN_MCIF = 0x10000000,
+	/* Bit 29 - CG statics screen signal is inactive */
+	FBC_IDLE_FORCE_CG_STATIC_SCREEN_IS_INACTIVE = 0x20000000,
+};
+
+static uint32_t lpt_size_alignment(struct dce110_compressor *cp110)
+{
+	/*LPT_ALIGNMENT (in bytes) = ROW_SIZE * #BANKS * # DRAM CHANNELS. */
+	return cp110->base.raw_size * cp110->base.banks_num *
+		cp110->base.dram_channels_num;
+}
+
+static uint32_t lpt_memory_control_config(struct dce110_compressor *cp110,
+	uint32_t lpt_control)
+{
+	/*LPT MC Config */
+	if (cp110->base.options.bits.LPT_MC_CONFIG == 1) {
+		/* POSSIBLE VALUES for LPT NUM_PIPES (DRAM CHANNELS):
+		 * 00 - 1 CHANNEL
+		 * 01 - 2 CHANNELS
+		 * 02 - 4 OR 6 CHANNELS
+		 * (Only for discrete GPU, N/A for CZ)
+		 * 03 - 8 OR 12 CHANNELS
+		 * (Only for discrete GPU, N/A for CZ) */
+		switch (cp110->base.dram_channels_num) {
+		case 2:
+			set_reg_field_value(
+				lpt_control,
+				1,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_PIPES);
+			break;
+		case 1:
+			set_reg_field_value(
+				lpt_control,
+				0,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_PIPES);
+			break;
+		default:
+			dal_logger_write(
+				cp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: Invalid LPT NUM_PIPES!!!",
+				__func__);
+			break;
+		}
+
+		/* The mapping for LPT NUM_BANKS is in
+		 * GRPH_CONTROL.GRPH_NUM_BANKS register field
+		 * Specifies the number of memory banks for tiling
+		 * purposes. Only applies to 2D and 3D tiling modes.
+		 * POSSIBLE VALUES:
+		 * 00 - DCP_GRPH_NUM_BANKS_2BANK: ADDR_SURF_2_BANK
+		 * 01 - DCP_GRPH_NUM_BANKS_4BANK: ADDR_SURF_4_BANK
+		 * 02 - DCP_GRPH_NUM_BANKS_8BANK: ADDR_SURF_8_BANK
+		 * 03 - DCP_GRPH_NUM_BANKS_16BANK: ADDR_SURF_16_BANK */
+		switch (cp110->base.banks_num) {
+		case 16:
+			set_reg_field_value(
+				lpt_control,
+				3,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_BANKS);
+			break;
+		case 8:
+			set_reg_field_value(
+				lpt_control,
+				2,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_BANKS);
+			break;
+		case 4:
+			set_reg_field_value(
+				lpt_control,
+				1,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_BANKS);
+			break;
+		case 2:
+			set_reg_field_value(
+				lpt_control,
+				0,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_NUM_BANKS);
+			break;
+		default:
+			dal_logger_write(
+				cp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: Invalid LPT NUM_BANKS!!!",
+				__func__);
+			break;
+		}
+
+		/* The mapping is in DMIF_ADDR_CALC.
+		 * ADDR_CONFIG_PIPE_INTERLEAVE_SIZE register field for
+		 * Carrizo specifies the memory interleave per pipe.
+		 * It effectively specifies the location of pipe bits in
+		 * the memory address.
+		 * POSSIBLE VALUES:
+		 * 00 - ADDR_CONFIG_PIPE_INTERLEAVE_256B: 256 byte
+		 * interleave
+		 * 01 - ADDR_CONFIG_PIPE_INTERLEAVE_512B: 512 byte
+		 * interleave
+		 */
+		switch (cp110->base.channel_interleave_size) {
+		case 256: /*256B */
+			set_reg_field_value(
+				lpt_control,
+				0,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
+			break;
+		case 512: /*512B */
+			set_reg_field_value(
+				lpt_control,
+				1,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE);
+			break;
+		default:
+			dal_logger_write(
+				cp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: Invalid LPT INTERLEAVE_SIZE!!!",
+				__func__);
+			break;
+		}
+
+		/* The mapping for LOW_POWER_TILING_ROW_SIZE is in
+		 * DMIF_ADDR_CALC.ADDR_CONFIG_ROW_SIZE register field
+		 * for Carrizo. Specifies the size of dram row in bytes.
+		 * This should match up with NOOFCOLS field in
+		 * MC_ARB_RAMCFG (ROW_SIZE = 4 * 2 ^^ columns).
+		 * This register DMIF_ADDR_CALC is not used by the
+		 * hardware as it is only used for addrlib assertions.
+		 * POSSIBLE VALUES:
+		 * 00 - ADDR_CONFIG_1KB_ROW: Treat 1KB as DRAM row
+		 * boundary
+		 * 01 - ADDR_CONFIG_2KB_ROW: Treat 2KB as DRAM row
+		 * boundary
+		 * 02 - ADDR_CONFIG_4KB_ROW: Treat 4KB as DRAM row
+		 * boundary */
+		switch (cp110->base.raw_size) {
+		case 4096: /*4 KB */
+			set_reg_field_value(
+				lpt_control,
+				2,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_ROW_SIZE);
+			break;
+		case 2048:
+			set_reg_field_value(
+				lpt_control,
+				1,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_ROW_SIZE);
+			break;
+		case 1024:
+			set_reg_field_value(
+				lpt_control,
+				0,
+				LOW_POWER_TILING_CONTROL,
+				LOW_POWER_TILING_ROW_SIZE);
+			break;
+		default:
+			dal_logger_write(
+				cp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: Invalid LPT ROW_SIZE!!!",
+				__func__);
+			break;
+		}
+	} else {
+		dal_logger_write(
+			cp110->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_CONTROLLER,
+			"%s: LPT MC Configuration is not provided",
+			__func__);
+	}
+
+	return lpt_control;
+}
+
+
+
+static bool is_source_bigger_than_epanel_size(
+	struct dce110_compressor *cp110,
+	uint32_t source_view_width,
+	uint32_t source_view_height)
+{
+	if (cp110->base.embedded_panel_h_size != 0 &&
+		cp110->base.embedded_panel_v_size != 0 &&
+		((source_view_width * source_view_height) >
+		(cp110->base.embedded_panel_h_size *
+			cp110->base.embedded_panel_v_size)))
+		return true;
+
+	return false;
+}
+
+static uint32_t align_to_chunks_number_per_line(
+	struct dce110_compressor *cp110,
+	uint32_t pixels)
+{
+	return 256 * ((pixels + 255) / 256);
+}
+
+static void wait_for_fbc_state_changed(
+	struct dce110_compressor *cp110,
+	bool enabled)
+{
+	uint8_t counter = 0;
+	uint32_t addr = mmFBC_STATUS;
+	uint32_t value;
+
+	while (counter < 10) {
+		value = dm_read_reg(cp110->base.ctx, addr);
+		if (get_reg_field_value(
+			value,
+			FBC_STATUS,
+			FBC_ENABLE_STATUS) == enabled)
+			break;
+		dm_delay_in_microseconds(cp110->base.ctx, 10);
+		counter++;
+	}
+
+	if (counter == 10) {
+		dal_logger_write(
+			cp110->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_CONTROLLER,
+			"%s: wait counter exceeded, changes to HW not applied",
+			__func__);
+	}
+}
+
+void dce110_compressor_power_up_fbc(struct compressor *compressor)
+{
+	uint32_t value;
+	uint32_t addr;
+
+	addr = mmFBC_CNTL;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
+	set_reg_field_value(value, 1, FBC_CNTL, FBC_EN);
+	set_reg_field_value(value, 2, FBC_CNTL, FBC_COHERENCY_MODE);
+	if (compressor->options.bits.CLK_GATING_DISABLED == 1) {
+		/* HW needs to do power measurement comparison. */
+		set_reg_field_value(
+			value,
+			0,
+			FBC_CNTL,
+			FBC_COMP_CLK_GATE_EN);
+	}
+	dm_write_reg(compressor->ctx, addr, value);
+
+	addr = mmFBC_COMP_MODE;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_RLE_EN);
+	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_DPCM4_RGB_EN);
+	set_reg_field_value(value, 1, FBC_COMP_MODE, FBC_IND_EN);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	addr = mmFBC_COMP_CNTL;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(value, 1, FBC_COMP_CNTL, FBC_DEPTH_RGB08_EN);
+	dm_write_reg(compressor->ctx, addr, value);
+	/*FBC_MIN_COMPRESSION 0 ==> 2:1 */
+	/*                    1 ==> 4:1 */
+	/*                    2 ==> 8:1 */
+	/*                  0xF ==> 1:1 */
+	set_reg_field_value(value, 0xF, FBC_COMP_CNTL, FBC_MIN_COMPRESSION);
+	dm_write_reg(compressor->ctx, addr, value);
+	compressor->min_compress_ratio = FBC_COMPRESS_RATIO_1TO1;
+
+	value = 0;
+	dm_write_reg(compressor->ctx, mmFBC_IND_LUT0, value);
+
+	value = 0xFFFFFF;
+	dm_write_reg(compressor->ctx, mmFBC_IND_LUT1, value);
+}
+
+void dce110_compressor_enable_fbc(
+	struct compressor *compressor,
+	uint32_t paths_num,
+	struct compr_addr_and_pitch_params *params)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+
+	if (compressor->options.bits.FBC_SUPPORT &&
+		(compressor->options.bits.DUMMY_BACKEND == 0) &&
+		(!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) &&
+		(!is_source_bigger_than_epanel_size(
+			cp110,
+			params->source_view_width,
+			params->source_view_height))) {
+
+		uint32_t addr;
+		uint32_t value;
+
+		/* Before enabling FBC first need to enable LPT if applicable
+		 * LPT state should always be changed (enable/disable) while FBC
+		 * is disabled */
+		if (compressor->options.bits.LPT_SUPPORT && (paths_num < 2) &&
+			(params->source_view_width *
+				params->source_view_height <=
+				dce11_one_lpt_channel_max_resolution)) {
+			dce110_compressor_enable_lpt(compressor);
+		}
+
+		addr = mmFBC_CNTL;
+		value = dm_read_reg(compressor->ctx, addr);
+		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
+		set_reg_field_value(
+			value,
+			params->inst,
+			FBC_CNTL, FBC_SRC_SEL);
+		dm_write_reg(compressor->ctx, addr, value);
+
+		/* Keep track of enum controller_id FBC is attached to */
+		compressor->is_enabled = true;
+		compressor->attached_inst = params->inst;
+		cp110->offsets = reg_offsets[params->inst - 1];
+
+		/*Toggle it as there is bug in HW */
+		set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
+		dm_write_reg(compressor->ctx, addr, value);
+		set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN);
+		dm_write_reg(compressor->ctx, addr, value);
+
+		wait_for_fbc_state_changed(cp110, true);
+	}
+}
+
+void dce110_compressor_disable_fbc(struct compressor *compressor)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+
+	if (compressor->options.bits.FBC_SUPPORT &&
+		dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) {
+		uint32_t reg_data;
+		/* Turn off compression */
+		reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);
+		set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
+		dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);
+
+		/* Reset enum controller_id to undefined */
+		compressor->attached_inst = 0;
+		compressor->is_enabled = false;
+
+		/* Whenever disabling FBC make sure LPT is disabled if LPT
+		 * supported */
+		if (compressor->options.bits.LPT_SUPPORT)
+			dce110_compressor_disable_lpt(compressor);
+
+		wait_for_fbc_state_changed(cp110, false);
+	}
+}
+
+bool dce110_compressor_is_fbc_enabled_in_hw(
+	struct compressor *compressor,
+	uint32_t *inst)
+{
+	/* Check the hardware register */
+	uint32_t value;
+
+	value = dm_read_reg(compressor->ctx, mmFBC_STATUS);
+	if (get_reg_field_value(value, FBC_STATUS, FBC_ENABLE_STATUS)) {
+		if (inst != NULL)
+			*inst = compressor->attached_inst;
+		return true;
+	}
+
+	value = dm_read_reg(compressor->ctx, mmFBC_MISC);
+	if (get_reg_field_value(value, FBC_MISC, FBC_STOP_ON_HFLIP_EVENT)) {
+		value = dm_read_reg(compressor->ctx, mmFBC_CNTL);
+
+		if (get_reg_field_value(value, FBC_CNTL, FBC_GRPH_COMP_EN)) {
+			if (inst != NULL)
+				*inst =
+					compressor->attached_inst;
+			return true;
+		}
+	}
+	return false;
+}
+
+bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *compressor)
+{
+	/* Check the hardware register */
+	uint32_t value = dm_read_reg(compressor->ctx,
+		mmLOW_POWER_TILING_CONTROL);
+
+	return get_reg_field_value(
+		value,
+		LOW_POWER_TILING_CONTROL,
+		LOW_POWER_TILING_ENABLE);
+}
+
+void dce110_compressor_program_compressed_surface_address_and_pitch(
+	struct compressor *compressor,
+	struct compr_addr_and_pitch_params *params)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+	uint32_t value = 0;
+	uint32_t fbc_pitch = 0;
+	uint32_t compressed_surf_address_low_part =
+		compressor->compr_surface_address.addr.low_part;
+
+	/* Clear content first. */
+	dm_write_reg(
+		compressor->ctx,
+		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
+		0);
+	dm_write_reg(compressor->ctx,
+		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS), 0);
+
+	if (compressor->options.bits.LPT_SUPPORT) {
+		uint32_t lpt_alignment = lpt_size_alignment(cp110);
+
+		if (lpt_alignment != 0) {
+			compressed_surf_address_low_part =
+				((compressed_surf_address_low_part
+					+ (lpt_alignment - 1)) / lpt_alignment)
+					* lpt_alignment;
+		}
+	}
+
+	/* Write address, HIGH has to be first. */
+	dm_write_reg(compressor->ctx,
+		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH),
+		compressor->compr_surface_address.addr.high_part);
+	dm_write_reg(compressor->ctx,
+		DCP_REG(mmGRPH_COMPRESS_SURFACE_ADDRESS),
+		compressed_surf_address_low_part);
+
+	fbc_pitch = align_to_chunks_number_per_line(
+		cp110,
+		params->source_view_width);
+
+	if (compressor->min_compress_ratio == FBC_COMPRESS_RATIO_1TO1)
+		fbc_pitch = fbc_pitch / 8;
+	else
+		dal_logger_write(
+			compressor->ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_CONTROLLER,
+			"%s: Unexpected DCE11 compression ratio",
+			__func__);
+
+	/* Clear content first. */
+	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), 0);
+
+	/* Write FBC Pitch. */
+	set_reg_field_value(
+		value,
+		fbc_pitch,
+		GRPH_COMPRESS_PITCH,
+		GRPH_COMPRESS_PITCH);
+	dm_write_reg(compressor->ctx, DCP_REG(mmGRPH_COMPRESS_PITCH), value);
+
+}
+
+void dce110_compressor_disable_lpt(struct compressor *compressor)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+	uint32_t value;
+	uint32_t addr;
+	uint32_t inx;
+
+	/* Disable all pipes LPT Stutter */
+	for (inx = 0; inx < 3; inx++) {
+		value =
+			dm_read_reg(
+				compressor->ctx,
+				DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
+		set_reg_field_value(
+			value,
+			0,
+			DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
+			STUTTER_ENABLE_NONLPTCH);
+		dm_write_reg(
+			compressor->ctx,
+			DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH),
+			value);
+	}
+	/* Disable Underlay pipe LPT Stutter */
+	addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		0,
+		DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
+		STUTTER_ENABLE_NONLPTCH);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Disable LPT */
+	addr = mmLOW_POWER_TILING_CONTROL;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		0,
+		LOW_POWER_TILING_CONTROL,
+		LOW_POWER_TILING_ENABLE);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Clear selection of Channel(s) containing Compressed Surface */
+	addr = mmGMCON_LPT_TARGET;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		0xFFFFFFFF,
+		GMCON_LPT_TARGET,
+		STCTRL_LPT_TARGET);
+	dm_write_reg(compressor->ctx, mmGMCON_LPT_TARGET, value);
+}
+
+void dce110_compressor_enable_lpt(struct compressor *compressor)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+	uint32_t value;
+	uint32_t addr;
+	uint32_t value_control;
+	uint32_t channels;
+
+	/* Enable LPT Stutter from Display pipe */
+	value = dm_read_reg(compressor->ctx,
+		DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH));
+	set_reg_field_value(
+		value,
+		1,
+		DPG_PIPE_STUTTER_CONTROL_NONLPTCH,
+		STUTTER_ENABLE_NONLPTCH);
+	dm_write_reg(compressor->ctx,
+		DMIF_REG(mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH), value);
+
+	/* Enable Underlay pipe LPT Stutter */
+	addr = mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH,
+		STUTTER_ENABLE_NONLPTCH);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Selection of Channel(s) containing Compressed Surface: 0xfffffff
+	 * will disable LPT.
+	 * STCTRL_LPT_TARGETn corresponds to channel n. */
+	addr = mmLOW_POWER_TILING_CONTROL;
+	value_control = dm_read_reg(compressor->ctx, addr);
+	channels = get_reg_field_value(value_control,
+			LOW_POWER_TILING_CONTROL,
+			LOW_POWER_TILING_MODE);
+
+	addr = mmGMCON_LPT_TARGET;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		channels + 1, /* not mentioned in programming guide,
+				but follow DCE8.1 */
+		GMCON_LPT_TARGET,
+		STCTRL_LPT_TARGET);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Enable LPT */
+	addr = mmLOW_POWER_TILING_CONTROL;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		1,
+		LOW_POWER_TILING_CONTROL,
+		LOW_POWER_TILING_ENABLE);
+	dm_write_reg(compressor->ctx, addr, value);
+}
+
+void dce110_compressor_program_lpt_control(
+	struct compressor *compressor,
+	struct compr_addr_and_pitch_params *params)
+{
+	struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
+	uint32_t rows_per_channel;
+	uint32_t lpt_alignment;
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+	uint32_t lpt_control = 0;
+
+	if (!compressor->options.bits.LPT_SUPPORT)
+		return;
+
+	lpt_control = dm_read_reg(compressor->ctx,
+		mmLOW_POWER_TILING_CONTROL);
+
+	/* POSSIBLE VALUES for Low Power Tiling Mode:
+	 * 00 - Use channel 0
+	 * 01 - Use Channel 0 and 1
+	 * 02 - Use Channel 0,1,2,3
+	 * 03 - reserved */
+	switch (compressor->lpt_channels_num) {
+	/* case 2:
+	 * Use Channel 0 & 1 / Not used for DCE 11 */
+	case 1:
+		/*Use Channel 0 for LPT for DCE 11 */
+		set_reg_field_value(
+			lpt_control,
+			0,
+			LOW_POWER_TILING_CONTROL,
+			LOW_POWER_TILING_MODE);
+		break;
+	default:
+		dal_logger_write(
+			compressor->ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_CONTROLLER,
+			"%s: Invalid selected DRAM channels for LPT!!!",
+			__func__);
+		break;
+	}
+
+	lpt_control = lpt_memory_control_config(cp110, lpt_control);
+
+	/* Program LOW_POWER_TILING_ROWS_PER_CHAN field which depends on
+	 * FBC compressed surface pitch.
+	 * LOW_POWER_TILING_ROWS_PER_CHAN = Roundup ((Surface Height *
+	 * Surface Pitch) / (Row Size * Number of Channels *
+	 * Number of Banks)). */
+	rows_per_channel = 0;
+	lpt_alignment = lpt_size_alignment(cp110);
+	source_view_width =
+		align_to_chunks_number_per_line(
+			cp110,
+			params->source_view_width);
+	source_view_height = (params->source_view_height + 1) & (~0x1);
+
+	if (lpt_alignment != 0) {
+		rows_per_channel = source_view_width * source_view_height * 4;
+		rows_per_channel =
+			(rows_per_channel % lpt_alignment) ?
+				(rows_per_channel / lpt_alignment + 1) :
+				rows_per_channel / lpt_alignment;
+	}
+
+	set_reg_field_value(
+		lpt_control,
+		rows_per_channel,
+		LOW_POWER_TILING_CONTROL,
+		LOW_POWER_TILING_ROWS_PER_CHAN);
+
+	dm_write_reg(compressor->ctx,
+		mmLOW_POWER_TILING_CONTROL, lpt_control);
+}
+
+/*
+ * DCE 11 Frame Buffer Compression Implementation
+ */
+
+
+void dce110_compressor_set_fbc_invalidation_triggers(
+	struct compressor *compressor,
+	uint32_t fbc_trigger)
+{
+	/* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19)
+	 * for DCE 11 regions cannot be used - does not work with S/G
+	 */
+	uint32_t addr = mmFBC_CLIENT_REGION_MASK;
+	uint32_t value = dm_read_reg(compressor->ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		FBC_CLIENT_REGION_MASK,
+		FBC_MEMORY_REGION_MASK);
+	dm_write_reg(compressor->ctx, addr, value);
+
+	/* Setup events when to clear all CSM entries (effectively marking
+	 * current compressed data invalid)
+	 * For DCE 11 CSM metadata 11111 means - "Not Compressed"
+	 * Used as the initial value of the metadata sent to the compressor
+	 * after invalidation, to indicate that the compressor should attempt
+	 * to compress all chunks on the current pass.  Also used when the chunk
+	 * is not successfully written to memory.
+	 * When this CSM value is detected, FBC reads from the uncompressed
+	 * buffer. Set events according to passed in value, these events are
+	 * valid for DCE11:
+	 *     - bit  0 - display register updated
+	 *     - bit 28 - memory write from any client except from MCIF
+	 *     - bit 29 - CG static screen signal is inactive
+	 * In addition, DCE11.1 also needs to set new DCE11.1 specific events
+	 * that are used to trigger invalidation on certain register changes,
+	 * for example enabling of Alpha Compression may trigger invalidation of
+	 * FBC once bit is set. These events are as follows:
+	 *      - Bit 2 - FBC_GRPH_COMP_EN register updated
+	 *      - Bit 3 - FBC_SRC_SEL register updated
+	 *      - Bit 4 - FBC_MIN_COMPRESSION register updated
+	 *      - Bit 5 - FBC_ALPHA_COMP_EN register updated
+	 *      - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated
+	 *      - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated
+	 */
+	addr = mmFBC_IDLE_FORCE_CLEAR_MASK;
+	value = dm_read_reg(compressor->ctx, addr);
+	set_reg_field_value(
+		value,
+		fbc_trigger |
+		FBC_IDLE_FORCE_GRPH_COMP_EN |
+		FBC_IDLE_FORCE_SRC_SEL_CHANGE |
+		FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE |
+		FBC_IDLE_FORCE_ALPHA_COMP_EN |
+		FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN |
+		FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF,
+		FBC_IDLE_FORCE_CLEAR_MASK,
+		FBC_IDLE_FORCE_CLEAR_MASK);
+	dm_write_reg(compressor->ctx, addr, value);
+}
+
+bool dce110_compressor_construct(struct dce110_compressor *compressor,
+	struct dc_context *ctx, struct adapter_service *as)
+{
+	struct embedded_panel_info panel_info;
+
+	compressor->base.options.bits.FBC_SUPPORT = true;
+	if (!(dal_adapter_service_is_feature_supported(
+		FEATURE_DISABLE_LPT_SUPPORT)))
+		compressor->base.options.bits.LPT_SUPPORT = true;
+	 /* For DCE 11 always use one DRAM channel for LPT */
+	compressor->base.lpt_channels_num = 1;
+
+	if (dal_adapter_service_is_feature_supported(FEATURE_DUMMY_FBC_BACKEND))
+		compressor->base.options.bits.DUMMY_BACKEND = true;
+
+	/* Check if this system has more than 1 DRAM channel; if only 1 then LPT
+	 * should not be supported */
+	if (compressor->base.memory_bus_width == 64)
+		compressor->base.options.bits.LPT_SUPPORT = false;
+
+	if (dal_adapter_service_is_feature_supported(
+		FEATURE_DISABLE_FBC_COMP_CLK_GATE))
+		compressor->base.options.bits.CLK_GATING_DISABLED = true;
+
+	compressor->base.ctx = ctx;
+	compressor->base.embedded_panel_h_size = 0;
+	compressor->base.embedded_panel_v_size = 0;
+	compressor->base.memory_bus_width =
+		dal_adapter_service_get_asic_vram_bit_width(as);
+	compressor->base.allocated_size = 0;
+	compressor->base.preferred_requested_size = 0;
+	compressor->base.min_compress_ratio = FBC_COMPRESS_RATIO_INVALID;
+	compressor->base.options.raw = 0;
+	compressor->base.banks_num = 0;
+	compressor->base.raw_size = 0;
+	compressor->base.channel_interleave_size = 0;
+	compressor->base.dram_channels_num = 0;
+	compressor->base.lpt_channels_num = 0;
+	compressor->base.attached_inst = 0;
+	compressor->base.is_enabled = false;
+
+	if (dal_adapter_service_get_embedded_panel_info(as,
+		&panel_info)) {
+		compressor->base.embedded_panel_h_size =
+			panel_info.lcd_timing.horizontal_addressable;
+		compressor->base.embedded_panel_v_size =
+			panel_info.lcd_timing.vertical_addressable;
+	}
+	return true;
+}
+
+struct compressor *dce110_compressor_create(struct dc_context *ctx,
+	struct adapter_service *as)
+{
+	struct dce110_compressor *cp110 =
+		dm_alloc(ctx, sizeof(struct dce110_compressor));
+
+	if (!cp110)
+		return NULL;
+
+	if (dce110_compressor_construct(cp110, ctx, as))
+		return &cp110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, cp110);
+	return NULL;
+}
+
+void dce110_compressor_destroy(struct compressor **compressor)
+{
+	dm_free((*compressor)->ctx, TO_DCE110_COMPRESSOR(*compressor));
+	*compressor = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h
new file mode 100644
index 000000000000..0beef2243d04
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h
@@ -0,0 +1,84 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_COMPRESSOR_DCE110_H__
+#define __DC_COMPRESSOR_DCE110_H__
+
+#include "../inc/compressor.h"
+
+#define TO_DCE110_COMPRESSOR(compressor)\
+	container_of(compressor, struct dce110_compressor, base)
+
+struct dce110_compressor_reg_offsets {
+	uint32_t dcp_offset;
+	uint32_t dmif_offset;
+};
+
+struct dce110_compressor {
+	struct compressor base;
+	struct dce110_compressor_reg_offsets offsets;
+};
+
+struct compressor *dce110_compressor_create(struct dc_context *ctx,
+	struct adapter_service *as);
+
+bool dce110_compressor_construct(struct dce110_compressor *cp110,
+	struct dc_context *ctx, struct adapter_service *as);
+
+void dce110_compressor_destroy(struct compressor **cp);
+
+/* FBC RELATED */
+void dce110_compressor_power_up_fbc(struct compressor *cp);
+
+void dce110_compressor_enable_fbc(struct compressor *cp, uint32_t paths_num,
+	struct compr_addr_and_pitch_params *params);
+
+void dce110_compressor_disable_fbc(struct compressor *cp);
+
+void dce110_compressor_set_fbc_invalidation_triggers(struct compressor *cp,
+	uint32_t fbc_trigger);
+
+void dce110_compressor_program_compressed_surface_address_and_pitch(
+	struct compressor *cp,
+	struct compr_addr_and_pitch_params *params);
+
+bool dce110_compressor_get_required_compressed_surface_size(
+	struct compressor *cp,
+	struct fbc_input_info *input_info,
+	struct fbc_requested_compressed_size *size);
+
+bool dce110_compressor_is_fbc_enabled_in_hw(struct compressor *cp,
+	uint32_t *fbc_mapped_crtc_id);
+
+/* LPT RELATED */
+void dce110_compressor_enable_lpt(struct compressor *cp);
+
+void dce110_compressor_disable_lpt(struct compressor *cp);
+
+void dce110_compressor_program_lpt_control(struct compressor *cp,
+	struct compr_addr_and_pitch_params *params);
+
+bool dce110_compressor_is_lpt_enabled_in_hw(struct compressor *cp);
+
+#endif
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 18/26] drm/amd/dal: Add input pixel processing HW programming
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (16 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 17/26] drm/amd/dal: Add framebuffer compression " Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:27   ` [PATCH v2 19/26] drm/amd/dal: Add output " Harry Wentland
                     ` (7 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Adds programming of cursor and input gamma.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c     |  65 ++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h     | 100 +++
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c  | 256 ++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c   | 872 +++++++++++++++++++++
 4 files changed, 1293 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
new file mode 100644
index 000000000000..6ab35272f979
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_ipp.h"
+
+static struct ipp_funcs funcs = {
+		.ipp_cursor_set_attributes = dce110_ipp_cursor_set_attributes,
+		.ipp_cursor_set_position = dce110_ipp_cursor_set_position,
+		.ipp_program_prescale = dce110_ipp_program_prescale,
+		.ipp_set_degamma = dce110_ipp_set_degamma,
+		.ipp_set_legacy_input_gamma_mode = dce110_ipp_set_legacy_input_gamma_mode,
+		.ipp_set_legacy_input_gamma_ramp = dce110_ipp_set_legacy_input_gamma_ramp,
+		.ipp_set_palette = dce110_ipp_set_palette,
+};
+
+bool dce110_ipp_construct(
+	struct dce110_ipp* ipp,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_ipp_reg_offsets *offset)
+{
+	ipp->base.ctx = ctx;
+
+	ipp->base.inst = inst;
+
+	ipp->offsets = *offset;
+
+	ipp->base.funcs = &funcs;
+
+	return true;
+}
+
+void dce110_ipp_destroy(struct input_pixel_processor **ipp)
+{
+	dm_free((*ipp)->ctx, TO_DCE110_IPP(*ipp));
+	*ipp = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
new file mode 100644
index 000000000000..709906face3f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_IPP_DCE110_H__
+#define __DC_IPP_DCE110_H__
+
+#include "inc/ipp.h"
+
+
+struct gamma_parameters;
+struct dev_c_lut;
+
+#define TO_DCE110_IPP(input_pixel_processor)\
+	container_of(input_pixel_processor, struct dce110_ipp, base)
+
+struct dce110_ipp_reg_offsets {
+	uint32_t dcp_offset;
+};
+
+struct dce110_ipp {
+	struct input_pixel_processor base;
+	struct dce110_ipp_reg_offsets offsets;
+	struct dev_c_lut saved_palette[RGB_256X3X16];
+};
+
+bool dce110_ipp_construct(
+	struct dce110_ipp* ipp,
+	struct dc_context *ctx,
+	enum controller_id id,
+	const struct dce110_ipp_reg_offsets *offset);
+
+void dce110_ipp_destroy(struct input_pixel_processor **ipp);
+
+/* CURSOR RELATED */
+bool dce110_ipp_cursor_set_position(
+	struct input_pixel_processor *ipp,
+	const struct dc_cursor_position *position);
+
+bool dce110_ipp_cursor_set_attributes(
+	struct input_pixel_processor *ipp,
+	const struct dc_cursor_attributes *attributes);
+
+/* DEGAMMA RELATED */
+bool dce110_ipp_set_degamma(
+	struct input_pixel_processor *ipp,
+	const struct gamma_parameters *params,
+	bool force_bypass);
+
+void dce110_ipp_program_prescale(
+	struct input_pixel_processor *ipp,
+	enum pixel_format pixel_format);
+
+void dce110_ipp_set_legacy_input_gamma_mode(
+		struct input_pixel_processor *ipp,
+		bool is_legacy);
+
+bool dce110_ipp_set_legacy_input_gamma_ramp(
+	struct input_pixel_processor *ipp,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params);
+
+bool dce110_ipp_set_palette(
+	struct input_pixel_processor *ipp,
+	const struct dev_c_lut *palette,
+	uint32_t start,
+	uint32_t length,
+	enum pixel_format surface_pixel_format);
+
+/*
+ * Helper functions to be resused in other ASICs
+ */
+void dce110_helper_select_lut(struct dce110_ipp *ipp110);
+
+void dce110_helper_program_black_white_offset(
+	struct dce110_ipp *ipp110,
+	enum pixel_format surface_pixel_format);
+
+#endif /*__DC_IPP_DCE110_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
new file mode 100644
index 000000000000..ef91f2db24e3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_ipp.h"
+
+#define CURSOR_COLOR_BLACK 0x00000000
+#define CURSOR_COLOR_WHITE 0xFFFFFFFF
+
+#define DCP_REG(reg)\
+	(reg + ipp110->offsets.dcp_offset)
+
+static void enable(
+	struct dce110_ipp *ipp110,
+	bool enable);
+
+static void lock(
+	struct dce110_ipp *ipp110,
+	bool enable);
+
+static void program_position(
+	struct dce110_ipp *ipp110,
+	uint32_t x,
+	uint32_t y);
+
+static bool program_control(
+	struct dce110_ipp *ipp110,
+	enum dc_cursor_color_format color_format,
+	bool enable_magnification,
+	bool inverse_transparent_clamping);
+
+static void program_hotspot(
+	struct dce110_ipp *ipp110,
+	uint32_t x,
+	uint32_t y);
+
+static void program_size(
+	struct dce110_ipp *ipp110,
+	uint32_t width,
+	uint32_t height);
+
+static void program_address(
+	struct dce110_ipp *ipp110,
+	PHYSICAL_ADDRESS_LOC address);
+
+
+bool dce110_ipp_cursor_set_position(
+	struct input_pixel_processor *ipp,
+	const struct dc_cursor_position *position)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	/* lock cursor registers */
+	lock(ipp110, true);
+
+	/* Flag passed in structure differentiates cursor enable/disable. */
+	/* Update if it differs from cached state. */
+	enable(ipp110, position->enable);
+
+	program_position(ipp110, position->x, position->y);
+
+	if (position->hot_spot_enable)
+		program_hotspot(
+				ipp110,
+				position->x_origin,
+				position->y_origin);
+
+	/* unlock cursor registers */
+	lock(ipp110, false);
+
+	return true;
+}
+
+bool dce110_ipp_cursor_set_attributes(
+	struct input_pixel_processor *ipp,
+	const struct dc_cursor_attributes *attributes)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+	/* Lock cursor registers */
+	lock(ipp110, true);
+
+	/* Program cursor control */
+	program_control(
+		ipp110,
+		attributes->color_format,
+		attributes->attribute_flags.bits.ENABLE_MAGNIFICATION,
+		attributes->attribute_flags.bits.INVERSE_TRANSPARENT_CLAMPING);
+
+	/* Program hot spot coordinates */
+	program_hotspot(ipp110, attributes->x_hot, attributes->y_hot);
+
+	/*
+	 * Program cursor size -- NOTE: HW spec specifies that HW register
+	 * stores size as (height - 1, width - 1)
+	 */
+	program_size(ipp110, attributes->width, attributes->height);
+
+	/* Program cursor surface address */
+	program_address(ipp110, attributes->address);
+
+	/* Unlock Cursor registers. */
+	lock(ipp110, false);
+
+	return true;
+}
+
+static void enable(
+	struct dce110_ipp *ipp110, bool enable)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_CONTROL);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, enable, CUR_CONTROL, CURSOR_EN);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static void lock(
+	struct dce110_ipp *ipp110, bool lock)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_UPDATE);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, lock, CUR_UPDATE, CURSOR_UPDATE_LOCK);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static void program_position(
+	struct dce110_ipp *ipp110,
+	uint32_t x,
+	uint32_t y)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_POSITION);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, x, CUR_POSITION, CURSOR_X_POSITION);
+	set_reg_field_value(value, y, CUR_POSITION, CURSOR_Y_POSITION);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static bool program_control(
+	struct dce110_ipp *ipp110,
+	enum dc_cursor_color_format color_format,
+	bool enable_magnification,
+	bool inverse_transparent_clamping)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_CONTROL);
+	uint32_t mode = 0;
+
+	switch (color_format) {
+	case CURSOR_MODE_MONO:
+		mode = 0;
+		break;
+	case CURSOR_MODE_COLOR_1BIT_AND:
+		mode = 1;
+		break;
+	case CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA:
+		mode = 2;
+		break;
+	case CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA:
+		mode = 3;
+		break;
+	default:
+		return false;
+	}
+
+	set_reg_field_value(value, mode, CUR_CONTROL, CURSOR_MODE);
+	set_reg_field_value(value, enable_magnification,
+			CUR_CONTROL, CURSOR_2X_MAGNIFY);
+	set_reg_field_value(value, inverse_transparent_clamping,
+			CUR_CONTROL, CUR_INV_TRANS_CLAMP);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+
+	if (color_format == CURSOR_MODE_MONO) {
+		addr = DCP_REG(mmCUR_COLOR1);
+		dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_BLACK);
+		addr = DCP_REG(mmCUR_COLOR2);
+		dm_write_reg(ipp110->base.ctx, addr, CURSOR_COLOR_WHITE);
+	}
+	return true;
+}
+
+static void program_hotspot(
+	struct dce110_ipp *ipp110,
+	uint32_t x,
+	uint32_t y)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_HOT_SPOT);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, x, CUR_HOT_SPOT, CURSOR_HOT_SPOT_X);
+	set_reg_field_value(value, y, CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static void program_size(
+	struct dce110_ipp *ipp110,
+	uint32_t width,
+	uint32_t height)
+{
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmCUR_SIZE);
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+	set_reg_field_value(value, width, CUR_SIZE, CURSOR_WIDTH);
+	set_reg_field_value(value, height, CUR_SIZE, CURSOR_HEIGHT);
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static void program_address(
+	struct dce110_ipp *ipp110,
+	PHYSICAL_ADDRESS_LOC address)
+{
+	uint32_t addr = DCP_REG(mmCUR_SURFACE_ADDRESS_HIGH);
+	/* SURFACE_ADDRESS_HIGH: Higher order bits (39:32) of hardware cursor
+	 * surface base address in byte. It is 4K byte aligned.
+	 * The correct way to program cursor surface address is to first write
+	 * to CUR_SURFACE_ADDRESS_HIGH, and then write to CUR_SURFACE_ADDRESS */
+
+	dm_write_reg(ipp110->base.ctx, addr, address.high_part);
+
+	addr = DCP_REG(mmCUR_SURFACE_ADDRESS);
+	dm_write_reg(ipp110->base.ctx, addr, address.low_part);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c
new file mode 100644
index 000000000000..fcf65f119af4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c
@@ -0,0 +1,872 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+#include "include/fixed31_32.h"
+#include "basics/conversion.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_ipp.h"
+#include "gamma_types.h"
+
+#define DCP_REG(reg)\
+	(reg + ipp110->offsets.dcp_offset)
+
+enum {
+	MAX_INPUT_LUT_ENTRY = 256
+};
+
+/* CALCULATION OPERATIONS*/
+static void convert_256_lut_entries_to_gxo_format(
+	const struct gamma_ramp_rgb256x3x16 *lut,
+	struct dev_c_lut16 *gamma)
+{
+	uint32_t i = 0;
+
+	ASSERT(lut);
+	ASSERT(gamma);
+
+	do {
+		gamma->red = lut->red[i];
+		gamma->green = lut->green[i];
+		gamma->blue = lut->blue[i];
+
+		++gamma;
+		++i;
+	} while (i != MAX_INPUT_LUT_ENTRY);
+}
+
+static void convert_udx_gamma_entries_to_gxo_format(
+	const struct gamma_ramp_dxgi_1 *lut,
+	struct dev_c_lut16 *gamma)
+{
+	/* TODO here we deal with DXGI gamma table,
+	 * originally, values was expressed as 'float',
+	 * now values expressed as 'dal_fixed20_12'. */
+}
+
+/*PROTOTYPE DECLARATIONS*/
+static void set_lut_inc(
+	struct dce110_ipp *ipp110,
+	uint8_t inc,
+	bool is_float,
+	bool is_signed);
+
+static void program_black_offsets(
+	struct dce110_ipp *ipp110,
+	struct dev_c_lut16 *offset);
+
+static void program_white_offsets(
+	struct dce110_ipp *ipp110,
+	struct dev_c_lut16 *offset);
+
+static void program_lut_gamma(
+	struct dce110_ipp *ipp110,
+	const struct dev_c_lut16 *gamma,
+	const struct gamma_parameters *params);
+
+static void program_prescale(
+	struct dce110_ipp *ipp110,
+	enum pixel_format pixel_format);
+
+static void set_legacy_input_gamma_mode(
+	struct dce110_ipp *ipp110,
+	bool is_legacy);
+
+static bool set_legacy_input_gamma_ramp_rgb256x3x16(
+	struct dce110_ipp *ipp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params);
+
+static bool set_legacy_input_gamma_ramp_dxgi1(
+	struct dce110_ipp *ipp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params);
+
+static bool set_default_gamma(
+	struct dce110_ipp *ipp110,
+	enum pixel_format surface_pixel_format);
+
+static void set_degamma(
+	struct dce110_ipp *ipp110,
+	const struct gamma_parameters *params,
+	bool force_bypass);
+
+bool dce110_ipp_set_legacy_input_gamma_ramp(
+	struct input_pixel_processor *ipp,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	switch (gamma_ramp->type) {
+	case GAMMA_RAMP_RBG256X3X16:
+		return set_legacy_input_gamma_ramp_rgb256x3x16(
+				ipp110, gamma_ramp, params);
+	case GAMMA_RAMP_DXGI_1:
+		return set_legacy_input_gamma_ramp_dxgi1(
+				ipp110, gamma_ramp, params);
+	default:
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+}
+
+bool dce110_ipp_set_palette(
+	struct input_pixel_processor *ipp,
+	const struct dev_c_lut *palette,
+	uint32_t start,
+	uint32_t length,
+	enum pixel_format surface_pixel_format)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+	uint32_t i;
+
+	if (((start + length) > MAX_INPUT_LUT_ENTRY) || (NULL == palette)) {
+		BREAK_TO_DEBUGGER();
+		/* wrong input */
+		return false;
+	}
+
+	for (i = start; i < start + length; i++) {
+		ipp110->saved_palette[i] = palette[i];
+		ipp110->saved_palette[i] = palette[i];
+		ipp110->saved_palette[i] = palette[i];
+	}
+
+	return set_default_gamma(ipp110, surface_pixel_format);
+}
+
+bool dce110_ipp_set_degamma(
+	struct input_pixel_processor *ipp,
+	const struct gamma_parameters *params,
+	bool force_bypass)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	set_degamma(ipp110, params, force_bypass);
+
+	return true;
+}
+
+void dce110_ipp_program_prescale(
+	struct input_pixel_processor *ipp,
+	enum pixel_format pixel_format)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	program_prescale(ipp110, pixel_format);
+}
+
+void dce110_ipp_set_legacy_input_gamma_mode(
+		struct input_pixel_processor *ipp,
+		bool is_legacy)
+{
+	struct dce110_ipp *ipp110 = TO_DCE110_IPP(ipp);
+
+	set_legacy_input_gamma_mode(ipp110, is_legacy);
+}
+
+static void set_lut_inc(
+	struct dce110_ipp *ipp110,
+	uint8_t inc,
+	bool is_float,
+	bool is_signed)
+{
+	const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL);
+
+	uint32_t value = dm_read_reg(ipp110->base.ctx, addr);
+
+	set_reg_field_value(
+		value,
+		inc,
+		DC_LUT_CONTROL,
+		DC_LUT_INC_R);
+
+	set_reg_field_value(
+		value,
+		inc,
+		DC_LUT_CONTROL,
+		DC_LUT_INC_G);
+
+	set_reg_field_value(
+		value,
+		inc,
+		DC_LUT_CONTROL,
+		DC_LUT_INC_B);
+
+	set_reg_field_value(
+		value,
+		is_float,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_R_FLOAT_POINT_EN);
+
+	set_reg_field_value(
+		value,
+		is_float,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_G_FLOAT_POINT_EN);
+
+	set_reg_field_value(
+		value,
+		is_float,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_B_FLOAT_POINT_EN);
+
+	set_reg_field_value(
+		value,
+		is_signed,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_R_SIGNED_EN);
+
+	set_reg_field_value(
+		value,
+		is_signed,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_G_SIGNED_EN);
+
+	set_reg_field_value(
+		value,
+		is_signed,
+		DC_LUT_CONTROL,
+		DC_LUT_DATA_B_SIGNED_EN);
+
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+void dce110_helper_select_lut(struct dce110_ipp *ipp110)
+{
+	uint32_t value = 0;
+
+	set_lut_inc(ipp110, 0, false, false);
+
+	{
+		const uint32_t addr = DCP_REG(mmDC_LUT_WRITE_EN_MASK);
+
+		value = dm_read_reg(ipp110->base.ctx, addr);
+
+		/* enable all */
+		set_reg_field_value(
+			value,
+			0x7,
+			DC_LUT_WRITE_EN_MASK,
+			DC_LUT_WRITE_EN_MASK);
+
+		dm_write_reg(ipp110->base.ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = DCP_REG(mmDC_LUT_RW_MODE);
+
+		value = dm_read_reg(ipp110->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_LUT_RW_MODE,
+			DC_LUT_RW_MODE);
+
+		dm_write_reg(ipp110->base.ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = DCP_REG(mmDC_LUT_CONTROL);
+
+		value = dm_read_reg(ipp110->base.ctx, addr);
+
+		/* 00 - new u0.12 */
+		set_reg_field_value(
+			value,
+			3,
+			DC_LUT_CONTROL,
+			DC_LUT_DATA_R_FORMAT);
+
+		set_reg_field_value(
+			value,
+			3,
+			DC_LUT_CONTROL,
+			DC_LUT_DATA_G_FORMAT);
+
+		set_reg_field_value(
+			value,
+			3,
+			DC_LUT_CONTROL,
+			DC_LUT_DATA_B_FORMAT);
+
+		dm_write_reg(ipp110->base.ctx, addr, value);
+	}
+
+	{
+		const uint32_t addr = DCP_REG(mmDC_LUT_RW_INDEX);
+
+		value = dm_read_reg(ipp110->base.ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			DC_LUT_RW_INDEX,
+			DC_LUT_RW_INDEX);
+
+		dm_write_reg(ipp110->base.ctx, addr, value);
+	}
+}
+
+static void program_black_offsets(
+	struct dce110_ipp *ipp110,
+	struct dev_c_lut16 *offset)
+{
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_BLACK_OFFSET_RED),
+		offset->red);
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_BLACK_OFFSET_GREEN),
+		offset->green);
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_BLACK_OFFSET_BLUE),
+		offset->blue);
+}
+
+static void program_white_offsets(
+	struct dce110_ipp *ipp110,
+	struct dev_c_lut16 *offset)
+{
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_WHITE_OFFSET_RED),
+		offset->red);
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_WHITE_OFFSET_GREEN),
+		offset->green);
+	dm_write_reg(ipp110->base.ctx,
+		DCP_REG(mmDC_LUT_WHITE_OFFSET_BLUE),
+		offset->blue);
+}
+
+void dce110_helper_program_black_white_offset(
+	struct dce110_ipp *ipp110,
+	enum pixel_format surface_pixel_format)
+{
+	struct dev_c_lut16 black_offset;
+	struct dev_c_lut16 white_offset;
+
+	/* get black offset */
+
+	switch (surface_pixel_format) {
+	case PIXEL_FORMAT_FP16:
+		/* sRGB gamut, [0.0...1.0] */
+		black_offset.red = 0;
+		black_offset.green = 0;
+		black_offset.blue = 0;
+	break;
+
+	case PIXEL_FORMAT_ARGB2101010_XRBIAS:
+		/* [-1.0...3.0] */
+		black_offset.red = 0x100;
+		black_offset.green = 0x100;
+		black_offset.blue = 0x100;
+	break;
+
+	default:
+		black_offset.red = 0;
+		black_offset.green = 0;
+		black_offset.blue = 0;
+	}
+
+	/* get white offset */
+
+	switch (surface_pixel_format) {
+	case PIXEL_FORMAT_FP16:
+		white_offset.red = 0x3BFF;
+		white_offset.green = 0x3BFF;
+		white_offset.blue = 0x3BFF;
+	break;
+
+	case PIXEL_FORMAT_ARGB2101010_XRBIAS:
+		white_offset.red = 0x37E;
+		white_offset.green = 0x37E;
+		white_offset.blue = 0x37E;
+		break;
+
+	case PIXEL_FORMAT_ARGB8888:
+		white_offset.red = 0xFF;
+		white_offset.green = 0xFF;
+		white_offset.blue = 0xFF;
+		break;
+
+	default:
+		white_offset.red = 0x3FF;
+		white_offset.green = 0x3FF;
+		white_offset.blue = 0x3FF;
+	}
+
+	program_black_offsets(ipp110, &black_offset);
+	program_white_offsets(ipp110, &white_offset);
+}
+
+static void program_lut_gamma(
+	struct dce110_ipp *ipp110,
+	const struct dev_c_lut16 *gamma,
+	const struct gamma_parameters *params)
+{
+	uint32_t i = 0;
+	uint32_t value = 0;
+	uint32_t addr;
+
+	{
+		uint8_t max_tries = 10;
+		uint8_t counter = 0;
+
+		/* Power on LUT memory */
+		value = dm_read_reg(
+				ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL));
+
+		set_reg_field_value(
+			value,
+			1,
+			DCFE_MEM_PWR_CTRL,
+			DCP_REGAMMA_MEM_PWR_DIS);
+
+		dm_write_reg(
+			ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value);
+
+		while (counter < max_tries) {
+			value =
+				dm_read_reg(
+					ipp110->base.ctx,
+					DCP_REG(mmDCFE_MEM_PWR_STATUS));
+
+			if (get_reg_field_value(
+				value,
+				DCFE_MEM_PWR_STATUS,
+				DCP_REGAMMA_MEM_PWR_STATE) == 0)
+				break;
+
+			++counter;
+		}
+
+		if (counter == max_tries) {
+			dal_logger_write(ipp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: regamma lut was not powered on in a timely manner, programming still proceeds\n",
+				__func__);
+		}
+	}
+
+	dce110_helper_program_black_white_offset(ipp110, params->surface_pixel_format);
+
+	dce110_helper_select_lut(ipp110);
+
+	if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8) {
+		addr = DCP_REG(mmDC_LUT_SEQ_COLOR);
+
+		do {
+			struct dev_c_lut *index =
+				ipp110->saved_palette + i;
+
+			set_reg_field_value(
+				value,
+				gamma[index->red].red,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+
+			set_reg_field_value(
+				value,
+				gamma[index->green].green,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+
+			set_reg_field_value(
+				value,
+				gamma[index->blue].blue,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+			++i;
+		} while (i != RGB_256X3X16);
+	} else {
+		addr = DCP_REG(mmDC_LUT_SEQ_COLOR);
+
+		do {
+			set_reg_field_value(
+				value,
+				gamma[i].red,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+
+			set_reg_field_value(
+				value,
+				gamma[i].green,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+
+			set_reg_field_value(
+				value,
+				gamma[i].blue,
+				DC_LUT_SEQ_COLOR,
+				DC_LUT_SEQ_COLOR);
+			dm_write_reg(ipp110->base.ctx, addr, value);
+
+			++i;
+		} while (i != RGB_256X3X16);
+	}
+
+	/*  we are done with DCP LUT memory; re-enable low power mode */
+	value = dm_read_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL));
+
+	set_reg_field_value(
+		value,
+		0,
+		DCFE_MEM_PWR_CTRL,
+		DCP_REGAMMA_MEM_PWR_DIS);
+
+	dm_write_reg(ipp110->base.ctx, DCP_REG(mmDCFE_MEM_PWR_CTRL), value);
+}
+
+static void program_prescale(
+	struct dce110_ipp *ipp110,
+	enum pixel_format pixel_format)
+{
+	uint32_t prescale_control;
+	uint32_t prescale_values_grph_r = 0;
+	uint32_t prescale_values_grph_g = 0;
+	uint32_t prescale_values_grph_b = 0;
+
+	uint32_t prescale_num;
+	uint32_t prescale_denom = 1;
+	uint16_t prescale_hw;
+	uint32_t bias_num = 0;
+	uint32_t bias_denom = 1;
+	uint16_t bias_hw;
+
+	const uint32_t addr_control = DCP_REG(mmPRESCALE_GRPH_CONTROL);
+
+	prescale_control = dm_read_reg(ipp110->base.ctx, addr_control);
+
+	set_reg_field_value(
+		prescale_control,
+		0,
+		PRESCALE_GRPH_CONTROL,
+		GRPH_PRESCALE_BYPASS);
+
+	switch (pixel_format) {
+	case PIXEL_FORMAT_RGB565:
+		prescale_num = 64;
+		prescale_denom = 63;
+	break;
+
+	case PIXEL_FORMAT_ARGB8888:
+		/* This function should only be called when using regamma
+		 * and bypassing legacy INPUT GAMMA LUT (function name is
+		 * misleading)
+		 */
+		prescale_num = 256;
+		prescale_denom = 255;
+	break;
+
+	case PIXEL_FORMAT_ARGB2101010:
+		prescale_num = 1024;
+		prescale_denom = 1023;
+	break;
+
+	case PIXEL_FORMAT_ARGB2101010_XRBIAS:
+		prescale_num = 1024;
+		prescale_denom = 510;
+		bias_num = 384;
+		bias_denom = 1024;
+	break;
+
+	case PIXEL_FORMAT_FP16:
+		prescale_num = 1;
+	break;
+
+	default:
+		prescale_num = 1;
+
+		set_reg_field_value(
+			prescale_control,
+			1,
+			PRESCALE_GRPH_CONTROL,
+			GRPH_PRESCALE_BYPASS);
+	}
+
+	prescale_hw = fixed_point_to_int_frac(
+		dal_fixed31_32_from_fraction(prescale_num, prescale_denom),
+		2, 13);
+
+	bias_hw = fixed_point_to_int_frac(
+		dal_fixed31_32_from_fraction(bias_num, bias_denom),
+		2, 13);
+
+
+	set_reg_field_value(
+		prescale_values_grph_r,
+		prescale_hw,
+		PRESCALE_VALUES_GRPH_R,
+		GRPH_PRESCALE_SCALE_R);
+
+	set_reg_field_value(
+		prescale_values_grph_r,
+		bias_hw,
+		PRESCALE_VALUES_GRPH_R,
+		GRPH_PRESCALE_BIAS_R);
+
+
+	set_reg_field_value(
+		prescale_values_grph_g,
+		prescale_hw,
+		PRESCALE_VALUES_GRPH_G,
+		GRPH_PRESCALE_SCALE_G);
+
+	set_reg_field_value(
+		prescale_values_grph_g,
+		bias_hw,
+		PRESCALE_VALUES_GRPH_G,
+		GRPH_PRESCALE_BIAS_G);
+
+
+	set_reg_field_value(
+		prescale_values_grph_b,
+		prescale_hw,
+		PRESCALE_VALUES_GRPH_B,
+		GRPH_PRESCALE_SCALE_B);
+
+	set_reg_field_value(
+		prescale_values_grph_b,
+		bias_hw,
+		PRESCALE_VALUES_GRPH_B,
+		GRPH_PRESCALE_BIAS_B);
+
+	dm_write_reg(ipp110->base.ctx,
+		addr_control, prescale_control);
+
+	{
+		dm_write_reg(ipp110->base.ctx,
+				DCP_REG(mmPRESCALE_VALUES_GRPH_R),
+				prescale_values_grph_r);
+	}
+
+	{
+		dm_write_reg(ipp110->base.ctx,
+				DCP_REG(mmPRESCALE_VALUES_GRPH_G),
+				prescale_values_grph_g);
+	}
+
+	{
+		dm_write_reg(ipp110->base.ctx,
+				DCP_REG(mmPRESCALE_VALUES_GRPH_B),
+				prescale_values_grph_b);
+	}
+}
+
+static void set_legacy_input_gamma_mode(
+	struct dce110_ipp *ipp110,
+	bool is_legacy)
+{
+	const uint32_t addr = DCP_REG(mmINPUT_GAMMA_CONTROL);
+	uint32_t value = dm_read_reg(ipp110->base.ctx, addr);
+
+	set_reg_field_value(
+		value,
+		!is_legacy,
+		INPUT_GAMMA_CONTROL,
+		GRPH_INPUT_GAMMA_MODE);
+
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
+static bool set_legacy_input_gamma_ramp_rgb256x3x16(
+	struct dce110_ipp *ipp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct dev_c_lut16 *gamma16 =
+		dm_alloc(
+			ipp110->base.ctx,
+			sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY);
+
+	if (!gamma16)
+		return false;
+
+	convert_256_lut_entries_to_gxo_format(
+		&gamma_ramp->gamma_ramp_rgb256x3x16, gamma16);
+
+	if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) &&
+		(params->surface_pixel_format !=
+			PIXEL_FORMAT_ARGB2101010_XRBIAS) &&
+		(params->surface_pixel_format != PIXEL_FORMAT_FP16)) {
+		program_lut_gamma(ipp110, gamma16, params);
+		dm_free(ipp110->base.ctx, gamma16);
+		return true;
+	}
+
+	/* TODO process DirectX-specific formats*/
+	dm_free(ipp110->base.ctx, gamma16);
+	return false;
+}
+
+static bool set_legacy_input_gamma_ramp_dxgi1(
+	struct dce110_ipp *ipp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct dev_c_lut16 *gamma16 =
+		dm_alloc(
+			ipp110->base.ctx,
+			sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY);
+
+	if (!gamma16)
+		return false;
+
+	convert_udx_gamma_entries_to_gxo_format(
+		&gamma_ramp->gamma_ramp_dxgi1, gamma16);
+
+	if ((params->surface_pixel_format != PIXEL_FORMAT_ARGB2101010) &&
+		(params->surface_pixel_format !=
+			PIXEL_FORMAT_ARGB2101010_XRBIAS) &&
+		(params->surface_pixel_format != PIXEL_FORMAT_FP16)) {
+		program_lut_gamma(ipp110, gamma16, params);
+		dm_free(ipp110->base.ctx, gamma16);
+		return true;
+	}
+
+	/* TODO process DirectX-specific formats*/
+	dm_free(ipp110->base.ctx, gamma16);
+	return false;
+}
+
+static bool set_default_gamma(
+	struct dce110_ipp *ipp110,
+	enum pixel_format surface_pixel_format)
+{
+	uint32_t i;
+
+	struct dev_c_lut16 *gamma16 = NULL;
+	struct gamma_parameters *params = NULL;
+
+	gamma16 = dm_alloc(
+			ipp110->base.ctx,
+			sizeof(struct dev_c_lut16) * MAX_INPUT_LUT_ENTRY);
+
+	if (!gamma16)
+		return false;
+
+	params = dm_alloc(ipp110->base.ctx, sizeof(*params));
+
+	if (!params) {
+		dm_free(ipp110->base.ctx, gamma16);
+		return false;
+	}
+
+	for (i = 0; i < MAX_INPUT_LUT_ENTRY; i++) {
+		gamma16[i].red = gamma16[i].green =
+			gamma16[i].blue = (uint16_t) (i << 8);
+	}
+
+	params->surface_pixel_format = surface_pixel_format;
+	params->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_HW;
+	params->degamma_adjust_type = GRAPHICS_DEGAMMA_ADJUST_HW;
+	params->selected_gamma_lut = GRAPHICS_GAMMA_LUT_REGAMMA;
+	params->disable_adjustments = false;
+
+	params->regamma.features.value = 0;
+
+	params->regamma.features.bits.GAMMA_RAMP_ARRAY = 0;
+	params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 1;
+	params->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 1;
+
+	for (i = 0; i < 3; i++) {
+		params->regamma.gamma_coeff.a0[i] = 31308;
+		params->regamma.gamma_coeff.a1[i] = 12920;
+		params->regamma.gamma_coeff.a2[i] = 55;
+		params->regamma.gamma_coeff.a3[i] = 55;
+		params->regamma.gamma_coeff.gamma[i] = 2400;
+
+	}
+
+	program_lut_gamma(ipp110, gamma16, params);
+
+	dm_free(ipp110->base.ctx, gamma16);
+	dm_free(ipp110->base.ctx, params);
+
+	return true;
+}
+
+static void set_degamma(
+	struct dce110_ipp *ipp110,
+	const struct gamma_parameters *params,
+	bool force_bypass)
+{
+	uint32_t value;
+	const uint32_t addr = DCP_REG(mmDEGAMMA_CONTROL);
+	uint32_t degamma_type =
+		params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB == 1 ?
+			1 : 2;
+
+	value = dm_read_reg(ipp110->base.ctx, addr);
+
+	/* if by pass - no degamma
+	 * when legacy and regamma LUT's we do degamma */
+	if (params->degamma_adjust_type == GRAPHICS_DEGAMMA_ADJUST_BYPASS ||
+		(params->surface_pixel_format == PIXEL_FORMAT_FP16 &&
+			params->selected_gamma_lut ==
+				GRAPHICS_GAMMA_LUT_REGAMMA))
+		degamma_type = 0;
+
+	if (force_bypass)
+		degamma_type = 0;
+
+	set_reg_field_value(
+		value,
+		degamma_type,
+		DEGAMMA_CONTROL,
+		GRPH_DEGAMMA_MODE);
+
+	set_reg_field_value(
+		value,
+		degamma_type,
+		DEGAMMA_CONTROL,
+		CURSOR_DEGAMMA_MODE);
+
+	set_reg_field_value(
+		value,
+		degamma_type,
+		DEGAMMA_CONTROL,
+		CURSOR2_DEGAMMA_MODE);
+
+	dm_write_reg(ipp110->base.ctx, addr, value);
+}
+
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 19/26] drm/amd/dal: Add output pixel processing HW programming
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (17 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 18/26] drm/amd/dal: Add input pixel processing " Harry Wentland
@ 2016-02-16 22:27   ` Harry Wentland
  2016-02-16 22:28   ` [PATCH v2 20/26] drm/amd/dal: Add transform & scaler " Harry Wentland
                     ` (6 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:27 UTC (permalink / raw)
  To: dri-devel

Adds programming for color space conversion (CSC),
regamma, and formatter.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c     |  272 +++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h     |  143 ++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c |  904 +++++++
 .../drm/amd/dal/dc/dce110/dce110_opp_formatter.c   |  610 +++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2474 ++++++++++++++++++++
 5 files changed, 4403 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
new file mode 100644
index 000000000000..acb405e7b2e7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_opp.h"
+
+#include "gamma_types.h"
+
+enum {
+	MAX_LUT_ENTRY = 256,
+	MAX_NUMBER_OF_ENTRIES = 256
+};
+
+static void build_evenly_distributed_points(
+	struct gamma_pixel *points,
+	uint32_t numberof_points,
+	struct fixed31_32 max_value,
+	struct fixed31_32 divider1,
+	struct fixed31_32 divider2,
+	struct fixed31_32 divider3)
+{
+	struct gamma_pixel *p = points;
+	struct gamma_pixel *p_last = p + numberof_points - 1;
+
+	uint32_t i = 0;
+
+	do {
+		struct fixed31_32 value = dal_fixed31_32_div_int(
+			dal_fixed31_32_mul_int(max_value, i),
+			numberof_points - 1);
+
+		p->r = value;
+		p->g = value;
+		p->b = value;
+
+		++p;
+		++i;
+	} while (i != numberof_points);
+
+	p->r = dal_fixed31_32_div(p_last->r, divider1);
+	p->g = dal_fixed31_32_div(p_last->g, divider1);
+	p->b = dal_fixed31_32_div(p_last->b, divider1);
+
+	++p;
+
+	p->r = dal_fixed31_32_div(p_last->r, divider2);
+	p->g = dal_fixed31_32_div(p_last->g, divider2);
+	p->b = dal_fixed31_32_div(p_last->b, divider2);
+
+	++p;
+
+	p->r = dal_fixed31_32_div(p_last->r, divider3);
+	p->g = dal_fixed31_32_div(p_last->g, divider3);
+	p->b = dal_fixed31_32_div(p_last->b, divider3);
+}
+
+/*****************************************/
+/* Constructor, Destructor               */
+/*****************************************/
+
+struct opp_funcs funcs = {
+		.opp_map_legacy_and_regamma_hw_to_x_user = dce110_opp_map_legacy_and_regamma_hw_to_x_user,
+		.opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
+		.opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction,
+		.opp_program_clamping_and_pixel_encoding = dce110_opp_program_clamping_and_pixel_encoding,
+		.opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
+		.opp_set_csc_default = dce110_opp_set_csc_default,
+		.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
+		.opp_set_regamma = dce110_opp_set_regamma
+};
+
+bool dce110_opp_construct(struct dce110_opp *opp110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offsets)
+{
+
+	opp110->base.funcs = &funcs;
+
+	opp110->base.ctx = ctx;
+
+	opp110->base.inst = inst;
+
+	opp110->offsets = *offsets;
+
+	opp110->regamma.hw_points_num = 128;
+	opp110->regamma.coordinates_x = NULL;
+	opp110->regamma.rgb_resulted = NULL;
+	opp110->regamma.rgb_regamma = NULL;
+	opp110->regamma.coeff128 = NULL;
+	opp110->regamma.coeff128_oem = NULL;
+	opp110->regamma.coeff128_dx = NULL;
+	opp110->regamma.axis_x_256 = NULL;
+	opp110->regamma.axis_x_1025 = NULL;
+	opp110->regamma.rgb_oem = NULL;
+	opp110->regamma.rgb_user = NULL;
+	opp110->regamma.extra_points = 3;
+	opp110->regamma.use_half_points = false;
+	opp110->regamma.x_max1 = dal_fixed31_32_one;
+	opp110->regamma.x_max2 = dal_fixed31_32_from_int(2);
+	opp110->regamma.x_min = dal_fixed31_32_zero;
+	opp110->regamma.divider1 = dal_fixed31_32_from_fraction(3, 2);
+	opp110->regamma.divider2 = dal_fixed31_32_from_int(2);
+	opp110->regamma.divider3 = dal_fixed31_32_from_fraction(5, 2);
+
+	opp110->regamma.rgb_user = dm_alloc(
+		ctx,
+		sizeof(struct pwl_float_data) *
+		(DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points));
+	if (!opp110->regamma.rgb_user)
+		goto failure_1;
+
+	opp110->regamma.rgb_oem = dm_alloc(
+		ctx,
+		sizeof(struct pwl_float_data) *
+		(DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points));
+	if (!opp110->regamma.rgb_oem)
+		goto failure_2;
+
+	opp110->regamma.rgb_resulted = dm_alloc(
+		ctx,
+		sizeof(struct pwl_result_data) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.rgb_resulted)
+		goto failure_3;
+
+	opp110->regamma.rgb_regamma = dm_alloc(
+		ctx,
+		sizeof(struct pwl_float_data_ex) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.rgb_regamma)
+		goto failure_4;
+
+	opp110->regamma.coordinates_x = dm_alloc(
+		ctx,
+		sizeof(struct hw_x_point) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.coordinates_x)
+		goto failure_5;
+
+	opp110->regamma.axis_x_256 = dm_alloc(
+		ctx,
+		sizeof(struct gamma_pixel) *
+		(MAX_LUT_ENTRY + opp110->regamma.extra_points));
+	if (!opp110->regamma.axis_x_256)
+		goto failure_6;
+
+	opp110->regamma.axis_x_1025 = dm_alloc(
+		ctx,
+		sizeof(struct gamma_pixel) *
+		(DX_GAMMA_RAMP_MAX + opp110->regamma.extra_points));
+	if (!opp110->regamma.axis_x_1025)
+		goto failure_7;
+
+	opp110->regamma.coeff128 = dm_alloc(
+		ctx,
+		sizeof(struct pixel_gamma_point) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.coeff128)
+		goto failure_8;
+
+	opp110->regamma.coeff128_oem = dm_alloc(
+		ctx,
+		sizeof(struct pixel_gamma_point) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.coeff128_oem)
+		goto failure_9;
+
+	opp110->regamma.coeff128_dx = dm_alloc(
+		ctx,
+		sizeof(struct pixel_gamma_point) *
+		(MAX_NUMBER_OF_ENTRIES + opp110->regamma.extra_points));
+	if (!opp110->regamma.coeff128_dx)
+		goto failure_10;
+
+	/* init palette */
+	{
+		uint32_t i = 0;
+
+		do {
+			opp110->regamma.saved_palette[i].red = (uint8_t)i;
+			opp110->regamma.saved_palette[i].green = (uint8_t)i;
+			opp110->regamma.saved_palette[i].blue = (uint8_t)i;
+
+			++i;
+		} while (i != MAX_LUT_ENTRY);
+	}
+
+	build_evenly_distributed_points(
+		opp110->regamma.axis_x_256,
+		MAX_LUT_ENTRY,
+		opp110->regamma.x_max1,
+		opp110->regamma.divider1,
+		opp110->regamma.divider2,
+		opp110->regamma.divider3);
+
+	build_evenly_distributed_points(
+		opp110->regamma.axis_x_1025,
+		DX_GAMMA_RAMP_MAX,
+		opp110->regamma.x_max1,
+		opp110->regamma.divider1,
+		opp110->regamma.divider2,
+		opp110->regamma.divider3);
+
+	return true;
+
+failure_10:
+	dm_free(ctx, opp110->regamma.coeff128_oem);
+failure_9:
+	dm_free(ctx, opp110->regamma.coeff128);
+failure_8:
+	dm_free(ctx, opp110->regamma.axis_x_1025);
+failure_7:
+	dm_free(ctx, opp110->regamma.axis_x_256);
+failure_6:
+	dm_free(ctx, opp110->regamma.coordinates_x);
+failure_5:
+	dm_free(ctx, opp110->regamma.rgb_regamma);
+failure_4:
+	dm_free(ctx, opp110->regamma.rgb_resulted);
+failure_3:
+	dm_free(ctx, opp110->regamma.rgb_oem);
+failure_2:
+	dm_free(ctx, opp110->regamma.rgb_user);
+failure_1:
+
+	return true;
+}
+
+void dce110_opp_destroy(struct output_pixel_processor **opp)
+{
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_dx);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_oem);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_1025);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_256);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coordinates_x);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_regamma);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_resulted);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_oem);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_user);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp));
+	*opp = NULL;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
new file mode 100644
index 000000000000..e53eb7413948
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
@@ -0,0 +1,143 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_OPP_DCE110_H__
+#define __DC_OPP_DCE110_H__
+
+#include "dc_types.h"
+#include "inc/opp.h"
+#include "gamma_types.h"
+
+struct gamma_parameters;
+
+#define FROM_DCE11_OPP(opp)\
+	container_of(opp, struct dce110_opp, base)
+
+enum dce110_opp_reg_type {
+	DCE110_OPP_REG_DCP = 0,
+	DCE110_OPP_REG_DCFE,
+	DCE110_OPP_REG_FMT,
+
+	DCE110_OPP_REG_MAX
+};
+
+struct dce110_regamma {
+	struct gamma_curve arr_curve_points[16];
+	struct curve_points arr_points[3];
+	uint32_t hw_points_num;
+	struct hw_x_point *coordinates_x;
+	struct pwl_result_data *rgb_resulted;
+
+	/* re-gamma curve */
+	struct pwl_float_data_ex *rgb_regamma;
+	/* coeff used to map user evenly distributed points
+	 * to our hardware points (predefined) for gamma 256 */
+	struct pixel_gamma_point *coeff128;
+	struct pixel_gamma_point *coeff128_oem;
+	/* coeff used to map user evenly distributed points
+	 * to our hardware points (predefined) for gamma 1025 */
+	struct pixel_gamma_point *coeff128_dx;
+	/* evenly distributed points, gamma 256 software points 0-255 */
+	struct gamma_pixel *axis_x_256;
+	/* evenly distributed points, gamma 1025 software points 0-1025 */
+	struct gamma_pixel *axis_x_1025;
+	/* OEM supplied gamma for regamma LUT */
+	struct pwl_float_data *rgb_oem;
+	/* user supplied gamma */
+	struct pwl_float_data *rgb_user;
+	struct dev_c_lut saved_palette[RGB_256X3X16];
+	uint32_t extra_points;
+	bool use_half_points;
+	struct fixed31_32 x_max1;
+	struct fixed31_32 x_max2;
+	struct fixed31_32 x_min;
+	struct fixed31_32 divider1;
+	struct fixed31_32 divider2;
+	struct fixed31_32 divider3;
+};
+
+/* OPP RELATED */
+#define TO_DCE110_OPP(opp)\
+	container_of(opp, struct dce110_opp, base)
+
+struct dce110_opp_reg_offsets {
+	uint32_t fmt_offset;
+	uint32_t dcp_offset;
+	uint32_t dcfe_offset;
+};
+
+struct dce110_opp {
+	struct output_pixel_processor base;
+	struct dce110_opp_reg_offsets offsets;
+	struct dce110_regamma regamma;
+};
+
+bool dce110_opp_construct(struct dce110_opp *opp110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offsets);
+
+void dce110_opp_destroy(struct output_pixel_processor **opp);
+
+/* REGAMMA RELATED */
+void dce110_opp_power_on_regamma_lut(
+	struct output_pixel_processor *opp,
+	bool power_on);
+
+bool dce110_opp_set_regamma(
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *ramp,
+	const struct gamma_parameters *params,
+	bool force_bypass);
+
+bool dce110_opp_map_legacy_and_regamma_hw_to_x_user(
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params);
+
+void dce110_opp_set_csc_adjustment(
+	struct output_pixel_processor *opp,
+	const struct grph_csc_adjustment *adjust);
+
+void dce110_opp_set_csc_default(
+	struct output_pixel_processor *opp,
+	const struct default_adjustment *default_adjust);
+
+/* FORMATTER RELATED */
+void dce110_opp_program_bit_depth_reduction(
+	struct output_pixel_processor *opp,
+	const struct bit_depth_reduction_params *params);
+
+void dce110_opp_program_clamping_and_pixel_encoding(
+	struct output_pixel_processor *opp,
+	const struct clamping_and_pixel_encoding_params *params);
+
+
+void dce110_opp_set_dyn_expansion(
+	struct output_pixel_processor *opp,
+	enum color_space color_sp,
+	enum dc_color_depth color_dpth,
+	enum signal_type signal);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
new file mode 100644
index 000000000000..8f651e9329bc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
@@ -0,0 +1,904 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dce110_opp.h"
+#include "basics/conversion.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#define DCP_REG(reg)\
+	(reg + opp110->offsets.dcp_offset)
+
+enum {
+	OUTPUT_CSC_MATRIX_SIZE = 12
+};
+
+struct out_csc_color_matrix {
+	enum color_space color_space;
+	uint16_t regval[OUTPUT_CSC_MATRIX_SIZE];
+};
+
+static const struct out_csc_color_matrix global_color_matrix[] = {
+{ COLOR_SPACE_SRGB_FULL_RANGE,
+	{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
+{ COLOR_SPACE_SRGB_LIMITED_RANGE,
+	{ 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
+{ COLOR_SPACE_YCBCR601,
+	{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
+		0xF6B9, 0xE00, 0x1000} },
+{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
+	0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
+/*  YOnly same as YCbCr709 but Y in Full range -To do. */
+{ COLOR_SPACE_YCBCR601_YONLY, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
+	0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
+{ COLOR_SPACE_YCBCR709_YONLY, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
+	0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
+};
+
+enum csc_color_mode {
+	/* 00 - BITS2:0 Bypass */
+	CSC_COLOR_MODE_GRAPHICS_BYPASS,
+	/* 01 - hard coded coefficient TV RGB */
+	CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
+	/* 04 - programmable OUTPUT CSC coefficient */
+	CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
+};
+
+static void program_color_matrix(
+	struct dce110_opp *opp110,
+	const struct out_csc_color_matrix *tbl_entry,
+	enum grph_color_adjust_option options)
+{
+	struct dc_context *ctx = opp110->base.ctx;
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C11_C12);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[0],
+			OUTPUT_CSC_C11_C12,
+			OUTPUT_CSC_C11);
+
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[1],
+			OUTPUT_CSC_C11_C12,
+			OUTPUT_CSC_C12);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C13_C14);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[2],
+			OUTPUT_CSC_C13_C14,
+			OUTPUT_CSC_C13);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[3],
+			OUTPUT_CSC_C13_C14,
+			OUTPUT_CSC_C14);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C21_C22);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[4],
+			OUTPUT_CSC_C21_C22,
+			OUTPUT_CSC_C21);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[5],
+			OUTPUT_CSC_C21_C22,
+			OUTPUT_CSC_C22);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C23_C24);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[6],
+			OUTPUT_CSC_C23_C24,
+			OUTPUT_CSC_C23);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[7],
+			OUTPUT_CSC_C23_C24,
+			OUTPUT_CSC_C24);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C31_C32);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[8],
+			OUTPUT_CSC_C31_C32,
+			OUTPUT_CSC_C31);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[9],
+			OUTPUT_CSC_C31_C32,
+			OUTPUT_CSC_C32);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		uint32_t value = 0;
+		uint32_t addr = DCP_REG(mmOUTPUT_CSC_C33_C34);
+		/* fixed S2.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[10],
+			OUTPUT_CSC_C33_C34,
+			OUTPUT_CSC_C33);
+		/* fixed S0.13 format */
+		set_reg_field_value(
+			value,
+			tbl_entry->regval[11],
+			OUTPUT_CSC_C33_C34,
+			OUTPUT_CSC_C34);
+
+		dm_write_reg(ctx, addr, value);
+	}
+}
+
+/*
+ * initialize_color_float_adj_reference_values
+ * This initialize display color adjust input from API to HW range for later
+ * calculation use. This is shared by all the display color adjustment.
+ * @param :
+ * @return None
+ */
+static void initialize_color_float_adj_reference_values(
+	const struct grph_csc_adjustment *adjust,
+	struct fixed31_32 *grph_cont,
+	struct fixed31_32 *grph_sat,
+	struct fixed31_32 *grph_bright,
+	struct fixed31_32 *sin_grph_hue,
+	struct fixed31_32 *cos_grph_hue)
+{
+	/* Hue adjustment could be negative. -45 ~ +45 */
+	struct fixed31_32 hue =
+		dal_fixed31_32_mul(
+			dal_fixed31_32_from_fraction(adjust->grph_hue, 180),
+			dal_fixed31_32_pi);
+
+	*sin_grph_hue = dal_fixed31_32_sin(hue);
+	*cos_grph_hue = dal_fixed31_32_cos(hue);
+
+	if (adjust->adjust_divider) {
+		*grph_cont =
+			dal_fixed31_32_from_fraction(
+				adjust->grph_cont,
+				adjust->adjust_divider);
+		*grph_sat =
+			dal_fixed31_32_from_fraction(
+				adjust->grph_sat,
+				adjust->adjust_divider);
+		*grph_bright =
+			dal_fixed31_32_from_fraction(
+				adjust->grph_bright,
+				adjust->adjust_divider);
+	} else {
+		*grph_cont = dal_fixed31_32_from_int(adjust->grph_cont);
+		*grph_sat = dal_fixed31_32_from_int(adjust->grph_sat);
+		*grph_bright = dal_fixed31_32_from_int(adjust->grph_bright);
+	}
+}
+
+static inline struct fixed31_32 fixed31_32_clamp(
+	struct fixed31_32 value,
+	int32_t min_numerator,
+	int32_t max_numerator,
+	int32_t denominator)
+{
+	return dal_fixed31_32_clamp(
+		value,
+		dal_fixed31_32_from_fraction(
+			min_numerator,
+			denominator),
+		dal_fixed31_32_from_fraction(
+			max_numerator,
+			denominator));
+}
+
+static void setup_reg_format(
+	struct fixed31_32 *coefficients,
+	uint16_t *reg_values)
+{
+	enum {
+		LENGTH = 12,
+		DENOMINATOR = 10000
+	};
+
+	static const int32_t min_numerator[] = {
+		-3 * DENOMINATOR,
+		-DENOMINATOR
+	};
+
+	static const int32_t max_numerator[] = {
+		DENOMINATOR,
+		DENOMINATOR
+	};
+
+	static const uint8_t integer_bits[] = { 2, 0 };
+
+	uint32_t i = 0;
+
+	do {
+		const uint32_t index = (i % 4) == 3;
+
+		reg_values[i] = fixed_point_to_int_frac(
+			fixed31_32_clamp(coefficients[(i + 8) % LENGTH],
+				min_numerator[index],
+				max_numerator[index],
+				DENOMINATOR),
+			integer_bits[index], 13);
+
+		++i;
+	} while (i != LENGTH);
+}
+
+/**
+ *****************************************************************************
+ *  Function: setup_adjustments
+ *  @note prepare to setup the values
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void setup_adjustments(const struct grph_csc_adjustment *adjust,
+	struct dc_csc_adjustments *adjustments)
+{
+	if (adjust->adjust_divider != 0) {
+		adjustments->brightness =
+			dal_fixed31_32_from_fraction(adjust->grph_bright,
+			adjust->adjust_divider);
+		adjustments->contrast =
+			dal_fixed31_32_from_fraction(adjust->grph_cont,
+			adjust->adjust_divider);
+		adjustments->saturation =
+			dal_fixed31_32_from_fraction(adjust->grph_sat,
+			adjust->adjust_divider);
+	} else {
+		adjustments->brightness =
+			dal_fixed31_32_from_fraction(adjust->grph_bright, 1);
+		adjustments->contrast =
+			dal_fixed31_32_from_fraction(adjust->grph_cont, 1);
+		adjustments->saturation =
+			dal_fixed31_32_from_fraction(adjust->grph_sat, 1);
+	}
+
+	/* convert degrees into radians */
+	adjustments->hue =
+		dal_fixed31_32_mul(
+			dal_fixed31_32_from_fraction(adjust->grph_hue, 180),
+			dal_fixed31_32_pi);
+}
+
+static void prepare_tv_rgb_ideal(
+	struct fixed31_32 *matrix)
+{
+	static const int32_t matrix_[] = {
+		85546875, 0, 0, 6250000,
+		0, 85546875, 0, 6250000,
+		0, 0, 85546875, 6250000
+	};
+
+	uint32_t i = 0;
+
+	do {
+		matrix[i] = dal_fixed31_32_from_fraction(
+			matrix_[i],
+			100000000);
+		++i;
+	} while (i != ARRAY_SIZE(matrix_));
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_rgb_adjustment_legacy
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and program color adjustments for sRGB color space
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void set_rgb_adjustment_legacy(
+	struct dce110_opp *opp110,
+	const struct grph_csc_adjustment *adjust)
+{
+	const struct fixed31_32 k1 =
+		dal_fixed31_32_from_fraction(701000, 1000000);
+	const struct fixed31_32 k2 =
+		dal_fixed31_32_from_fraction(236568, 1000000);
+	const struct fixed31_32 k3 =
+		dal_fixed31_32_from_fraction(-587000, 1000000);
+	const struct fixed31_32 k4 =
+		dal_fixed31_32_from_fraction(464432, 1000000);
+	const struct fixed31_32 k5 =
+		dal_fixed31_32_from_fraction(-114000, 1000000);
+	const struct fixed31_32 k6 =
+		dal_fixed31_32_from_fraction(-701000, 1000000);
+	const struct fixed31_32 k7 =
+		dal_fixed31_32_from_fraction(-299000, 1000000);
+	const struct fixed31_32 k8 =
+		dal_fixed31_32_from_fraction(-292569, 1000000);
+	const struct fixed31_32 k9 =
+		dal_fixed31_32_from_fraction(413000, 1000000);
+	const struct fixed31_32 k10 =
+		dal_fixed31_32_from_fraction(-92482, 1000000);
+	const struct fixed31_32 k11 =
+		dal_fixed31_32_from_fraction(-114000, 1000000);
+	const struct fixed31_32 k12 =
+		dal_fixed31_32_from_fraction(385051, 1000000);
+	const struct fixed31_32 k13 =
+		dal_fixed31_32_from_fraction(-299000, 1000000);
+	const struct fixed31_32 k14 =
+		dal_fixed31_32_from_fraction(886000, 1000000);
+	const struct fixed31_32 k15 =
+		dal_fixed31_32_from_fraction(-587000, 1000000);
+	const struct fixed31_32 k16 =
+		dal_fixed31_32_from_fraction(-741914, 1000000);
+	const struct fixed31_32 k17 =
+		dal_fixed31_32_from_fraction(886000, 1000000);
+	const struct fixed31_32 k18 =
+		dal_fixed31_32_from_fraction(-144086, 1000000);
+
+	const struct fixed31_32 luma_r =
+		dal_fixed31_32_from_fraction(299, 1000);
+	const struct fixed31_32 luma_g =
+		dal_fixed31_32_from_fraction(587, 1000);
+	const struct fixed31_32 luma_b =
+		dal_fixed31_32_from_fraction(114, 1000);
+
+	struct out_csc_color_matrix tbl_entry;
+	struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE];
+
+	struct fixed31_32 grph_cont;
+	struct fixed31_32 grph_sat;
+	struct fixed31_32 grph_bright;
+	struct fixed31_32 sin_grph_hue;
+	struct fixed31_32 cos_grph_hue;
+
+	initialize_color_float_adj_reference_values(
+		adjust, &grph_cont, &grph_sat,
+		&grph_bright, &sin_grph_hue, &cos_grph_hue);
+
+	/* COEF_1_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 +
+	 * Sin(GrphHue) * K2)) */
+	/* (Cos(GrphHue) * K1 + Sin(GrphHue) * K2) */
+	matrix[0] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k1),
+			dal_fixed31_32_mul(sin_grph_hue, k2));
+	/* GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2 */
+	matrix[0] = dal_fixed31_32_mul(grph_sat, matrix[0]);
+	/* (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) * K2)) */
+	matrix[0] = dal_fixed31_32_add(luma_r, matrix[0]);
+	/* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K1 + Sin(GrphHue) *
+	 * K2)) */
+	matrix[0] = dal_fixed31_32_mul(grph_cont, matrix[0]);
+
+	/* COEF_1_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 +
+	 * Sin(GrphHue) * K4)) */
+	/* (Cos(GrphHue) * K3 + Sin(GrphHue) * K4) */
+	matrix[1] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k3),
+			dal_fixed31_32_mul(sin_grph_hue, k4));
+	/* GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4) */
+	matrix[1] = dal_fixed31_32_mul(grph_sat, matrix[1]);
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) * K4)) */
+	matrix[1] = dal_fixed31_32_add(luma_g, matrix[1]);
+	/* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K3 + Sin(GrphHue) *
+	 * K4)) */
+	matrix[1] = dal_fixed31_32_mul(grph_cont, matrix[1]);
+
+	/* COEF_1_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K5 +
+	 * Sin(GrphHue) * K6)) */
+	/* (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */
+	matrix[2] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k5),
+			dal_fixed31_32_mul(sin_grph_hue, k6));
+	/* GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */
+	matrix[2] = dal_fixed31_32_mul(grph_sat, matrix[2]);
+	/* LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) * K6) */
+	matrix[2] = dal_fixed31_32_add(luma_b, matrix[2]);
+	/* GrphCont  * (LumaB + GrphSat * (Cos(GrphHue) * K5 + Sin(GrphHue) *
+	 * K6)) */
+	matrix[2] = dal_fixed31_32_mul(grph_cont, matrix[2]);
+
+	/* COEF_1_4 = GrphBright */
+	matrix[3] = grph_bright;
+
+	/* COEF_2_1 = GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 +
+	 * Sin(GrphHue) * K8)) */
+	/* (Cos(GrphHue) * K7 + Sin(GrphHue) * K8) */
+	matrix[4] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k7),
+			dal_fixed31_32_mul(sin_grph_hue, k8));
+	/* GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8) */
+	matrix[4] = dal_fixed31_32_mul(grph_sat, matrix[4]);
+	/* (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) * K8)) */
+	matrix[4] = dal_fixed31_32_add(luma_r, matrix[4]);
+	/* GrphCont * (LumaR + GrphSat * (Cos(GrphHue) * K7 + Sin(GrphHue) *
+	 * K8)) */
+	matrix[4] = dal_fixed31_32_mul(grph_cont, matrix[4]);
+
+	/* COEF_2_2 = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 +
+	 * Sin(GrphHue) * K10)) */
+	/* (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */
+	matrix[5] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k9),
+			dal_fixed31_32_mul(sin_grph_hue, k10));
+	/* GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */
+	matrix[5] = dal_fixed31_32_mul(grph_sat, matrix[5]);
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) * K10)) */
+	matrix[5] = dal_fixed31_32_add(luma_g, matrix[5]);
+	/* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K9 + Sin(GrphHue) *
+	 * K10)) */
+	matrix[5] = dal_fixed31_32_mul(grph_cont, matrix[5]);
+
+	/*  COEF_2_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 +
+	 * Sin(GrphHue) * K12)) */
+	/* (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */
+	matrix[6] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k11),
+			dal_fixed31_32_mul(sin_grph_hue, k12));
+	/* GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */
+	matrix[6] = dal_fixed31_32_mul(grph_sat, matrix[6]);
+	/*  (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) * K12)) */
+	matrix[6] = dal_fixed31_32_add(luma_b, matrix[6]);
+	/* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K11 + Sin(GrphHue) *
+	 * K12)) */
+	matrix[6] = dal_fixed31_32_mul(grph_cont, matrix[6]);
+
+	/* COEF_2_4 = GrphBright */
+	matrix[7] = grph_bright;
+
+	/* COEF_3_1 = GrphCont  * (LumaR + GrphSat * (Cos(GrphHue) * K13 +
+	 * Sin(GrphHue) * K14)) */
+	/* (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
+	matrix[8] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k13),
+			dal_fixed31_32_mul(sin_grph_hue, k14));
+	/* GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
+	matrix[8] = dal_fixed31_32_mul(grph_sat, matrix[8]);
+	/* (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) * K14)) */
+	matrix[8] = dal_fixed31_32_add(luma_r, matrix[8]);
+	/* GrphCont  * (LumaR + GrphSat * (Cos(GrphHue) * K13 + Sin(GrphHue) *
+	 * K14)) */
+	matrix[8] = dal_fixed31_32_mul(grph_cont, matrix[8]);
+
+	/* COEF_3_2    = GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 +
+	 * Sin(GrphHue) * K16)) */
+	/* GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16) */
+	matrix[9] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k15),
+			dal_fixed31_32_mul(sin_grph_hue, k16));
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */
+	matrix[9] = dal_fixed31_32_mul(grph_sat, matrix[9]);
+	/* (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) * K16)) */
+	matrix[9] = dal_fixed31_32_add(luma_g, matrix[9]);
+	 /* GrphCont * (LumaG + GrphSat * (Cos(GrphHue) * K15 + Sin(GrphHue) *
+	  * K16)) */
+	matrix[9] = dal_fixed31_32_mul(grph_cont, matrix[9]);
+
+	/*  COEF_3_3 = GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 +
+	 * Sin(GrphHue) * K18)) */
+	/* (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
+	matrix[10] =
+		dal_fixed31_32_add(
+			dal_fixed31_32_mul(cos_grph_hue, k17),
+			dal_fixed31_32_mul(sin_grph_hue, k18));
+	/*  GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
+	matrix[10] = dal_fixed31_32_mul(grph_sat, matrix[10]);
+	/* (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) * K18)) */
+	matrix[10] = dal_fixed31_32_add(luma_b, matrix[10]);
+	 /* GrphCont * (LumaB + GrphSat * (Cos(GrphHue) * K17 + Sin(GrphHue) *
+	  * K18)) */
+	matrix[10] = dal_fixed31_32_mul(grph_cont, matrix[10]);
+
+	/*  COEF_3_4    = GrphBright */
+	matrix[11] = grph_bright;
+
+	tbl_entry.color_space = adjust->c_space;
+
+	convert_float_matrix(tbl_entry.regval, matrix, OUTPUT_CSC_MATRIX_SIZE);
+
+	program_color_matrix(
+		opp110, &tbl_entry, adjust->color_adjust_option);
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_rgb_limited_range_adjustment
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and program color adjustments for sRGB limited color space
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void set_rgb_limited_range_adjustment(
+	struct dce110_opp *opp110,
+	const struct grph_csc_adjustment *adjust)
+{
+	struct out_csc_color_matrix reg_matrix;
+	struct fixed31_32 change_matrix[OUTPUT_CSC_MATRIX_SIZE];
+	struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE];
+	struct dc_csc_adjustments adjustments;
+	struct fixed31_32 ideals[OUTPUT_CSC_MATRIX_SIZE];
+
+	prepare_tv_rgb_ideal(ideals);
+
+	setup_adjustments(adjust, &adjustments);
+
+	calculate_adjustments(ideals, &adjustments, matrix);
+
+	dm_memmove(change_matrix, matrix, sizeof(matrix));
+
+	/* from 1 -> 3 */
+	matrix[8] = change_matrix[0];
+	matrix[9] = change_matrix[1];
+	matrix[10] = change_matrix[2];
+	matrix[11] = change_matrix[3];
+
+	/* from 2 -> 1 */
+	matrix[0] = change_matrix[4];
+	matrix[1] = change_matrix[5];
+	matrix[2] = change_matrix[6];
+	matrix[3] = change_matrix[7];
+
+	/* from 3 -> 2 */
+	matrix[4] = change_matrix[8];
+	matrix[5] = change_matrix[9];
+	matrix[6] = change_matrix[10];
+	matrix[7] = change_matrix[11];
+
+	dm_memset(&reg_matrix, 0, sizeof(struct out_csc_color_matrix));
+
+	setup_reg_format(matrix, reg_matrix.regval);
+
+	program_color_matrix(opp110, &reg_matrix, GRPH_COLOR_MATRIX_SW);
+}
+
+static void prepare_yuv_ideal(
+	bool b601,
+	struct fixed31_32 *matrix)
+{
+	static const int32_t matrix_1[] = {
+		25578516, 50216016, 9752344, 6250000,
+		-14764391, -28985609, 43750000, 50000000,
+		43750000, -36635164, -7114836, 50000000
+	};
+
+	static const int32_t matrix_2[] = {
+		18187266, 61183125, 6176484, 6250000,
+		-10025059, -33724941, 43750000, 50000000,
+		43750000, -39738379, -4011621, 50000000
+	};
+
+	const int32_t *matrix_x = b601 ? matrix_1 : matrix_2;
+
+	uint32_t i = 0;
+
+	do {
+		matrix[i] = dal_fixed31_32_from_fraction(
+			matrix_x[i],
+			100000000);
+		++i;
+	} while (i != ARRAY_SIZE(matrix_1));
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_yuv_adjustment
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and program color adjustments for YUV  color spaces
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void set_yuv_adjustment(
+	struct dce110_opp *opp110,
+	const struct grph_csc_adjustment *adjust)
+{
+	bool b601 = (adjust->c_space == COLOR_SPACE_YPBPR601) ||
+		(adjust->c_space == COLOR_SPACE_YCBCR601) ||
+		(adjust->c_space == COLOR_SPACE_YCBCR601_YONLY);
+	struct out_csc_color_matrix reg_matrix;
+	struct fixed31_32 matrix[OUTPUT_CSC_MATRIX_SIZE];
+	struct dc_csc_adjustments adjustments;
+	struct fixed31_32 ideals[OUTPUT_CSC_MATRIX_SIZE];
+
+	prepare_yuv_ideal(b601, ideals);
+
+	setup_adjustments(adjust, &adjustments);
+
+	if ((adjust->c_space == COLOR_SPACE_YCBCR601_YONLY) ||
+		(adjust->c_space == COLOR_SPACE_YCBCR709_YONLY))
+		calculate_adjustments_y_only(
+			ideals, &adjustments, matrix);
+	else
+		calculate_adjustments(
+			ideals, &adjustments, matrix);
+
+	dm_memset(&reg_matrix, 0, sizeof(struct out_csc_color_matrix));
+
+	setup_reg_format(matrix, reg_matrix.regval);
+
+	program_color_matrix(opp110, &reg_matrix, GRPH_COLOR_MATRIX_SW);
+}
+
+static bool configure_graphics_mode(
+	struct dce110_opp *opp110,
+	enum csc_color_mode config,
+	enum graphics_csc_adjust_type csc_adjust_type,
+	enum color_space color_space)
+{
+	struct dc_context *ctx = opp110->base.ctx;
+	uint32_t addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		OUTPUT_CSC_CONTROL,
+		OUTPUT_CSC_GRPH_MODE);
+
+	if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
+		if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
+			set_reg_field_value(
+				value,
+				4,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+		} else {
+
+			switch (color_space) {
+			case COLOR_SPACE_SRGB_FULL_RANGE:
+				/* by pass */
+				set_reg_field_value(
+					value,
+					0,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			case COLOR_SPACE_SRGB_LIMITED_RANGE:
+				/* TV RGB */
+				set_reg_field_value(
+					value,
+					1,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			case COLOR_SPACE_YCBCR601:
+			case COLOR_SPACE_YPBPR601:
+			case COLOR_SPACE_YCBCR601_YONLY:
+				/* YCbCr601 */
+				set_reg_field_value(
+					value,
+					2,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			case COLOR_SPACE_YCBCR709:
+			case COLOR_SPACE_YPBPR709:
+			case COLOR_SPACE_YCBCR709_YONLY:
+				/* YCbCr709 */
+				set_reg_field_value(
+					value,
+					3,
+					OUTPUT_CSC_CONTROL,
+					OUTPUT_CSC_GRPH_MODE);
+				break;
+			default:
+				return false;
+			}
+		}
+	} else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
+		switch (color_space) {
+		case COLOR_SPACE_SRGB_FULL_RANGE:
+			/* by pass */
+			set_reg_field_value(
+				value,
+				0,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		case COLOR_SPACE_SRGB_LIMITED_RANGE:
+			/* TV RGB */
+			set_reg_field_value(
+				value,
+				1,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		case COLOR_SPACE_YCBCR601:
+		case COLOR_SPACE_YPBPR601:
+		case COLOR_SPACE_YCBCR601_YONLY:
+			/* YCbCr601 */
+			set_reg_field_value(
+				value,
+				2,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		case COLOR_SPACE_YCBCR709:
+		case COLOR_SPACE_YPBPR709:
+		case COLOR_SPACE_YCBCR709_YONLY:
+			 /* YCbCr709 */
+			set_reg_field_value(
+				value,
+				3,
+				OUTPUT_CSC_CONTROL,
+				OUTPUT_CSC_GRPH_MODE);
+			break;
+		default:
+			return false;
+		}
+
+	} else
+		/* by pass */
+		set_reg_field_value(
+			value,
+			0,
+			OUTPUT_CSC_CONTROL,
+			OUTPUT_CSC_GRPH_MODE);
+
+	addr = DCP_REG(mmOUTPUT_CSC_CONTROL);
+	dm_write_reg(ctx, addr, value);
+
+	return true;
+}
+
+void dce110_opp_set_csc_adjustment(
+	struct output_pixel_processor *opp,
+	const struct grph_csc_adjustment *adjust)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+	enum csc_color_mode config =
+			CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
+
+	/* Apply color adjustments: brightness, saturation, hue, contrast and
+	 * CSC. No need for different color space routine, color space defines
+	 * the ideal values only, but keep original design to allow quick switch
+	 * to the old legacy routines */
+	switch (adjust->c_space) {
+	case COLOR_SPACE_SRGB_FULL_RANGE:
+		set_rgb_adjustment_legacy(opp110, adjust);
+		break;
+	case COLOR_SPACE_SRGB_LIMITED_RANGE:
+		set_rgb_limited_range_adjustment(
+			opp110, adjust);
+		break;
+	case COLOR_SPACE_YCBCR601:
+	case COLOR_SPACE_YCBCR709:
+	case COLOR_SPACE_YCBCR601_YONLY:
+	case COLOR_SPACE_YCBCR709_YONLY:
+	case COLOR_SPACE_YPBPR601:
+	case COLOR_SPACE_YPBPR709:
+		set_yuv_adjustment(opp110, adjust);
+		break;
+	default:
+		set_rgb_adjustment_legacy(opp110, adjust);
+		break;
+	}
+
+	/*  We did everything ,now program DxOUTPUT_CSC_CONTROL */
+	configure_graphics_mode(opp110, config, adjust->csc_adjust_type,
+		adjust->c_space);
+}
+
+void dce110_opp_set_csc_default(
+	struct output_pixel_processor *opp,
+	const struct default_adjustment *default_adjust)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+	enum csc_color_mode config =
+			CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
+
+	if (default_adjust->force_hw_default == false) {
+		const struct out_csc_color_matrix *elm;
+		/* currently parameter not in use */
+		enum grph_color_adjust_option option =
+			GRPH_COLOR_MATRIX_HW_DEFAULT;
+		uint32_t i;
+		/*
+		 * HW default false we program locally defined matrix
+		 * HW default true  we use predefined hw matrix and we
+		 * do not need to program matrix
+		 * OEM wants the HW default via runtime parameter.
+		 */
+		option = GRPH_COLOR_MATRIX_SW;
+
+		for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
+			elm = &global_color_matrix[i];
+			if (elm->color_space != default_adjust->color_space)
+				continue;
+			/* program the matrix with default values from this
+			 * file */
+			program_color_matrix(opp110, elm, option);
+			config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
+			break;
+		}
+	}
+
+	/* configure the what we programmed :
+	 * 1. Default values from this file
+	 * 2. Use hardware default from ROM_A and we do not need to program
+	 * matrix */
+
+	configure_graphics_mode(opp110, config,
+		default_adjust->csc_adjust_type,
+		default_adjust->color_space);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
new file mode 100644
index 000000000000..235b92e3af61
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
@@ -0,0 +1,610 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_opp.h"
+
+#define FMT_REG(reg)\
+	(reg + opp110->offsets.fmt_offset)
+
+/**
+ *	set_truncation
+ *	1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
+ *	2) enable truncation
+ *	3) HW remove 12bit FMT support for DCE11 power saving reason.
+ */
+static void set_truncation(
+		struct dce110_opp *opp110,
+		const struct bit_depth_reduction_params *params)
+{
+	uint32_t value = 0;
+	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+
+	/*Disable truncation*/
+	value = dm_read_reg(opp110->base.ctx, addr);
+	set_reg_field_value(value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
+	set_reg_field_value(value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
+	set_reg_field_value(value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+	/* no 10bpc trunc on DCE11*/
+	if (params->flags.TRUNCATE_ENABLED == 0 ||
+		params->flags.TRUNCATE_DEPTH == 2)
+		return;
+
+	/*Set truncation depth and Enable truncation*/
+	set_reg_field_value(value, 1,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN);
+	set_reg_field_value(value, params->flags.TRUNCATE_MODE,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE);
+	set_reg_field_value(value, params->flags.TRUNCATE_DEPTH,
+		FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH);
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+}
+
+/**
+ *	set_spatial_dither
+ *	1) set spatial dithering mode: pattern of seed
+ *	2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp
+ *	3) set random seed
+ *	4) set random mode
+ *		lfsr is reset every frame or not reset
+ *		RGB dithering method
+ *		0: RGB data are all dithered with x^28+x^3+1
+ *		1: R data is dithered with x^28+x^3+1
+ *		G data is dithered with x^28+X^9+1
+ *		B data is dithered with x^28+x^13+1
+ *		enable high pass filter or not
+ *	5) enable spatical dithering
+ */
+static void set_spatial_dither(
+	struct dce110_opp *opp110,
+	const struct bit_depth_reduction_params *params)
+{
+	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	uint32_t depth_cntl_value = 0;
+	uint32_t fmt_cntl_value = 0;
+	uint32_t dither_r_value = 0;
+	uint32_t dither_g_value = 0;
+	uint32_t dither_b_value = 0;
+
+	/*Disable spatial (random) dithering*/
+	depth_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE);
+	set_reg_field_value(depth_cntl_value, 0,
+		FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE);
+
+	dm_write_reg(opp110->base.ctx, addr, depth_cntl_value);
+
+	/* no 10bpc on DCE11*/
+	if (params->flags.SPATIAL_DITHER_ENABLED == 0 ||
+		params->flags.SPATIAL_DITHER_DEPTH == 2)
+		return;
+
+	addr = FMT_REG(mmFMT_CONTROL);
+	fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+	/* only use FRAME_COUNTER_MAX if frameRandom == 1*/
+	if (params->flags.FRAME_RANDOM == 1) {
+		if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
+		params->flags.SPATIAL_DITHER_DEPTH == 1) {
+			set_reg_field_value(fmt_cntl_value, 15,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
+			set_reg_field_value(fmt_cntl_value, 2,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
+		} else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
+			set_reg_field_value(fmt_cntl_value, 3,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
+			set_reg_field_value(fmt_cntl_value, 1,
+				FMT_CONTROL,
+				FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
+		} else
+			return;
+	} else {
+		set_reg_field_value(fmt_cntl_value, 0,
+			FMT_CONTROL,
+			FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX);
+		set_reg_field_value(fmt_cntl_value, 0,
+			FMT_CONTROL,
+			FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP);
+	}
+
+	dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
+
+	/*Set seed for random values for
+	 * spatial dithering for R,G,B channels*/
+	addr = FMT_REG(mmFMT_DITHER_RAND_R_SEED);
+	set_reg_field_value(dither_r_value, params->r_seed_value,
+		FMT_DITHER_RAND_R_SEED,
+		FMT_RAND_R_SEED);
+	dm_write_reg(opp110->base.ctx, addr, dither_r_value);
+
+	addr = FMT_REG(mmFMT_DITHER_RAND_G_SEED);
+	set_reg_field_value(dither_g_value,
+		params->g_seed_value,
+		FMT_DITHER_RAND_G_SEED,
+		FMT_RAND_G_SEED);
+	dm_write_reg(opp110->base.ctx, addr, dither_g_value);
+
+	addr = FMT_REG(mmFMT_DITHER_RAND_B_SEED);
+	set_reg_field_value(dither_b_value, params->b_seed_value,
+		FMT_DITHER_RAND_B_SEED,
+		FMT_RAND_B_SEED);
+	dm_write_reg(opp110->base.ctx, addr, dither_b_value);
+
+	/* FMT_OFFSET_R_Cr  31:16 0x0 Setting the zero
+	 * offset for the R/Cr channel, lower 4LSB
+	 * is forced to zeros. Typically set to 0
+	 * RGB and 0x80000 YCbCr.
+	 */
+	/* FMT_OFFSET_G_Y   31:16 0x0 Setting the zero
+	 * offset for the G/Y  channel, lower 4LSB is
+	 * forced to zeros. Typically set to 0 RGB
+	 * and 0x80000 YCbCr.
+	 */
+	/* FMT_OFFSET_B_Cb  31:16 0x0 Setting the zero
+	 * offset for the B/Cb channel, lower 4LSB is
+	 * forced to zeros. Typically set to 0 RGB and
+	 * 0x80000 YCbCr.
+	 */
+
+	/*Set spatial dithering bit depth*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.SPATIAL_DITHER_DEPTH,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_SPATIAL_DITHER_DEPTH);
+
+	/* Set spatial dithering mode
+	 * (default is Seed patterrn AAAA...)
+	 */
+	set_reg_field_value(depth_cntl_value,
+		params->flags.SPATIAL_DITHER_MODE,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_SPATIAL_DITHER_MODE);
+
+	/*Reset only at startup*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.FRAME_RANDOM,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_RGB_RANDOM_ENABLE);
+
+	/*Set RGB data dithered with x^28+x^3+1*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.RGB_RANDOM,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_RGB_RANDOM_ENABLE);
+
+	/*Disable High pass filter*/
+	set_reg_field_value(depth_cntl_value,
+		params->flags.HIGHPASS_RANDOM,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_HIGHPASS_RANDOM_ENABLE);
+
+	/*Enable spatial dithering*/
+	set_reg_field_value(depth_cntl_value,
+		1,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_SPATIAL_DITHER_EN);
+
+	addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	dm_write_reg(opp110->base.ctx, addr, depth_cntl_value);
+
+}
+
+/**
+ *	SetTemporalDither (Frame Modulation)
+ *	1) set temporal dither depth
+ *	2) select pattern: from hard-coded pattern or programmable pattern
+ *	3) select optimized strips for BGR or RGB LCD sub-pixel
+ *	4) set s matrix
+ *	5) set t matrix
+ *	6) set grey level for 0.25, 0.5, 0.75
+ *	7) enable temporal dithering
+ */
+static void set_temporal_dither(
+	struct dce110_opp *opp110,
+	const struct bit_depth_reduction_params *params)
+{
+	uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	uint32_t value;
+
+	/*Disable temporal (frame modulation) dithering first*/
+	value = dm_read_reg(opp110->base.ctx, addr);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_EN);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_RESET);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_OFFSET);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_DEPTH);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_LEVEL);
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_25FRC_SEL);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_50FRC_SEL);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_75FRC_SEL);
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+	/* no 10bpc dither on DCE11*/
+	if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
+		params->flags.FRAME_MODULATION_DEPTH == 2)
+		return;
+
+	/* Set temporal dithering depth*/
+	set_reg_field_value(value,
+		params->flags.FRAME_MODULATION_DEPTH,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_DEPTH);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_RESET);
+
+	set_reg_field_value(value,
+		0,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_OFFSET);
+
+	/*Select legacy pattern based on FRC and Temporal level*/
+	addr = FMT_REG(mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL);
+	dm_write_reg(opp110->base.ctx, addr, 0);
+	/*Set s matrix*/
+	addr = FMT_REG(
+		mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX);
+	dm_write_reg(opp110->base.ctx, addr, 0);
+	/*Set t matrix*/
+	addr = FMT_REG(
+		mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX);
+	dm_write_reg(opp110->base.ctx, addr, 0);
+
+	/*Select patterns for 0.25, 0.5 and 0.75 grey level*/
+	set_reg_field_value(value,
+		params->flags.TEMPORAL_LEVEL,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_LEVEL);
+
+	set_reg_field_value(value,
+		params->flags.FRC25,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_25FRC_SEL);
+
+	set_reg_field_value(value,
+		params->flags.FRC50,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_50FRC_SEL);
+
+	set_reg_field_value(value,
+		params->flags.FRC75,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_75FRC_SEL);
+
+	/*Enable bit reduction by temporal (frame modulation) dithering*/
+	set_reg_field_value(value,
+		1,
+		FMT_BIT_DEPTH_CONTROL,
+		FMT_TEMPORAL_DITHER_EN);
+
+	addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL);
+	dm_write_reg(opp110->base.ctx, addr, value);
+
+}
+
+/**
+ *	Set Clamping
+ *	1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
+ *		1 for 8 bpc
+ *		2 for 10 bpc
+ *		3 for 12 bpc
+ *		7 for programable
+ *	2) Enable clamp if Limited range requested
+ */
+static void set_clamping(
+	struct dce110_opp *opp110,
+	const struct clamping_and_pixel_encoding_params *params)
+{
+	uint32_t clamp_cntl_value = 0;
+	uint32_t red_clamp_value = 0;
+	uint32_t green_clamp_value = 0;
+	uint32_t blue_clamp_value = 0;
+	uint32_t addr = FMT_REG(mmFMT_CLAMP_CNTL);
+
+	clamp_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+
+	set_reg_field_value(clamp_cntl_value,
+		0,
+		FMT_CLAMP_CNTL,
+		FMT_CLAMP_DATA_EN);
+
+	set_reg_field_value(clamp_cntl_value,
+		0,
+		FMT_CLAMP_CNTL,
+		FMT_CLAMP_COLOR_FORMAT);
+
+	switch (params->clamping_level) {
+	case CLAMPING_FULL_RANGE:
+		break;
+
+	case CLAMPING_LIMITED_RANGE_8BPC:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		break;
+
+	case CLAMPING_LIMITED_RANGE_10BPC:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			2,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		break;
+	case CLAMPING_LIMITED_RANGE_12BPC:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			3,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		break;
+	case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
+		set_reg_field_value(clamp_cntl_value,
+			1,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_DATA_EN);
+
+		set_reg_field_value(clamp_cntl_value,
+			7,
+			FMT_CLAMP_CNTL,
+			FMT_CLAMP_COLOR_FORMAT);
+
+		/*set the defaults*/
+		set_reg_field_value(red_clamp_value,
+			0x10,
+			FMT_CLAMP_COMPONENT_R,
+			FMT_CLAMP_LOWER_R);
+
+		set_reg_field_value(red_clamp_value,
+			0xFEF,
+			FMT_CLAMP_COMPONENT_R,
+			FMT_CLAMP_UPPER_R);
+
+		addr = FMT_REG(mmFMT_CLAMP_COMPONENT_R);
+		dm_write_reg(opp110->base.ctx, addr, red_clamp_value);
+
+		set_reg_field_value(green_clamp_value,
+			0x10,
+			FMT_CLAMP_COMPONENT_G,
+			FMT_CLAMP_LOWER_G);
+
+		set_reg_field_value(green_clamp_value,
+			0xFEF,
+			FMT_CLAMP_COMPONENT_G,
+			FMT_CLAMP_UPPER_G);
+
+		addr = FMT_REG(mmFMT_CLAMP_COMPONENT_G);
+		dm_write_reg(opp110->base.ctx, addr, green_clamp_value);
+
+		set_reg_field_value(blue_clamp_value,
+			0x10,
+			FMT_CLAMP_COMPONENT_B,
+			FMT_CLAMP_LOWER_B);
+
+		set_reg_field_value(blue_clamp_value,
+			0xFEF,
+			FMT_CLAMP_COMPONENT_B,
+			FMT_CLAMP_UPPER_B);
+
+		addr = FMT_REG(mmFMT_CLAMP_COMPONENT_B);
+		dm_write_reg(opp110->base.ctx, addr, blue_clamp_value);
+
+		break;
+
+	default:
+		break;
+	}
+
+	addr = FMT_REG(mmFMT_CLAMP_CNTL);
+	/*Set clamp control*/
+	dm_write_reg(opp110->base.ctx, addr, clamp_cntl_value);
+
+}
+
+/**
+ *	set_pixel_encoding
+ *
+ *	Set Pixel Encoding
+ *		0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
+ *		1: YCbCr 4:2:2
+ */
+static void set_pixel_encoding(
+	struct dce110_opp *opp110,
+	const struct clamping_and_pixel_encoding_params *params)
+{
+	uint32_t fmt_cntl_value;
+	uint32_t addr = FMT_REG(mmFMT_CONTROL);
+
+	/*RGB 4:4:4 or YCbCr 4:4:4 - 0; YCbCr 4:2:2 -1.*/
+	fmt_cntl_value = dm_read_reg(opp110->base.ctx, addr);
+
+	set_reg_field_value(fmt_cntl_value,
+		0,
+		FMT_CONTROL,
+		FMT_PIXEL_ENCODING);
+
+	if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+		set_reg_field_value(fmt_cntl_value,
+			1,
+			FMT_CONTROL,
+			FMT_PIXEL_ENCODING);
+
+		/*00 - Pixels drop mode ,01 - Pixels average mode*/
+		set_reg_field_value(fmt_cntl_value,
+			0,
+			FMT_CONTROL,
+			FMT_SUBSAMPLING_MODE);
+
+		/*00 - Cb before Cr ,01 - Cr before Cb*/
+		set_reg_field_value(fmt_cntl_value,
+			0,
+			FMT_CONTROL,
+			FMT_SUBSAMPLING_ORDER);
+	}
+	dm_write_reg(opp110->base.ctx, addr, fmt_cntl_value);
+
+}
+
+void dce110_opp_program_bit_depth_reduction(
+	struct output_pixel_processor *opp,
+	const struct bit_depth_reduction_params *params)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	set_truncation(opp110, params);
+	set_spatial_dither(opp110, params);
+	set_temporal_dither(opp110, params);
+}
+
+void dce110_opp_program_clamping_and_pixel_encoding(
+	struct output_pixel_processor *opp,
+	const struct clamping_and_pixel_encoding_params *params)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	set_clamping(opp110, params);
+	set_pixel_encoding(opp110, params);
+}
+
+void dce110_opp_set_dyn_expansion(
+	struct output_pixel_processor *opp,
+	enum color_space color_sp,
+	enum dc_color_depth color_dpth,
+	enum signal_type signal)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+	uint32_t value;
+	bool enable_dyn_exp = false;
+	uint32_t addr = FMT_REG(mmFMT_DYNAMIC_EXP_CNTL);
+
+	value = dm_read_reg(opp->ctx, addr);
+
+	set_reg_field_value(value, 0,
+		FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
+	set_reg_field_value(value, 0,
+		FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
+
+	/* From HW programming guide:
+		FMT_DYNAMIC_EXP_EN = 0 for limited RGB or YCbCr output
+		FMT_DYNAMIC_EXP_EN = 1 for RGB full range only*/
+	if (color_sp == COLOR_SPACE_SRGB_FULL_RANGE)
+		enable_dyn_exp = true;
+
+	/*00 - 10-bit -> 12-bit dynamic expansion*/
+	/*01 - 8-bit  -> 12-bit dynamic expansion*/
+	if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+		switch (color_dpth) {
+		case COLOR_DEPTH_888:
+			set_reg_field_value(value, enable_dyn_exp ? 1:0,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
+			set_reg_field_value(value, 1,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
+			break;
+		case COLOR_DEPTH_101010:
+			set_reg_field_value(value, enable_dyn_exp ? 1:0,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN);
+			set_reg_field_value(value, 0,
+				FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE);
+			break;
+		case COLOR_DEPTH_121212:
+			break;
+		default:
+			break;
+		}
+	}
+
+	dm_write_reg(opp->ctx, addr, value);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
new file mode 100644
index 000000000000..32cf57dd80d2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
@@ -0,0 +1,2474 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_opp.h"
+#include "gamma_types.h"
+
+#define DCP_REG(reg)\
+	(reg + opp110->offsets.dcp_offset)
+
+#define DCFE_REG(reg)\
+	(reg + opp110->offsets.dcfe_offset)
+
+enum {
+	MAX_PWL_ENTRY = 128,
+	MAX_REGIONS_NUMBER = 16
+
+};
+
+struct curve_config {
+	uint32_t offset;
+	int8_t segments[MAX_REGIONS_NUMBER];
+	int8_t begin;
+};
+
+/* BASE */
+static bool find_software_points(
+	struct dce110_opp *opp110,
+	struct fixed31_32 hw_point,
+	enum channel_name channel,
+	uint32_t *index_to_start,
+	uint32_t *index_left,
+	uint32_t *index_right,
+	enum hw_point_position *pos)
+{
+	const uint32_t max_number =
+			RGB_256X3X16 + opp110->regamma.extra_points;
+
+	struct fixed31_32 left, right;
+
+	uint32_t i = *index_to_start;
+
+	while (i < max_number) {
+		if (channel == CHANNEL_NAME_RED) {
+			left = opp110->
+					regamma.axis_x_256[i].r;
+
+			if (i < max_number - 1)
+				right = opp110->
+					regamma.axis_x_256[i + 1].r;
+			else
+				right = opp110->
+					regamma.axis_x_256[max_number - 1].r;
+		} else if (channel == CHANNEL_NAME_GREEN) {
+			left = opp110->regamma.axis_x_256[i].g;
+
+			if (i < max_number - 1)
+				right = opp110->
+					regamma.axis_x_256[i + 1].g;
+			else
+				right = opp110->
+					regamma.axis_x_256[max_number - 1].g;
+		} else {
+			left = opp110->regamma.axis_x_256[i].b;
+
+			if (i < max_number - 1)
+				right = opp110->
+					regamma.axis_x_256[i + 1].b;
+			else
+				right = opp110->
+					regamma.axis_x_256[max_number - 1].b;
+		}
+
+		if (dal_fixed31_32_le(left, hw_point) &&
+			dal_fixed31_32_le(hw_point, right)) {
+			*index_to_start = i;
+			*index_left = i;
+
+			if (i < max_number - 1)
+				*index_right = i + 1;
+			else
+				*index_right = max_number - 1;
+
+			*pos = HW_POINT_POSITION_MIDDLE;
+
+			return true;
+		} else if ((i == *index_to_start) &&
+			dal_fixed31_32_le(hw_point, left)) {
+			*index_to_start = i;
+			*index_left = i;
+			*index_right = i;
+
+			*pos = HW_POINT_POSITION_LEFT;
+
+			return true;
+		} else if ((i == max_number - 1) &&
+			dal_fixed31_32_le(right, hw_point)) {
+			*index_to_start = i;
+			*index_left = i;
+			*index_right = i;
+
+			*pos = HW_POINT_POSITION_RIGHT;
+
+			return true;
+		}
+
+		++i;
+	}
+
+	return false;
+}
+
+static bool find_software_points_dx(
+	struct dce110_opp *opp110,
+	struct fixed31_32 hw_point,
+	enum channel_name channel,
+	uint32_t *index_to_start,
+	uint32_t *index_left,
+	uint32_t *index_right,
+	enum hw_point_position *pos)
+{
+	const uint32_t max_number = DX_GAMMA_RAMP_MAX +
+					opp110->regamma.extra_points;
+
+	struct fixed31_32 left, right;
+
+	uint32_t i = *index_to_start;
+
+	while (i < max_number) {
+		if (channel == CHANNEL_NAME_RED) {
+			left = opp110->regamma.axis_x_1025[i].r;
+
+			if (i < DX_GAMMA_RAMP_MAX - 1)
+				right = opp110->
+					regamma.axis_x_1025[i + 1].r;
+			else
+				right = opp110->
+				regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].r;
+		} else if (channel == CHANNEL_NAME_GREEN) {
+			left = opp110->regamma.axis_x_1025[i].g;
+
+			if (i < DX_GAMMA_RAMP_MAX - 1)
+				right = opp110->
+					regamma.axis_x_1025[i + 1].g;
+			else
+				right = opp110->
+				regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].g;
+		} else {
+			left = opp110->regamma.axis_x_1025[i].b;
+
+			if (i < DX_GAMMA_RAMP_MAX - 1)
+				right = opp110->
+					regamma.axis_x_1025[i + 1].b;
+			else
+				right = opp110->
+				regamma.axis_x_1025[DX_GAMMA_RAMP_MAX-1].b;
+		}
+
+		if (dal_fixed31_32_le(left, hw_point) &&
+			dal_fixed31_32_le(hw_point, right)) {
+			*index_to_start = i;
+			*index_left = i;
+
+			if (i < DX_GAMMA_RAMP_MAX - 1)
+				*index_right = i + 1;
+			else
+				*index_right = DX_GAMMA_RAMP_MAX - 1;
+
+			*pos = HW_POINT_POSITION_MIDDLE;
+
+			return true;
+		} else if ((i == *index_to_start) &&
+			dal_fixed31_32_le(hw_point, left)) {
+			*index_to_start = i;
+			*index_left = i;
+			*index_right = i;
+
+			*pos = HW_POINT_POSITION_LEFT;
+
+			return true;
+		} else if ((i == max_number - 1) &&
+			dal_fixed31_32_le(right, hw_point)) {
+			*index_to_start = i;
+			*index_left = i;
+			*index_right = i;
+
+			*pos = HW_POINT_POSITION_RIGHT;
+
+			return true;
+		}
+
+		++i;
+	}
+
+	return false;
+}
+
+static bool build_custom_gamma_mapping_coefficients_worker(
+	struct dce110_opp *opp110,
+	struct pixel_gamma_point *coeff,
+	enum channel_name channel,
+	uint32_t number_of_points,
+	enum pixel_format pixel_format)
+{
+	uint32_t i = 0;
+
+	while (i <= number_of_points) {
+		struct fixed31_32 coord_x;
+
+		uint32_t index_to_start = 0;
+		uint32_t index_left = 0;
+		uint32_t index_right = 0;
+
+		enum hw_point_position hw_pos;
+
+		struct gamma_point *point;
+
+		struct fixed31_32 left_pos;
+		struct fixed31_32 right_pos;
+
+		if (pixel_format == PIXEL_FORMAT_FP16)
+			coord_x = opp110->
+				regamma.coordinates_x[i].adjusted_x;
+		else if (channel == CHANNEL_NAME_RED)
+			coord_x = opp110->
+				regamma.coordinates_x[i].regamma_y_red;
+		else if (channel == CHANNEL_NAME_GREEN)
+			coord_x = opp110->
+				regamma.coordinates_x[i].regamma_y_green;
+		else
+			coord_x = opp110->
+				regamma.coordinates_x[i].regamma_y_blue;
+
+		if (!find_software_points(
+			opp110, coord_x, channel,
+			&index_to_start, &index_left, &index_right, &hw_pos)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (index_left >= RGB_256X3X16 +
+				opp110->regamma.extra_points) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (index_right >= RGB_256X3X16 +
+				opp110->regamma.extra_points) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (channel == CHANNEL_NAME_RED) {
+			point = &coeff[i].r;
+
+			left_pos = opp110->
+					regamma.axis_x_256[index_left].r;
+			right_pos = opp110->
+					regamma.axis_x_256[index_right].r;
+		} else if (channel == CHANNEL_NAME_GREEN) {
+			point = &coeff[i].g;
+
+			left_pos = opp110->
+					regamma.axis_x_256[index_left].g;
+			right_pos = opp110->
+					regamma.axis_x_256[index_right].g;
+		} else {
+			point = &coeff[i].b;
+
+			left_pos = opp110->
+					regamma.axis_x_256[index_left].b;
+			right_pos = opp110->
+					regamma.axis_x_256[index_right].b;
+		}
+
+		if (hw_pos == HW_POINT_POSITION_MIDDLE)
+			point->coeff = dal_fixed31_32_div(
+				dal_fixed31_32_sub(
+					coord_x,
+					left_pos),
+				dal_fixed31_32_sub(
+					right_pos,
+					left_pos));
+		else if (hw_pos == HW_POINT_POSITION_LEFT)
+			point->coeff = opp110->regamma.x_min;
+		else if (hw_pos == HW_POINT_POSITION_RIGHT)
+			point->coeff = opp110->regamma.x_max2;
+		else {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		point->left_index = index_left;
+		point->right_index = index_right;
+		point->pos = hw_pos;
+
+		++i;
+	}
+
+	return true;
+}
+
+static inline bool build_custom_gamma_mapping_coefficients(
+	struct dce110_opp *opp110,
+	enum channel_name channel,
+	uint32_t number_of_points,
+	enum pixel_format pixel_format)
+{
+	return build_custom_gamma_mapping_coefficients_worker(
+		opp110, opp110->regamma.coeff128, channel,
+		number_of_points, pixel_format);
+}
+
+static inline bool build_oem_custom_gamma_mapping_coefficients(
+	struct dce110_opp *opp110,
+	enum channel_name channel,
+	uint32_t number_of_points,
+	enum pixel_format pixel_format)
+{
+	return build_custom_gamma_mapping_coefficients_worker(
+		opp110, opp110->regamma.coeff128_oem, channel,
+		number_of_points, pixel_format);
+}
+
+static bool build_custom_dx_gamma_mapping_coefficients(
+	struct dce110_opp *opp110,
+	enum channel_name channel,
+	uint32_t number_of_points,
+	enum pixel_format pixel_format)
+{
+	uint32_t i = 0;
+
+	while (i <= number_of_points) {
+		struct fixed31_32 coord_x;
+
+		uint32_t index_to_start = 0;
+		uint32_t index_left = 0;
+		uint32_t index_right = 0;
+
+		enum hw_point_position hw_pos;
+
+		struct gamma_point *point;
+
+		struct fixed31_32 left_pos;
+		struct fixed31_32 right_pos;
+
+		if (pixel_format == PIXEL_FORMAT_FP16)
+			coord_x = opp110->
+			regamma.coordinates_x[i].adjusted_x;
+		else if (channel == CHANNEL_NAME_RED)
+			coord_x = opp110->
+			regamma.coordinates_x[i].regamma_y_red;
+		else if (channel == CHANNEL_NAME_GREEN)
+			coord_x = opp110->
+			regamma.coordinates_x[i].regamma_y_green;
+		else
+			coord_x = opp110->
+			regamma.coordinates_x[i].regamma_y_blue;
+
+		if (!find_software_points_dx(
+			opp110, coord_x, channel,
+			&index_to_start, &index_left, &index_right, &hw_pos)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (index_left >= DX_GAMMA_RAMP_MAX +
+				opp110->regamma.extra_points) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (index_right >= DX_GAMMA_RAMP_MAX +
+				opp110->regamma.extra_points) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (channel == CHANNEL_NAME_RED) {
+			point = &opp110->regamma.coeff128_dx[i].r;
+
+			left_pos = opp110->
+					regamma.axis_x_1025[index_left].r;
+			right_pos = opp110->
+					regamma.axis_x_1025[index_right].r;
+		} else if (channel == CHANNEL_NAME_GREEN) {
+			point = &opp110->regamma.coeff128_dx[i].g;
+
+			left_pos = opp110->
+					regamma.axis_x_1025[index_left].g;
+			right_pos = opp110->
+					regamma.axis_x_1025[index_right].g;
+		} else {
+			point = &opp110->regamma.coeff128_dx[i].b;
+
+			left_pos = opp110->
+					regamma.axis_x_1025[index_left].b;
+			right_pos = opp110->
+					regamma.axis_x_1025[index_right].b;
+		}
+
+		if (hw_pos == HW_POINT_POSITION_MIDDLE)
+			point->coeff = dal_fixed31_32_div(
+				dal_fixed31_32_sub(
+					coord_x,
+					left_pos),
+				dal_fixed31_32_sub(
+					right_pos,
+					left_pos));
+		else if (hw_pos == HW_POINT_POSITION_LEFT)
+			point->coeff = opp110->regamma.x_min;
+		else if (hw_pos == HW_POINT_POSITION_RIGHT)
+			point->coeff = opp110->regamma.x_max2;
+		else {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		point->left_index = index_left;
+		point->right_index = index_right;
+		point->pos = hw_pos;
+
+		++i;
+	}
+
+	return true;
+}
+
+static struct fixed31_32 calculate_mapped_value(
+	struct dce110_opp *opp110,
+	struct pwl_float_data *rgb,
+	const struct pixel_gamma_point *coeff,
+	enum channel_name channel,
+	uint32_t max_index)
+{
+	const struct gamma_point *point;
+
+	struct fixed31_32 result;
+
+	if (channel == CHANNEL_NAME_RED)
+		point = &coeff->r;
+	else if (channel == CHANNEL_NAME_GREEN)
+		point = &coeff->g;
+	else
+		point = &coeff->b;
+
+	if ((point->left_index < 0) || (point->left_index > max_index)) {
+		BREAK_TO_DEBUGGER();
+		return dal_fixed31_32_zero;
+	}
+
+	if ((point->right_index < 0) || (point->right_index > max_index)) {
+		BREAK_TO_DEBUGGER();
+		return dal_fixed31_32_zero;
+	}
+
+	if (point->pos == HW_POINT_POSITION_MIDDLE)
+		if (channel == CHANNEL_NAME_RED)
+			result = dal_fixed31_32_add(
+				dal_fixed31_32_mul(
+					point->coeff,
+					dal_fixed31_32_sub(
+						rgb[point->right_index].r,
+						rgb[point->left_index].r)),
+				rgb[point->left_index].r);
+		else if (channel == CHANNEL_NAME_GREEN)
+			result = dal_fixed31_32_add(
+				dal_fixed31_32_mul(
+					point->coeff,
+					dal_fixed31_32_sub(
+						rgb[point->right_index].g,
+						rgb[point->left_index].g)),
+				rgb[point->left_index].g);
+		else
+			result = dal_fixed31_32_add(
+				dal_fixed31_32_mul(
+					point->coeff,
+					dal_fixed31_32_sub(
+						rgb[point->right_index].b,
+						rgb[point->left_index].b)),
+				rgb[point->left_index].b);
+	else if (point->pos == HW_POINT_POSITION_LEFT) {
+		BREAK_TO_DEBUGGER();
+		result = opp110->regamma.x_min;
+	} else {
+		BREAK_TO_DEBUGGER();
+		result = opp110->regamma.x_max1;
+	}
+
+	return result;
+}
+
+static inline struct fixed31_32 calculate_regamma_user_mapped_value(
+	struct dce110_opp *opp110,
+	const struct pixel_gamma_point *coeff,
+	enum channel_name channel,
+	uint32_t max_index)
+{
+	return calculate_mapped_value(
+		opp110, opp110->regamma.rgb_oem,
+		coeff, channel, max_index);
+}
+
+static inline struct fixed31_32 calculate_user_mapped_value(
+	struct dce110_opp *opp110,
+	const struct pixel_gamma_point *coeff,
+	enum channel_name channel,
+	uint32_t max_index)
+{
+	return calculate_mapped_value(
+		opp110, opp110->regamma.rgb_user,
+		coeff, channel, max_index);
+}
+
+static inline struct fixed31_32 calculate_oem_mapped_value(
+	struct dce110_opp *opp110,
+	uint32_t index,
+	enum channel_name channel,
+	uint32_t max_index)
+{
+	return calculate_regamma_user_mapped_value(
+		opp110, opp110->regamma.coeff128_oem +
+		index, channel, max_index);
+}
+
+static void scale_oem_gamma(
+	struct dce110_opp *opp110,
+	const struct regamma_ramp *regamma_ramp)
+{
+	const uint16_t max_driver = 0xFFFF;
+	const uint16_t max_os = 0xFF00;
+
+	uint16_t scale = max_os;
+
+	uint32_t i;
+
+	struct pwl_float_data *rgb = opp110->regamma.rgb_oem;
+	struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1;
+
+	/* find OEM maximum */
+
+	i = 0;
+
+	do {
+		if ((regamma_ramp->gamma[i] > max_os) ||
+			(regamma_ramp->gamma[i + RGB_256X3X16] > max_os) ||
+			(regamma_ramp->gamma[i + 2 * RGB_256X3X16] > max_os)) {
+			scale = max_driver;
+			break;
+		}
+
+		++i;
+	} while (i != RGB_256X3X16);
+
+	/* scale */
+
+	i = 0;
+
+	do {
+		rgb->r = dal_fixed31_32_div_int(
+			dal_fixed31_32_from_int(
+				regamma_ramp->gamma[i]),
+			scale);
+		rgb->g = dal_fixed31_32_div_int(
+			dal_fixed31_32_from_int(
+				regamma_ramp->gamma[i + RGB_256X3X16]),
+			scale);
+		rgb->b = dal_fixed31_32_div_int(
+			dal_fixed31_32_from_int(
+				regamma_ramp->gamma[i + 2 * RGB_256X3X16]),
+			scale);
+
+		++rgb;
+		++i;
+	} while (i != RGB_256X3X16);
+
+	/* add 3 extra points, 2 physical plus 1 virtual */
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider1);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider1);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider1);
+
+	++rgb;
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider2);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider2);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider2);
+
+	++rgb;
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider3);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider3);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider3);
+}
+
+static inline void copy_rgb_regamma_to_coordinates_x(
+	struct dce110_opp *opp110)
+{
+	struct hw_x_point *coords = opp110->regamma.coordinates_x;
+	const struct pwl_float_data_ex *rgb_regamma =
+			opp110->regamma.rgb_regamma;
+
+	uint32_t i = 0;
+
+	while (i <= opp110->regamma.hw_points_num) {
+		coords->regamma_y_red = rgb_regamma->r;
+		coords->regamma_y_green = rgb_regamma->g;
+		coords->regamma_y_blue = rgb_regamma->b;
+
+		++coords;
+		++rgb_regamma;
+		++i;
+	}
+}
+
+static bool calculate_interpolated_hardware_curve(
+	struct dce110_opp *opp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct pwl_result_data *rgb_resulted =
+			opp110->regamma.rgb_resulted;
+
+	const struct pixel_gamma_point *coeff;
+	uint32_t max_entries = opp110->regamma.extra_points - 1;
+
+	uint32_t i = 0;
+
+	if (gamma_ramp->type == GAMMA_RAMP_RBG256X3X16) {
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		coeff = opp110->regamma.coeff128;
+		max_entries += RGB_256X3X16;
+	} else if (gamma_ramp->type == GAMMA_RAMP_DXGI_1) {
+		if (!build_custom_dx_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_dx_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_dx_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		coeff = opp110->regamma.coeff128_dx;
+		max_entries += DX_GAMMA_RAMP_MAX;
+	} else {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	while (i <= opp110->regamma.hw_points_num) {
+		rgb_resulted->red = calculate_user_mapped_value(
+			opp110, coeff, CHANNEL_NAME_RED, max_entries);
+		rgb_resulted->green = calculate_user_mapped_value(
+			opp110, coeff, CHANNEL_NAME_GREEN, max_entries);
+		rgb_resulted->blue = calculate_user_mapped_value(
+			opp110, coeff, CHANNEL_NAME_BLUE, max_entries);
+
+		++coeff;
+		++rgb_resulted;
+		++i;
+	}
+
+	return true;
+}
+
+static void map_standard_regamma_hw_to_x_user(
+	struct dce110_opp *opp110,
+	enum gamma_ramp_type type,
+	const struct gamma_parameters *params)
+{
+	struct pwl_result_data *rgb_resulted =
+			opp110->regamma.rgb_resulted;
+	const struct pwl_float_data_ex *rgb_regamma =
+			opp110->regamma.rgb_regamma;
+
+	uint32_t i = 0;
+
+	while (i <= opp110->regamma.hw_points_num) {
+		rgb_resulted->red = rgb_regamma->r;
+		rgb_resulted->green = rgb_regamma->g;
+		rgb_resulted->blue = rgb_regamma->b;
+
+		++rgb_resulted;
+		++rgb_regamma;
+		++i;
+	}
+}
+
+bool dce110_opp_map_legacy_and_regamma_hw_to_x_user(
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	if (params->regamma.features.bits.GAMMA_RAMP_ARRAY ||
+		params->regamma.features.bits.APPLY_DEGAMMA) {
+
+		const uint32_t max_entries =
+			RGB_256X3X16 + opp110->regamma.extra_points - 1;
+
+		const struct pixel_gamma_point *coeff =
+				opp110->regamma.coeff128;
+		struct pwl_result_data *rgb_resulted =
+				opp110->regamma.rgb_resulted;
+
+		uint32_t i = 0;
+
+		scale_oem_gamma(opp110, &params->regamma.regamma_ramp);
+
+		copy_rgb_regamma_to_coordinates_x(opp110);
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		while (i <= opp110->regamma.hw_points_num) {
+			rgb_resulted->red =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_RED, max_entries);
+			rgb_resulted->green =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_GREEN, max_entries);
+			rgb_resulted->blue =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_BLUE, max_entries);
+
+			++coeff;
+			++rgb_resulted;
+			++i;
+		}
+	} else
+		map_standard_regamma_hw_to_x_user(opp110,
+				gamma_ramp->type,
+				params);
+
+	return true;
+}
+
+static bool map_regamma_hw_to_x_user(
+	struct dce110_opp *opp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	/* setup to spare calculated ideal regamma values */
+	if (params->regamma.features.bits.GAMMA_RAMP_ARRAY ||
+		params->regamma.features.bits.APPLY_DEGAMMA) {
+
+		const uint32_t max_entries =
+			RGB_256X3X16 + opp110->regamma.extra_points - 1;
+
+		const struct pixel_gamma_point *coeff =
+				opp110->regamma.coeff128;
+		struct hw_x_point *coords =
+				opp110->regamma.coordinates_x;
+
+		uint32_t i = 0;
+
+		scale_oem_gamma(opp110, &params->regamma.regamma_ramp);
+
+		copy_rgb_regamma_to_coordinates_x(opp110);
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		while (i <= opp110->regamma.hw_points_num) {
+			coords->regamma_y_red =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_RED, max_entries);
+			coords->regamma_y_green =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_GREEN, max_entries);
+			coords->regamma_y_blue =
+				calculate_regamma_user_mapped_value(opp110,
+					coeff,
+					CHANNEL_NAME_BLUE, max_entries);
+
+			++coeff;
+			++coords;
+			++i;
+		}
+	} else {
+		copy_rgb_regamma_to_coordinates_x(opp110);
+	}
+
+	return calculate_interpolated_hardware_curve(opp110, gamma_ramp,
+		params);
+}
+
+static void build_regamma_coefficients(
+	const struct regamma_lut *regamma,
+	bool is_degamma_srgb,
+	struct gamma_coefficients *coefficients)
+{
+	/* sRGB should apply 2.4 */
+	static const int32_t numerator01[3] = { 31308, 31308, 31308 };
+	static const int32_t numerator02[3] = { 12920, 12920, 12920 };
+	static const int32_t numerator03[3] = { 55, 55, 55 };
+	static const int32_t numerator04[3] = { 55, 55, 55 };
+	static const int32_t numerator05[3] = { 2400, 2400, 2400 };
+
+	/* Non-sRGB should apply 2.2 */
+	static const int32_t numerator11[3] = { 180000, 180000, 180000 };
+	static const int32_t numerator12[3] = { 4500, 4500, 4500 };
+	static const int32_t numerator13[3] = { 99, 99, 99 };
+	static const int32_t numerator14[3] = { 99, 99, 99 };
+	static const int32_t numerator15[3] = { 2200, 2200, 2200 };
+
+	const int32_t *numerator1;
+	const int32_t *numerator2;
+	const int32_t *numerator3;
+	const int32_t *numerator4;
+	const int32_t *numerator5;
+
+	uint32_t i = 0;
+
+	if (!regamma->features.bits.GAMMA_RAMP_ARRAY) {
+		numerator1 = regamma->gamma_coeff.a0;
+		numerator2 = regamma->gamma_coeff.a1;
+		numerator3 = regamma->gamma_coeff.a2;
+		numerator4 = regamma->gamma_coeff.a3;
+		numerator5 = regamma->gamma_coeff.gamma;
+	} else if (is_degamma_srgb) {
+		numerator1 = numerator01;
+		numerator2 = numerator02;
+		numerator3 = numerator03;
+		numerator4 = numerator04;
+		numerator5 = numerator05;
+	} else {
+		numerator1 = numerator11;
+		numerator2 = numerator12;
+		numerator3 = numerator13;
+		numerator4 = numerator14;
+		numerator5 = numerator15;
+	}
+
+	do {
+		coefficients->a0[i] = dal_fixed31_32_from_fraction(
+			numerator1[i], 10000000);
+		coefficients->a1[i] = dal_fixed31_32_from_fraction(
+			numerator2[i], 1000);
+		coefficients->a2[i] = dal_fixed31_32_from_fraction(
+			numerator3[i], 1000);
+		coefficients->a3[i] = dal_fixed31_32_from_fraction(
+			numerator4[i], 1000);
+		coefficients->user_gamma[i] = dal_fixed31_32_from_fraction(
+			numerator5[i], 1000);
+
+		++i;
+	} while (i != ARRAY_SIZE(regamma->gamma_coeff.a0));
+}
+
+static struct fixed31_32 translate_from_linear_space(
+	struct fixed31_32 arg,
+	struct fixed31_32 a0,
+	struct fixed31_32 a1,
+	struct fixed31_32 a2,
+	struct fixed31_32 a3,
+	struct fixed31_32 gamma)
+{
+	const struct fixed31_32 one = dal_fixed31_32_from_int(1);
+
+	if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0)))
+		return dal_fixed31_32_sub(
+			a2,
+			dal_fixed31_32_mul(
+				dal_fixed31_32_add(
+					one,
+					a3),
+				dal_fixed31_32_pow(
+					dal_fixed31_32_neg(arg),
+					dal_fixed31_32_recip(gamma))));
+	else if (dal_fixed31_32_le(a0, arg))
+		return dal_fixed31_32_sub(
+			dal_fixed31_32_mul(
+				dal_fixed31_32_add(
+					one,
+					a3),
+				dal_fixed31_32_pow(
+					arg,
+					dal_fixed31_32_recip(gamma))),
+			a2);
+	else
+		return dal_fixed31_32_mul(
+			arg,
+			a1);
+}
+
+static inline struct fixed31_32 translate_from_linear_space_ex(
+	struct fixed31_32 arg,
+	struct gamma_coefficients *coeff,
+	uint32_t color_index)
+{
+	return translate_from_linear_space(
+		arg,
+		coeff->a0[color_index],
+		coeff->a1[color_index],
+		coeff->a2[color_index],
+		coeff->a3[color_index],
+		coeff->user_gamma[color_index]);
+}
+
+static bool build_regamma_curve(
+	struct dce110_opp *opp110,
+	const struct gamma_parameters *params)
+{
+	struct pwl_float_data_ex *rgb = opp110->regamma.rgb_regamma;
+
+	uint32_t i;
+
+	struct gamma_coefficients coeff;
+
+	struct hw_x_point *coord_x =
+		opp110->regamma.coordinates_x;
+
+	build_regamma_coefficients(
+		&params->regamma,
+		params->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB,
+		&coeff);
+
+	/* Use opp110->regamma.coordinates_x to retrieve
+	 * coordinates chosen base on given user curve (future task).
+	 * The x values are exponentially distributed and currently
+	 * it is hard-coded, the user curve shape is ignored.
+	 * The future task is to recalculate opp110-
+	 * regamma.coordinates_x based on input/user curve,
+	 * translation from 256/1025 to 128 pwl points.
+	 */
+
+	i = 0;
+
+	while (i != opp110->regamma.hw_points_num + 1) {
+		rgb->r = translate_from_linear_space_ex(
+			coord_x->adjusted_x, &coeff, 0);
+		rgb->g = translate_from_linear_space_ex(
+			coord_x->adjusted_x, &coeff, 1);
+		rgb->b = translate_from_linear_space_ex(
+			coord_x->adjusted_x, &coeff, 2);
+
+		++coord_x;
+		++rgb;
+		++i;
+	}
+
+	if (params->regamma.features.bits.GAMMA_RAMP_ARRAY &&
+			!params->regamma.features.bits.APPLY_DEGAMMA) {
+		const uint32_t max_entries =
+			RGB_256X3X16 + opp110->regamma.extra_points - 1;
+
+		/* interpolate between 256 input points and output 185 points */
+
+		scale_oem_gamma(opp110, &params->regamma.regamma_ramp);
+
+		if (!build_oem_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_RED,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_oem_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_GREEN,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!build_oem_custom_gamma_mapping_coefficients(
+			opp110, CHANNEL_NAME_BLUE,
+			opp110->regamma.hw_points_num,
+			params->surface_pixel_format)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		i = 0;
+
+		while (i != opp110->regamma.hw_points_num + 1) {
+			rgb->r = calculate_oem_mapped_value(
+				opp110, i, CHANNEL_NAME_RED, max_entries);
+			rgb->g = calculate_oem_mapped_value(
+				opp110, i, CHANNEL_NAME_GREEN, max_entries);
+			rgb->b = calculate_oem_mapped_value(
+				opp110, i, CHANNEL_NAME_BLUE, max_entries);
+			++rgb;
+			++i;
+		}
+	}
+
+	return true;
+}
+
+static void build_new_custom_resulted_curve(
+	struct dce110_opp *opp110,
+	const struct gamma_parameters *params)
+{
+	struct pwl_result_data *rgb = opp110->regamma.rgb_resulted;
+	struct pwl_result_data *rgb_plus_1 = rgb + 1;
+
+	uint32_t i;
+
+	i = 0;
+
+	while (i != opp110->regamma.hw_points_num + 1) {
+		rgb->red = dal_fixed31_32_clamp(
+			rgb->red, opp110->regamma.x_min,
+			opp110->regamma.x_max1);
+		rgb->green = dal_fixed31_32_clamp(
+			rgb->green, opp110->regamma.x_min,
+			opp110->regamma.x_max1);
+		rgb->blue = dal_fixed31_32_clamp(
+			rgb->blue, opp110->regamma.x_min,
+			opp110->regamma.x_max1);
+
+		++rgb;
+		++i;
+	}
+
+	rgb = opp110->regamma.rgb_resulted;
+
+	i = 1;
+
+	while (i != opp110->regamma.hw_points_num + 1) {
+		if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
+			rgb_plus_1->red = rgb->red;
+		if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
+			rgb_plus_1->green = rgb->green;
+		if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
+			rgb_plus_1->blue = rgb->blue;
+
+		rgb->delta_red = dal_fixed31_32_sub(
+			rgb_plus_1->red,
+			rgb->red);
+		rgb->delta_green = dal_fixed31_32_sub(
+			rgb_plus_1->green,
+			rgb->green);
+		rgb->delta_blue = dal_fixed31_32_sub(
+			rgb_plus_1->blue,
+			rgb->blue);
+
+		++rgb_plus_1;
+		++rgb;
+		++i;
+	}
+}
+
+static bool rebuild_curve_configuration_magic(
+	struct dce110_opp *opp110)
+{
+	const struct fixed31_32 magic_number =
+		dal_fixed31_32_from_fraction(249, 1000);
+
+	struct fixed31_32 y_r;
+	struct fixed31_32 y_g;
+	struct fixed31_32 y_b;
+
+	struct fixed31_32 y1_min;
+	struct fixed31_32 y2_max;
+	struct fixed31_32 y3_max;
+
+	y_r = opp110->regamma.rgb_resulted[0].red;
+	y_g = opp110->regamma.rgb_resulted[0].green;
+	y_b = opp110->regamma.rgb_resulted[0].blue;
+
+	y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
+
+	opp110->regamma.arr_points[0].x =
+			opp110->regamma.coordinates_x[0].adjusted_x;
+	opp110->regamma.arr_points[0].y = y1_min;
+	opp110->regamma.arr_points[0].slope = dal_fixed31_32_div(
+		opp110->regamma.arr_points[0].y,
+		opp110->regamma.arr_points[0].x);
+
+	opp110->regamma.arr_points[1].x = dal_fixed31_32_add(
+		opp110->regamma.coordinates_x
+		[opp110->regamma.hw_points_num - 1].adjusted_x,
+		magic_number);
+
+	opp110->regamma.arr_points[2].x =
+			opp110->regamma.arr_points[1].x;
+
+	y_r = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num - 1].red;
+	y_g = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num - 1].green;
+	y_b = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num - 1].blue;
+
+	y2_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
+
+	opp110->regamma.arr_points[1].y = y2_max;
+
+	y_r = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num].red;
+	y_g = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num].green;
+	y_b = opp110->regamma.rgb_resulted
+			[opp110->regamma.hw_points_num].blue;
+
+	y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
+
+	opp110->regamma.arr_points[2].y = y3_max;
+
+	opp110->regamma.arr_points[2].slope = dal_fixed31_32_one;
+
+	return true;
+}
+
+static bool build_custom_float(
+	struct fixed31_32 value,
+	const struct custom_float_format *format,
+	bool *negative,
+	uint32_t *mantissa,
+	uint32_t *exponenta)
+{
+	uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
+
+	const struct fixed31_32 mantissa_constant_plus_max_fraction =
+		dal_fixed31_32_from_fraction(
+			(1LL << (format->mantissa_bits + 1)) - 1,
+			1LL << format->mantissa_bits);
+
+	struct fixed31_32 mantiss;
+
+	if (dal_fixed31_32_eq(
+		value,
+		dal_fixed31_32_zero)) {
+		*negative = false;
+		*mantissa = 0;
+		*exponenta = 0;
+		return true;
+	}
+
+	if (dal_fixed31_32_lt(
+		value,
+		dal_fixed31_32_zero)) {
+		*negative = format->sign;
+		value = dal_fixed31_32_neg(value);
+	} else {
+		*negative = false;
+	}
+
+	if (dal_fixed31_32_lt(
+		value,
+		dal_fixed31_32_one)) {
+		uint32_t i = 1;
+
+		do {
+			value = dal_fixed31_32_shl(value, 1);
+			++i;
+		} while (dal_fixed31_32_lt(
+			value,
+			dal_fixed31_32_one));
+
+		--i;
+
+		if (exp_offset <= i) {
+			*mantissa = 0;
+			*exponenta = 0;
+			return true;
+		}
+
+		*exponenta = exp_offset - i;
+	} else if (dal_fixed31_32_le(
+		mantissa_constant_plus_max_fraction,
+		value)) {
+		uint32_t i = 1;
+
+		do {
+			value = dal_fixed31_32_shr(value, 1);
+			++i;
+		} while (dal_fixed31_32_lt(
+			mantissa_constant_plus_max_fraction,
+			value));
+
+		*exponenta = exp_offset + i - 1;
+	} else {
+		*exponenta = exp_offset;
+	}
+
+	mantiss = dal_fixed31_32_sub(
+		value,
+		dal_fixed31_32_one);
+
+	if (dal_fixed31_32_lt(
+			mantiss,
+			dal_fixed31_32_zero) ||
+		dal_fixed31_32_lt(
+			dal_fixed31_32_one,
+			mantiss))
+		mantiss = dal_fixed31_32_zero;
+	else
+		mantiss = dal_fixed31_32_shl(
+			mantiss,
+			format->mantissa_bits);
+
+	*mantissa = dal_fixed31_32_floor(mantiss);
+
+	return true;
+}
+
+static bool setup_custom_float(
+	const struct custom_float_format *format,
+	bool negative,
+	uint32_t mantissa,
+	uint32_t exponenta,
+	uint32_t *result)
+{
+	uint32_t i = 0;
+	uint32_t j = 0;
+
+	uint32_t value = 0;
+
+	/* verification code:
+	 * once calculation is ok we can remove it */
+
+	const uint32_t mantissa_mask =
+		(1 << (format->mantissa_bits + 1)) - 1;
+
+	const uint32_t exponenta_mask =
+		(1 << (format->exponenta_bits + 1)) - 1;
+
+	if (mantissa & ~mantissa_mask) {
+		BREAK_TO_DEBUGGER();
+		mantissa = mantissa_mask;
+	}
+
+	if (exponenta & ~exponenta_mask) {
+		BREAK_TO_DEBUGGER();
+		exponenta = exponenta_mask;
+	}
+
+	/* end of verification code */
+
+	while (i < format->mantissa_bits) {
+		uint32_t mask = 1 << i;
+
+		if (mantissa & mask)
+			value |= mask;
+
+		++i;
+	}
+
+	while (j < format->exponenta_bits) {
+		uint32_t mask = 1 << j;
+
+		if (exponenta & mask)
+			value |= mask << i;
+
+		++j;
+	}
+
+	if (negative && format->sign)
+		value |= 1 << (i + j);
+
+	*result = value;
+
+	return true;
+}
+
+static bool convert_to_custom_float_format(
+	struct fixed31_32 value,
+	const struct custom_float_format *format,
+	uint32_t *result)
+{
+	uint32_t mantissa;
+	uint32_t exponenta;
+	bool negative;
+
+	return build_custom_float(
+		value, format, &negative, &mantissa, &exponenta) &&
+	setup_custom_float(
+		format, negative, mantissa, exponenta, result);
+}
+
+static bool convert_to_custom_float_format_ex(
+	struct fixed31_32 value,
+	const struct custom_float_format *format,
+	struct custom_float_value *result)
+{
+	return build_custom_float(
+		value, format,
+		&result->negative, &result->mantissa, &result->exponenta) &&
+	setup_custom_float(
+		format, result->negative, result->mantissa, result->exponenta,
+		&result->value);
+}
+
+static bool convert_to_custom_float(
+	struct dce110_opp *opp110)
+{
+	struct custom_float_format fmt;
+
+	struct pwl_result_data *rgb = opp110->regamma.rgb_resulted;
+
+	uint32_t i = 0;
+
+	fmt.exponenta_bits = 6;
+	fmt.mantissa_bits = 12;
+	fmt.sign = true;
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[0].x,
+		&fmt,
+		&opp110->regamma.arr_points[0].custom_float_x)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[0].offset,
+		&fmt,
+		&opp110->regamma.arr_points[0].custom_float_offset)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[0].slope,
+		&fmt,
+		&opp110->regamma.arr_points[0].custom_float_slope)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	fmt.mantissa_bits = 10;
+	fmt.sign = false;
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[1].x,
+		&fmt,
+		&opp110->regamma.arr_points[1].custom_float_x)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[1].y,
+		&fmt,
+		&opp110->regamma.arr_points[1].custom_float_y)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	if (!convert_to_custom_float_format(
+		opp110->regamma.arr_points[2].slope,
+		&fmt,
+		&opp110->regamma.arr_points[2].custom_float_slope)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	fmt.mantissa_bits = 12;
+	fmt.sign = true;
+
+	while (i != opp110->regamma.hw_points_num) {
+		if (!convert_to_custom_float_format(
+			rgb->red,
+			&fmt,
+			&rgb->red_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->green,
+			&fmt,
+			&rgb->green_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->blue,
+			&fmt,
+			&rgb->blue_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->delta_red,
+			&fmt,
+			&rgb->delta_red_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->delta_green,
+			&fmt,
+			&rgb->delta_green_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		if (!convert_to_custom_float_format(
+			rgb->delta_blue,
+			&fmt,
+			&rgb->delta_blue_reg)) {
+			BREAK_TO_DEBUGGER();
+			return false;
+		}
+
+		++rgb;
+		++i;
+	}
+
+	return true;
+}
+
+static bool round_custom_float_6_12(
+	struct hw_x_point *x)
+{
+	struct custom_float_format fmt;
+
+	struct custom_float_value value;
+
+	fmt.exponenta_bits = 6;
+	fmt.mantissa_bits = 12;
+	fmt.sign = true;
+
+	if (!convert_to_custom_float_format_ex(
+		x->x, &fmt, &value))
+		return false;
+
+	x->adjusted_x = x->x;
+
+	if (value.mantissa) {
+		BREAK_TO_DEBUGGER();
+
+		return false;
+	}
+
+	return true;
+}
+
+static bool build_hw_curve_configuration(
+	const struct curve_config *curve_config,
+	struct gamma_curve *gamma_curve,
+	struct curve_points *curve_points,
+	struct hw_x_point *points,
+	uint32_t *number_of_points)
+{
+	const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments);
+
+	int8_t i;
+
+	uint8_t segments_calculation[8] = { 0 };
+
+	struct fixed31_32 region1 = dal_fixed31_32_zero;
+	struct fixed31_32 region2;
+	struct fixed31_32 increment;
+
+	uint32_t index = 0;
+	uint32_t segments = 0;
+	uint32_t max_number;
+
+	bool result = false;
+
+	if (!number_of_points) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	max_number = *number_of_points;
+
+	i = 0;
+
+	while (i != max_regions_number) {
+		gamma_curve[i].offset = 0;
+		gamma_curve[i].segments_num = 0;
+
+		++i;
+	}
+
+	i = 0;
+
+	while (i != max_regions_number) {
+		/* number should go in uninterruptible sequence */
+		if (curve_config->segments[i] == -1)
+			break;
+
+		ASSERT(curve_config->segments[i] >= 0);
+
+		segments += (1 << curve_config->segments[i]);
+
+		++i;
+	}
+
+	if (segments > max_number) {
+		BREAK_TO_DEBUGGER();
+	} else {
+		int32_t divisor;
+		uint32_t offset = 0;
+		int8_t begin = curve_config->begin;
+		int32_t region_number = 0;
+
+		i = begin;
+
+		while ((index < max_number) &&
+			(region_number < max_regions_number) &&
+			(i <= 1)) {
+			int32_t j = 0;
+
+			segments = curve_config->segments[region_number];
+			divisor = 1 << segments;
+
+			if (segments == -1) {
+				if (i > 0) {
+					region1 = dal_fixed31_32_shl(
+						dal_fixed31_32_one,
+						i - 1);
+					region2 = dal_fixed31_32_shl(
+						dal_fixed31_32_one,
+						i);
+				} else {
+					region1 = dal_fixed31_32_shr(
+						dal_fixed31_32_one,
+						-(i - 1));
+					region2 = dal_fixed31_32_shr(
+						dal_fixed31_32_one,
+						-i);
+				}
+
+				break;
+			}
+
+			if (i > -1) {
+				region1 = dal_fixed31_32_shl(
+					dal_fixed31_32_one,
+					i);
+				region2 = dal_fixed31_32_shl(
+					dal_fixed31_32_one,
+					i + 1);
+			} else {
+				region1 = dal_fixed31_32_shr(
+					dal_fixed31_32_one,
+					-i);
+				region2 = dal_fixed31_32_shr(
+					dal_fixed31_32_one,
+					-(i + 1));
+			}
+
+			gamma_curve[region_number].offset = offset;
+			gamma_curve[region_number].segments_num = segments;
+
+			offset += divisor;
+
+			++segments_calculation[segments];
+
+			increment = dal_fixed31_32_div_int(
+				dal_fixed31_32_sub(
+					region2,
+					region1),
+				divisor);
+
+			points[index].x = region1;
+
+			round_custom_float_6_12(points + index);
+
+			++index;
+			++region_number;
+
+			while ((index < max_number) && (j < divisor - 1)) {
+				region1 = dal_fixed31_32_add(
+					region1,
+					increment);
+
+				points[index].x = region1;
+				points[index].adjusted_x = region1;
+
+				++index;
+				++j;
+			}
+
+			++i;
+		}
+
+		points[index].x = region1;
+
+		round_custom_float_6_12(points + index);
+
+		*number_of_points = index;
+
+		result = true;
+	}
+
+	curve_points[0].x = points[0].adjusted_x;
+	curve_points[0].offset = dal_fixed31_32_zero;
+
+	curve_points[1].x = points[index - 1].adjusted_x;
+	curve_points[1].offset = dal_fixed31_32_zero;
+
+	curve_points[2].x = points[index].adjusted_x;
+	curve_points[2].offset = dal_fixed31_32_zero;
+
+	return result;
+}
+
+static bool setup_distribution_points(
+	struct dce110_opp *opp110)
+{
+	uint32_t hw_points_num = MAX_PWL_ENTRY * 2;
+
+	struct curve_config cfg;
+
+	cfg.offset = 0;
+
+		cfg.segments[0] = 3;
+		cfg.segments[1] = 4;
+		cfg.segments[2] = 4;
+		cfg.segments[3] = 4;
+		cfg.segments[4] = 4;
+		cfg.segments[5] = 4;
+		cfg.segments[6] = 4;
+		cfg.segments[7] = 4;
+		cfg.segments[8] = 5;
+		cfg.segments[9] = 5;
+		cfg.segments[10] = 0;
+		cfg.segments[11] = -1;
+		cfg.segments[12] = -1;
+		cfg.segments[13] = -1;
+		cfg.segments[14] = -1;
+		cfg.segments[15] = -1;
+
+	cfg.begin = -10;
+
+	if (!build_hw_curve_configuration(
+		&cfg, opp110->regamma.arr_curve_points,
+		opp110->regamma.arr_points,
+		opp110->regamma.coordinates_x, &hw_points_num)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	opp110->regamma.hw_points_num = hw_points_num;
+
+	return true;
+}
+
+
+/*
+ *****************************************************************************
+ *  Function: regamma_config_regions_and_segments
+ *
+ *     build regamma curve by using predefined hw points
+ *     uses interface parameters ,like EDID coeff.
+ *
+ * @param   : parameters   interface parameters
+ *  @return void
+ *
+ *  @note
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+static void regamma_config_regions_and_segments(
+	struct dce110_opp *opp110)
+{
+	struct gamma_curve *curve;
+	uint32_t value = 0;
+
+	{
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[0].custom_float_x,
+			REGAMMA_CNTLA_START_CNTL,
+			REGAMMA_CNTLA_EXP_REGION_START);
+
+		set_reg_field_value(
+			value,
+			0,
+			REGAMMA_CNTLA_START_CNTL,
+			REGAMMA_CNTLA_EXP_REGION_START_SEGMENT);
+
+		dm_write_reg(opp110->base.ctx,
+				DCP_REG(mmREGAMMA_CNTLA_START_CNTL),
+				value);
+	}
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[0].custom_float_slope,
+			REGAMMA_CNTLA_SLOPE_CNTL,
+			REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_SLOPE_CNTL), value);
+	}
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[1].custom_float_x,
+			REGAMMA_CNTLA_END_CNTL1,
+			REGAMMA_CNTLA_EXP_REGION_END);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_END_CNTL1), value);
+	}
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[2].custom_float_slope,
+			REGAMMA_CNTLA_END_CNTL2,
+			REGAMMA_CNTLA_EXP_REGION_END_BASE);
+
+		set_reg_field_value(
+			value,
+			opp110->regamma.arr_points[1].custom_float_y,
+			REGAMMA_CNTLA_END_CNTL2,
+			REGAMMA_CNTLA_EXP_REGION_END_SLOPE);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_END_CNTL2), value);
+	}
+
+	curve = opp110->regamma.arr_curve_points;
+
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_0_1,
+			REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS);
+
+		dm_write_reg(
+			opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_0_1),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_2_3,
+			REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_2_3),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_4_5,
+			REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_4_5),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_6_7,
+			REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_6_7),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_8_9,
+			REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_8_9),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_10_11,
+			REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_10_11),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_12_13,
+			REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_12_13),
+			value);
+	}
+
+	curve += 2;
+	{
+		value = 0;
+		set_reg_field_value(
+			value,
+			curve[0].offset,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[0].segments_num,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS);
+
+		set_reg_field_value(
+			value,
+			curve[1].offset,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET);
+
+		set_reg_field_value(
+			value,
+			curve[1].segments_num,
+			REGAMMA_CNTLA_REGION_14_15,
+			REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS);
+
+		dm_write_reg(opp110->base.ctx,
+			DCP_REG(mmREGAMMA_CNTLA_REGION_14_15),
+			value);
+	}
+}
+
+static void program_pwl(
+	struct dce110_opp *opp110,
+	const struct gamma_parameters *params)
+{
+	uint32_t value;
+
+	{
+		uint8_t max_tries = 10;
+		uint8_t counter = 0;
+
+		/* Power on LUT memory */
+		value = dm_read_reg(opp110->base.ctx,
+				DCFE_REG(mmDCFE_MEM_PWR_CTRL));
+
+		set_reg_field_value(
+			value,
+			1,
+			DCFE_MEM_PWR_CTRL,
+			DCP_REGAMMA_MEM_PWR_DIS);
+
+		dm_write_reg(opp110->base.ctx,
+				DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
+
+		while (counter < max_tries) {
+			value =
+				dm_read_reg(
+					opp110->base.ctx,
+					DCFE_REG(mmDCFE_MEM_PWR_STATUS));
+
+			if (get_reg_field_value(
+				value,
+				DCFE_MEM_PWR_STATUS,
+				DCP_REGAMMA_MEM_PWR_STATE) == 0)
+				break;
+
+			++counter;
+		}
+
+		if (counter == max_tries) {
+			dal_logger_write(opp110->base.ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: regamma lut was not powered on "
+				"in a timely manner,"
+				" programming still proceeds\n",
+				__func__);
+		}
+	}
+
+	value = 0;
+
+	set_reg_field_value(
+		value,
+		7,
+		REGAMMA_LUT_WRITE_EN_MASK,
+		REGAMMA_LUT_WRITE_EN_MASK);
+
+	dm_write_reg(opp110->base.ctx,
+		DCP_REG(mmREGAMMA_LUT_WRITE_EN_MASK), value);
+	dm_write_reg(opp110->base.ctx,
+		DCP_REG(mmREGAMMA_LUT_INDEX), 0);
+
+	/* Program REGAMMA_LUT_DATA */
+	{
+		const uint32_t addr = DCP_REG(mmREGAMMA_LUT_DATA);
+
+		uint32_t i = 0;
+
+		struct pwl_result_data *rgb =
+				opp110->regamma.rgb_resulted;
+
+		while (i != opp110->regamma.hw_points_num) {
+			dm_write_reg(opp110->base.ctx, addr, rgb->red_reg);
+			dm_write_reg(opp110->base.ctx, addr, rgb->green_reg);
+			dm_write_reg(opp110->base.ctx, addr, rgb->blue_reg);
+
+			dm_write_reg(opp110->base.ctx, addr,
+				rgb->delta_red_reg);
+			dm_write_reg(opp110->base.ctx, addr,
+				rgb->delta_green_reg);
+			dm_write_reg(opp110->base.ctx, addr,
+				rgb->delta_blue_reg);
+
+			++rgb;
+			++i;
+		}
+	}
+
+	/*  we are done with DCP LUT memory; re-enable low power mode */
+	value = dm_read_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL));
+
+	set_reg_field_value(
+		value,
+		0,
+		DCFE_MEM_PWR_CTRL,
+		DCP_REGAMMA_MEM_PWR_DIS);
+
+	dm_write_reg(opp110->base.ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
+}
+
+void dce110_opp_power_on_regamma_lut(
+	struct output_pixel_processor *opp,
+	bool power_on)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	uint32_t value =
+		dm_read_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL));
+
+	set_reg_field_value(
+		value,
+		power_on,
+		DCFE_MEM_PWR_CTRL,
+		DCP_REGAMMA_MEM_PWR_DIS);
+
+	set_reg_field_value(
+		value,
+		power_on,
+		DCFE_MEM_PWR_CTRL,
+		DCP_LUT_MEM_PWR_DIS);
+
+	dm_write_reg(opp->ctx, DCFE_REG(mmDCFE_MEM_PWR_CTRL), value);
+}
+
+static bool scale_gamma(
+	struct dce110_opp *opp110,
+	const struct gamma_ramp *gamma_ramp,
+	const struct gamma_parameters *params)
+{
+	const struct gamma_ramp_rgb256x3x16 *gamma;
+	bool use_palette = params->surface_pixel_format == PIXEL_FORMAT_INDEX8;
+
+	const uint16_t max_driver = 0xFFFF;
+	const uint16_t max_os = 0xFF00;
+
+	uint16_t scaler = max_os;
+
+	uint32_t i;
+
+	struct dev_c_lut *palette = opp110->regamma.saved_palette;
+
+	struct pwl_float_data *rgb = opp110->regamma.rgb_user;
+	struct pwl_float_data *rgb_last = rgb + RGB_256X3X16 - 1;
+
+	if (gamma_ramp->type == GAMMA_RAMP_RBG256X3X16)
+		gamma = &gamma_ramp->gamma_ramp_rgb256x3x16;
+	else
+		return false; /* invalid option */
+
+	i = 0;
+
+	do {
+		if ((gamma->red[i] > max_os) ||
+			(gamma->green[i] > max_os) ||
+			(gamma->blue[i] > max_os)) {
+			scaler = max_driver;
+			break;
+		}
+		++i;
+	} while (i != RGB_256X3X16);
+
+	i = 0;
+
+	if (use_palette)
+		do {
+			rgb->r = dal_fixed31_32_from_fraction(
+				gamma->red[palette->red], scaler);
+			rgb->g = dal_fixed31_32_from_fraction(
+				gamma->green[palette->green], scaler);
+			rgb->b = dal_fixed31_32_from_fraction(
+				gamma->blue[palette->blue], scaler);
+
+			++palette;
+			++rgb;
+			++i;
+		} while (i != RGB_256X3X16);
+	else
+		do {
+			rgb->r = dal_fixed31_32_from_fraction(
+				gamma->red[i], scaler);
+			rgb->g = dal_fixed31_32_from_fraction(
+				gamma->green[i], scaler);
+			rgb->b = dal_fixed31_32_from_fraction(
+				gamma->blue[i], scaler);
+
+			++rgb;
+			++i;
+		} while (i != RGB_256X3X16);
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider1);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider1);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider1);
+
+	++rgb;
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider2);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider2);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider2);
+
+	++rgb;
+
+	rgb->r = dal_fixed31_32_mul(rgb_last->r,
+			opp110->regamma.divider3);
+	rgb->g = dal_fixed31_32_mul(rgb_last->g,
+			opp110->regamma.divider3);
+	rgb->b = dal_fixed31_32_mul(rgb_last->b,
+			opp110->regamma.divider3);
+
+	return true;
+}
+
+
+static void configure_regamma_mode(
+	struct dce110_opp *opp110,
+	const struct gamma_parameters *params,
+	bool force_bypass)
+{
+	const uint32_t addr = DCP_REG(mmREGAMMA_CONTROL);
+
+	enum wide_gamut_regamma_mode mode =
+		WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A;
+
+	uint32_t value = dm_read_reg(opp110->base.ctx, addr);
+
+	if (force_bypass) {
+
+		set_reg_field_value(
+			value,
+			0,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+
+		dm_write_reg(opp110->base.ctx, addr, value);
+
+		return;
+	}
+
+	if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_BYPASS)
+		mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS;
+	else if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_HW) {
+		if (params->surface_pixel_format == PIXEL_FORMAT_FP16)
+			mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS;
+		else
+			mode = WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24;
+	}
+
+	switch (mode) {
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS:
+		set_reg_field_value(
+			value,
+			0,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24:
+		set_reg_field_value(
+			value,
+			1,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22:
+		set_reg_field_value(
+			value,
+			2,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A:
+		set_reg_field_value(
+			value,
+			3,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	case WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B:
+		set_reg_field_value(
+			value,
+			4,
+			REGAMMA_CONTROL,
+			GRPH_REGAMMA_MODE);
+		break;
+	default:
+		break;
+	}
+
+	dm_write_reg(opp110->base.ctx, addr, value);
+}
+
+bool dce110_opp_set_regamma(
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *ramp,
+	const struct gamma_parameters *params,
+	bool force_bypass)
+{
+	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
+
+	if (force_bypass) {
+		configure_regamma_mode(opp110, params, true);
+	} else {
+		/* 1. Scale gamma to 0 - 1 to m_pRgbUser */
+		if (!scale_gamma(opp110, ramp, params)) {
+			ASSERT_CRITICAL(false);
+			/* invalid option */
+			return false;
+		}
+
+		/* 2. Configure regamma curve without analysis (future task) */
+		/*    and program the PWL regions and segments */
+		if (params->regamma_adjust_type == GRAPHICS_REGAMMA_ADJUST_SW ||
+			params->surface_pixel_format == PIXEL_FORMAT_FP16) {
+
+			/* 3. Setup x exponentially distributed points */
+			if (!setup_distribution_points(opp110)) {
+				ASSERT_CRITICAL(false);
+				/* invalid option */
+				return false;
+			}
+
+			/* 4. Build ideal regamma curve */
+			if (!build_regamma_curve(opp110, params)) {
+				ASSERT_CRITICAL(false);
+				/* invalid parameters or bug */
+				return false;
+			}
+
+			/* 5. Map user gamma (evenly distributed x points) to
+			 * new curve when x is y from ideal regamma , step 5 */
+			if (!map_regamma_hw_to_x_user(
+				opp110, ramp, params)) {
+				ASSERT_CRITICAL(false);
+				/* invalid parameters or bug */
+				return false;
+			}
+
+			/* 6.Build and verify resulted curve */
+			build_new_custom_resulted_curve(opp110, params);
+
+			/* 7. Build and translate x to hw format */
+			if (!rebuild_curve_configuration_magic(opp110)) {
+				ASSERT_CRITICAL(false);
+				/* invalid parameters or bug */
+				return false;
+			}
+
+			/* 8. convert all params to the custom float format */
+			if (!convert_to_custom_float(opp110)) {
+				ASSERT_CRITICAL(false);
+				/* invalid parameters or bug */
+				return false;
+			}
+
+			/* 9. program regamma curve configuration */
+			regamma_config_regions_and_segments(opp110);
+
+			/* 10. Program PWL */
+			program_pwl(opp110, params);
+		}
+
+		/*
+		 * 11. program regamma config
+		 */
+		configure_regamma_mode(opp110, params, false);
+	}
+	return true;
+}
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 20/26] drm/amd/dal: Add transform & scaler HW programming
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (18 preceding siblings ...)
  2016-02-16 22:27   ` [PATCH v2 19/26] drm/amd/dal: Add output " Harry Wentland
@ 2016-02-16 22:28   ` Harry Wentland
  2016-02-16 22:28   ` [PATCH v2 21/26] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
                     ` (5 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:28 UTC (permalink / raw)
  To: dri-devel

Adds scaler, viewport, gamut remap, and pixel depth programming.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c   |  91 +++
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.h   |  87 +++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.c | 851 +++++++++++++++++++++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.h |  51 ++
 .../drm/amd/dal/dc/dce110/dce110_transform_gamut.c | 296 +++++++
 .../drm/amd/dal/dc/dce110/dce110_transform_scl.c   | 818 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c  | 531 +++++++++++++
 7 files changed, 2725 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
new file mode 100644
index 000000000000..2654a965065d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dc_types.h"
+#include "core_types.h"
+
+#include "include/grph_object_id.h"
+#include "include/fixed31_32.h"
+#include "include/logger_interface.h"
+
+#include "dce110_transform.h"
+
+#include "dce110_transform_bit_depth.h"
+
+static struct transform_funcs dce110_transform_funcs = {
+	.transform_power_up =
+		dce110_transform_power_up,
+	.transform_set_scaler =
+		dce110_transform_set_scaler,
+	.transform_set_scaler_bypass =
+		dce110_transform_set_scaler_bypass,
+	.transform_update_viewport =
+		dce110_transform_update_viewport,
+	.transform_set_scaler_filter =
+		dce110_transform_set_scaler_filter,
+	.transform_set_gamut_remap =
+		dce110_transform_set_gamut_remap,
+	.transform_set_pixel_storage_depth =
+		dce110_transform_set_pixel_storage_depth,
+	.transform_get_current_pixel_storage_depth =
+		dce110_transform_get_current_pixel_storage_depth
+};
+
+/*****************************************/
+/* Constructor, Destructor               */
+/*****************************************/
+
+bool dce110_transform_construct(
+	struct dce110_transform *xfm110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *reg_offsets)
+{
+	xfm110->base.ctx = ctx;
+
+	xfm110->base.inst = inst;
+	xfm110->base.funcs = &dce110_transform_funcs;
+
+	xfm110->offsets = *reg_offsets;
+
+	xfm110->lb_pixel_depth_supported =
+			LB_PIXEL_DEPTH_18BPP |
+			LB_PIXEL_DEPTH_24BPP |
+			LB_PIXEL_DEPTH_30BPP;
+
+	return true;
+}
+
+bool dce110_transform_power_up(struct transform *xfm)
+{
+	return dce110_transform_power_up_line_buffer(xfm);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
new file mode 100644
index 000000000000..117aca337f9d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
@@ -0,0 +1,87 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TRANSFORM_DCE110_H__
+#define __DAL_TRANSFORM_DCE110_H__
+
+#include "inc/transform.h"
+#include "include/grph_csc_types.h"
+
+#define TO_DCE110_TRANSFORM(transform)\
+	container_of(transform, struct dce110_transform, base)
+
+struct dce110_transform_reg_offsets {
+	uint32_t scl_offset;
+	uint32_t dcfe_offset;
+	uint32_t dcp_offset;
+	uint32_t lb_offset;
+};
+
+struct dce110_transform {
+	struct transform base;
+	struct dce110_transform_reg_offsets offsets;
+
+	uint32_t lb_pixel_depth_supported;
+};
+
+bool dce110_transform_construct(struct dce110_transform *xfm110,
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *reg_offsets);
+
+bool dce110_transform_power_up(struct transform *xfm);
+
+/* SCALER RELATED */
+bool dce110_transform_set_scaler(
+	struct transform *xfm,
+	const struct scaler_data *data);
+
+void dce110_transform_set_scaler_bypass(struct transform *xfm);
+
+bool dce110_transform_update_viewport(
+	struct transform *xfm,
+	const struct rect *view_port,
+	bool is_fbc_attached);
+
+void dce110_transform_set_scaler_filter(
+	struct transform *xfm,
+	struct scaler_filter *filter);
+
+/* GAMUT RELATED */
+void dce110_transform_set_gamut_remap(
+	struct transform *xfm,
+	const struct grph_csc_adjustment *adjust);
+
+/* BIT DEPTH RELATED */
+bool dce110_transform_set_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth depth,
+	const struct bit_depth_reduction_params *bit_depth_params);
+
+bool dce110_transform_get_current_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth *depth);
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
new file mode 100644
index 000000000000..fb5ef6d2c859
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
@@ -0,0 +1,851 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_transform.h"
+#include "opp.h"
+#include "include/logger_interface.h"
+#include "include/fixed32_32.h"
+
+#define DCP_REG(reg)\
+	(reg + xfm110->offsets.dcp_offset)
+
+#define LB_REG(reg)\
+	(reg + xfm110->offsets.lb_offset)
+
+#define LB_TOTAL_NUMBER_OF_ENTRIES 1712
+#define LB_BITS_PER_ENTRY 144
+
+enum dcp_out_trunc_round_mode {
+	DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+	DCP_OUT_TRUNC_ROUND_MODE_ROUND
+};
+
+enum dcp_out_trunc_round_depth {
+	DCP_OUT_TRUNC_ROUND_DEPTH_14BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_13BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_12BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_11BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_10BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_9BIT,
+	DCP_OUT_TRUNC_ROUND_DEPTH_8BIT
+};
+
+/*  defines the various methods of bit reduction available for use */
+enum dcp_bit_depth_reduction_mode {
+	DCP_BIT_DEPTH_REDUCTION_MODE_DITHER,
+	DCP_BIT_DEPTH_REDUCTION_MODE_ROUND,
+	DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE,
+	DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED,
+	DCP_BIT_DEPTH_REDUCTION_MODE_INVALID
+};
+
+enum dcp_spatial_dither_mode {
+	DCP_SPATIAL_DITHER_MODE_AAAA,
+	DCP_SPATIAL_DITHER_MODE_A_AA_A,
+	DCP_SPATIAL_DITHER_MODE_AABBAABB,
+	DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC,
+	DCP_SPATIAL_DITHER_MODE_INVALID
+};
+
+enum dcp_spatial_dither_depth {
+	DCP_SPATIAL_DITHER_DEPTH_30BPP,
+	DCP_SPATIAL_DITHER_DEPTH_24BPP
+};
+
+static bool set_clamp(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth);
+
+static bool set_round(
+	struct dce110_transform *xfm110,
+	enum dcp_out_trunc_round_mode mode,
+	enum dcp_out_trunc_round_depth depth);
+
+static bool set_dither(
+	struct dce110_transform *xfm110,
+	bool dither_enable,
+	enum dcp_spatial_dither_mode dither_mode,
+	enum dcp_spatial_dither_depth dither_depth,
+	bool frame_random_enable,
+	bool rgb_random_enable,
+	bool highpass_random_enable);
+
+/**
+ *******************************************************************************
+ * dce110_transform_bit_depth_reduction_program
+ *
+ * @brief
+ *     Programs the DCP bit depth reduction registers (Clamp, Round/Truncate,
+ *      Dither) for dce110
+ *
+ * @param depth : bit depth to set the clamp to (should match denorm)
+ *
+ * @return
+ *     true if succeeds.
+ *******************************************************************************
+ */
+static bool program_bit_depth_reduction(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth,
+	const struct bit_depth_reduction_params *bit_depth_params)
+{
+	enum dcp_bit_depth_reduction_mode depth_reduction_mode;
+	enum dcp_spatial_dither_mode spatial_dither_mode;
+	bool frame_random_enable;
+	bool rgb_random_enable;
+	bool highpass_random_enable;
+
+	if (depth > COLOR_DEPTH_121212) {
+		ASSERT_CRITICAL(false); /* Invalid clamp bit depth */
+		return false;
+	}
+
+	if (bit_depth_params->flags.SPATIAL_DITHER_ENABLED) {
+		depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DITHER;
+		frame_random_enable = true;
+		rgb_random_enable = true;
+		highpass_random_enable = true;
+
+	} else {
+		depth_reduction_mode = DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED;
+		frame_random_enable = false;
+		rgb_random_enable = false;
+		highpass_random_enable = false;
+	}
+
+	spatial_dither_mode = DCP_SPATIAL_DITHER_MODE_A_AA_A;
+
+	if (!set_clamp(xfm110, depth)) {
+		/* Failure in set_clamp() */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	switch (depth_reduction_mode) {
+	case DCP_BIT_DEPTH_REDUCTION_MODE_DITHER:
+		/*  Spatial Dither: Set round/truncate to bypass (12bit),
+		 *  enable Dither (30bpp) */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+			DCP_OUT_TRUNC_ROUND_DEPTH_12BIT);
+
+		set_dither(xfm110, true, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+	case DCP_BIT_DEPTH_REDUCTION_MODE_ROUND:
+		/*  Round: Enable round (10bit), disable Dither */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_ROUND,
+			DCP_OUT_TRUNC_ROUND_DEPTH_10BIT);
+
+		set_dither(xfm110, false, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+	case DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE: /*  Truncate */
+		/*  Truncate: Enable truncate (10bit), disable Dither */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+			DCP_OUT_TRUNC_ROUND_DEPTH_10BIT);
+
+		set_dither(xfm110, false, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+
+	case DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED: /*  Disabled */
+		/*  Truncate: Set round/truncate to bypass (12bit),
+		 * disable Dither */
+		set_round(xfm110,
+			DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
+			DCP_OUT_TRUNC_ROUND_DEPTH_12BIT);
+
+		set_dither(xfm110, false, spatial_dither_mode,
+			DCP_SPATIAL_DITHER_DEPTH_30BPP, frame_random_enable,
+			rgb_random_enable, highpass_random_enable);
+		break;
+	default:
+		/* Invalid DCP Depth reduction mode */
+		ASSERT_CRITICAL(false);
+		break;
+	}
+
+	return true;
+}
+
+/**
+ *******************************************************************************
+ * set_clamp
+ *
+ * @param depth : bit depth to set the clamp to (should match denorm)
+ *
+ * @brief
+ *     Programs clamp according to panel bit depth.
+ *
+ * @return
+ *     true if succeeds
+ *
+ *******************************************************************************
+ */
+static bool set_clamp(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth)
+{
+	uint32_t clamp_max = 0;
+
+	/* At the clamp block the data will be MSB aligned, so we set the max
+	 * clamp accordingly.
+	 * For example, the max value for 6 bits MSB aligned (14 bit bus) would
+	 * be "11 1111 0000 0000" in binary, so 0x3F00.
+	 */
+	switch (depth) {
+	case COLOR_DEPTH_666:
+		/* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */
+		clamp_max = 0x3F00;
+		break;
+	case COLOR_DEPTH_888:
+		/* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */
+		clamp_max = 0x3FC0;
+		break;
+	case COLOR_DEPTH_101010:
+		/* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
+		clamp_max = 0x3FFC;
+		break;
+	case COLOR_DEPTH_121212:
+		/* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */
+		clamp_max = 0x3FFF;
+		break;
+	default:
+		ASSERT_CRITICAL(false); /* Invalid clamp bit depth */
+		return false;
+	}
+
+	{
+		uint32_t value = 0;
+		/*  always set min to 0 */
+			set_reg_field_value(
+			value,
+			0,
+			OUT_CLAMP_CONTROL_B_CB,
+			OUT_CLAMP_MIN_B_CB);
+
+		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_B_CB,
+			OUT_CLAMP_MAX_B_CB);
+
+		dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmOUT_CLAMP_CONTROL_B_CB),
+			value);
+	}
+
+	{
+		uint32_t value = 0;
+		/*  always set min to 0 */
+		set_reg_field_value(
+			value,
+			0,
+			OUT_CLAMP_CONTROL_G_Y,
+			OUT_CLAMP_MIN_G_Y);
+
+		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_G_Y,
+			OUT_CLAMP_MAX_G_Y);
+
+		dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmOUT_CLAMP_CONTROL_G_Y),
+			value);
+	}
+
+	{
+		uint32_t value = 0;
+		/*  always set min to 0 */
+		set_reg_field_value(
+			value,
+			0,
+			OUT_CLAMP_CONTROL_R_CR,
+			OUT_CLAMP_MIN_R_CR);
+
+		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_R_CR,
+			OUT_CLAMP_MAX_R_CR);
+
+		dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmOUT_CLAMP_CONTROL_R_CR),
+			value);
+	}
+
+	return true;
+}
+
+/**
+ *******************************************************************************
+ * set_round
+ *
+ * @brief
+ *     Programs Round/Truncate
+ *
+ * @param [in] mode  :round or truncate
+ * @param [in] depth :bit depth to round/truncate to
+ OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode
+ POSSIBLE VALUES:
+      00 - truncate to u0.12
+      01 - truncate to u0.11
+      02 - truncate to u0.10
+      03 - truncate to u0.9
+      04 - truncate to u0.8
+      05 - reserved
+      06 - truncate to u0.14
+      07 - truncate to u0.13		set_reg_field_value(
+			value,
+			clamp_max,
+			OUT_CLAMP_CONTROL_R_CR,
+			OUT_CLAMP_MAX_R_CR);
+      08 - round to u0.12
+      09 - round to u0.11
+      10 - round to u0.10
+      11 - round to u0.9
+      12 - round to u0.8
+      13 - reserved
+      14 - round to u0.14
+      15 - round to u0.13
+
+ * @return
+ *     true if succeeds.
+ *******************************************************************************
+ */
+static bool set_round(
+	struct dce110_transform *xfm110,
+	enum dcp_out_trunc_round_mode mode,
+	enum dcp_out_trunc_round_depth depth)
+{
+	uint32_t depth_bits = 0;
+	uint32_t mode_bit = 0;
+	/*  zero out all bits */
+	uint32_t value = 0;
+
+	/*  set up bit depth */
+	switch (depth) {
+	case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT:
+		depth_bits = 6;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT:
+		depth_bits = 7;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT:
+		depth_bits = 0;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT:
+		depth_bits = 1;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT:
+		depth_bits = 2;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT:
+		depth_bits = 3;
+		break;
+	case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT:
+		depth_bits = 4;
+		break;
+	default:
+		/* Invalid dcp_out_trunc_round_depth */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	set_reg_field_value(
+		value,
+		depth_bits,
+		OUT_ROUND_CONTROL,
+		OUT_ROUND_TRUNC_MODE);
+
+	/*  set up round or truncate */
+	switch (mode) {
+	case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE:
+		mode_bit = 0;
+		break;
+	case DCP_OUT_TRUNC_ROUND_MODE_ROUND:
+		mode_bit = 1;
+		break;
+	default:
+		/* Invalid dcp_out_trunc_round_mode */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	depth_bits |= mode_bit << 3;
+
+	set_reg_field_value(
+		value,
+		depth_bits,
+		OUT_ROUND_CONTROL,
+		OUT_ROUND_TRUNC_MODE);
+
+	/*  write the register */
+	dm_write_reg(xfm110->base.ctx,
+				DCP_REG(mmOUT_ROUND_CONTROL),
+				value);
+
+	return true;
+}
+
+/**
+ *******************************************************************************
+ * set_dither
+ *
+ * @brief
+ *     Programs Dither
+ *
+ * @param [in] dither_enable        : enable dither
+ * @param [in] dither_mode           : dither mode to set
+ * @param [in] dither_depth          : bit depth to dither to
+ * @param [in] frame_random_enable    : enable frame random
+ * @param [in] rgb_random_enable      : enable rgb random
+ * @param [in] highpass_random_enable : enable highpass random
+ *
+ * @return
+ *     true if succeeds.
+ *******************************************************************************
+ */
+
+static bool set_dither(
+	struct dce110_transform *xfm110,
+	bool dither_enable,
+	enum dcp_spatial_dither_mode dither_mode,
+	enum dcp_spatial_dither_depth dither_depth,
+	bool frame_random_enable,
+	bool rgb_random_enable,
+	bool highpass_random_enable)
+{
+	uint32_t dither_depth_bits = 0;
+	uint32_t dither_mode_bits = 0;
+	/*  zero out all bits */
+	uint32_t value = 0;
+
+	/* set up the fields */
+	if (dither_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_SPATIAL_DITHER_EN);
+
+	switch (dither_mode) {
+	case DCP_SPATIAL_DITHER_MODE_AAAA:
+		dither_mode_bits = 0;
+		break;
+	case DCP_SPATIAL_DITHER_MODE_A_AA_A:
+		dither_mode_bits = 1;
+		break;
+	case DCP_SPATIAL_DITHER_MODE_AABBAABB:
+		dither_mode_bits = 2;
+		break;
+	case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC:
+		dither_mode_bits = 3;
+		break;
+	default:
+		/* Invalid dcp_spatial_dither_mode */
+		ASSERT_CRITICAL(false);
+		return false;
+
+	}
+	set_reg_field_value(
+		value,
+		dither_mode_bits,
+		DCP_SPATIAL_DITHER_CNTL,
+		DCP_SPATIAL_DITHER_MODE);
+
+	switch (dither_depth) {
+	case DCP_SPATIAL_DITHER_DEPTH_30BPP:
+		dither_depth_bits = 0;
+		break;
+	case DCP_SPATIAL_DITHER_DEPTH_24BPP:
+		dither_depth_bits = 1;
+		break;
+	default:
+		/* Invalid dcp_spatial_dither_depth */
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	set_reg_field_value(
+		value,
+		dither_depth_bits,
+		DCP_SPATIAL_DITHER_CNTL,
+		DCP_SPATIAL_DITHER_DEPTH);
+
+	if (frame_random_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_FRAME_RANDOM_ENABLE);
+
+	if (rgb_random_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_RGB_RANDOM_ENABLE);
+
+	if (highpass_random_enable)
+		set_reg_field_value(
+			value,
+			1,
+			DCP_SPATIAL_DITHER_CNTL,
+			DCP_HIGHPASS_RANDOM_ENABLE);
+
+	/*  write the register */
+	dm_write_reg(xfm110->base.ctx,
+				DCP_REG(mmDCP_SPATIAL_DITHER_CNTL),
+				value);
+
+	return true;
+}
+
+bool dce110_transform_get_max_num_of_supported_lines(
+	struct dce110_transform *xfm110,
+	enum lb_pixel_depth depth,
+	uint32_t pixel_width,
+	uint32_t *lines)
+{
+	uint32_t pixels_per_entries = 0;
+	uint32_t max_pixels_supports = 0;
+
+	if (pixel_width == 0)
+		return false;
+
+	/* Find number of pixels that can fit into a single LB entry and
+	 * take floor of the value since we cannot store a single pixel
+	 * across multiple entries. */
+	switch (depth) {
+	case LB_PIXEL_DEPTH_18BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 18;
+		break;
+
+	case LB_PIXEL_DEPTH_24BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 24;
+		break;
+
+	case LB_PIXEL_DEPTH_30BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 30;
+		break;
+
+	case LB_PIXEL_DEPTH_36BPP:
+		pixels_per_entries = LB_BITS_PER_ENTRY / 36;
+		break;
+
+	default:
+		dal_logger_write(xfm110->base.ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Invalid LB pixel depth",
+			__func__);
+		break;
+	}
+
+	if (pixels_per_entries == 0)
+		return false;
+
+	max_pixels_supports = pixels_per_entries * LB_TOTAL_NUMBER_OF_ENTRIES;
+
+	*lines = max_pixels_supports / pixel_width;
+	return true;
+}
+
+void dce110_transform_enable_alpha(
+	struct dce110_transform *xfm110,
+	bool enable)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value;
+	uint32_t addr = LB_REG(mmLB_DATA_FORMAT);
+
+	value = dm_read_reg(ctx, addr);
+
+	if (enable == 1)
+		set_reg_field_value(
+				value,
+				1,
+				LB_DATA_FORMAT,
+				ALPHA_EN);
+	else
+		set_reg_field_value(
+				value,
+				0,
+				LB_DATA_FORMAT,
+				ALPHA_EN);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static enum lb_pixel_depth translate_display_bpp_to_lb_depth(
+	uint32_t display_bpp)
+{
+	switch (display_bpp) {
+	case 18:
+		return LB_PIXEL_DEPTH_18BPP;
+	case 24:
+		return LB_PIXEL_DEPTH_24BPP;
+	case 36:
+	case 42:
+	case 48:
+		return LB_PIXEL_DEPTH_36BPP;
+	case 30:
+	default:
+		return LB_PIXEL_DEPTH_30BPP;
+	}
+}
+
+bool dce110_transform_get_next_lower_pixel_storage_depth(
+	struct dce110_transform *xfm110,
+	uint32_t display_bpp,
+	enum lb_pixel_depth depth,
+	enum lb_pixel_depth *lower_depth)
+{
+	enum lb_pixel_depth depth_req_by_display =
+		translate_display_bpp_to_lb_depth(display_bpp);
+	uint32_t current_required_depth = depth_req_by_display;
+	uint32_t current_depth = depth;
+
+	/* if required display depth < current we could go down, for example
+	 * from LB_PIXEL_DEPTH_30BPP to LB_PIXEL_DEPTH_24BPP
+	 */
+	if (current_required_depth < current_depth) {
+		current_depth = current_depth >> 1;
+		if (xfm110->lb_pixel_depth_supported & current_depth) {
+			*lower_depth = current_depth;
+			return true;
+		}
+	}
+	return false;
+}
+
+bool dce110_transform_is_prefetch_enabled(
+	struct dce110_transform *xfm110)
+{
+	uint32_t value = dm_read_reg(
+			xfm110->base.ctx, LB_REG(mmLB_DATA_FORMAT));
+
+	if (get_reg_field_value(value, LB_DATA_FORMAT, PREFETCH) == 1)
+		return true;
+
+	return false;
+}
+
+bool dce110_transform_get_current_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth *depth)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	uint32_t value = 0;
+
+	if (depth == NULL)
+		return false;
+
+	value = dm_read_reg(
+			xfm->ctx,
+			LB_REG(mmLB_DATA_FORMAT));
+
+	switch (get_reg_field_value(value, LB_DATA_FORMAT, PIXEL_DEPTH)) {
+	case 0:
+		*depth = LB_PIXEL_DEPTH_30BPP;
+		break;
+	case 1:
+		*depth = LB_PIXEL_DEPTH_24BPP;
+		break;
+	case 2:
+		*depth = LB_PIXEL_DEPTH_18BPP;
+		break;
+	case 3:
+		*depth = LB_PIXEL_DEPTH_36BPP;
+		break;
+	default:
+		dal_logger_write(xfm->ctx->logger,
+			LOG_MAJOR_WARNING,
+			LOG_MINOR_COMPONENT_GPU,
+			"%s: Invalid LB pixel depth",
+			__func__);
+		*depth = LB_PIXEL_DEPTH_30BPP;
+		break;
+	}
+	return true;
+
+}
+
+static void set_denormalization(
+	struct dce110_transform *xfm110,
+	enum dc_color_depth depth)
+{
+	uint32_t value = dm_read_reg(xfm110->base.ctx,
+			DCP_REG(mmDENORM_CONTROL));
+
+	switch (depth) {
+	case COLOR_DEPTH_666:
+		/* 63/64 for 6 bit output color depth */
+		set_reg_field_value(
+			value,
+			1,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_888:
+		/* Unity for 8 bit output color depth
+		 * because prescale is disabled by default */
+		set_reg_field_value(
+			value,
+			0,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_101010:
+		/* 1023/1024 for 10 bit output color depth */
+		set_reg_field_value(
+			value,
+			3,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_121212:
+		/* 4095/4096 for 12 bit output color depth */
+		set_reg_field_value(
+			value,
+			5,
+			DENORM_CONTROL,
+			DENORM_MODE);
+		break;
+	case COLOR_DEPTH_141414:
+	case COLOR_DEPTH_161616:
+	default:
+		/* not valid used case! */
+		break;
+	}
+
+	dm_write_reg(xfm110->base.ctx,
+			DCP_REG(mmDENORM_CONTROL),
+			value);
+
+}
+
+bool dce110_transform_set_pixel_storage_depth(
+	struct transform *xfm,
+	enum lb_pixel_depth depth,
+	const struct bit_depth_reduction_params *bit_depth_params)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool ret = true;
+	uint32_t value;
+	enum dc_color_depth color_depth;
+
+	value = dm_read_reg(
+			xfm->ctx,
+			LB_REG(mmLB_DATA_FORMAT));
+	switch (depth) {
+	case LB_PIXEL_DEPTH_18BPP:
+		color_depth = COLOR_DEPTH_666;
+		set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	case LB_PIXEL_DEPTH_24BPP:
+		color_depth = COLOR_DEPTH_888;
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	case LB_PIXEL_DEPTH_30BPP:
+		color_depth = COLOR_DEPTH_101010;
+		set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	case LB_PIXEL_DEPTH_36BPP:
+		color_depth = COLOR_DEPTH_121212;
+		set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH);
+		set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
+		break;
+	default:
+		ret = false;
+		break;
+	}
+
+	if (ret == true) {
+		set_denormalization(xfm110, color_depth);
+		ret = program_bit_depth_reduction(xfm110, color_depth,
+				bit_depth_params);
+
+		set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN);
+		dm_write_reg(
+				xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value);
+		if (!(xfm110->lb_pixel_depth_supported & depth)) {
+			/*we should use unsupported capabilities
+			 *  unless it is required by w/a*/
+			dal_logger_write(xfm->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_GPU,
+				"%s: Capability not supported",
+				__func__);
+		}
+	}
+
+	return ret;
+}
+
+/* LB_MEMORY_CONFIG
+ *  00 - Use all three pieces of memory
+ *  01 - Use only one piece of memory of total 720x144 bits
+ *  10 - Use two pieces of memory of total 960x144 bits
+ *  11 - reserved
+ *
+ * LB_MEMORY_SIZE
+ *  Total entries of LB memory.
+ *  This number should be larger than 960. The default value is 1712(0x6B0) */
+bool dce110_transform_power_up_line_buffer(struct transform *xfm)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	uint32_t value;
+
+	value = dm_read_reg(xfm110->base.ctx, LB_REG(mmLB_MEMORY_CTRL));
+
+	/*Use all three pieces of memory always*/
+	set_reg_field_value(value, 0, LB_MEMORY_CTRL, LB_MEMORY_CONFIG);
+	/*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/
+	set_reg_field_value(value, LB_TOTAL_NUMBER_OF_ENTRIES, LB_MEMORY_CTRL,
+			LB_MEMORY_SIZE);
+
+	dm_write_reg(xfm110->base.ctx, LB_REG(mmLB_MEMORY_CTRL), value);
+
+	return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
new file mode 100644
index 000000000000..ff100cc7f30f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
@@ -0,0 +1,51 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_TRANSFORM_BIT_DEPTH_DCE110_H__
+#define __DC_TRANSFORM_BIT_DEPTH_DCE110_H__
+
+#include "dce110_transform.h"
+
+bool dce110_transform_power_up_line_buffer(struct transform *xfm);
+
+bool dce110_transform_get_max_num_of_supported_lines(
+	struct dce110_transform *xfm110,
+	enum lb_pixel_depth depth,
+	uint32_t pixel_width,
+	uint32_t *lines);
+
+void dce110_transform_enable_alpha(
+	struct dce110_transform *xfm110,
+	bool enable);
+
+bool dce110_transform_get_next_lower_pixel_storage_depth(
+	struct dce110_transform *xfm110,
+	uint32_t display_bpp,
+	enum lb_pixel_depth depth,
+	enum lb_pixel_depth *lower_depth);
+
+bool dce110_transform_is_prefetch_enabled(
+	struct dce110_transform *xfm110);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
new file mode 100644
index 000000000000..05309c9f9482
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
@@ -0,0 +1,296 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dce110_transform.h"
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "include/fixed31_32.h"
+#include "basics/conversion.h"
+#include "include/grph_object_id.h"
+
+enum {
+	GAMUT_MATRIX_SIZE = 12
+};
+
+#define DCP_REG(reg)\
+	(reg + xfm110->offsets.dcp_offset)
+
+#define DISP_BRIGHTNESS_DEFAULT_HW 0
+#define DISP_BRIGHTNESS_MIN_HW -25
+#define DISP_BRIGHTNESS_MAX_HW 25
+#define DISP_BRIGHTNESS_STEP_HW 1
+#define DISP_BRIGHTNESS_HW_DIVIDER 100
+
+#define DISP_HUE_DEFAULT_HW 0
+#define DISP_HUE_MIN_HW -30
+#define DISP_HUE_MAX_HW 30
+#define DISP_HUE_STEP_HW 1
+#define DISP_HUE_HW_DIVIDER 1
+
+#define DISP_CONTRAST_DEFAULT_HW 100
+#define DISP_CONTRAST_MIN_HW 50
+#define DISP_CONTRAST_MAX_HW 150
+#define DISP_CONTRAST_STEP_HW 1
+#define DISP_CONTRAST_HW_DIVIDER 100
+
+#define DISP_SATURATION_DEFAULT_HW 100
+#define DISP_SATURATION_MIN_HW 0
+#define DISP_SATURATION_MAX_HW 200
+#define DISP_SATURATION_STEP_HW 1
+#define DISP_SATURATION_HW_DIVIDER 100
+
+#define DISP_KELVIN_DEGRES_DEFAULT 6500
+#define DISP_KELVIN_DEGRES_MIN 4000
+#define DISP_KELVIN_DEGRES_MAX 10000
+#define DISP_KELVIN_DEGRES_STEP 100
+#define DISP_KELVIN_HW_DIVIDER 10000
+
+static void program_gamut_remap(
+	struct dce110_transform *xfm110,
+	const uint16_t *reg_val)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+	uint32_t addr = DCP_REG(mmGAMUT_REMAP_CONTROL);
+
+	/* the register controls ovl also */
+	value = dm_read_reg(ctx, addr);
+
+	if (reg_val) {
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C11_C12);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[0],
+				GAMUT_REMAP_C11_C12,
+				GAMUT_REMAP_C11);
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[1],
+				GAMUT_REMAP_C11_C12,
+				GAMUT_REMAP_C12);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C13_C14);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[2],
+				GAMUT_REMAP_C13_C14,
+				GAMUT_REMAP_C13);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[3],
+				GAMUT_REMAP_C13_C14,
+				GAMUT_REMAP_C14);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C21_C22);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[4],
+				GAMUT_REMAP_C21_C22,
+				GAMUT_REMAP_C21);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[5],
+				GAMUT_REMAP_C21_C22,
+				GAMUT_REMAP_C22);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C23_C24);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[6],
+				GAMUT_REMAP_C23_C24,
+				GAMUT_REMAP_C23);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[7],
+				GAMUT_REMAP_C23_C24,
+				GAMUT_REMAP_C24);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C31_C32);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[8],
+				GAMUT_REMAP_C31_C32,
+				GAMUT_REMAP_C31);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[9],
+				GAMUT_REMAP_C31_C32,
+				GAMUT_REMAP_C32);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+		{
+			uint32_t reg_data = 0;
+			uint32_t addr = DCP_REG(mmGAMUT_REMAP_C33_C34);
+
+			/* fixed S2.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[10],
+				GAMUT_REMAP_C33_C34,
+				GAMUT_REMAP_C33);
+
+			/* fixed S0.13 format */
+			set_reg_field_value(
+				reg_data,
+				reg_val[11],
+				GAMUT_REMAP_C33_C34,
+				GAMUT_REMAP_C34);
+
+			dm_write_reg(ctx, addr, reg_data);
+		}
+
+		set_reg_field_value(
+			value,
+			1,
+			GAMUT_REMAP_CONTROL,
+			GRPH_GAMUT_REMAP_MODE);
+
+	} else
+		set_reg_field_value(
+			value,
+			0,
+			GAMUT_REMAP_CONTROL,
+			GRPH_GAMUT_REMAP_MODE);
+
+	addr = DCP_REG(mmGAMUT_REMAP_CONTROL);
+	dm_write_reg(ctx, addr, value);
+
+}
+
+/**
+ *****************************************************************************
+ *  Function: dal_transform_wide_gamut_set_gamut_remap
+ *
+ *  @param [in] const struct grph_csc_adjustment *adjust
+ *
+ *  @return
+ *     void
+ *
+ *  @note calculate and apply color temperature adjustment to in Rgb color space
+ *
+ *  @see
+ *
+ *****************************************************************************
+ */
+void dce110_transform_set_gamut_remap(
+	struct transform *xfm,
+	const struct grph_csc_adjustment *adjust)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+
+	if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW ||
+		adjust->temperature_divider == 0)
+		program_gamut_remap(xfm110, NULL);
+	else {
+		struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE];
+		uint16_t arr_reg_val[GAMUT_MATRIX_SIZE];
+
+		arr_matrix[0] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[0],
+				adjust->temperature_divider);
+		arr_matrix[1] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[1],
+				adjust->temperature_divider);
+		arr_matrix[2] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[2],
+				adjust->temperature_divider);
+		arr_matrix[3] = dal_fixed31_32_zero;
+
+		arr_matrix[4] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[3],
+				adjust->temperature_divider);
+		arr_matrix[5] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[4],
+				adjust->temperature_divider);
+		arr_matrix[6] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[5],
+				adjust->temperature_divider);
+		arr_matrix[7] = dal_fixed31_32_zero;
+
+		arr_matrix[8] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[6],
+				adjust->temperature_divider);
+		arr_matrix[9] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[7],
+				adjust->temperature_divider);
+		arr_matrix[10] =
+			dal_fixed31_32_from_fraction(
+				adjust->temperature_matrix[8],
+				adjust->temperature_divider);
+		arr_matrix[11] = dal_fixed31_32_zero;
+
+		convert_float_matrix(
+			arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE);
+
+		program_gamut_remap(xfm110, arr_reg_val);
+	}
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
new file mode 100644
index 000000000000..7c15a13cb9fc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
@@ -0,0 +1,818 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_transform.h"
+
+#define UP_SCALER_RATIO_MAX 16000
+#define DOWN_SCALER_RATIO_MAX 250
+#define SCALER_RATIO_DIVIDER 1000
+
+#define SCL_REG(reg)\
+	(reg + xfm110->offsets.scl_offset)
+
+#define DCFE_REG(reg)\
+	(reg + xfm110->offsets.dcfe_offset)
+
+static void disable_enhanced_sharpness(struct dce110_transform *xfm110)
+{
+	uint32_t  value;
+
+	value = dm_read_reg(xfm110->base.ctx,
+			SCL_REG(mmSCL_F_SHARP_CONTROL));
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_HF_SHARP_EN);
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_VF_SHARP_EN);
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_HF_SHARP_SCALE_FACTOR);
+
+	set_reg_field_value(value, 0,
+			SCL_F_SHARP_CONTROL, SCL_VF_SHARP_SCALE_FACTOR);
+
+	dm_write_reg(xfm110->base.ctx,
+			SCL_REG(mmSCL_F_SHARP_CONTROL), value);
+}
+
+/**
+* Function:
+* void setup_scaling_configuration
+*
+* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
+* Input:   data
+*
+* Output:
+   void
+*/
+static bool setup_scaling_configuration(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t addr;
+	uint32_t value;
+
+	if (data->taps.h_taps + data->taps.v_taps <= 2) {
+		dce110_transform_set_scaler_bypass(&xfm110->base);
+		return false;
+	}
+
+	{
+		addr = SCL_REG(mmSCL_MODE);
+		value = dm_read_reg(ctx, addr);
+
+		if (data->dal_pixel_format <= PIXEL_FORMAT_GRPH_END)
+			set_reg_field_value(value, 1, SCL_MODE, SCL_MODE);
+		else
+			set_reg_field_value(value, 2, SCL_MODE, SCL_MODE);
+
+		set_reg_field_value(value, 1, SCL_MODE, SCL_PSCL_EN);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		addr = SCL_REG(mmSCL_TAP_CONTROL);
+		value = dm_read_reg(ctx, addr);
+
+		set_reg_field_value(value, data->taps.h_taps - 1,
+				SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
+
+		set_reg_field_value(value, data->taps.v_taps - 1,
+				SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
+
+		dm_write_reg(ctx, addr, value);
+	}
+	{
+		addr = SCL_REG(mmSCL_CONTROL);
+		value = dm_read_reg(ctx, addr);
+		 /* 1 - Replaced out of bound pixels with edge */
+		set_reg_field_value(value, 1, SCL_CONTROL, SCL_BOUNDARY_MODE);
+
+		/* 1 - Replaced out of bound pixels with the edge pixel. */
+		dm_write_reg(ctx, addr, value);
+	}
+
+	return true;
+}
+
+/**
+* Function:
+* void program_overscan
+*
+* Purpose: Programs overscan border
+* Input:   overscan
+*
+* Output:
+   void
+*/
+static void program_overscan(
+		struct dce110_transform *xfm110,
+		const struct overscan_info *overscan)
+{
+	uint32_t overscan_left_right = 0;
+	uint32_t overscan_top_bottom = 0;
+
+	set_reg_field_value(overscan_left_right, overscan->left,
+			EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
+
+	set_reg_field_value(overscan_left_right, overscan->right,
+			EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
+
+	set_reg_field_value(overscan_top_bottom, overscan->top,
+			EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
+
+	set_reg_field_value(overscan_top_bottom, overscan->bottom,
+			EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
+
+	dm_write_reg(xfm110->base.ctx,
+			SCL_REG(mmEXT_OVERSCAN_LEFT_RIGHT),
+			overscan_left_right);
+
+	dm_write_reg(xfm110->base.ctx,
+			SCL_REG(mmEXT_OVERSCAN_TOP_BOTTOM),
+			overscan_top_bottom);
+}
+
+static void program_two_taps_filter(
+	struct dce110_transform *xfm110,
+	bool enable,
+	bool vertical)
+{
+	uint32_t addr;
+	uint32_t value;
+	/* 1: Hard coded 2 tap filter
+	 * 0: Programmable 2 tap filter from coefficient RAM
+	 */
+	if (vertical) {
+		addr = SCL_REG(mmSCL_VERT_FILTER_CONTROL);
+		value = dm_read_reg(xfm110->base.ctx, addr);
+		set_reg_field_value(
+			value,
+			enable ? 1 : 0,
+				SCL_VERT_FILTER_CONTROL,
+				SCL_V_2TAP_HARDCODE_COEF_EN);
+
+	} else {
+		addr = SCL_REG(mmSCL_HORZ_FILTER_CONTROL);
+		value = dm_read_reg(xfm110->base.ctx, addr);
+		set_reg_field_value(
+			value,
+			enable ? 1 : 0,
+			SCL_HORZ_FILTER_CONTROL,
+			SCL_H_2TAP_HARDCODE_COEF_EN);
+	}
+
+	dm_write_reg(xfm110->base.ctx, addr, value);
+}
+
+static void set_coeff_update_complete(struct dce110_transform *xfm110)
+{
+	uint32_t value;
+	uint32_t addr = SCL_REG(mmSCL_UPDATE);
+
+	value = dm_read_reg(xfm110->base.ctx, addr);
+	set_reg_field_value(value, 1,
+			SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+}
+
+static void program_filter(
+	struct dce110_transform *xfm110,
+	enum ram_filter_type filter_type,
+	struct scaler_filter_params *scl_filter_params,
+	uint32_t *coeffs,
+	uint32_t coeffs_num)
+{
+	uint32_t phase = 0;
+	uint32_t array_idx = 0;
+	uint32_t pair = 0;
+
+	uint32_t taps_pairs = (scl_filter_params->taps + 1) / 2;
+	uint32_t phases_to_program = scl_filter_params->phases / 2 + 1;
+
+	uint32_t i;
+	uint32_t addr;
+	uint32_t select_addr;
+	uint32_t select;
+	uint32_t data;
+	/* We need to disable power gating on coeff memory to do programming */
+
+	uint32_t pwr_ctrl_orig;
+	uint32_t pwr_ctrl_off;
+
+	addr = DCFE_REG(mmDCFE_MEM_PWR_CTRL);
+	pwr_ctrl_orig = dm_read_reg(xfm110->base.ctx, addr);
+	pwr_ctrl_off = pwr_ctrl_orig;
+	set_reg_field_value(
+		pwr_ctrl_off,
+		1,
+		DCFE_MEM_PWR_CTRL,
+		SCL_COEFF_MEM_PWR_DIS);
+	dm_write_reg(xfm110->base.ctx, addr, pwr_ctrl_off);
+
+	addr = DCFE_REG(mmDCFE_MEM_PWR_STATUS);
+	/* Wait to disable gating: */
+	for (i = 0;
+		i < 10 &&
+		get_reg_field_value(
+			dm_read_reg(xfm110->base.ctx, addr),
+			DCFE_MEM_PWR_STATUS,
+			SCL_COEFF_MEM_PWR_STATE);
+		i++)
+		dm_delay_in_microseconds(xfm110->base.ctx, 1);
+
+	ASSERT(i < 10);
+
+	select_addr = SCL_REG(mmSCL_COEF_RAM_SELECT);
+	select = dm_read_reg(xfm110->base.ctx, select_addr);
+
+	set_reg_field_value(
+		select,
+		filter_type,
+		SCL_COEF_RAM_SELECT,
+		SCL_C_RAM_FILTER_TYPE);
+	set_reg_field_value(
+		select,
+		0,
+		SCL_COEF_RAM_SELECT,
+		SCL_C_RAM_TAP_PAIR_IDX);
+	set_reg_field_value(
+		select,
+		0,
+		SCL_COEF_RAM_SELECT,
+		SCL_C_RAM_PHASE);
+
+	data = 0;
+
+	for (phase = 0; phase < phases_to_program; phase++) {
+		/* we always program N/2 + 1 phases, total phases N, but N/2-1
+		 * are just mirror phase 0 is unique and phase N/2 is unique
+		 * if N is even
+		 */
+
+		set_reg_field_value(
+			select,
+			phase,
+			SCL_COEF_RAM_SELECT,
+			SCL_C_RAM_PHASE);
+
+		for (pair = 0; pair < taps_pairs; pair++) {
+			set_reg_field_value(
+				select,
+				pair,
+				SCL_COEF_RAM_SELECT,
+				SCL_C_RAM_TAP_PAIR_IDX);
+			dm_write_reg(xfm110->base.ctx, select_addr, select);
+
+			/* even tap write enable */
+			set_reg_field_value(
+				data,
+				1,
+				SCL_COEF_RAM_TAP_DATA,
+				SCL_C_RAM_EVEN_TAP_COEF_EN);
+			/* even tap data */
+			set_reg_field_value(
+				data,
+				coeffs[array_idx],
+				SCL_COEF_RAM_TAP_DATA,
+				SCL_C_RAM_EVEN_TAP_COEF);
+
+			/* if we have odd number of taps and the last pair is
+			 * here then we do not need to program
+			 */
+			if (scl_filter_params->taps % 2 &&
+				pair == taps_pairs - 1) {
+				/* odd tap write disable */
+				set_reg_field_value(
+					data,
+					0,
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF_EN);
+				set_reg_field_value(
+					data,
+					0,
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF);
+				array_idx += 1;
+			} else {
+				/* odd tap write enable */
+				set_reg_field_value(
+					data,
+					1,
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF_EN);
+				/* dbg_val: 0x1000 / sclFilterParams->taps; */
+				set_reg_field_value(
+					data,
+					coeffs[array_idx + 1],
+					SCL_COEF_RAM_TAP_DATA,
+					SCL_C_RAM_ODD_TAP_COEF);
+
+				array_idx += 2;
+			}
+
+			dm_write_reg(
+				xfm110->base.ctx,
+				SCL_REG(mmSCL_COEF_RAM_TAP_DATA),
+				data);
+		}
+	}
+
+	ASSERT(coeffs_num == array_idx);
+
+	/* reset the power gating register */
+	dm_write_reg(
+		xfm110->base.ctx,
+		DCFE_REG(mmDCFE_MEM_PWR_CTRL),
+		pwr_ctrl_orig);
+
+	set_coeff_update_complete(xfm110);
+}
+
+/*
+ *
+ * Populates an array with filter coefficients in 1.1.12 fixed point form
+*/
+static bool get_filter_coefficients(
+	struct dce110_transform *xfm110,
+	uint32_t taps,
+	uint32_t **data_tab,
+	uint32_t *data_size)
+{
+	uint32_t num = 0;
+	uint32_t i;
+	const struct fixed31_32 *filter =
+		dal_scaler_filter_get(
+			xfm110->base.filter,
+			data_tab,
+			&num);
+	uint32_t *data_row;
+
+	if (!filter) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+	data_row = *data_tab;
+
+	for (i = 0; i < num; ++i) {
+		/* req. format sign fixed 1.1.12, the values are always between
+		 * [-1; 1]
+		 *
+		 * Each phase is mirrored as follows :
+		 * 0 : Phase 0
+		 * 1 : Phase 1 or Phase 64 - 1 / 128 - 1
+		 * N : Phase N or Phase 64 - N / 128 - N
+		 *
+		 * Convert from Fixed31_32 to 1.1.12 by using floor on value
+		 * shifted by number of required fractional bits(12)
+		 */
+		struct fixed31_32 value = filter[i];
+
+		data_row[i] =
+			dal_fixed31_32_floor(dal_fixed31_32_shl(value, 12)) &
+			0x3FFC;
+	}
+	*data_size = num;
+
+	return true;
+}
+
+static bool program_multi_taps_filter(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	bool horizontal)
+{
+	struct scaler_filter_params filter_params;
+	enum ram_filter_type filter_type;
+	uint32_t src_size;
+	uint32_t dst_size;
+
+	uint32_t *filter_data = NULL;
+	uint32_t filter_data_size = 0;
+
+	/* 16 phases total for DCE11 */
+	filter_params.phases = 16;
+
+	if (horizontal) {
+		filter_params.taps = data->taps.h_taps;
+		filter_params.sharpness = data->h_sharpness;
+		filter_params.flags.bits.HORIZONTAL = 1;
+
+		src_size = data->viewport.width;
+		dst_size =
+			dal_fixed31_32_floor(
+				dal_fixed31_32_div(
+					dal_fixed31_32_from_int(
+						data->viewport.width),
+					data->ratios->horz));
+
+		filter_type = FILTER_TYPE_RGB_Y_HORIZONTAL;
+	} else {
+		filter_params.taps = data->taps.v_taps;
+		filter_params.sharpness = data->v_sharpness;
+		filter_params.flags.bits.HORIZONTAL = 0;
+
+		src_size = data->viewport.height;
+		dst_size =
+			dal_fixed31_32_floor(
+				dal_fixed31_32_div(
+					dal_fixed31_32_from_int(
+						data->viewport.height),
+					data->ratios->vert));
+
+		filter_type = FILTER_TYPE_RGB_Y_VERTICAL;
+	}
+
+	/* 1. Generate the coefficients */
+	if (!dal_scaler_filter_generate(
+		xfm110->base.filter,
+		&filter_params,
+		src_size,
+		dst_size))
+		return false;
+
+	/* 2. Convert coefficients to fixed point format 1.12 (note coeff.
+	 * could be negative(!) and  range is [ from -1 to 1 ]) */
+	if (!get_filter_coefficients(
+		xfm110,
+		filter_params.taps,
+		&filter_data,
+		&filter_data_size))
+		return false;
+
+	/* 3. Program the filter */
+	program_filter(
+		xfm110,
+		filter_type,
+		&filter_params,
+		filter_data,
+		filter_data_size);
+
+	/* 4. Program the alpha if necessary */
+	if (data->flags.bits.SHOULD_PROGRAM_ALPHA) {
+		if (horizontal)
+			filter_type = FILTER_TYPE_ALPHA_HORIZONTAL;
+		else
+			filter_type = FILTER_TYPE_ALPHA_VERTICAL;
+
+		program_filter(
+			xfm110,
+			filter_type,
+			&filter_params,
+			filter_data,
+			filter_data_size);
+	}
+
+	return true;
+}
+
+static void program_viewport(
+	struct dce110_transform *xfm110,
+	const struct rect *view_port)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+	uint32_t addr = 0;
+
+	addr = SCL_REG(mmVIEWPORT_START);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		view_port->x,
+		VIEWPORT_START,
+		VIEWPORT_X_START);
+	set_reg_field_value(
+		value,
+		view_port->y,
+		VIEWPORT_START,
+		VIEWPORT_Y_START);
+	dm_write_reg(ctx, addr, value);
+
+	addr = SCL_REG(mmVIEWPORT_SIZE);
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		view_port->height,
+		VIEWPORT_SIZE,
+		VIEWPORT_HEIGHT);
+	set_reg_field_value(
+		value,
+		view_port->width,
+		VIEWPORT_SIZE,
+		VIEWPORT_WIDTH);
+	dm_write_reg(ctx, addr, value);
+
+	/* TODO: add stereo support */
+}
+
+static void calculate_inits(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	struct scl_ratios_inits *inits)
+{
+	struct fixed31_32 h_init;
+	struct fixed31_32 v_init;
+	struct fixed31_32 v_init_bot;
+
+	inits->bottom_enable = 0;
+	inits->h_int_scale_ratio =
+		dal_fixed31_32_u2d19(data->ratios->horz) << 5;
+	inits->v_int_scale_ratio =
+		dal_fixed31_32_u2d19(data->ratios->vert) << 5;
+
+	h_init =
+		dal_fixed31_32_div_int(
+			dal_fixed31_32_add(
+				data->ratios->horz,
+				dal_fixed31_32_from_int(data->taps.h_taps + 1)),
+				2);
+	inits->h_init.integer = dal_fixed31_32_floor(h_init);
+	inits->h_init.fraction = dal_fixed31_32_u0d19(h_init) << 5;
+
+	v_init =
+		dal_fixed31_32_div_int(
+			dal_fixed31_32_add(
+				data->ratios->vert,
+				dal_fixed31_32_from_int(data->taps.v_taps + 1)),
+				2);
+	inits->v_init.integer = dal_fixed31_32_floor(v_init);
+	inits->v_init.fraction = dal_fixed31_32_u0d19(v_init) << 5;
+
+	if (data->flags.bits.INTERLACED) {
+		v_init_bot =
+			dal_fixed31_32_add(
+				dal_fixed31_32_div_int(
+					dal_fixed31_32_add(
+						data->ratios->vert,
+						dal_fixed31_32_from_int(
+							data->taps.v_taps + 1)),
+					2),
+				data->ratios->vert);
+		inits->v_init_bottom.integer = dal_fixed31_32_floor(v_init_bot);
+		inits->v_init_bottom.fraction =
+			dal_fixed31_32_u0d19(v_init_bot) << 5;
+
+		inits->bottom_enable = 1;
+	}
+}
+
+static void program_scl_ratios_inits(
+	struct dce110_transform *xfm110,
+	struct scl_ratios_inits *inits)
+{
+	uint32_t addr = SCL_REG(mmSCL_HORZ_FILTER_SCALE_RATIO);
+	uint32_t value = 0;
+
+	set_reg_field_value(
+		value,
+		inits->h_int_scale_ratio,
+		SCL_HORZ_FILTER_SCALE_RATIO,
+		SCL_H_SCALE_RATIO);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	addr = SCL_REG(mmSCL_VERT_FILTER_SCALE_RATIO);
+	value = 0;
+	set_reg_field_value(
+		value,
+		inits->v_int_scale_ratio,
+		SCL_VERT_FILTER_SCALE_RATIO,
+		SCL_V_SCALE_RATIO);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	addr = SCL_REG(mmSCL_HORZ_FILTER_INIT);
+	value = 0;
+	set_reg_field_value(
+		value,
+		inits->h_init.integer,
+		SCL_HORZ_FILTER_INIT,
+		SCL_H_INIT_INT);
+	set_reg_field_value(
+		value,
+		inits->h_init.fraction,
+		SCL_HORZ_FILTER_INIT,
+		SCL_H_INIT_FRAC);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	addr = SCL_REG(mmSCL_VERT_FILTER_INIT);
+	value = 0;
+	set_reg_field_value(
+		value,
+		inits->v_init.integer,
+		SCL_VERT_FILTER_INIT,
+		SCL_V_INIT_INT);
+	set_reg_field_value(
+		value,
+		inits->v_init.fraction,
+		SCL_VERT_FILTER_INIT,
+		SCL_V_INIT_FRAC);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+
+	if (inits->bottom_enable) {
+		addr = SCL_REG(mmSCL_VERT_FILTER_INIT_BOT);
+		value = 0;
+		set_reg_field_value(
+			value,
+			inits->v_init_bottom.integer,
+			SCL_VERT_FILTER_INIT_BOT,
+			SCL_V_INIT_INT_BOT);
+		set_reg_field_value(
+			value,
+			inits->v_init_bottom.fraction,
+			SCL_VERT_FILTER_INIT_BOT,
+			SCL_V_INIT_FRAC_BOT);
+		dm_write_reg(xfm110->base.ctx, addr, value);
+	}
+
+	addr = SCL_REG(mmSCL_AUTOMATIC_MODE_CONTROL);
+	value = 0;
+	set_reg_field_value(
+		value,
+		0,
+		SCL_AUTOMATIC_MODE_CONTROL,
+		SCL_V_CALC_AUTO_RATIO_EN);
+	set_reg_field_value(
+		value,
+		0,
+		SCL_AUTOMATIC_MODE_CONTROL,
+		SCL_H_CALC_AUTO_RATIO_EN);
+	dm_write_reg(xfm110->base.ctx, addr, value);
+}
+
+static void get_viewport(
+		struct dce110_transform *xfm110,
+		struct rect *current_view_port)
+{
+	uint32_t value_start;
+	uint32_t value_size;
+
+	if (current_view_port == NULL)
+		return;
+
+	value_start = dm_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_START));
+	value_size = dm_read_reg(xfm110->base.ctx, SCL_REG(mmVIEWPORT_SIZE));
+
+	current_view_port->x = get_reg_field_value(
+			value_start,
+			VIEWPORT_START,
+			VIEWPORT_X_START);
+	current_view_port->y = get_reg_field_value(
+			value_start,
+			VIEWPORT_START,
+			VIEWPORT_Y_START);
+	current_view_port->height = get_reg_field_value(
+			value_size,
+			VIEWPORT_SIZE,
+			VIEWPORT_HEIGHT);
+	current_view_port->width = get_reg_field_value(
+			value_size,
+			VIEWPORT_SIZE,
+			VIEWPORT_WIDTH);
+}
+
+
+bool dce110_transform_set_scaler(
+	struct transform *xfm,
+	const struct scaler_data *data)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool is_scaling_required;
+	struct dc_context *ctx = xfm->ctx;
+
+	{
+		uint32_t addr = SCL_REG(mmSCL_BYPASS_CONTROL);
+		uint32_t value = dm_read_reg(xfm->ctx, addr);
+
+		set_reg_field_value(
+			value,
+			0,
+			SCL_BYPASS_CONTROL,
+			SCL_BYPASS_MODE);
+		dm_write_reg(xfm->ctx, addr, value);
+	}
+
+	disable_enhanced_sharpness(xfm110);
+
+	/* 3. Program overscan */
+	program_overscan(xfm110, &data->overscan);
+
+	/* 4. Program taps and configuration */
+	is_scaling_required = setup_scaling_configuration(xfm110, data);
+	if (is_scaling_required) {
+		/* 5. Calculate and program ratio, filter initialization */
+		struct scl_ratios_inits inits = { 0 };
+
+		calculate_inits(xfm110, data, &inits);
+
+		program_scl_ratios_inits(xfm110, &inits);
+
+		/* 6. Program vertical filters */
+		if (data->taps.v_taps > 2) {
+			program_two_taps_filter(xfm110, false, true);
+
+			if (!program_multi_taps_filter(xfm110, data, false)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed vertical taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter(xfm110, true, true);
+
+		/* 7. Program horizontal filters */
+		if (data->taps.h_taps > 2) {
+			program_two_taps_filter(xfm110, false, false);
+
+			if (!program_multi_taps_filter(xfm110, data, true)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed horizontal taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter(xfm110, true, false);
+	}
+
+	return true;
+}
+
+void dce110_transform_set_scaler_bypass(struct transform *xfm)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	uint32_t sclv_mode;
+
+	disable_enhanced_sharpness(xfm110);
+
+	sclv_mode = dm_read_reg(xfm->ctx, SCL_REG(mmSCL_MODE));
+	set_reg_field_value(sclv_mode, 0, SCL_MODE, SCL_MODE);
+	set_reg_field_value(sclv_mode, 0, SCL_MODE, SCL_PSCL_EN);
+	dm_write_reg(xfm->ctx, SCL_REG(mmSCL_MODE), sclv_mode);
+}
+
+bool dce110_transform_update_viewport(
+	struct transform *xfm,
+	const struct rect *view_port,
+	bool is_fbc_attached)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool program_req = false;
+	struct rect current_view_port;
+
+	if (view_port == NULL)
+		return program_req;
+
+	get_viewport(xfm110, &current_view_port);
+
+	if (current_view_port.x != view_port->x ||
+			current_view_port.y != view_port->y ||
+			current_view_port.height != view_port->height ||
+			current_view_port.width != view_port->width)
+		program_req = true;
+
+	if (program_req) {
+		/*underlay viewport is programmed with scaler
+		 *program_viewport function pointer is not exposed*/
+		program_viewport(xfm110, view_port);
+	}
+
+	return program_req;
+}
+
+void dce110_transform_set_scaler_filter(
+	struct transform *xfm,
+	struct scaler_filter *filter)
+{
+	xfm->filter = filter;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
new file mode 100644
index 000000000000..1968296bd596
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
@@ -0,0 +1,531 @@
+/* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#include "dce110_transform.h"
+
+#define NOT_IMPLEMENTED()  DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_CONTROLLER,\
+			"TRANSFORM SCALER:%s()\n", __func__)
+
+/*
+*****************************************************************************
+*  Function: calculateViewport
+*
+*  @brief
+*     Calculates all of the data required to set the viewport
+*
+*  @param [in]  pData:      scaler settings data
+*  @param [out] pLumaVp:    luma viewport information
+*  @param [out] pChromaVp:  chroma viewport information
+*  @param [out] srcResCx2:  source chroma resolution times 2  - for multi-taps
+*
+*****************************************************************************
+*/
+static void calculate_viewport(
+		const struct scaler_data *scl_data,
+		struct rect *luma_viewport,
+		struct rect *chroma_viewport)
+{
+	/*Do not set chroma vp for rgb444 pixel format*/
+	luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2;
+	luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2;
+	luma_viewport->width =
+		scl_data->viewport.width - scl_data->viewport.width % 2;
+	luma_viewport->height =
+		scl_data->viewport.height - scl_data->viewport.height % 2;
+
+
+	if (scl_data->dal_pixel_format == PIXEL_FORMAT_422BPP16) {
+		luma_viewport->width += luma_viewport->width % 2;
+
+		chroma_viewport->x = luma_viewport->x / 2;
+		chroma_viewport->width = luma_viewport->width / 2;
+	} else if (scl_data->dal_pixel_format == PIXEL_FORMAT_420BPP12) {
+		luma_viewport->height += luma_viewport->height % 2;
+		luma_viewport->width += luma_viewport->width % 2;
+		/*for 420 video chroma is 1/4 the area of luma, scaled
+		 *vertically and horizontally
+		 */
+		chroma_viewport->x = luma_viewport->x / 2;
+		chroma_viewport->y = luma_viewport->y / 2;
+		chroma_viewport->height = luma_viewport->height / 2;
+		chroma_viewport->width = luma_viewport->width / 2;
+	}
+}
+
+
+static void program_viewport(
+	struct dce110_transform *xfm110,
+	struct rect *luma_view_port,
+	struct rect *chroma_view_port)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+	uint32_t addr = 0;
+
+	if (luma_view_port->width != 0 && luma_view_port->height != 0) {
+		addr = mmSCLV_VIEWPORT_START;
+		value = 0;
+		set_reg_field_value(
+			value,
+			luma_view_port->x,
+			SCLV_VIEWPORT_START,
+			VIEWPORT_X_START);
+		set_reg_field_value(
+			value,
+			luma_view_port->y,
+			SCLV_VIEWPORT_START,
+			VIEWPORT_Y_START);
+		dm_write_reg(ctx, addr, value);
+
+		addr = mmSCLV_VIEWPORT_SIZE;
+		value = 0;
+		set_reg_field_value(
+			value,
+			luma_view_port->height,
+			SCLV_VIEWPORT_SIZE,
+			VIEWPORT_HEIGHT);
+		set_reg_field_value(
+			value,
+			luma_view_port->width,
+			SCLV_VIEWPORT_SIZE,
+			VIEWPORT_WIDTH);
+		dm_write_reg(ctx, addr, value);
+	}
+
+	if (chroma_view_port->width != 0 && chroma_view_port->height != 0) {
+		addr = mmSCLV_VIEWPORT_START_C;
+		value = 0;
+		set_reg_field_value(
+			value,
+			chroma_view_port->x,
+			SCLV_VIEWPORT_START_C,
+			VIEWPORT_X_START_C);
+		set_reg_field_value(
+			value,
+			chroma_view_port->y,
+			SCLV_VIEWPORT_START_C,
+			VIEWPORT_Y_START_C);
+		dm_write_reg(ctx, addr, value);
+
+		addr = mmSCLV_VIEWPORT_SIZE_C;
+		value = 0;
+		set_reg_field_value(
+			value,
+			chroma_view_port->height,
+			SCLV_VIEWPORT_SIZE_C,
+			VIEWPORT_HEIGHT_C);
+		set_reg_field_value(
+			value,
+			chroma_view_port->width,
+			SCLV_VIEWPORT_SIZE_C,
+			VIEWPORT_WIDTH_C);
+		dm_write_reg(ctx, addr, value);
+	}
+	/* TODO: add stereo support */
+}
+
+
+/* Until and For MPO video play story, to reduce time for implementation,
+ * below limits are applied for now: 2_TAPS only
+ * Use auto-calculated filter values
+ * Following routines will be empty for now:
+ *
+ * programSclRatiosInits -- calcualate scaler ratio manually
+ * calculateInits --- calcualate scaler ratio manually
+ * programFilter -- multi-taps
+ * GetOptimalNumberOfTaps -- will hard coded to 2 TAPS
+ * GetNextLowerNumberOfTaps -- will hard coded to 2TAPS
+ * validateRequestedScaleRatio - used by GetOptimalNumberOfTaps internally
+ */
+
+/**
+* Function:
+* void setup_scaling_configuration
+*
+* Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps
+* Input:   data
+*
+* Output:
+   void
+*/
+static bool setup_scaling_configuration(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data)
+{
+	bool is_scaling_needed = false;
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t value = 0;
+
+	if (data->taps.h_taps + data->taps.v_taps > 2) {
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE);
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN);
+		is_scaling_needed = true;
+	} else {
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
+	}
+
+	if (data->taps.h_taps_c + data->taps.v_taps_c > 2) {
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C);
+		set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C);
+		is_scaling_needed = true;
+	} else if (data->dal_pixel_format != PIXEL_FORMAT_420BPP12 &&
+		data->dal_pixel_format != PIXEL_FORMAT_422BPP16) {
+		set_reg_field_value(
+			value,
+			get_reg_field_value(value, SCLV_MODE, SCL_MODE),
+			SCLV_MODE,
+			SCL_MODE_C);
+		set_reg_field_value(
+			value,
+			get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN),
+			SCLV_MODE,
+			SCL_PSCL_EN_C);
+	} else {
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
+		set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
+	}
+	dm_write_reg(ctx, mmSCLV_MODE, value);
+
+	{
+		value = dm_read_reg(ctx, mmSCLV_TAP_CONTROL);
+
+		set_reg_field_value(value, data->taps.h_taps - 1,
+				SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS);
+
+		set_reg_field_value(value, data->taps.v_taps - 1,
+				SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS);
+
+		set_reg_field_value(value, data->taps.h_taps_c - 1,
+				SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C);
+
+		set_reg_field_value(value, data->taps.v_taps_c - 1,
+				SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C);
+
+		dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value);
+	}
+
+	{
+		/* we can ignore this register because we are ok with hw
+		 * default 0 -- change to 1 according to dal2 code*/
+		value = dm_read_reg(ctx, mmSCLV_CONTROL);
+		 /* 0 - Replaced out of bound pixels with black pixel
+		  * (or any other required color) */
+		set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE);
+
+		/* 1 - Replaced out of bound pixels with the edge pixel. */
+		dm_write_reg(ctx, mmSCLV_CONTROL, value);
+	}
+
+	return is_scaling_needed;
+}
+
+/**
+* Function:
+* void program_overscan
+*
+* Purpose: Programs overscan border
+* Input:   overscan
+*
+* Output:
+   void
+*/
+static void program_overscan(
+		struct dce110_transform *xfm110,
+		const struct overscan_info *overscan)
+{
+	uint32_t overscan_left_right = 0;
+	uint32_t overscan_top_bottom = 0;
+
+	set_reg_field_value(overscan_left_right, overscan->left,
+		SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT);
+
+	set_reg_field_value(overscan_left_right, overscan->right,
+		SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT);
+
+	set_reg_field_value(overscan_top_bottom, overscan->top,
+		SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP);
+
+	set_reg_field_value(overscan_top_bottom, overscan->bottom,
+		SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_EXT_OVERSCAN_LEFT_RIGHT,
+			overscan_left_right);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_EXT_OVERSCAN_TOP_BOTTOM,
+			overscan_top_bottom);
+}
+/*
+static void setup_auto_scaling(struct dce110_transform *xfm110)
+{
+	uint32_t value = 0;
+	set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL,
+			SCL_V_CALC_AUTO_RATIO_EN);
+	set_reg_field_value(value, 1, SCLV_AUTOMATIC_MODE_CONTROL,
+			SCL_H_CALC_AUTO_RATIO_EN);
+	dal_write_reg(xfm->ctx,
+			xfm->regs[IDX_SCL_AUTOMATIC_MODE_CONTROL],
+			value);
+}
+*/
+
+static void program_two_taps_filter_horz(
+	struct dce110_transform *xfm110,
+	bool hardcode_coff)
+{
+	uint32_t value = 0;
+
+	if (hardcode_coff)
+		set_reg_field_value(
+				value,
+				1,
+				SCLV_HORZ_FILTER_CONTROL,
+				SCL_H_2TAP_HARDCODE_COEF_EN);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_HORZ_FILTER_CONTROL,
+			value);
+}
+
+static void program_two_taps_filter_vert(
+	struct dce110_transform *xfm110,
+	bool hardcode_coff)
+{
+	uint32_t value = 0;
+
+	if (hardcode_coff)
+		set_reg_field_value(value, 1, SCLV_VERT_FILTER_CONTROL,
+				SCL_V_2TAP_HARDCODE_COEF_EN);
+
+	dm_write_reg(xfm110->base.ctx,
+			mmSCLV_VERT_FILTER_CONTROL,
+			value);
+}
+
+static void set_coeff_update_complete(
+		struct dce110_transform *xfm110)
+{
+	/*TODO: Until now, only scaler bypass, up-scaler 2 -TAPS coeff auto
+	 * calculation are implemented. Coefficient RAM is not used
+	 * Do not check this flag yet
+	 */
+
+	/*uint32_t value;
+	uint32_t addr = xfm->regs[IDX_SCL_UPDATE];
+
+	value = dal_read_reg(xfm->ctx, addr);
+	set_reg_field_value(value, 0,
+			SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE);
+	dal_write_reg(xfm->ctx, addr, value);*/
+}
+
+static bool program_multi_taps_filter(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	bool horizontal)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+
+	NOT_IMPLEMENTED();
+	return false;
+}
+
+static void calculate_inits(
+	struct dce110_transform *xfm110,
+	const struct scaler_data *data,
+	struct sclv_ratios_inits *inits,
+	struct rect *luma_viewport,
+	struct rect *chroma_viewport)
+{
+	if (data->dal_pixel_format == PIXEL_FORMAT_420BPP12 ||
+		data->dal_pixel_format == PIXEL_FORMAT_422BPP16)
+		inits->chroma_enable = true;
+
+	/* TODO: implement rest of this function properly */
+	if (inits->chroma_enable) {
+		inits->h_int_scale_ratio_luma = 0x1000000;
+		inits->v_int_scale_ratio_luma = 0x1000000;
+		inits->h_int_scale_ratio_chroma = 0x800000;
+		inits->v_int_scale_ratio_chroma = 0x800000;
+	}
+}
+
+static void program_scl_ratios_inits(
+	struct dce110_transform *xfm110,
+	struct sclv_ratios_inits *inits)
+{
+	struct dc_context *ctx = xfm110->base.ctx;
+	uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO;
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		inits->h_int_scale_ratio_luma,
+		SCLV_HORZ_FILTER_SCALE_RATIO,
+		SCL_H_SCALE_RATIO);
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmSCLV_VERT_FILTER_SCALE_RATIO;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		inits->v_int_scale_ratio_luma,
+		SCLV_VERT_FILTER_SCALE_RATIO,
+		SCL_V_SCALE_RATIO);
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		inits->h_int_scale_ratio_chroma,
+		SCLV_HORZ_FILTER_SCALE_RATIO_C,
+		SCL_H_SCALE_RATIO_C);
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C;
+	value = dm_read_reg(ctx, addr);
+	set_reg_field_value(
+		value,
+		inits->v_int_scale_ratio_chroma,
+		SCLV_VERT_FILTER_SCALE_RATIO_C,
+		SCL_V_SCALE_RATIO_C);
+	dm_write_reg(ctx, addr, value);
+}
+
+void dce110_transform_underlay_set_scalerv_bypass(struct transform *xfm)
+{
+	uint32_t addr = mmSCLV_MODE;
+	uint32_t value = dm_read_reg(xfm->ctx, addr);
+
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE);
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C);
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN);
+	set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C);
+	dm_write_reg(xfm->ctx, addr, value);
+}
+
+bool dce110_transform_underlay_is_scaling_enabled(struct transform *xfm)
+{
+	uint32_t value = dm_read_reg(xfm->ctx, mmSCLV_MODE);
+	uint8_t scl_mode = get_reg_field_value(value, SCLV_MODE, SCL_MODE);
+
+	return scl_mode == 0;
+}
+
+/* TODO: sync this one with DAL2 */
+bool dce110_transform_underlay_set_scaler(
+	struct transform *xfm,
+	const struct scaler_data *data)
+{
+	struct dce110_transform *xfm110 = TO_DCE110_TRANSFORM(xfm);
+	bool is_scaling_required;
+	struct rect luma_viewport = {0};
+	struct rect chroma_viewport = {0};
+	struct dc_context *ctx = xfm->ctx;
+
+	/* 1. Lock Scaler TODO: enable?*/
+	/*set_scaler_update_lock(xfm, true);*/
+
+	/* 2. Calculate viewport, viewport programming should happen after init
+	 * calculations as they may require an adjustment in the viewport.
+	 */
+
+	calculate_viewport(data, &luma_viewport, &chroma_viewport);
+
+	/* 3. Program overscan */
+	program_overscan(xfm110, &data->overscan);
+
+	/* 4. Program taps and configuration */
+	is_scaling_required = setup_scaling_configuration(xfm110, data);
+
+	if (is_scaling_required) {
+		/* 5. Calculate and program ratio, filter initialization */
+
+		struct sclv_ratios_inits inits = { 0 };
+
+		calculate_inits(
+			xfm110,
+			data,
+			&inits,
+			&luma_viewport,
+			&chroma_viewport);
+
+		program_scl_ratios_inits(xfm110, &inits);
+
+		/*scaler coeff of 2-TAPS use hardware auto calculated value*/
+
+		/* 6. Program vertical filters */
+		if (data->taps.v_taps > 2) {
+			program_two_taps_filter_vert(xfm110, false);
+
+			if (!program_multi_taps_filter(xfm110, data, false)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed vertical taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter_vert(xfm110, true);
+
+		/* 7. Program horizontal filters */
+		if (data->taps.h_taps > 2) {
+			program_two_taps_filter_horz(xfm110, false);
+
+			if (!program_multi_taps_filter(xfm110, data, true)) {
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_DCP,
+					LOG_MINOR_DCP_SCALER,
+					"Failed horizontal taps programming\n");
+				return false;
+			}
+		} else
+			program_two_taps_filter_horz(xfm110, true);
+	}
+
+	/* 8. Program the viewport */
+	if (data->flags.bits.SHOULD_PROGRAM_VIEWPORT)
+		program_viewport(xfm110, &luma_viewport, &chroma_viewport);
+
+	/* 9. Unlock the Scaler TODO: enable?*/
+	/* Every call to "set_scaler_update_lock(xfm, TRUE)"
+	 * must have a corresponding call to
+	 * "set_scaler_update_lock(xfm, FALSE)" */
+	/*set_scaler_update_lock(xfm, false);*/
+
+	/* TODO: investigate purpose/need of SHOULD_UNLOCK */
+	if (data->flags.bits.SHOULD_UNLOCK == false)
+		set_coeff_update_complete(xfm110);
+
+	return true;
+}
+
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 21/26] drm/amd/dal: Add Carrizo HW sequencer and resource
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (19 preceding siblings ...)
  2016-02-16 22:28   ` [PATCH v2 20/26] drm/amd/dal: Add transform & scaler " Harry Wentland
@ 2016-02-16 22:28   ` Harry Wentland
  2016-02-16 22:28   ` [PATCH v2 22/26] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
                     ` (4 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:28 UTC (permalink / raw)
  To: dri-devel

Adds dce110_resource and dce110_hw_sequencer files.

dce110_resource manages creation of HW resources, along with correct
ASIC register offset for each block.

dce110_hw_sequencers is responsible for programming HW sequences,
such as enable_stream, program_scaler, power_down_encoders, etc.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce110/Makefile         |   15 +
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 1658 ++++++++++++++++++++
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h    |   36 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c    | 1238 +++++++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.h    |   46 +
 5 files changed, 2993 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile
new file mode 100644
index 000000000000..ae9d2de92da2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the 'controller' sub-component of DAL.
+# It provides the control and status of HW CRTC block.
+
+DCE110 = dce110_ipp.o dce110_ipp_cursor.o \
+dce110_ipp_gamma.o dce110_link_encoder.o dce110_opp.o \
+dce110_opp_formatter.o dce110_opp_regamma.o dce110_stream_encoder.o \
+dce110_timing_generator.o dce110_transform.o dce110_transform_gamut.o \
+dce110_transform_scl.o dce110_transform_sclv.o dce110_opp_csc.o\
+dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \
+dce110_resource.o dce110_transform_bit_depth.o dce110_clock_source.o
+
+AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_DCE110)
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
new file mode 100644
index 000000000000..71fa7b1f8061
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
@@ -0,0 +1,1658 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "dc.h"
+#include "dc_bios_types.h"
+#include "core_types.h"
+#include "core_status.h"
+#include "resource.h"
+#include "hw_sequencer.h"
+#include "dm_helpers.h"
+#include "dce110_hw_sequencer.h"
+
+#include "gpu/dce110/dc_clock_gating_dce110.h"
+
+#include "timing_generator.h"
+#include "mem_input.h"
+#include "opp.h"
+#include "ipp.h"
+#include "transform.h"
+#include "stream_encoder.h"
+#include "link_encoder.h"
+#include "clock_source.h"
+
+/* include DCE11 register header files */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+struct dce110_hw_seq_reg_offsets {
+	uint32_t dcfe;
+	uint32_t blnd;
+	uint32_t crtc;
+};
+
+enum pipe_lock_control {
+	PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0,
+	PIPE_LOCK_CONTROL_BLENDER = 1 << 1,
+	PIPE_LOCK_CONTROL_SCL = 1 << 2,
+	PIPE_LOCK_CONTROL_SURFACE = 1 << 3,
+	PIPE_LOCK_CONTROL_MODE = 1 << 4
+};
+
+enum blender_mode {
+	BLENDER_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */
+	BLENDER_MODE_OTHER_PIPE, /* Data from other pipe only */
+	BLENDER_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */
+	BLENDER_MODE_STEREO
+};
+
+static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
+{
+	.dcfe = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.blnd = (mmBLND0_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+	.dcfe = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.blnd = (mmBLND1_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+	.dcfe = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.blnd = (mmBLND2_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+}
+};
+
+#define HW_REG_DCFE(reg, id)\
+	(reg + reg_offsets[id].dcfe)
+
+#define HW_REG_BLND(reg, id)\
+	(reg + reg_offsets[id].blnd)
+
+#define HW_REG_CRTC(reg, id)\
+	(reg + reg_offsets[id].crtc)
+
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+/***************************PIPE_CONTROL***********************************/
+static void dce110_enable_fe_clock(
+	struct dc_context *ctx, uint8_t controller_id, bool enable)
+{
+	uint32_t value = 0;
+	uint32_t addr;
+
+	/*TODO: proper offset*/
+	addr = HW_REG_DCFE(mmDCFE_CLOCK_CONTROL, controller_id);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		enable,
+		DCFE_CLOCK_CONTROL,
+		DCFE_CLOCK_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void dce110_init_pte(struct dc_context *ctx)
+{
+	uint32_t addr;
+	uint32_t value = 0;
+	uint32_t chunk_int = 0;
+	uint32_t chunk_mul = 0;
+
+	addr = mmUNP_DVMM_PTE_CONTROL;
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		0,
+		DVMM_PTE_CONTROL,
+		DVMM_USE_SINGLE_PTE);
+
+	set_reg_field_value(
+		value,
+		1,
+		DVMM_PTE_CONTROL,
+		DVMM_PTE_BUFFER_MODE0);
+
+	set_reg_field_value(
+		value,
+		1,
+		DVMM_PTE_CONTROL,
+		DVMM_PTE_BUFFER_MODE1);
+
+	dm_write_reg(ctx, addr, value);
+
+	addr = mmDVMM_PTE_REQ;
+	value = dm_read_reg(ctx, addr);
+
+	chunk_int = get_reg_field_value(
+		value,
+		DVMM_PTE_REQ,
+		HFLIP_PTEREQ_PER_CHUNK_INT);
+
+	chunk_mul = get_reg_field_value(
+		value,
+		DVMM_PTE_REQ,
+		HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
+
+	if (chunk_int != 0x4 || chunk_mul != 0x4) {
+
+		set_reg_field_value(
+			value,
+			255,
+			DVMM_PTE_REQ,
+			MAX_PTEREQ_TO_ISSUE);
+
+		set_reg_field_value(
+			value,
+			4,
+			DVMM_PTE_REQ,
+			HFLIP_PTEREQ_PER_CHUNK_INT);
+
+		set_reg_field_value(
+			value,
+			4,
+			DVMM_PTE_REQ,
+			HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
+
+		dm_write_reg(ctx, addr, value);
+	}
+}
+
+/* this is a workaround for hw bug - it is a trigger on r/w */
+static void trigger_write_crtc_h_blank_start_end(
+	struct dc_context *ctx,
+	uint8_t controller_id)
+{
+	uint32_t value;
+	uint32_t addr;
+
+	addr =  HW_REG_CRTC(mmCRTC_H_BLANK_START_END, controller_id);
+	value = dm_read_reg(ctx, addr);
+	dm_write_reg(ctx, addr, value);
+}
+
+static bool dce110_pipe_control_lock(
+	struct dc_context *ctx,
+	uint8_t controller_idx,
+	uint32_t control_mask,
+	bool lock)
+{
+	uint32_t addr = HW_REG_BLND(mmBLND_V_UPDATE_LOCK, controller_idx);
+	uint32_t value = dm_read_reg(ctx, addr);
+	bool need_to_wait = false;
+
+	if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_DCP_GRPH_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_SCL)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_SCL_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_SURFACE)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_DCP_GRPH_SURF_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_BLND_V_UPDATE_LOCK);
+		need_to_wait = true;
+	}
+
+	if (control_mask & PIPE_LOCK_CONTROL_MODE)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_V_UPDATE_LOCK_MODE);
+
+	dm_write_reg(ctx, addr, value);
+
+	if (!lock && need_to_wait) {
+		uint8_t counter = 0;
+		const uint8_t counter_limit = 100;
+		const uint16_t delay_us = 1000;
+
+		uint8_t pipe_pending;
+
+		addr = HW_REG_BLND(mmBLND_REG_UPDATE_STATUS,
+				controller_idx);
+
+		while (counter < counter_limit) {
+			value = dm_read_reg(ctx, addr);
+
+			pipe_pending = 0;
+
+			if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						BLND_BLNDC_UPDATE_PENDING);
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					BLND_BLNDO_UPDATE_PENDING);
+			}
+
+			if (control_mask & PIPE_LOCK_CONTROL_SCL) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						SCL_BLNDC_UPDATE_PENDING);
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						SCL_BLNDO_UPDATE_PENDING);
+			}
+			if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						DCP_BLNDC_GRPH_UPDATE_PENDING);
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						DCP_BLNDO_GRPH_UPDATE_PENDING);
+			}
+			if (control_mask & PIPE_LOCK_CONTROL_SURFACE) {
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					DCP_BLNDC_GRPH_SURF_UPDATE_PENDING);
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					DCP_BLNDO_GRPH_SURF_UPDATE_PENDING);
+			}
+
+			if (pipe_pending == 0)
+				break;
+
+			counter++;
+			dm_delay_in_microseconds(ctx, delay_us);
+		}
+
+		if (counter == counter_limit) {
+			dal_logger_write(
+				ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: wait for update exceeded (wait %d us)\n",
+				__func__,
+				counter * delay_us);
+			dal_logger_write(
+				ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: control %d, remain value %x\n",
+				__func__,
+				control_mask,
+				value);
+		} else {
+			/* OK. */
+		}
+	}
+
+	if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER))
+		trigger_write_crtc_h_blank_start_end(ctx, controller_idx);
+
+	return true;
+}
+
+static void dce110_set_blender_mode(
+	struct dc_context *ctx,
+	uint8_t controller_id,
+	uint32_t mode)
+{
+	uint32_t value;
+	uint32_t addr = HW_REG_BLND(mmBLND_CONTROL, controller_id);
+	uint32_t blnd_mode;
+	uint32_t feedthrough = 0;
+
+	switch (mode) {
+	case BLENDER_MODE_OTHER_PIPE:
+		feedthrough = 0;
+		blnd_mode = 1;
+		break;
+	case BLENDER_MODE_BLENDING:
+		feedthrough = 0;
+		blnd_mode = 2;
+		break;
+	case BLENDER_MODE_CURRENT_PIPE:
+	default:
+		feedthrough = 1;
+		blnd_mode = 0;
+		break;
+	}
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		feedthrough,
+		BLND_CONTROL,
+		BLND_FEEDTHROUGH_EN);
+
+	set_reg_field_value(
+		value,
+		blnd_mode,
+		BLND_CONTROL,
+		BLND_MODE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void dce110_crtc_switch_to_clk_src(
+				struct clock_source *clk_src, uint8_t crtc_inst)
+{
+	uint32_t pixel_rate_cntl_value;
+	uint32_t addr;
+
+	addr = mmCRTC0_PIXEL_RATE_CNTL + crtc_inst *
+			(mmCRTC1_PIXEL_RATE_CNTL - mmCRTC0_PIXEL_RATE_CNTL);
+
+	pixel_rate_cntl_value = dm_read_reg(clk_src->ctx, addr);
+
+	if (clk_src->id == CLOCK_SOURCE_ID_EXTERNAL)
+		set_reg_field_value(pixel_rate_cntl_value, 1,
+			CRTC0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE);
+	else {
+		set_reg_field_value(pixel_rate_cntl_value,
+				0,
+				CRTC0_PIXEL_RATE_CNTL,
+				DP_DTO0_ENABLE);
+
+		set_reg_field_value(pixel_rate_cntl_value,
+				clk_src->id - 1,
+				CRTC0_PIXEL_RATE_CNTL,
+				CRTC0_PIXEL_RATE_SOURCE);
+	}
+	dm_write_reg(clk_src->ctx, addr, pixel_rate_cntl_value);
+}
+/**************************************************************************/
+
+static void enable_display_pipe_clock_gating(
+	struct dc_context *ctx,
+	bool clock_gating)
+{
+	/*TODO*/
+}
+
+static bool dce110_enable_display_power_gating(
+	struct dc_context *ctx,
+	uint8_t controller_id,
+	struct dc_bios *dcb,
+	enum pipe_gating_control power_gating)
+{
+	enum bp_result bp_result = BP_RESULT_OK;
+	enum bp_pipe_control_action cntl;
+
+	if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
+		return true;
+
+	if (power_gating == PIPE_GATING_CONTROL_INIT)
+		cntl = ASIC_PIPE_INIT;
+	else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
+		cntl = ASIC_PIPE_ENABLE;
+	else
+		cntl = ASIC_PIPE_DISABLE;
+
+	if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0))
+		bp_result = dcb->funcs->enable_disp_power_gating(
+						dcb, controller_id + 1, cntl);
+
+	if (power_gating != PIPE_GATING_CONTROL_ENABLE)
+		dce110_init_pte(ctx);
+
+	if (bp_result == BP_RESULT_OK)
+		return true;
+	else
+		return false;
+}
+
+
+static bool set_gamma_ramp(
+	struct input_pixel_processor *ipp,
+	struct output_pixel_processor *opp,
+	const struct gamma_ramp *ramp,
+	const struct gamma_parameters *params)
+{
+	/*Power on LUT memory*/
+	opp->funcs->opp_power_on_regamma_lut(opp, true);
+
+
+	if (params->surface_pixel_format == PIXEL_FORMAT_INDEX8 ||
+		params->selected_gamma_lut == GRAPHICS_GAMMA_LUT_LEGACY) {
+		/* do legacy DCP for 256 colors if we are requested to do so */
+		ipp->funcs->ipp_set_legacy_input_gamma_ramp(
+			ipp, ramp, params);
+
+		ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, true);
+
+		/* set bypass */
+		ipp->funcs->ipp_program_prescale(ipp, PIXEL_FORMAT_UNINITIALIZED);
+
+		ipp->funcs->ipp_set_degamma(ipp, params, true);
+
+		opp->funcs->opp_set_regamma(opp, ramp, params, true);
+	} else if (params->selected_gamma_lut ==
+			GRAPHICS_GAMMA_LUT_LEGACY_AND_REGAMMA) {
+		if (!opp->funcs->opp_map_legacy_and_regamma_hw_to_x_user(
+			opp, ramp, params)) {
+			BREAK_TO_DEBUGGER();
+			/* invalid parameters or bug */
+			return false;
+		}
+
+		/* do legacy DCP for 256 colors if we are requested to do so */
+		ipp->funcs->ipp_set_legacy_input_gamma_ramp(
+			ipp, ramp, params);
+
+		ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, true);
+
+		/* set bypass */
+		ipp->funcs->ipp_program_prescale(ipp, PIXEL_FORMAT_UNINITIALIZED);
+	} else {
+		ipp->funcs->ipp_set_legacy_input_gamma_mode(ipp, false);
+
+		ipp->funcs->ipp_program_prescale(ipp, params->surface_pixel_format);
+
+		/* Do degamma step : remove the given gamma value from FB.
+		 * For FP16 or no degamma do by pass */
+		ipp->funcs->ipp_set_degamma(ipp, params, false);
+
+		opp->funcs->opp_set_regamma(opp, ramp, params, false);
+	}
+
+	/*re-enable low power mode for LUT memory*/
+	opp->funcs->opp_power_on_regamma_lut(opp, false);
+
+	return true;
+}
+
+static enum dc_status bios_parser_crtc_source_select(
+		struct core_stream *stream)
+{
+	struct dc_bios *dcb;
+	/* call VBIOS table to set CRTC source for the HW
+	 * encoder block
+	 * note: video bios clears all FMT setting here. */
+	struct bp_crtc_source_select crtc_source_select = {0};
+	const struct core_sink *sink = stream->sink;
+
+	crtc_source_select.engine_id = stream->stream_enc->id;
+	crtc_source_select.controller_id = stream->controller_idx + 1;
+	/*TODO: Need to un-hardcode color depth, dp_audio and account for
+	 * the case where signal and sink signal is different (translator
+	 * encoder)*/
+	crtc_source_select.signal = sink->public.sink_signal;
+	crtc_source_select.enable_dp_audio = false;
+	crtc_source_select.sink_signal = sink->public.sink_signal;
+	crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
+
+	dcb = dal_adapter_service_get_bios_parser(sink->link->adapter_srv);
+
+	if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
+		dcb,
+		&crtc_source_select)) {
+		return DC_ERROR_UNEXPECTED;
+	}
+
+	return DC_OK;
+}
+
+static enum color_space surface_color_to_color_space(
+	struct plane_colorimetry *colorimetry)
+{
+	enum color_space color_space = COLOR_SPACE_UNKNOWN;
+
+	switch (colorimetry->color_space) {
+	case SURFACE_COLOR_SPACE_SRGB:
+	case SURFACE_COLOR_SPACE_XRRGB:
+		if (colorimetry->limited_range)
+			color_space = COLOR_SPACE_SRGB_LIMITED_RANGE;
+		else
+			color_space = COLOR_SPACE_SRGB_FULL_RANGE;
+		break;
+	case SURFACE_COLOR_SPACE_BT601:
+	case SURFACE_COLOR_SPACE_XVYCC_BT601:
+		color_space = COLOR_SPACE_YCBCR601;
+		break;
+	case SURFACE_COLOR_SPACE_BT709:
+	case SURFACE_COLOR_SPACE_XVYCC_BT709:
+		color_space = COLOR_SPACE_YCBCR709;
+		break;
+	}
+
+	return color_space;
+}
+
+/*******************************FMT**************************************/
+static void program_fmt(
+		struct output_pixel_processor *opp,
+		struct bit_depth_reduction_params *fmt_bit_depth,
+		struct clamping_and_pixel_encoding_params *clamping)
+{
+	/* dithering is affected by <CrtcSourceSelect>, hence should be
+	 * programmed afterwards */
+
+	opp->funcs->opp_program_bit_depth_reduction(
+		opp,
+		fmt_bit_depth);
+
+	opp->funcs->opp_program_clamping_and_pixel_encoding(
+		opp,
+		clamping);
+
+	return;
+}
+
+static void update_bios_scratch_critical_state(struct adapter_service *as,
+		bool state)
+{
+	struct dc_bios *dcb = dal_adapter_service_get_bios_parser(as);
+
+	dcb->funcs->set_scratch_critical_state(dcb, state);
+}
+
+static void update_info_frame(struct core_stream *stream)
+{
+	if (dc_is_hdmi_signal(stream->signal))
+		stream->stream_enc->funcs->update_hdmi_info_packets(
+			stream->stream_enc,
+			&stream->encoder_info_frame);
+	else if (dc_is_dp_signal(stream->signal))
+		stream->stream_enc->funcs->update_dp_info_packets(
+			stream->stream_enc,
+			&stream->encoder_info_frame);
+}
+
+
+static void enable_stream(struct core_stream *stream)
+{
+	enum lane_count lane_count =
+			stream->sink->link->cur_link_settings.lane_count;
+
+	struct dc_crtc_timing *timing = &stream->public.timing;
+	struct core_link *link = stream->sink->link;
+
+	/* 1. update AVI info frame (HDMI, DP)
+	 * we always need to update info frame
+	*/
+	uint32_t active_total_with_borders;
+	uint32_t early_control = 0;
+	struct timing_generator *tg = stream->tg;
+
+	update_info_frame(stream);
+	/* enable early control to avoid corruption on DP monitor*/
+	active_total_with_borders =
+			timing->h_addressable
+				+ timing->h_border_left
+				+ timing->h_border_right;
+
+	if (lane_count != 0)
+		early_control = active_total_with_borders % lane_count;
+
+	if (early_control == 0)
+		early_control = lane_count;
+
+	tg->funcs->set_early_control(tg, early_control);
+
+	/* enable audio only within mode set */
+	if (stream->audio != NULL) {
+		dal_audio_enable_output(
+			stream->audio,
+			stream->stream_enc->id,
+			stream->signal);
+	}
+
+	/* For MST, there are multiply stream go to only one link.
+	 * connect DIG back_end to front_end while enable_stream and
+	 * disconnect them during disable_stream
+	 * BY this, it is logic clean to separate stream and link */
+	 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
+			stream->stream_enc->id, true);
+
+}
+
+static void disable_stream(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+
+	if (dc_is_hdmi_signal(stream->signal))
+		stream->stream_enc->funcs->stop_hdmi_info_packets(
+			stream->stream_enc);
+
+	if (dc_is_dp_signal(stream->signal))
+		stream->stream_enc->funcs->stop_dp_info_packets(
+			stream->stream_enc);
+
+	if (stream->audio) {
+		/* mute audio */
+		dal_audio_mute(stream->audio, stream->stream_enc->id,
+				stream->signal);
+
+		/* TODO: notify audio driver for if audio modes list changed
+		 * add audio mode list change flag */
+		/* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
+		 * stream->stream_engine_id);
+		 */
+	}
+
+	/* blank at encoder level */
+	if (dc_is_dp_signal(stream->signal))
+		stream->stream_enc->funcs->dp_blank(stream->stream_enc);
+
+	link->link_enc->funcs->connect_dig_be_to_fe(
+			link->link_enc,
+			stream->stream_enc->id,
+			false);
+
+}
+
+static void unblank_stream(struct core_stream *stream,
+		struct link_settings *link_settings)
+{
+	struct encoder_unblank_param params = { { 0 } };
+
+	/* only 3 items below are used by unblank */
+	params.crtc_timing.pixel_clock =
+		stream->public.timing.pix_clk_khz;
+	params.link_settings.link_rate = link_settings->link_rate;
+	stream->stream_enc->funcs->dp_unblank(
+		stream->stream_enc, &params);
+}
+
+static enum color_space get_output_color_space(
+				const struct dc_crtc_timing *dc_crtc_timing)
+{
+	enum color_space color_space = COLOR_SPACE_SRGB_FULL_RANGE;
+
+	switch (dc_crtc_timing->pixel_encoding)	{
+	case PIXEL_ENCODING_YCBCR422:
+	case PIXEL_ENCODING_YCBCR444:
+	case PIXEL_ENCODING_YCBCR420:
+	{
+		if ((dc_crtc_timing->timing_standard ==
+			TIMING_STANDARD_CEA770) ||
+			(dc_crtc_timing->timing_standard ==
+				TIMING_STANDARD_CEA861)) {
+			if (dc_crtc_timing->pix_clk_khz > 27030) {
+				if (dc_crtc_timing->flags.Y_ONLY)
+					color_space =
+						COLOR_SPACE_YCBCR709_YONLY;
+				else
+					color_space = COLOR_SPACE_YCBCR709;
+			} else {
+				if (dc_crtc_timing->flags.Y_ONLY)
+					color_space =
+						COLOR_SPACE_YCBCR601_YONLY;
+				else
+					color_space = COLOR_SPACE_YCBCR601;
+			}
+		}
+	}
+	break;
+
+	default:
+		break;
+	}
+
+	return color_space;
+}
+
+static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx,
+		struct validate_context *context,
+		const struct dc *dc)
+{
+	struct core_stream *stream =
+			context->res_ctx.controller_ctx[controller_idx].stream;
+	struct output_pixel_processor *opp =
+		context->res_ctx.pool.opps[controller_idx];
+	bool timing_changed = context->res_ctx.controller_ctx[controller_idx]
+			.flags.timing_changed;
+	enum color_space color_space;
+
+	if (timing_changed) {
+		/* Must blank CRTC after disabling power gating and before any
+		 * programming, otherwise CRTC will be hung in bad state
+		 */
+		stream->tg->funcs->set_blank(stream->tg, true);
+
+		core_link_disable_stream(stream->sink->link, stream);
+
+		/*TODO: AUTO check if timing changed*/
+		if (false == stream->clock_source->funcs->program_pix_clk(
+				stream->clock_source,
+				&stream->pix_clk_params,
+				&stream->pll_settings)) {
+			BREAK_TO_DEBUGGER();
+			return DC_ERROR_UNEXPECTED;
+		}
+
+		stream->tg->funcs->program_timing(
+				stream->tg,
+				&stream->public.timing,
+				true);
+	}
+
+	/*TODO: mst support - use total stream count*/
+	stream->mi->funcs->mem_input_allocate_dmif_buffer(
+					stream->mi,
+					&stream->public.timing,
+					context->target_count);
+
+	if (timing_changed) {
+		if (false == stream->tg->funcs->enable_crtc(
+				stream->tg)) {
+			BREAK_TO_DEBUGGER();
+			return DC_ERROR_UNEXPECTED;
+		}
+	}
+
+	/* TODO: move to stream encoder */
+	if (stream->signal != SIGNAL_TYPE_VIRTUAL)
+		if (DC_OK != bios_parser_crtc_source_select(stream)) {
+			BREAK_TO_DEBUGGER();
+			return DC_ERROR_UNEXPECTED;
+		}
+
+	opp->funcs->opp_set_dyn_expansion(
+			opp,
+			COLOR_SPACE_YCBCR601,
+			stream->public.timing.display_color_depth,
+			stream->sink->public.sink_signal);
+
+	program_fmt(opp, &stream->bit_depth_params, &stream->clamping);
+
+	stream->sink->link->link_enc->funcs->setup(
+		stream->sink->link->link_enc,
+		stream->signal);
+
+	if (dc_is_dp_signal(stream->signal))
+		stream->stream_enc->funcs->dp_set_stream_attribute(
+			stream->stream_enc,
+			&stream->public.timing);
+
+	if (dc_is_hdmi_signal(stream->signal))
+		stream->stream_enc->funcs->hdmi_set_stream_attribute(
+			stream->stream_enc,
+			&stream->public.timing,
+			stream->audio != NULL);
+
+	if (dc_is_dvi_signal(stream->signal))
+		stream->stream_enc->funcs->dvi_set_stream_attribute(
+			stream->stream_enc,
+			&stream->public.timing,
+			(stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
+			true : false);
+
+	if (stream->audio != NULL) {
+		if (AUDIO_RESULT_OK != dal_audio_setup(
+				stream->audio,
+				&stream->audio_output,
+				&stream->public.audio_info)) {
+			BREAK_TO_DEBUGGER();
+			return DC_ERROR_UNEXPECTED;
+		}
+	}
+
+	/* Setup audio rate clock source */
+	if (stream->audio != NULL)
+		dal_audio_setup_audio_wall_dto(
+				stream->audio,
+				stream->signal,
+				&stream->audio_output.crtc_info,
+				&stream->audio_output.pll_info);
+
+	/* program blank color */
+	color_space = get_output_color_space(&stream->public.timing);
+	stream->tg->funcs->set_blank_color(
+			context->res_ctx.pool.timing_generators[controller_idx],
+			color_space);
+
+	if (timing_changed)
+		core_link_enable_stream(stream->sink->link, stream);
+
+	if (dc_is_dp_signal(stream->signal))
+		unblank_stream(stream, &stream->sink->link->cur_link_settings);
+
+	return DC_OK;
+}
+
+
+/******************************************************************************/
+
+static void power_down_encoders(struct dc *dc)
+{
+	int i;
+
+	for (i = 0; i < dc->link_count; i++) {
+		dc->links[i]->link_enc->funcs->disable_output(
+				dc->links[i]->link_enc, SIGNAL_TYPE_NONE);
+	}
+}
+
+static void power_down_controllers(struct dc *dc)
+{
+	int i;
+
+	for (i = 0; i < dc->res_pool.controller_count; i++) {
+		dc->res_pool.timing_generators[i]->funcs->disable_crtc(
+				dc->res_pool.timing_generators[i]);
+	}
+}
+
+static void power_down_clock_sources(struct dc *dc)
+{
+	int i;
+
+	for (i = 0; i < dc->res_pool.clk_src_count; i++) {
+		if (dc->res_pool.clock_sources[i]->funcs->cs_power_down(
+				dc->res_pool.clock_sources[i]) == false)
+			dm_error("Failed to power down pll! (clk src index=%d)\n", i);
+	}
+}
+
+static void power_down_all_hw_blocks(struct dc *dc)
+{
+	power_down_encoders(dc);
+
+	power_down_controllers(dc);
+
+	power_down_clock_sources(dc);
+}
+
+static void disable_vga_and_power_gate_all_controllers(
+		struct dc *dc)
+{
+	int i;
+	struct timing_generator *tg;
+	struct dc_bios *dcb;
+	struct dc_context *ctx;
+
+	dcb = dal_adapter_service_get_bios_parser(
+			dc->res_pool.adapter_srv);
+
+	for (i = 0; i < dc->res_pool.controller_count; i++) {
+		tg = dc->res_pool.timing_generators[i];
+		ctx = dc->ctx;
+
+		tg->funcs->disable_vga(tg);
+
+		/* Enable CLOCK gating for each pipe BEFORE controller
+		 * powergating. */
+		enable_display_pipe_clock_gating(ctx,
+				true);
+		dc->hwss.enable_display_power_gating(ctx, i, dcb,
+				PIPE_GATING_CONTROL_ENABLE);
+	}
+}
+
+/**
+ * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
+ *  1. Power down all DC HW blocks
+ *  2. Disable VGA engine on all controllers
+ *  3. Enable power gating for controller
+ *  4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
+ */
+static void enable_accelerated_mode(struct dc *dc)
+{
+	struct dc_bios *dcb;
+
+	dcb = dal_adapter_service_get_bios_parser(dc->res_pool.adapter_srv);
+
+	power_down_all_hw_blocks(dc);
+
+	disable_vga_and_power_gate_all_controllers(dc);
+
+	dcb->funcs->set_scratch_acc_mode_change(dcb);
+}
+
+#if 0
+static enum clocks_state get_required_clocks_state(
+	struct display_clock *display_clock,
+	struct state_dependent_clocks *req_state_dep_clks)
+{
+	enum clocks_state clocks_required_state;
+	enum clocks_state dp_link_required_state;
+	enum clocks_state overall_required_state;
+
+	clocks_required_state = dal_display_clock_get_required_clocks_state(
+			display_clock, req_state_dep_clks);
+
+	dp_link_required_state = CLOCKS_STATE_ULTRA_LOW;
+
+	/* overall required state is the max of required state for clocks
+	 * (pixel, display clock) and the required state for DP link. */
+	overall_required_state =
+		clocks_required_state > dp_link_required_state ?
+			clocks_required_state : dp_link_required_state;
+
+	/* return the min required state */
+	return overall_required_state;
+}
+
+static bool dc_pre_clock_change(
+		struct dc_context *ctx,
+		struct minimum_clocks_calculation_result *min_clk_in,
+		enum clocks_state required_clocks_state,
+		struct power_to_dal_info *output)
+{
+	struct dal_to_power_info input = {0};
+
+	input.min_deep_sleep_sclk = min_clk_in->min_deep_sleep_sclk;
+	input.min_mclk = min_clk_in->min_mclk_khz;
+	input.min_sclk = min_clk_in->min_sclk_khz;
+
+	switch (required_clocks_state) {
+	case CLOCKS_STATE_ULTRA_LOW:
+		input.required_clock = PP_CLOCKS_STATE_ULTRA_LOW;
+		break;
+	case CLOCKS_STATE_LOW:
+		input.required_clock = PP_CLOCKS_STATE_LOW;
+		break;
+	case CLOCKS_STATE_NOMINAL:
+		input.required_clock = PP_CLOCKS_STATE_NOMINAL;
+		break;
+	case CLOCKS_STATE_PERFORMANCE:
+		input.required_clock = PP_CLOCKS_STATE_PERFORMANCE;
+		break;
+	default:
+		input.required_clock = PP_CLOCKS_STATE_NOMINAL;
+		break;
+	}
+
+	if (!dc_service_pp_pre_dce_clock_change(ctx, &input, output)) {
+		dm_error("DC: dc_service_pp_pre_dce_clock_change failed!\n");
+		return false;
+	}
+
+	return true;
+}
+
+static bool dc_set_clocks_and_clock_state (
+		struct validate_context *context)
+{
+	struct power_to_dal_info output = {0};
+
+	struct display_clock *disp_clk = context->res_ctx.pool.display_clock;
+	struct dc_context *ctx = context->targets[0]->ctx;
+
+
+	if (!dc_pre_clock_change(
+			ctx,
+			&context->res_ctx.min_clocks,
+			get_required_clocks_state(
+					context->res_ctx.pool.display_clock,
+					&context->res_ctx.state_clocks),
+			&output)) {
+		/* "output" was not updated by PPLib.
+		 * DAL will use default values for set mode.
+		 *
+		 * Do NOT fail this call. */
+		return true;
+	}
+
+	/* PPLib accepted the "clock state" that we need, that means we
+	 * can store it as minimum state because PPLib guarantees not go below
+	 * that state.
+	 *
+	 * Update the clock state here (prior to setting Pixel clock,
+	 * or Display clock)
+	 **/
+	if (!dal_display_clock_set_min_clocks_state(
+			disp_clk, context->res_ctx.required_clocks_state)) {
+		BREAK_TO_DEBUGGER();
+		dm_error("DC: failed to set minimum clock state!\n");
+	}
+
+
+	/*bm_clk_info.max_mclk_khz = output.max_mclk;
+	bm_clk_info.min_mclk_khz = output.min_mclk;
+	bm_clk_info.max_sclk_khz = output.max_sclk;
+	bm_clk_info.min_sclk_khz = output.min_sclk;*/
+
+	/* Now let Bandwidth Manager know about values we got from PPLib. */
+	/*dal_bandwidth_manager_set_dynamic_clock_info(bw_mgr, &bm_clk_info);*/
+
+	return true;
+}
+#endif
+
+/**
+ * Call display_engine_clock_dce80 to perform the Dclk programming.
+ */
+static void set_display_clock(struct validate_context *context)
+{
+	/* Program the display engine clock.
+	 * Check DFS bypass mode support or not. DFSbypass feature is only when
+	 * BIOS GPU info table reports support. */
+
+	if (/*dal_adapter_service_is_dfs_bypass_enabled()*/ false) {
+		/*TODO: set_display_clock_dfs_bypass(
+				hws,
+				path_set,
+				context->res_ctx.pool.display_clock,
+				context->res_ctx.min_clocks.min_dclk_khz);*/
+	} else
+		dal_display_clock_set_clock(context->res_ctx.pool.display_clock,
+				context->bw_results.dispclk_khz);
+
+	/* TODO: When changing display engine clock, DMCU WaitLoop must be
+	 * reconfigured in order to maintain the same delays within DMCU
+	 * programming sequences. */
+
+	/* TODO: Start GTC counter */
+}
+
+static void set_displaymarks(
+	const struct dc *dc, struct validate_context *context)
+{
+	uint8_t i, j;
+	uint8_t total_streams = 0;
+	uint8_t target_count = context->target_count;
+
+	for (i = 0; i < target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			stream->mi->funcs->mem_input_program_display_marks(
+				stream->mi,
+				context->bw_results
+				.nbp_state_change_wm_ns[total_streams],
+				context->bw_results
+					.stutter_exit_wm_ns[total_streams],
+				context->bw_results
+					.urgent_wm_ns[total_streams],
+				stream->public.timing.h_total,
+				stream->public.timing.pix_clk_khz,
+				1000 * dc->bw_vbios.blackout_duration
+								.value >> 24);
+			total_streams++;
+		}
+	}
+}
+
+static void set_safe_displaymarks(struct validate_context *context)
+{
+	uint8_t i, j;
+	uint8_t target_count = context->target_count;
+
+	for (i = 0; i < target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			stream->mi->funcs->mem_input_program_safe_display_marks(
+					stream->mi);
+		}
+	}
+}
+
+static void program_bw(struct dc *dc, struct validate_context *context)
+{
+	set_safe_displaymarks(context);
+	/*TODO: when pplib works*/
+	/*dc_set_clocks_and_clock_state(context);*/
+
+	dc->hwss.set_display_clock(context);
+	dc->hwss.set_displaymarks(dc, context);
+}
+
+static void switch_dp_clock_sources(
+	const struct dc *dc,
+	struct validate_context *val_context)
+{
+	uint8_t i, j;
+	for (i = 0; i < val_context->target_count; i++) {
+		struct core_target *target = val_context->targets[i];
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			if (dc_is_dp_signal(stream->signal)) {
+				struct clock_source *clk_src =
+					find_used_clk_src_for_sharing(
+							val_context, stream);
+
+				if (clk_src &&
+					clk_src != stream->clock_source) {
+					unreference_clock_source(
+							&val_context->res_ctx,
+							stream->clock_source);
+					stream->clock_source = clk_src;
+					reference_clock_source(
+						&val_context->res_ctx, clk_src);
+					dc->hwss.crtc_switch_to_clk_src(
+						clk_src, stream->opp->inst);
+				}
+			}
+		}
+	}
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+/*TODO: const validate_context*/
+static enum dc_status apply_ctx_to_hw(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	enum dc_status status;
+	uint8_t i;
+	struct resource_pool *pool = &context->res_ctx.pool;
+
+	update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
+			true);
+
+	for (i = 0; i < pool->controller_count; i++) {
+		struct controller_ctx *ctlr_ctx
+			= &context->res_ctx.controller_ctx[i];
+		struct dc_bios *dcb;
+
+		if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream)
+			continue;
+
+		dcb = dal_adapter_service_get_bios_parser(
+				context->res_ctx.pool.adapter_srv);
+
+		dc->hwss.enable_display_power_gating(
+				dc->ctx, i, dcb,
+				PIPE_GATING_CONTROL_DISABLE);
+	}
+
+	set_safe_displaymarks(context);
+	/*TODO: when pplib works*/
+	/*dc_set_clocks_and_clock_state(context);*/
+
+	if (context->bw_results.dispclk_khz
+		> dc->current_context.bw_results.dispclk_khz)
+		set_display_clock(context);
+
+	for (i = 0; i < pool->controller_count; i++) {
+		struct controller_ctx *ctlr_ctx
+			= &context->res_ctx.controller_ctx[i];
+		if (ctlr_ctx->flags.unchanged || !ctlr_ctx->stream)
+			continue;
+
+		status = apply_single_controller_ctx_to_hw(
+				i,
+				context,
+				dc);
+
+		if (DC_OK != status)
+			return status;
+	}
+	dc->hwss.set_displaymarks(dc, context);
+
+	update_bios_scratch_critical_state(context->res_ctx.pool.adapter_srv,
+			false);
+
+	switch_dp_clock_sources(dc, context);
+
+	return DC_OK;
+}
+
+
+/*******************************************************************************
+ * Front End programming
+ ******************************************************************************/
+
+static bool setup_line_buffer_pixel_depth(
+	const struct core_stream *stream,
+	enum lb_pixel_depth depth,
+	bool blank)
+{
+	enum lb_pixel_depth current_depth;
+
+	struct timing_generator *tg = stream->tg;
+	struct transform *xfm = stream->xfm;
+
+	if (!xfm->funcs->transform_get_current_pixel_storage_depth(
+		xfm,
+		&current_depth))
+		return false;
+
+	if (current_depth != depth) {
+		if (blank)
+			tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
+
+		return xfm->funcs->transform_set_pixel_storage_depth(xfm, depth,
+				&stream->bit_depth_params);
+	}
+
+	return false;
+}
+
+static void hw_sequencer_build_scaler_parameter_plane(
+		const struct core_stream *stream,
+		struct scaler_data *scaler_data)
+{
+	/*TODO: per pipe not per stream*/
+	/*TODO: get from feature from adapterservice*/
+	scaler_data->flags.bits.SHOW_COLOURED_BORDER = false;
+
+	scaler_data->flags.bits.SHOULD_PROGRAM_ALPHA = 1;
+
+	scaler_data->flags.bits.SHOULD_PROGRAM_VIEWPORT = 0;
+
+	scaler_data->flags.bits.SHOULD_UNLOCK = 0;
+
+	scaler_data->flags.bits.INTERLACED = 0;
+
+	scaler_data->dal_pixel_format = stream->format;
+
+	scaler_data->taps = stream->taps;
+
+	scaler_data->viewport = stream->viewport;
+
+	scaler_data->overscan = stream->overscan;
+
+	scaler_data->ratios = &stream->ratios;
+
+	/*TODO rotation and adjustment */
+	scaler_data->h_sharpness = 0;
+	scaler_data->v_sharpness = 0;
+
+}
+
+static void set_default_colors(
+				struct input_pixel_processor *ipp,
+				struct output_pixel_processor *opp,
+				enum pixel_format format,
+				enum color_space input_color_space,
+				enum color_space output_color_space,
+				enum dc_color_depth color_depth)
+{
+	struct default_adjustment default_adjust = { 0 };
+
+	default_adjust.force_hw_default = false;
+	default_adjust.color_space = output_color_space;
+	default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
+	default_adjust.surface_pixel_format = format;
+
+	/* display color depth */
+	default_adjust.color_depth = color_depth;
+
+	/* Lb color depth */
+	default_adjust.lb_color_depth = LB_PIXEL_DEPTH_24BPP;
+	/*dal_hw_sequencer_translate_to_lb_color_depth(
+			build_params->
+			line_buffer_params[path_id][plane_id].depth);*/
+
+	opp->funcs->opp_set_csc_default(opp, &default_adjust);
+}
+
+static void program_scaler(
+	uint8_t controller_idx,
+	struct timing_generator *tg,
+	struct transform *xfm,
+	const struct core_surface *surface,
+	const struct core_stream *stream)
+{
+	struct scaler_data scaler_data = { { 0 } };
+
+	hw_sequencer_build_scaler_parameter_plane(
+		stream,
+		&scaler_data);
+
+	setup_line_buffer_pixel_depth(
+		stream,
+		LB_PIXEL_DEPTH_24BPP,
+		false);
+
+	tg->funcs->set_overscan_blank_color(tg, surface->public.colorimetry.color_space);
+
+	xfm->funcs->transform_set_scaler(xfm, &scaler_data);
+
+	xfm->funcs->transform_update_viewport(
+			xfm,
+			&scaler_data.viewport,
+			false);
+}
+
+/**
+ * Program the Front End of the Pipe.
+ * The Back End was already programmed by Set Mode.
+ */
+static bool set_plane_config(
+	const struct dc *dc,
+	struct core_surface *surface,
+	struct core_target *target)
+{
+	const struct core_stream *core_stream =
+		DC_STREAM_TO_CORE(target->public.streams[0]);
+	const struct dc_crtc_timing *dc_crtc_timing =
+			&target->public.streams[0]->timing;
+	struct mem_input *mi = core_stream->mi;
+	struct input_pixel_processor *ipp = core_stream->ipp;
+	struct timing_generator *tg = core_stream->tg;
+	struct transform *xfm = core_stream->xfm;
+	struct output_pixel_processor *opp = core_stream->opp;
+	struct dc_context *ctx = core_stream->ctx;
+	uint8_t controller_idx = core_stream->controller_idx;
+
+	/* TODO: Clean up change, possibly change to use same type */
+	enum color_space input_color_space =
+					surface_color_to_color_space(&(surface->public.colorimetry));
+
+	dc->hwss.pipe_control_lock(
+			ctx,
+			controller_idx,
+			PIPE_LOCK_CONTROL_MODE,
+			false);
+
+	/* While a non-root controller is programmed we
+	 * have to lock the root controller. */
+	dc->hwss.pipe_control_lock(
+			ctx,
+			controller_idx,
+			PIPE_LOCK_CONTROL_GRAPHICS |
+			PIPE_LOCK_CONTROL_SCL |
+			PIPE_LOCK_CONTROL_BLENDER |
+			PIPE_LOCK_CONTROL_SURFACE,
+			true);
+
+	tg->funcs->program_timing(tg, dc_crtc_timing, false);
+
+	dc->hwss.enable_fe_clock(ctx, controller_idx, true);
+
+	set_default_colors(
+			ipp,
+			opp,
+			core_stream->format,
+			input_color_space,
+			get_output_color_space(dc_crtc_timing),
+			dc_crtc_timing->display_color_depth);
+
+	/* program Scaler */
+	program_scaler(
+		controller_idx, tg, xfm, surface, core_stream);
+
+	dc->hwss.set_blender_mode(
+			ctx,
+			controller_idx,
+			BLENDER_MODE_CURRENT_PIPE);
+
+	mi->funcs->mem_input_program_surface_config(
+			mi,
+			surface->public.format,
+			&surface->public.tiling_info,
+			&surface->public.plane_size,
+			surface->public.rotation);
+
+	dc->hwss.pipe_control_lock(
+			ctx,
+			controller_idx,
+			PIPE_LOCK_CONTROL_GRAPHICS |
+			PIPE_LOCK_CONTROL_SCL |
+			PIPE_LOCK_CONTROL_BLENDER |
+			PIPE_LOCK_CONTROL_SURFACE,
+			false);
+
+	return true;
+}
+
+static bool update_plane_address(
+	const struct dc *dc,
+	const struct core_surface *surface,
+	struct core_target *target)
+{
+	const struct core_stream *core_stream =
+		DC_STREAM_TO_CORE(target->public.streams[0]);
+	struct dc_context *ctx = core_stream->ctx;
+	struct mem_input *mi = core_stream->mi;
+	uint8_t controller_id = core_stream->controller_idx;
+
+	/* TODO: crtc should be per surface, NOT per-target */
+	dc->hwss.pipe_control_lock(
+		ctx,
+		controller_id,
+		PIPE_LOCK_CONTROL_SURFACE,
+		true);
+
+	if (false ==
+		core_stream->mi->funcs->mem_input_program_surface_flip_and_addr(
+		mi, &surface->public.address, surface->public.flip_immediate))
+		return false;
+
+	dc->hwss.pipe_control_lock(
+		ctx,
+		controller_id,
+		PIPE_LOCK_CONTROL_SURFACE,
+		false);
+
+	return true;
+}
+
+static void reset_single_stream_hw_ctx(
+		const struct dc *dc,
+		struct core_stream *stream,
+		struct validate_context *context)
+{
+	struct dc_bios *dcb;
+
+	dcb = dal_adapter_service_get_bios_parser(
+			context->res_ctx.pool.adapter_srv);
+	if (stream->audio) {
+		dal_audio_disable_output(stream->audio,
+				stream->stream_enc->id,
+				stream->signal);
+		stream->audio = NULL;
+	}
+
+	core_link_disable_stream(stream->sink->link, stream);
+
+	stream->tg->funcs->set_blank(stream->tg, true);
+	stream->tg->funcs->disable_crtc(stream->tg);
+	stream->mi->funcs->mem_input_deallocate_dmif_buffer(
+			stream->mi, context->target_count);
+	stream->xfm->funcs->transform_set_scaler_bypass(stream->xfm);
+	unreference_clock_source(&context->res_ctx, stream->clock_source);
+	dc->hwss.enable_display_power_gating(
+			stream->ctx, stream->controller_idx, dcb,
+			PIPE_GATING_CONTROL_ENABLE);
+}
+
+static void reset_hw_ctx(struct dc *dc,
+		struct validate_context *context,
+		uint8_t target_count)
+{
+	uint8_t i;
+	/* look up the targets that have been removed since last commit */
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		const struct core_target *core_target =
+			dc->current_context.targets[i];
+		struct core_stream *core_stream =
+			DC_STREAM_TO_CORE(core_target->public.streams[0]);
+		uint8_t controller_idx = core_stream->controller_idx;
+
+		if (context->res_ctx.controller_ctx[controller_idx].stream &&
+				!context->res_ctx.controller_ctx[controller_idx]
+				.flags.timing_changed)
+			continue;
+
+		reset_single_stream_hw_ctx(dc, core_stream, &dc->current_context);
+	}
+}
+
+static void power_down(struct dc *dc)
+{
+	power_down_all_hw_blocks(dc);
+	disable_vga_and_power_gate_all_controllers(dc);
+
+}
+
+static bool wait_for_reset_trigger_to_occur(
+	struct dc_context *dc_ctx,
+	struct timing_generator *tg)
+{
+	bool rc = false;
+
+	/* To avoid endless loop we wait at most
+	 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
+	const uint32_t frames_to_wait_on_triggered_reset = 10;
+	uint32_t i;
+
+	for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
+
+		if (!tg->funcs->is_counter_moving(tg)) {
+			DC_ERROR("TG counter is not moving!\n");
+			break;
+		}
+
+		if (tg->funcs->did_triggered_reset_occur(tg)) {
+			rc = true;
+			/* usually occurs at i=1 */
+			DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
+					i);
+			break;
+		}
+
+		/* Wait for one frame. */
+		tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
+		tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
+	}
+
+	if (false == rc)
+		DC_ERROR("GSL: Timeout on reset trigger!\n");
+
+	return rc;
+}
+
+/* Enable timing synchronization for a group of Timing Generators. */
+static void enable_timing_synchronization(
+	struct dc_context *dc_ctx,
+	uint32_t timing_generator_num,
+	struct timing_generator *tgs[])
+{
+	struct dcp_gsl_params gsl_params = { 0 };
+	struct trigger_params trigger_params;
+	uint32_t i;
+
+	DC_SYNC_INFO("GSL: Setting-up...\n");
+
+	gsl_params.gsl_group = SYNC_SOURCE_GSL_GROUP0;
+	gsl_params.gsl_purpose = DCP_GSL_PURPOSE_SURFACE_FLIP;
+
+	for (i = 0; i < timing_generator_num; i++) {
+		/* Designate a single TG in the group as a master.
+		 * Since HW doesn't care which one, we always assign
+		 * the 1st one in the group. */
+		gsl_params.timing_server = (0 == i ? true : false);
+
+		tgs[i]->funcs->setup_global_swap_lock(tgs[i], &gsl_params);
+	}
+
+	/* Reset slave controllers on master VSync */
+	DC_SYNC_INFO("GSL: enabling trigger-reset\n");
+	dm_memset(&trigger_params, 0, sizeof(trigger_params));
+
+	trigger_params.edge = TRIGGER_EDGE_DEFAULT;
+	trigger_params.source = SYNC_SOURCE_GSL_GROUP0;
+
+	for (i = 1 /* skip the master */; i < timing_generator_num; i++) {
+		tgs[i]->funcs->enable_reset_trigger(tgs[i], &trigger_params);
+
+		DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
+		wait_for_reset_trigger_to_occur(dc_ctx, tgs[i]);
+
+		/* Regardless of success of the wait above, remove the reset or
+		 * the driver will start timing out on Display requests. */
+		DC_SYNC_INFO("GSL: disabling trigger-reset.\n");
+		tgs[i]->funcs->disable_reset_trigger(tgs[i]);
+	}
+
+	/* GSL Vblank synchronization is a one time sync mechanism, assumption
+	 * is that the sync'ed displays will not drift out of sync over time*/
+	DC_SYNC_INFO("GSL: Restoring register states.\n");
+	for (i = 0; i < timing_generator_num; i++)
+		tgs[i]->funcs->tear_down_global_swap_lock(tgs[i]);
+
+	DC_SYNC_INFO("GSL: Set-up complete.\n");
+}
+
+static const struct hw_sequencer_funcs dce110_funcs = {
+	.apply_ctx_to_hw = apply_ctx_to_hw,
+	.reset_hw_ctx = reset_hw_ctx,
+	.set_plane_config = set_plane_config,
+	.update_plane_address = update_plane_address,
+	.set_gamma_ramp = set_gamma_ramp,
+	.power_down = power_down,
+	.enable_accelerated_mode = enable_accelerated_mode,
+	.enable_timing_synchronization = enable_timing_synchronization,
+	.program_bw = program_bw,
+	.enable_stream = enable_stream,
+	.disable_stream = disable_stream,
+	.enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
+	.crtc_switch_to_clk_src = dce110_crtc_switch_to_clk_src,
+	.enable_display_power_gating = dce110_enable_display_power_gating,
+	.enable_fe_clock = dce110_enable_fe_clock,
+	.pipe_control_lock = dce110_pipe_control_lock,
+	.set_blender_mode = dce110_set_blender_mode,
+	.clock_gating_power_up = dal_dc_clock_gating_dce110_power_up,/*todo*/
+	.set_display_clock = set_display_clock,
+	.set_displaymarks = set_displaymarks,
+};
+
+bool dce110_hw_sequencer_construct(struct dc *dc)
+{
+	dc->hwss = dce110_funcs;
+
+	return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
new file mode 100644
index 000000000000..def54df283d5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
@@ -0,0 +1,36 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HWSS_DCE110_H__
+#define __DC_HWSS_DCE110_H__
+
+#include "core_types.h"
+
+struct dc;
+
+bool dce110_hw_sequencer_construct(struct dc *dc);
+
+#endif /* __DC_HWSS_DCE110_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
new file mode 100644
index 000000000000..9e2b5d95a521
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
@@ -0,0 +1,1238 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "link_encoder.h"
+#include "stream_encoder.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+#include "../virtual/virtual_stream_encoder.h"
+#include "dce110/dce110_timing_generator.h"
+#include "dce110/dce110_link_encoder.h"
+#include "dce110/dce110_mem_input.h"
+#include "dce110/dce110_ipp.h"
+#include "dce110/dce110_transform.h"
+#include "dce110/dce110_stream_encoder.h"
+#include "dce110/dce110_opp.h"
+#include "dce110/dce110_clock_source.h"
+
+#include "dce/dce_11_0_d.h"
+
+#ifndef mmDP_DPHY_INTERNAL_CTRL
+	#define mmDP_DPHY_INTERNAL_CTRL 0x4aa7
+	#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7
+	#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7
+	#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7
+	#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7
+	#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7
+	#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7
+	#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7
+	#define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7
+	#define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7
+#endif
+
+enum dce110_clk_src_array_id {
+	DCE110_CLK_SRC_PLL0 = 0,
+	DCE110_CLK_SRC_PLL1,
+	DCE110_CLK_SRC_EXT,
+
+	DCE110_CLK_SRC_TOTAL
+};
+
+static const struct dce110_timing_generator_offsets dce110_tg_offsets[] = {
+	{
+		.crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp =  (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp =  (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
+	}
+};
+
+static const struct dce110_mem_input_reg_offsets dce110_mi_reg_offsets[] = {
+	{
+		.dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE0_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE1_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE2_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	}
+};
+
+static const struct dce110_transform_reg_offsets dce110_xfm_offsets[] = {
+{
+	.scl_offset = (mmSCL0_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB0_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL1_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB1_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL2_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB2_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+}
+};
+
+static const struct dce110_ipp_reg_offsets dce110_ipp_reg_offsets[] = {
+{
+	.dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL),
+}
+};
+
+static const struct dce110_link_enc_bl_registers link_enc_bl_regs = {
+		.BL_PWM_CNTL = mmBL_PWM_CNTL,
+		.BL_PWM_GRP1_REG_LOCK = mmBL_PWM_GRP1_REG_LOCK,
+		.BL_PWM_PERIOD_CNTL = mmBL_PWM_PERIOD_CNTL,
+		.LVTMA_PWRSEQ_CNTL = mmLVTMA_PWRSEQ_CNTL,
+		.LVTMA_PWRSEQ_STATE = mmLVTMA_PWRSEQ_STATE
+};
+
+#define aux_regs(id)\
+[id] = {\
+	.AUX_CONTROL = mmDP_AUX ## id ## _AUX_CONTROL,\
+	.AUX_DPHY_RX_CONTROL0 = mmDP_AUX ## id ## _AUX_DPHY_RX_CONTROL0\
+}
+
+static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = {
+		aux_regs(0),
+		aux_regs(1),
+		aux_regs(2),
+		aux_regs(3),
+		aux_regs(4),
+		aux_regs(5)
+};
+
+#define link_regs(id)\
+[id] = {\
+	.DIG_BE_CNTL = mmDIG ## id ## _DIG_BE_CNTL,\
+	.DIG_BE_EN_CNTL = mmDIG ## id ## _DIG_BE_EN_CNTL,\
+	.DP_CONFIG = mmDP ## id ## _DP_CONFIG,\
+	.DP_DPHY_CNTL = mmDP ## id ## _DP_DPHY_CNTL,\
+	.DP_DPHY_INTERNAL_CTRL = mmDP ## id ## _DP_DPHY_INTERNAL_CTRL,\
+	.DP_DPHY_PRBS_CNTL = mmDP ## id ## _DP_DPHY_PRBS_CNTL,\
+	.DP_DPHY_SYM0 = mmDP ## id ## _DP_DPHY_SYM0,\
+	.DP_DPHY_SYM1 = mmDP ## id ## _DP_DPHY_SYM1,\
+	.DP_DPHY_SYM2 = mmDP ## id ## _DP_DPHY_SYM2,\
+	.DP_DPHY_TRAINING_PATTERN_SEL = mmDP ## id ## _DP_DPHY_TRAINING_PATTERN_SEL,\
+	.DP_LINK_CNTL = mmDP ## id ## _DP_LINK_CNTL,\
+	.DP_LINK_FRAMING_CNTL = mmDP ## id ## _DP_LINK_FRAMING_CNTL,\
+	.DP_MSE_SAT0 = mmDP ## id ## _DP_MSE_SAT0,\
+	.DP_MSE_SAT1 = mmDP ## id ## _DP_MSE_SAT1,\
+	.DP_MSE_SAT2 = mmDP ## id ## _DP_MSE_SAT2,\
+	.DP_MSE_SAT_UPDATE = mmDP ## id ## _DP_MSE_SAT_UPDATE,\
+	.DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\
+	.DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL\
+}
+
+static const struct dce110_link_enc_registers link_enc_regs[] = {
+		link_regs(0),
+		link_regs(1),
+		link_regs(2),
+		link_regs(3),
+		link_regs(4),
+		link_regs(5),
+		link_regs(6)
+};
+
+#define stream_enc_regs(id)\
+[id] = {\
+	.AFMT_AVI_INFO0 = mmDIG ## id ## _AFMT_AVI_INFO0,\
+	.AFMT_AVI_INFO1 = mmDIG ## id ## _AFMT_AVI_INFO1,\
+	.AFMT_AVI_INFO2 = mmDIG ## id ## _AFMT_AVI_INFO2,\
+	.AFMT_AVI_INFO3 = mmDIG ## id ## _AFMT_AVI_INFO3,\
+	.AFMT_GENERIC_0 = mmDIG ## id ## _AFMT_GENERIC_0,\
+	.AFMT_GENERIC_7 = mmDIG ## id ## _AFMT_GENERIC_7,\
+	.AFMT_GENERIC_HDR = mmDIG ## id ## _AFMT_GENERIC_HDR,\
+	.AFMT_INFOFRAME_CONTROL0 = mmDIG ## id ## _AFMT_INFOFRAME_CONTROL0,\
+	.AFMT_VBI_PACKET_CONTROL = mmDIG ## id ## _AFMT_VBI_PACKET_CONTROL,\
+	.DIG_FE_CNTL = mmDIG ## id ## _DIG_FE_CNTL,\
+	.DP_MSE_RATE_CNTL = mmDP ## id ## _DP_MSE_RATE_CNTL,\
+	.DP_MSE_RATE_UPDATE = mmDP ## id ## _DP_MSE_RATE_UPDATE,\
+	.DP_PIXEL_FORMAT = mmDP ## id ## _DP_PIXEL_FORMAT,\
+	.DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\
+	.DP_STEER_FIFO = mmDP ## id ## _DP_STEER_FIFO,\
+	.DP_VID_M = mmDP ## id ## _DP_VID_M,\
+	.DP_VID_N = mmDP ## id ## _DP_VID_N,\
+	.DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL,\
+	.DP_VID_TIMING = mmDP ## id ## _DP_VID_TIMING,\
+	.HDMI_CONTROL = mmDIG ## id ## _HDMI_CONTROL,\
+	.HDMI_GC = mmDIG ## id ## _HDMI_GC,\
+	.HDMI_GENERIC_PACKET_CONTROL0 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL0,\
+	.HDMI_GENERIC_PACKET_CONTROL1 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL1,\
+	.HDMI_INFOFRAME_CONTROL0 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL0,\
+	.HDMI_INFOFRAME_CONTROL1 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL1,\
+	.HDMI_VBI_PACKET_CONTROL = mmDIG ## id ## _HDMI_VBI_PACKET_CONTROL,\
+	.TMDS_CNTL = mmDIG ## id ## _TMDS_CNTL\
+}
+
+static const struct dce110_stream_enc_registers stream_enc_regs[] = {
+		stream_enc_regs(0),
+		stream_enc_regs(1),
+		stream_enc_regs(2),
+		stream_enc_regs(3),
+		stream_enc_regs(4),
+		stream_enc_regs(5),
+		stream_enc_regs(6)
+};
+
+
+/* AG TBD Needs to be reduced back to 3 pipes once dce10 hw sequencer implemented. */
+static const struct dce110_opp_reg_offsets dce110_opp_reg_offsets[] = {
+{
+	.fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE0_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE1_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE2_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{
+	.fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE3_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE4_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmDCFE5_DCFE_MEM_PWR_CTRL - mmDCFE0_DCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+}
+};
+
+
+static const struct dce110_clk_src_reg_offsets dce110_clk_src_reg_offsets[] = {
+	{
+		.pll_cntl = mmBPHYC_PLL0_PLL_CNTL,
+		.pixclk_resync_cntl  = mmPIXCLK0_RESYNC_CNTL
+	},
+	{
+		.pll_cntl = mmBPHYC_PLL1_PLL_CNTL,
+		.pixclk_resync_cntl  = mmPIXCLK1_RESYNC_CNTL
+	}
+};
+
+static struct timing_generator *dce110_timing_generator_create(
+		struct adapter_service *as,
+		struct dc_context *ctx,
+		uint32_t instance,
+		const struct dce110_timing_generator_offsets *offsets)
+{
+	struct dce110_timing_generator *tg110 =
+		dm_alloc(ctx, sizeof(struct dce110_timing_generator));
+
+	if (!tg110)
+		return NULL;
+
+	if (dce110_timing_generator_construct(tg110, as, ctx, instance, offsets))
+		return &tg110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, tg110);
+	return NULL;
+}
+
+static struct stream_encoder *dce110_stream_encoder_create(
+	enum engine_id eng_id,
+	struct dc_context *ctx,
+	struct dc_bios *bp,
+	const struct dce110_stream_enc_registers *regs)
+{
+	struct dce110_stream_encoder *enc110 =
+		dm_alloc(ctx, sizeof(struct dce110_stream_encoder));
+
+	if (!enc110)
+		return NULL;
+
+	if (dce110_stream_encoder_construct(enc110, ctx, bp, eng_id, regs))
+		return &enc110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, enc110);
+	return NULL;
+}
+
+static struct mem_input *dce110_mem_input_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_mem_input_reg_offsets *offset)
+{
+	struct dce110_mem_input *mem_input110 =
+		dm_alloc(ctx, sizeof(struct dce110_mem_input));
+
+	if (!mem_input110)
+		return NULL;
+
+	if (dce110_mem_input_construct(mem_input110,
+			ctx, inst, offset))
+		return &mem_input110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, mem_input110);
+	return NULL;
+}
+
+static void dce110_transform_destroy(struct transform **xfm)
+{
+	dm_free((*xfm)->ctx, TO_DCE110_TRANSFORM(*xfm));
+	*xfm = NULL;
+}
+
+static struct transform *dce110_transform_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *offsets)
+{
+	struct dce110_transform *transform =
+		dm_alloc(ctx, sizeof(struct dce110_transform));
+
+	if (!transform)
+		return NULL;
+
+	if (dce110_transform_construct(transform, ctx, inst, offsets))
+		return &transform->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, transform);
+	return NULL;
+}
+
+static struct input_pixel_processor *dce110_ipp_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_ipp_reg_offsets *offsets)
+{
+	struct dce110_ipp *ipp =
+		dm_alloc(ctx, sizeof(struct dce110_ipp));
+
+	if (!ipp)
+		return NULL;
+
+	if (dce110_ipp_construct(ipp, ctx, inst, offsets))
+		return &ipp->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, ipp);
+	return NULL;
+}
+
+struct link_encoder *dce110_link_encoder_create(
+	const struct encoder_init_data *enc_init_data)
+{
+	struct dce110_link_encoder *enc110 =
+		dm_alloc(
+			enc_init_data->ctx,
+			sizeof(struct dce110_link_encoder));
+
+	if (!enc110)
+		return NULL;
+
+	if (dce110_link_encoder_construct(
+			enc110,
+			enc_init_data,
+			&link_enc_regs[enc_init_data->transmitter],
+			&link_enc_aux_regs[enc_init_data->channel - 1],
+			&link_enc_bl_regs))
+		return &enc110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(enc_init_data->ctx, enc110);
+	return NULL;
+}
+
+void dce110_link_encoder_destroy(struct link_encoder **enc)
+{
+	dm_free((*enc)->ctx, TO_DCE110_LINK_ENC(*enc));
+	*enc = NULL;
+}
+
+
+static struct output_pixel_processor *dce110_opp_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offsets)
+{
+	struct dce110_opp *opp =
+		dm_alloc(ctx, sizeof(struct dce110_opp));
+
+	if (!opp)
+		return NULL;
+
+	if (dce110_opp_construct(opp,
+			ctx, inst, offsets))
+		return &opp->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, opp);
+	return NULL;
+}
+
+struct clock_source *dce110_clock_source_create(
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_reg_offsets *offsets)
+{
+	struct dce110_clk_src *clk_src =
+		dm_alloc(ctx, sizeof(struct dce110_clk_src));
+
+	if (!clk_src)
+		return NULL;
+
+	if (dce110_clk_src_construct(clk_src, ctx, bios, id, offsets))
+		return &clk_src->base;
+
+	BREAK_TO_DEBUGGER();
+	return NULL;
+}
+
+void dce110_clock_source_destroy(struct clock_source **clk_src)
+{
+	dm_free((*clk_src)->ctx, TO_DCE110_CLK_SRC(*clk_src));
+	*clk_src = NULL;
+}
+
+void dce110_destruct_resource_pool(struct resource_pool *pool)
+{
+	unsigned int i;
+
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->opps[i] != NULL)
+			dce110_opp_destroy(&pool->opps[i]);
+
+		if (pool->transforms[i] != NULL)
+			dce110_transform_destroy(&pool->transforms[i]);
+
+		if (pool->ipps[i] != NULL)
+			dce110_ipp_destroy(&pool->ipps[i]);
+
+		if (pool->mis[i] != NULL) {
+			dm_free(pool->mis[i]->ctx,
+					TO_DCE110_MEM_INPUT(pool->mis[i]));
+			pool->mis[i] = NULL;
+		}
+
+		if (pool->timing_generators[i] != NULL)	{
+			dm_free(pool->timing_generators[i]->ctx, DCE110TG_FROM_TG(pool->timing_generators[i]));
+			pool->timing_generators[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		if (pool->stream_enc[i] != NULL)
+			dm_free(pool->stream_enc[i]->ctx,
+				DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+	}
+
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] != NULL) {
+			dce110_clock_source_destroy(&pool->clock_sources[i]);
+		}
+	}
+
+	for (i = 0; i < pool->audio_count; i++)	{
+		if (pool->audios[i] != NULL) {
+			dal_audio_destroy(&pool->audios[i]);
+		}
+	}
+
+	if (pool->display_clock != NULL) {
+		dal_display_clock_destroy(&pool->display_clock);
+	}
+
+	if (pool->scaler_filter != NULL) {
+		dal_scaler_filter_destroy(&pool->scaler_filter);
+	}
+	if (pool->irqs != NULL) {
+		dal_irq_service_destroy(&pool->irqs);
+	}
+
+	if (pool->adapter_srv != NULL) {
+		dal_adapter_service_destroy(&pool->adapter_srv);
+	}
+}
+
+static struct clock_source *find_first_free_pll(
+		struct resource_context *res_ctx)
+{
+	if (res_ctx->clock_source_ref_count[DCE110_CLK_SRC_PLL0] == 0) {
+		return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL0];
+	}
+	if (res_ctx->clock_source_ref_count[DCE110_CLK_SRC_PLL1] == 0) {
+		return res_ctx->pool.clock_sources[DCE110_CLK_SRC_PLL1];
+	}
+
+	return 0;
+}
+
+static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
+{
+	switch (crtc_id) {
+	case CONTROLLER_ID_D0:
+		return DTO_SOURCE_ID0;
+	case CONTROLLER_ID_D1:
+		return DTO_SOURCE_ID1;
+	case CONTROLLER_ID_D2:
+		return DTO_SOURCE_ID2;
+	case CONTROLLER_ID_D3:
+		return DTO_SOURCE_ID3;
+	case CONTROLLER_ID_D4:
+		return DTO_SOURCE_ID4;
+	case CONTROLLER_ID_D5:
+		return DTO_SOURCE_ID5;
+	default:
+		return DTO_SOURCE_UNKNOWN;
+	}
+}
+
+static void build_audio_output(
+	const struct core_stream *stream,
+	struct audio_output *audio_output)
+{
+	audio_output->engine_id = stream->stream_enc->id;
+
+	audio_output->signal = stream->signal;
+
+	/* audio_crtc_info  */
+
+	audio_output->crtc_info.h_total =
+		stream->public.timing.h_total;
+
+	/* Audio packets are sent during actual CRTC blank physical signal, we
+	 * need to specify actual active signal portion */
+	audio_output->crtc_info.h_active =
+			stream->public.timing.h_addressable
+			+ stream->public.timing.h_border_left
+			+ stream->public.timing.h_border_right;
+
+	audio_output->crtc_info.v_active =
+			stream->public.timing.v_addressable
+			+ stream->public.timing.v_border_top
+			+ stream->public.timing.v_border_bottom;
+
+	audio_output->crtc_info.pixel_repetition = 1;
+
+	audio_output->crtc_info.interlaced =
+			stream->public.timing.flags.INTERLACE;
+
+	audio_output->crtc_info.refresh_rate =
+		(stream->public.timing.pix_clk_khz*1000)/
+		(stream->public.timing.h_total*stream->public.timing.v_total);
+
+	audio_output->crtc_info.color_depth =
+		stream->public.timing.display_color_depth;
+
+	audio_output->crtc_info.requested_pixel_clock =
+			stream->pix_clk_params.requested_pix_clk;
+
+	/* TODO - Investigate why calculated pixel clk has to be
+	 * requested pixel clk */
+	audio_output->crtc_info.calculated_pixel_clock =
+			stream->pix_clk_params.requested_pix_clk;
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
+			stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+		audio_output->pll_info.dp_dto_source_clock_in_khz =
+			dal_display_clock_get_dp_ref_clk_frequency(
+				stream->dis_clk);
+	}
+
+	audio_output->pll_info.feed_back_divider =
+			stream->pll_settings.feedback_divider;
+
+	audio_output->pll_info.dto_source =
+		translate_to_dto_source(
+			stream->controller_idx + 1);
+
+	/* TODO hard code to enable for now. Need get from stream */
+	audio_output->pll_info.ss_enabled = true;
+
+	audio_output->pll_info.ss_percentage =
+			stream->pll_settings.ss_percentage;
+}
+
+static void get_pixel_clock_parameters(
+	const struct core_stream *stream,
+	struct pixel_clk_params *pixel_clk_params)
+{
+	pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz;
+	pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
+	pixel_clk_params->signal_type = stream->sink->public.sink_signal;
+	pixel_clk_params->controller_id = stream->controller_idx + 1;
+	/* TODO: un-hardcode*/
+	pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
+		LINK_RATE_REF_FREQ_IN_KHZ;
+	pixel_clk_params->flags.ENABLE_SS = 0;
+	pixel_clk_params->color_depth =
+		stream->public.timing.display_color_depth;
+	pixel_clk_params->flags.DISPLAY_BLANKED = 1;
+}
+
+static enum dc_status build_stream_hw_param(struct core_stream *stream)
+{
+	/*TODO: unhardcode*/
+	stream->max_tmds_clk_from_edid_in_mhz = 0;
+	stream->max_hdmi_deep_color = COLOR_DEPTH_121212;
+	stream->max_hdmi_pixel_clock = 600000;
+
+	get_pixel_clock_parameters(stream, &stream->pix_clk_params);
+	stream->clock_source->funcs->get_pix_clk_dividers(
+		stream->clock_source,
+		&stream->pix_clk_params,
+		&stream->pll_settings);
+
+	build_audio_output(stream, &stream->audio_output);
+
+	return DC_OK;
+}
+
+static enum dc_status validate_mapped_resource(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	enum dc_status status = DC_OK;
+	uint8_t i, j;
+
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		if (context->target_flags[i].unchanged)
+			continue;
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct core_link *link = stream->sink->link;
+
+			if (!stream->tg->funcs->validate_timing(
+					stream->tg, &stream->public.timing))
+				return DC_FAIL_CONTROLLER_VALIDATE;
+
+			status = build_stream_hw_param(stream);
+
+			if (status != DC_OK)
+				return status;
+
+			if (!link->link_enc->funcs->validate_output_with_stream(
+					link->link_enc,
+					stream))
+				return DC_FAIL_ENC_VALIDATE;
+
+			/* TODO: validate audio ASIC caps, encoder */
+
+			status = dc_link_validate_mode_timing(stream->sink,
+					link,
+					&stream->public.timing);
+
+			if (status != DC_OK)
+				return status;
+
+			build_info_frame(stream);
+		}
+	}
+
+	return DC_OK;
+}
+
+enum dc_status dce110_validate_bandwidth(
+	const struct dc *dc,
+	struct validate_context *context)
+{
+	uint8_t i, j;
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	uint8_t number_of_displays = 0;
+	uint8_t max_htaps = 1;
+	uint8_t max_vtaps = 1;
+	bool all_displays_in_sync = true;
+	struct dc_crtc_timing prev_timing;
+
+	memset(&context->bw_mode_data, 0, sizeof(context->bw_mode_data));
+
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct bw_calcs_input_single_display *disp = &context->
+				bw_mode_data.displays_data[number_of_displays];
+
+			if (target->status.surface_count == 0) {
+				disp->graphics_scale_ratio = bw_int_to_fixed(1);
+				disp->graphics_h_taps = 2;
+				disp->graphics_v_taps = 2;
+
+				/* TODO: remove when bw formula accepts taps per
+				 * display
+				 */
+				if (max_vtaps < 2)
+					max_vtaps = 2;
+				if (max_htaps < 2)
+					max_htaps = 2;
+
+			} else {
+				disp->graphics_scale_ratio =
+					fixed31_32_to_bw_fixed(
+						stream->ratios.vert.value);
+				disp->graphics_h_taps = stream->taps.h_taps;
+				disp->graphics_v_taps = stream->taps.v_taps;
+
+				/* TODO: remove when bw formula accepts taps per
+				 * display
+				 */
+				if (max_vtaps < stream->taps.v_taps)
+					max_vtaps = stream->taps.v_taps;
+				if (max_htaps < stream->taps.h_taps)
+					max_htaps = stream->taps.h_taps;
+			}
+
+			disp->graphics_src_width =
+					stream->public.timing.h_addressable;
+			disp->graphics_src_height =
+					stream->public.timing.v_addressable;
+			disp->h_total = stream->public.timing.h_total;
+			disp->pixel_rate = bw_frc_to_fixed(
+				stream->public.timing.pix_clk_khz, 1000);
+
+			/*TODO: get from surface*/
+			disp->graphics_bytes_per_pixel = 4;
+			disp->graphics_tiling_mode = bw_def_tiled;
+
+			/* DCE11 defaults*/
+			disp->graphics_lb_bpc = 10;
+			disp->graphics_interlace_mode = false;
+			disp->fbc_enable = false;
+			disp->lpt_enable = false;
+			disp->graphics_stereo_mode = bw_def_mono;
+			disp->underlay_mode = bw_def_none;
+
+			/*All displays will be synchronized if timings are all
+			 * the same
+			 */
+			if (number_of_displays != 0 && all_displays_in_sync)
+				if (dm_memcmp(&prev_timing,
+					&stream->public.timing,
+					sizeof(struct dc_crtc_timing))!= 0)
+					all_displays_in_sync = false;
+			if (number_of_displays == 0)
+				prev_timing = stream->public.timing;
+
+			number_of_displays++;
+		}
+	}
+
+	/* TODO: remove when bw formula accepts taps per
+	 * display
+	 */
+	context->bw_mode_data.displays_data[0].graphics_v_taps = max_vtaps;
+	context->bw_mode_data.displays_data[0].graphics_h_taps = max_htaps;
+
+	context->bw_mode_data.number_of_displays = number_of_displays;
+	context->bw_mode_data.display_synchronization_enabled =
+							all_displays_in_sync;
+
+	dal_logger_write(
+		dc->ctx->logger,
+		LOG_MAJOR_BWM,
+		LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS,
+		"%s: start\n",
+		__func__);
+
+	if (!bw_calcs(
+			dc->ctx,
+			&dc->bw_dceip,
+			&dc->bw_vbios,
+			&context->bw_mode_data,
+			&context->bw_results))
+		result =  DC_FAIL_BANDWIDTH_VALIDATE;
+	else
+		result =  DC_OK;
+
+	if (result == DC_FAIL_BANDWIDTH_VALIDATE)
+		dal_logger_write(dc->ctx->logger,
+			LOG_MAJOR_BWM,
+			LOG_MINOR_BWM_MODE_VALIDATION,
+			"%s: Bandwidth validation failed!",
+			__func__);
+
+	if (dm_memcmp(&dc->current_context.bw_results,
+			&context->bw_results, sizeof(context->bw_results))) {
+		struct log_entry log_entry;
+		dal_logger_open(
+			dc->ctx->logger,
+			&log_entry,
+			LOG_MAJOR_BWM,
+			LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS);
+		dal_logger_append(&log_entry, "%s: finish, numDisplays: %d\n"
+			"nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
+			"stutMark_b: %d stutMark_a: %d\n",
+			__func__, number_of_displays,
+			context->bw_results.nbp_state_change_wm_ns[0].b_mark,
+			context->bw_results.nbp_state_change_wm_ns[0].a_mark,
+			context->bw_results.urgent_wm_ns[0].b_mark,
+			context->bw_results.urgent_wm_ns[0].a_mark,
+			context->bw_results.stutter_exit_wm_ns[0].b_mark,
+			context->bw_results.stutter_exit_wm_ns[0].a_mark);
+		dal_logger_append(&log_entry,
+			"nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
+			"stutMark_b: %d stutMark_a: %d\n",
+			context->bw_results.nbp_state_change_wm_ns[1].b_mark,
+			context->bw_results.nbp_state_change_wm_ns[1].a_mark,
+			context->bw_results.urgent_wm_ns[1].b_mark,
+			context->bw_results.urgent_wm_ns[1].a_mark,
+			context->bw_results.stutter_exit_wm_ns[1].b_mark,
+			context->bw_results.stutter_exit_wm_ns[1].a_mark);
+		dal_logger_append(&log_entry,
+			"nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
+			"stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n",
+			context->bw_results.nbp_state_change_wm_ns[2].b_mark,
+			context->bw_results.nbp_state_change_wm_ns[2].a_mark,
+			context->bw_results.urgent_wm_ns[2].b_mark,
+			context->bw_results.urgent_wm_ns[2].a_mark,
+			context->bw_results.stutter_exit_wm_ns[2].b_mark,
+			context->bw_results.stutter_exit_wm_ns[2].a_mark,
+			context->bw_results.stutter_mode_enable);
+		dal_logger_append(&log_entry,
+			"cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n"
+			"sclk: %d sclk_sleep: %d yclk: %d blackout_duration: %d\n",
+			context->bw_results.cpuc_state_change_enable,
+			context->bw_results.cpup_state_change_enable,
+			context->bw_results.nbp_state_change_enable,
+			context->bw_results.all_displays_in_sync,
+			context->bw_results.dispclk_khz,
+			context->bw_results.required_sclk,
+			context->bw_results.required_sclk_deep_sleep,
+			context->bw_results.required_yclk,
+			context->bw_results.required_blackout_duration_us);
+		dal_logger_close(&log_entry);
+	}
+	return result;
+}
+
+static void set_target_unchanged(
+		struct validate_context *context,
+		uint8_t target_idx)
+{
+	uint8_t i;
+	struct core_target *target = context->targets[target_idx];
+	context->target_flags[target_idx].unchanged = true;
+	for (i = 0; i < target->public.stream_count; i++) {
+		struct core_stream *core_stream =
+			DC_STREAM_TO_CORE(target->public.streams[i]);
+		uint8_t index = core_stream->controller_idx;
+		context->res_ctx.controller_ctx[index].flags.unchanged = true;
+	}
+}
+
+static enum dc_status map_clock_resources(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	uint8_t i, j;
+
+	/* mark resources used for targets that are already active */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (!context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			reference_clock_source(
+				&context->res_ctx,
+				stream->clock_source);
+		}
+	}
+
+	/* acquire new resources */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			if (dc_is_dp_signal(stream->signal)
+				|| stream->signal == SIGNAL_TYPE_VIRTUAL)
+				stream->clock_source = context->res_ctx.
+					pool.clock_sources[DCE110_CLK_SRC_EXT];
+			else
+				stream->clock_source =
+					find_used_clk_src_for_sharing(
+							context, stream);
+			if (stream->clock_source == NULL)
+				stream->clock_source =
+					find_first_free_pll(&context->res_ctx);
+
+			if (stream->clock_source == NULL)
+				return DC_NO_CLOCK_SOURCE_RESOURCE;
+
+			reference_clock_source(
+					&context->res_ctx,
+					stream->clock_source);
+		}
+	}
+
+	return DC_OK;
+}
+
+enum dc_status dce110_validate_with_context(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count,
+		struct validate_context *context)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	uint8_t i, j;
+	struct dc_context *dc_ctx = dc->ctx;
+
+	for (i = 0; i < set_count; i++) {
+		context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
+
+		for (j = 0; j < dc->current_context.target_count; j++)
+			if (dc->current_context.targets[j] == context->targets[i])
+				set_target_unchanged(context, i);
+
+		if (!context->target_flags[i].unchanged)
+			if (!logical_attach_surfaces_to_target(
+							(struct dc_surface **)set[i].surfaces,
+							set[i].surface_count,
+							&context->targets[i]->public)) {
+				DC_ERROR("Failed to attach surface to target!\n");
+				return DC_FAIL_ATTACH_SURFACES;
+			}
+	}
+
+	context->target_count = set_count;
+
+	context->res_ctx.pool = dc->res_pool;
+
+	result = map_resources(dc, context);
+
+	if (result == DC_OK)
+		result = map_clock_resources(dc, context);
+
+	if (result == DC_OK)
+		result = validate_mapped_resource(dc, context);
+
+	if (result == DC_OK)
+		build_scaling_params_for_context(dc, context);
+
+	if (result == DC_OK)
+		result = dce110_validate_bandwidth(dc, context);
+
+	return result;
+}
+
+static struct resource_funcs dce110_res_pool_funcs = {
+	.destruct = dce110_destruct_resource_pool,
+	.link_enc_create = dce110_link_encoder_create,
+	.link_enc_destroy = dce110_link_encoder_destroy,
+	.validate_with_context = dce110_validate_with_context,
+	.validate_bandwidth = dce110_validate_bandwidth
+};
+
+bool dce110_construct_resource_pool(
+	struct adapter_service *adapter_serv,
+	uint8_t num_virtual_links,
+	struct dc *dc,
+	struct resource_pool *pool)
+{
+	unsigned int i;
+	struct audio_init_data audio_init_data = { 0 };
+	struct dc_context *ctx = dc->ctx;
+	pool->adapter_srv = adapter_serv;
+	pool->funcs = &dce110_res_pool_funcs;
+
+	pool->stream_engines.engine.ENGINE_ID_DIGA = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGB = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGC = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGD = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGE = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGF = 1;
+
+	pool->clock_sources[DCE110_CLK_SRC_PLL0] = dce110_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_PLL0, &dce110_clk_src_reg_offsets[0]);
+	pool->clock_sources[DCE110_CLK_SRC_PLL1] = dce110_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_PLL1, &dce110_clk_src_reg_offsets[1]);
+	pool->clock_sources[DCE110_CLK_SRC_EXT] =  dce110_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_EXTERNAL, &dce110_clk_src_reg_offsets[0]);
+	pool->clk_src_count = DCE110_CLK_SRC_TOTAL;
+
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] == NULL) {
+			dm_error("DC: failed to create clock sources!\n");
+			BREAK_TO_DEBUGGER();
+			goto clk_src_create_fail;
+		}
+	}
+
+	pool->display_clock = dal_display_clock_dce110_create(ctx, adapter_serv);
+	if (pool->display_clock == NULL) {
+		dm_error("DC: failed to create display clock!\n");
+		BREAK_TO_DEBUGGER();
+		goto disp_clk_create_fail;
+	}
+
+	{
+		struct irq_service_init_data init_data;
+		init_data.ctx = dc->ctx;
+		pool->irqs = dal_irq_service_create(
+				dal_adapter_service_get_dce_version(
+					dc->res_pool.adapter_srv),
+				&init_data);
+		if (!pool->irqs)
+			goto irqs_create_fail;
+
+	}
+
+	pool->controller_count =
+		dal_adapter_service_get_func_controllers_num(adapter_serv);
+	pool->stream_enc_count = dal_adapter_service_get_stream_engines_num(
+			adapter_serv);
+	pool->scaler_filter = dal_scaler_filter_create(ctx);
+	if (pool->scaler_filter == NULL) {
+		BREAK_TO_DEBUGGER();
+		dm_error("DC: failed to create filter!\n");
+		goto filter_create_fail;
+	}
+
+	for (i = 0; i < pool->controller_count; i++) {
+		pool->timing_generators[i] = dce110_timing_generator_create(
+				adapter_serv, ctx, i, &dce110_tg_offsets[i]);
+		if (pool->timing_generators[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create tg!\n");
+			goto controller_create_fail;
+		}
+
+		pool->mis[i] = dce110_mem_input_create(ctx, i,
+				&dce110_mi_reg_offsets[i]);
+		if (pool->mis[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create memory input!\n");
+			goto controller_create_fail;
+		}
+
+		pool->ipps[i] = dce110_ipp_create(ctx, i, &dce110_ipp_reg_offsets[i]);
+		if (pool->ipps[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create input pixel processor!\n");
+			goto controller_create_fail;
+		}
+
+		pool->transforms[i] = dce110_transform_create(
+					ctx, i, &dce110_xfm_offsets[i]);
+		if (pool->transforms[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create transform!\n");
+			goto controller_create_fail;
+		}
+		pool->transforms[i]->funcs->transform_set_scaler_filter(
+				pool->transforms[i],
+				pool->scaler_filter);
+
+		pool->opps[i] = dce110_opp_create(ctx, i, &dce110_opp_reg_offsets[i]);
+		if (pool->opps[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create output pixel processor!\n");
+			goto controller_create_fail;
+		}
+	}
+
+	audio_init_data.as = adapter_serv;
+	audio_init_data.ctx = ctx;
+	pool->audio_count = 0;
+	for (i = 0; i < pool->controller_count; i++) {
+		struct graphics_object_id obj_id;
+
+		obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i);
+		if (false == dal_graphics_object_id_is_valid(obj_id)) {
+			/* no more valid audio objects */
+			break;
+		}
+
+		audio_init_data.audio_stream_id = obj_id;
+		pool->audios[i] = dal_audio_create(&audio_init_data);
+		if (pool->audios[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create DPPs!\n");
+			goto audio_create_fail;
+		}
+		pool->audio_count++;
+	}
+
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		/* TODO: rework fragile code*/
+		if (pool->stream_engines.u_all & 1 << i) {
+			pool->stream_enc[i] = dce110_stream_encoder_create(
+				i, dc->ctx,
+				dal_adapter_service_get_bios_parser(
+					adapter_serv),
+				&stream_enc_regs[i]);
+			if (pool->stream_enc[i] == NULL) {
+				BREAK_TO_DEBUGGER();
+				dm_error("DC: failed to create stream_encoder!\n");
+				goto stream_enc_create_fail;
+			}
+		}
+	}
+
+	for (i = 0; i < num_virtual_links; i++) {
+		pool->stream_enc[pool->stream_enc_count] =
+			virtual_stream_encoder_create(
+				dc->ctx, dal_adapter_service_get_bios_parser(
+								adapter_serv));
+		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create stream_encoder!\n");
+			goto stream_enc_create_fail;
+		}
+		pool->stream_enc_count++;
+	}
+
+	return true;
+
+stream_enc_create_fail:
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		if (pool->stream_enc[i] != NULL)
+			dm_free(pool->stream_enc[i]->ctx,
+				DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+	}
+
+audio_create_fail:
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->audios[i] != NULL)
+			dal_audio_destroy(&pool->audios[i]);
+	}
+
+controller_create_fail:
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->opps[i] != NULL)
+			dce110_opp_destroy(&pool->opps[i]);
+
+		if (pool->transforms[i] != NULL)
+			dce110_transform_destroy(&pool->transforms[i]);
+
+		if (pool->ipps[i] != NULL)
+			dce110_ipp_destroy(&pool->ipps[i]);
+
+		if (pool->mis[i] != NULL) {
+			dm_free(pool->mis[i]->ctx,
+					TO_DCE110_MEM_INPUT(pool->mis[i]));
+			pool->mis[i] = NULL;
+		}
+
+		if (pool->timing_generators[i] != NULL)	{
+			dm_free(pool->timing_generators[i]->ctx,
+				DCE110TG_FROM_TG(pool->timing_generators[i]));
+			pool->timing_generators[i] = NULL;
+		}
+	}
+
+filter_create_fail:
+	dal_irq_service_destroy(&pool->irqs);
+
+irqs_create_fail:
+	dal_display_clock_destroy(&pool->display_clock);
+
+disp_clk_create_fail:
+clk_src_create_fail:
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] != NULL)
+			dce110_clock_source_destroy(&pool->clock_sources[i]);
+	}
+
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
new file mode 100644
index 000000000000..5d60df286835
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
@@ -0,0 +1,46 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_RESOURCE_DCE110_H__
+#define __DC_RESOURCE_DCE110_H__
+
+#include "core_types.h"
+
+struct adapter_service;
+struct dc;
+struct resource_pool;
+
+bool dce110_construct_resource_pool(
+	struct adapter_service *adapter_serv,
+	uint8_t num_virtual_links,
+	struct dc *dc,
+	struct resource_pool *pool);
+
+void dce110_destruct_resource_pool(struct resource_pool *pool);
+
+void dce110_link_encoder_destroy(struct link_encoder **enc);
+
+#endif /* __DC_RESOURCE_DCE110_H__ */
+
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 22/26] drm/amd/dal: Add Tonga/Fiji HW sequencer and resource
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (20 preceding siblings ...)
  2016-02-16 22:28   ` [PATCH v2 21/26] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
@ 2016-02-16 22:28   ` Harry Wentland
  2016-02-16 22:28   ` [PATCH v2 23/26] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
                     ` (3 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:28 UTC (permalink / raw)
  To: dri-devel

Enables HW programming on Tonga and Fiji (DCE 10) ASICs. This
mostly re-uses DCE 11 programming code with minor exceptions
and using DCE 10 register offsets.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/dce100/Makefile         |   23 +
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.c    |  360 +++++++
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.h    |   36 +
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c    | 1135 ++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.h    |   43 +
 5 files changed, 1597 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h

diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/Makefile b/drivers/gpu/drm/amd/dal/dc/dce100/Makefile
new file mode 100644
index 000000000000..656c38e1b0f5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile for the 'controller' sub-component of DAL.
+# It provides the control and status of HW CRTC block.
+
+DCE100 = dce100_resource.o dce100_hw_sequencer.o
+
+AMD_DAL_DCE100 = $(addprefix $(AMDDALPATH)/dc/dce100/,$(DCE100))
+
+AMD_DAL_FILES += $(AMD_DAL_DCE100)
+
+
+###############################################################################
+# DCE 10x
+###############################################################################
+ifdef 0#CONFIG_DRM_AMD_DAL_DCE11_0
+TG_DCE100 = dce100_resource.o
+
+AMD_DAL_TG_DCE100 = $(addprefix \
+	$(AMDDALPATH)/dc/dce100/,$(TG_DCE100))
+
+AMD_DAL_FILES += $(AMD_DAL_TG_DCE100)
+endif
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
new file mode 100644
index 000000000000..a1dbac487366
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "dc.h"
+#include "core_dc.h"
+#include "core_types.h"
+#include "hw_sequencer.h"
+#include "dce100_hw_sequencer.h"
+#include "dce110/dce110_hw_sequencer.h"
+
+/* include DCE10 register header files */
+#include "dce/dce_10_0_d.h"
+#include "dce/dce_10_0_sh_mask.h"
+
+struct dce100_hw_seq_reg_offsets {
+	uint32_t blnd;
+	uint32_t crtc;
+};
+
+enum pipe_lock_control {
+	PIPE_LOCK_CONTROL_GRAPHICS = 1 << 0,
+	PIPE_LOCK_CONTROL_BLENDER = 1 << 1,
+	PIPE_LOCK_CONTROL_SCL = 1 << 2,
+	PIPE_LOCK_CONTROL_SURFACE = 1 << 3,
+	PIPE_LOCK_CONTROL_MODE = 1 << 4
+};
+
+enum blender_mode {
+	BLENDER_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */
+	BLENDER_MODE_OTHER_PIPE, /* Data from other pipe only */
+	BLENDER_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */
+	BLENDER_MODE_STEREO
+};
+
+static const struct dce100_hw_seq_reg_offsets reg_offsets[] = {
+{
+	.blnd = (mmBLND0_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+	.blnd = (mmBLND1_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+},
+{
+	.blnd = (mmBLND2_BLND_CONTROL - mmBLND_CONTROL),
+	.crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
+}
+};
+
+#define HW_REG_BLND(reg, id)\
+	(reg + reg_offsets[id].blnd)
+
+#define HW_REG_CRTC(reg, id)\
+	(reg + reg_offsets[id].crtc)
+
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+/***************************PIPE_CONTROL***********************************/
+static void dce100_enable_fe_clock(
+	struct dc_context *ctx, uint8_t controller_id, bool enable)
+{
+	uint32_t value = 0;
+	uint32_t addr;
+
+	addr = HW_REG_CRTC(mmDCFE_CLOCK_CONTROL, controller_id);
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		enable,
+		DCFE_CLOCK_CONTROL,
+		DCFE_CLOCK_ENABLE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static bool dce100_pipe_control_lock(
+	struct dc_context *ctx,
+	uint8_t controller_idx,
+	uint32_t control_mask,
+	bool lock)
+{
+	uint32_t addr = HW_REG_BLND(mmBLND_V_UPDATE_LOCK, controller_idx);
+	uint32_t value = dm_read_reg(ctx, addr);
+	bool need_to_wait = false;
+
+	if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_DCP_GRPH_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_SCL)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_SCL_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_SURFACE)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_DCP_GRPH_SURF_V_UPDATE_LOCK);
+
+	if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_BLND_V_UPDATE_LOCK);
+		need_to_wait = true;
+	}
+
+	if (control_mask & PIPE_LOCK_CONTROL_MODE)
+		set_reg_field_value(
+			value,
+			lock,
+			BLND_V_UPDATE_LOCK,
+			BLND_V_UPDATE_LOCK_MODE);
+
+	dm_write_reg(ctx, addr, value);
+
+	if (!lock && need_to_wait) {
+		uint8_t counter = 0;
+		const uint8_t counter_limit = 100;
+		const uint16_t delay_us = 1000;
+
+		uint8_t pipe_pending;
+
+		addr = HW_REG_BLND(mmBLND_REG_UPDATE_STATUS,
+				controller_idx);
+
+		while (counter < counter_limit) {
+			value = dm_read_reg(ctx, addr);
+
+			pipe_pending = 0;
+
+			if (control_mask & PIPE_LOCK_CONTROL_BLENDER) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						BLND_BLNDC_UPDATE_PENDING);
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					BLND_BLNDO_UPDATE_PENDING);
+			}
+
+			if (control_mask & PIPE_LOCK_CONTROL_SCL) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						SCL_BLNDC_UPDATE_PENDING);
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						SCL_BLNDO_UPDATE_PENDING);
+			}
+			if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS) {
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						DCP_BLNDC_GRPH_UPDATE_PENDING);
+				pipe_pending |=
+					get_reg_field_value(
+						value,
+						BLND_REG_UPDATE_STATUS,
+						DCP_BLNDO_GRPH_UPDATE_PENDING);
+			}
+			if (control_mask & PIPE_LOCK_CONTROL_SURFACE) {
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					DCP_BLNDC_GRPH_SURF_UPDATE_PENDING);
+				pipe_pending |= get_reg_field_value(
+					value,
+					BLND_REG_UPDATE_STATUS,
+					DCP_BLNDO_GRPH_SURF_UPDATE_PENDING);
+			}
+
+			if (pipe_pending == 0)
+				break;
+
+			counter++;
+			dm_delay_in_microseconds(ctx, delay_us);
+		}
+
+		if (counter == counter_limit) {
+			dal_logger_write(
+				ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: wait for update exceeded (wait %d us)\n",
+				__func__,
+				counter * delay_us);
+			dal_logger_write(
+				ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_CONTROLLER,
+				"%s: control %d, remain value %x\n",
+				__func__,
+				control_mask,
+				value);
+		} else {
+			/* OK. */
+		}
+	}
+
+	return true;
+}
+
+static void dce100_set_blender_mode(
+	struct dc_context *ctx,
+	uint8_t controller_id,
+	uint32_t mode)
+{
+	uint32_t value;
+	uint32_t addr = HW_REG_BLND(mmBLND_CONTROL, controller_id);
+	uint32_t blnd_mode;
+	uint32_t feedthrough = 0;
+
+	switch (mode) {
+	case BLENDER_MODE_OTHER_PIPE:
+		feedthrough = 0;
+		blnd_mode = 1;
+		break;
+	case BLENDER_MODE_BLENDING:
+		feedthrough = 0;
+		blnd_mode = 2;
+		break;
+	case BLENDER_MODE_CURRENT_PIPE:
+	default:
+		feedthrough = 1;
+		blnd_mode = 0;
+		break;
+	}
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		feedthrough,
+		BLND_CONTROL,
+		BLND_FEEDTHROUGH_EN);
+
+	set_reg_field_value(
+		value,
+		blnd_mode,
+		BLND_CONTROL,
+		BLND_MODE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static bool dce100_enable_display_power_gating(
+	struct dc_context *ctx,
+	uint8_t controller_id,
+	struct dc_bios *dcb,
+	enum pipe_gating_control power_gating)
+{
+	enum bp_result bp_result = BP_RESULT_OK;
+	enum bp_pipe_control_action cntl;
+
+	if (power_gating == PIPE_GATING_CONTROL_INIT)
+		cntl = ASIC_PIPE_INIT;
+	else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
+		cntl = ASIC_PIPE_ENABLE;
+	else
+		cntl = ASIC_PIPE_DISABLE;
+
+	if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0))
+		bp_result = dcb->funcs->enable_disp_power_gating(
+						dcb, controller_id + 1, cntl);
+
+	if (bp_result == BP_RESULT_OK)
+		return true;
+	else
+		return false;
+}
+
+static void enable_hw_base_light_sleep(void)
+{
+	/* TODO: implement */
+}
+
+static void disable_sw_manual_control_light_sleep(void)
+{
+	/* TODO: implement */
+}
+
+static void enable_sw_manual_control_light_sleep(void)
+{
+	/* TODO: implement */
+}
+
+static void dal_dc_clock_gating_dce100_power_up(struct dc_context *ctx, bool enable)
+{
+	if (enable) {
+		enable_hw_base_light_sleep();
+		disable_sw_manual_control_light_sleep();
+	} else {
+		enable_sw_manual_control_light_sleep();
+	}
+}
+
+static void set_displaymarks(
+		const struct dc *dc, struct validate_context *context)
+{
+	/* Do nothing until we have proper bandwitdth calcs */
+}
+
+/**************************************************************************/
+
+bool dce100_hw_sequencer_construct(struct dc *dc)
+{
+	dce110_hw_sequencer_construct(dc);
+
+	/* TODO: dce80 is empty implementation at the moment*/
+	dc->hwss.clock_gating_power_up = dal_dc_clock_gating_dce100_power_up;
+
+	dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating;
+	dc->hwss.enable_fe_clock = dce100_enable_fe_clock;
+	dc->hwss.pipe_control_lock = dce100_pipe_control_lock;
+	dc->hwss.set_blender_mode = dce100_set_blender_mode;
+	dc->hwss.set_displaymarks = set_displaymarks;
+	return true;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
new file mode 100644
index 000000000000..0ce637e6bd85
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
@@ -0,0 +1,36 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HWSS_DCE100_H__
+#define __DC_HWSS_DCE100_H__
+
+#include "core_types.h"
+
+struct dc;
+
+bool dce100_hw_sequencer_construct(struct dc *dc);
+
+#endif /* __DC_HWSS_DCE100_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
new file mode 100644
index 000000000000..783d47eba325
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
@@ -0,0 +1,1135 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "link_encoder.h"
+#include "stream_encoder.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+
+#include "../virtual/virtual_stream_encoder.h"
+#include "dce110/dce110_resource.h"
+#include "dce110/dce110_timing_generator.h"
+#include "dce110/dce110_link_encoder.h"
+#include "dce110/dce110_mem_input.h"
+#include "dce110/dce110_ipp.h"
+#include "dce110/dce110_transform.h"
+#include "dce110/dce110_stream_encoder.h"
+#include "dce110/dce110_opp.h"
+#include "dce110/dce110_clock_source.h"
+
+#include "dce/dce_10_0_d.h"
+
+#ifndef mmDP_DPHY_INTERNAL_CTRL
+	#define mmDP_DPHY_INTERNAL_CTRL 0x4aa7
+	#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7
+	#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7
+	#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7
+	#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7
+	#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7
+	#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7
+	#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7
+	#define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7
+	#define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7
+#endif
+
+enum dce100_clk_src_array_id {
+	DCE100_CLK_SRC_PLL0 = 0,
+	DCE100_CLK_SRC_PLL1,
+	DCE100_CLK_SRC_EXT,
+
+	DCE100_CLK_SRC_TOTAL
+};
+
+static const struct dce110_timing_generator_offsets dce100_tg_offsets[] = {
+	{
+		.crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp =  (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp =  (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
+	},
+	{
+		.crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL),
+		.dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
+	}
+};
+
+static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = {
+	{
+		.dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE0_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE1_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE2_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE3_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE4_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	},
+	{
+		.dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
+		.dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL
+				- mmDPG_WATERMARK_MASK_CONTROL),
+		.pipe = (mmPIPE5_DMIF_BUFFER_CONTROL
+				- mmPIPE0_DMIF_BUFFER_CONTROL),
+	}
+};
+
+
+static const struct dce110_clk_src_reg_offsets dce100_clk_src_reg_offsets[] = {
+	{
+		.pll_cntl = mmBPHYC_PLL0_PLL_CNTL,
+		.pixclk_resync_cntl  = mmPIXCLK0_RESYNC_CNTL
+	},
+	{
+		.pll_cntl = mmBPHYC_PLL1_PLL_CNTL,
+		.pixclk_resync_cntl  = mmPIXCLK1_RESYNC_CNTL
+	}
+};
+
+static const struct dce110_transform_reg_offsets dce100_xfm_offsets[] = {
+{
+	.scl_offset = (mmSCL0_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB0_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL1_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB1_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL2_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB2_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{
+	.scl_offset = (mmSCL3_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB3_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL4_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB4_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+},
+{	.scl_offset = (mmSCL5_SCL_CONTROL - mmSCL_CONTROL),
+	.dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - mmDCFE_MEM_PWR_CTRL),
+	.dcp_offset = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
+	.lb_offset = (mmLB5_LB_DATA_FORMAT - mmLB_DATA_FORMAT),
+}
+};
+
+static const struct dce110_ipp_reg_offsets dce100_ipp_reg_offsets[] = {
+{
+	.dcp_offset = (mmDCP0_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP1_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP2_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP3_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP4_CUR_CONTROL - mmCUR_CONTROL),
+},
+{
+	.dcp_offset = (mmDCP5_CUR_CONTROL - mmCUR_CONTROL),
+}
+};
+
+
+static const struct dce110_link_enc_bl_registers link_enc_bl_regs = {
+		.BL_PWM_CNTL = mmBL_PWM_CNTL,
+		.BL_PWM_GRP1_REG_LOCK = mmBL_PWM_GRP1_REG_LOCK,
+		.BL_PWM_PERIOD_CNTL = mmBL_PWM_PERIOD_CNTL,
+		.LVTMA_PWRSEQ_CNTL = mmLVTMA_PWRSEQ_CNTL,
+		.LVTMA_PWRSEQ_STATE = mmLVTMA_PWRSEQ_STATE
+};
+
+#define aux_regs(id)\
+[id] = {\
+	.AUX_CONTROL = mmDP_AUX ## id ## _AUX_CONTROL,\
+	.AUX_DPHY_RX_CONTROL0 = mmDP_AUX ## id ## _AUX_DPHY_RX_CONTROL0\
+}
+
+static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = {
+	aux_regs(0),
+	aux_regs(1),
+	aux_regs(2),
+	aux_regs(3),
+	aux_regs(4),
+	aux_regs(5)
+};
+
+#define link_regs(id)\
+[id] = {\
+	.DIG_BE_CNTL = mmDIG ## id ## _DIG_BE_CNTL,\
+	.DIG_BE_EN_CNTL = mmDIG ## id ## _DIG_BE_EN_CNTL,\
+	.DP_CONFIG = mmDP ## id ## _DP_CONFIG,\
+	.DP_DPHY_CNTL = mmDP ## id ## _DP_DPHY_CNTL,\
+	.DP_DPHY_INTERNAL_CTRL = mmDP ## id ## _DP_DPHY_INTERNAL_CTRL,\
+	.DP_DPHY_PRBS_CNTL = mmDP ## id ## _DP_DPHY_PRBS_CNTL,\
+	.DP_DPHY_SYM0 = mmDP ## id ## _DP_DPHY_SYM0,\
+	.DP_DPHY_SYM1 = mmDP ## id ## _DP_DPHY_SYM1,\
+	.DP_DPHY_SYM2 = mmDP ## id ## _DP_DPHY_SYM2,\
+	.DP_DPHY_TRAINING_PATTERN_SEL = mmDP ## id ## _DP_DPHY_TRAINING_PATTERN_SEL,\
+	.DP_LINK_CNTL = mmDP ## id ## _DP_LINK_CNTL,\
+	.DP_LINK_FRAMING_CNTL = mmDP ## id ## _DP_LINK_FRAMING_CNTL,\
+	.DP_MSE_SAT0 = mmDP ## id ## _DP_MSE_SAT0,\
+	.DP_MSE_SAT1 = mmDP ## id ## _DP_MSE_SAT1,\
+	.DP_MSE_SAT2 = mmDP ## id ## _DP_MSE_SAT2,\
+	.DP_MSE_SAT_UPDATE = mmDP ## id ## _DP_MSE_SAT_UPDATE,\
+	.DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\
+	.DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL\
+}
+
+static const struct dce110_link_enc_registers link_enc_regs[] = {
+	link_regs(0),
+	link_regs(1),
+	link_regs(2),
+	link_regs(3),
+	link_regs(4),
+	link_regs(5),
+	link_regs(6)
+};
+
+#define stream_enc_regs(id)\
+[id] = {\
+	.AFMT_AVI_INFO0 = mmDIG ## id ## _AFMT_AVI_INFO0,\
+	.AFMT_AVI_INFO1 = mmDIG ## id ## _AFMT_AVI_INFO1,\
+	.AFMT_AVI_INFO2 = mmDIG ## id ## _AFMT_AVI_INFO2,\
+	.AFMT_AVI_INFO3 = mmDIG ## id ## _AFMT_AVI_INFO3,\
+	.AFMT_GENERIC_0 = mmDIG ## id ## _AFMT_GENERIC_0,\
+	.AFMT_GENERIC_7 = mmDIG ## id ## _AFMT_GENERIC_7,\
+	.AFMT_GENERIC_HDR = mmDIG ## id ## _AFMT_GENERIC_HDR,\
+	.AFMT_INFOFRAME_CONTROL0 = mmDIG ## id ## _AFMT_INFOFRAME_CONTROL0,\
+	.AFMT_VBI_PACKET_CONTROL = mmDIG ## id ## _AFMT_VBI_PACKET_CONTROL,\
+	.DIG_FE_CNTL = mmDIG ## id ## _DIG_FE_CNTL,\
+	.DP_MSE_RATE_CNTL = mmDP ## id ## _DP_MSE_RATE_CNTL,\
+	.DP_MSE_RATE_UPDATE = mmDP ## id ## _DP_MSE_RATE_UPDATE,\
+	.DP_PIXEL_FORMAT = mmDP ## id ## _DP_PIXEL_FORMAT,\
+	.DP_SEC_CNTL = mmDP ## id ## _DP_SEC_CNTL,\
+	.DP_STEER_FIFO = mmDP ## id ## _DP_STEER_FIFO,\
+	.DP_VID_M = mmDP ## id ## _DP_VID_M,\
+	.DP_VID_N = mmDP ## id ## _DP_VID_N,\
+	.DP_VID_STREAM_CNTL = mmDP ## id ## _DP_VID_STREAM_CNTL,\
+	.DP_VID_TIMING = mmDP ## id ## _DP_VID_TIMING,\
+	.HDMI_CONTROL = mmDIG ## id ## _HDMI_CONTROL,\
+	.HDMI_GC = mmDIG ## id ## _HDMI_GC,\
+	.HDMI_GENERIC_PACKET_CONTROL0 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL0,\
+	.HDMI_GENERIC_PACKET_CONTROL1 = mmDIG ## id ## _HDMI_GENERIC_PACKET_CONTROL1,\
+	.HDMI_INFOFRAME_CONTROL0 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL0,\
+	.HDMI_INFOFRAME_CONTROL1 = mmDIG ## id ## _HDMI_INFOFRAME_CONTROL1,\
+	.HDMI_VBI_PACKET_CONTROL = mmDIG ## id ## _HDMI_VBI_PACKET_CONTROL,\
+	.TMDS_CNTL = mmDIG ## id ## _TMDS_CNTL\
+}
+
+static const struct dce110_stream_enc_registers stream_enc_regs[] = {
+	stream_enc_regs(0),
+	stream_enc_regs(1),
+	stream_enc_regs(2),
+	stream_enc_regs(3),
+	stream_enc_regs(4),
+	stream_enc_regs(5),
+	stream_enc_regs(6)
+};
+
+#define DCFE_MEM_PWR_CTRL_REG_BASE 0x1b03
+
+static const struct dce110_opp_reg_offsets dce100_opp_reg_offsets[] = {
+{
+	.fmt_offset = (mmFMT0_FMT_CONTROL - mmFMT_CONTROL),
+	.dcfe_offset = (mmCRTC0_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT1_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC1_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT2_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC2_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{
+	.fmt_offset = (mmFMT3_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC3_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT4_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC4_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+},
+{	.fmt_offset = (mmFMT5_FMT_CONTROL - mmFMT0_FMT_CONTROL),
+	.dcfe_offset = (mmCRTC5_DCFE_MEM_PWR_CTRL - DCFE_MEM_PWR_CTRL_REG_BASE),
+	.dcp_offset = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL),
+}
+};
+
+
+static struct timing_generator *dce100_timing_generator_create(
+		struct adapter_service *as,
+		struct dc_context *ctx,
+		uint32_t instance,
+		const struct dce110_timing_generator_offsets *offsets)
+{
+	struct dce110_timing_generator *tg110 =
+		dm_alloc(ctx, sizeof(struct dce110_timing_generator));
+
+	if (!tg110)
+		return NULL;
+
+	if (dce110_timing_generator_construct(tg110, as, ctx, instance,
+			offsets))
+		return &tg110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, tg110);
+	return NULL;
+}
+
+static struct stream_encoder *dce100_stream_encoder_create(
+	enum engine_id eng_id,
+	struct dc_context *ctx,
+	struct dc_bios *bp,
+	const struct dce110_stream_enc_registers *regs)
+{
+	struct dce110_stream_encoder *enc110 =
+		dm_alloc(ctx, sizeof(struct dce110_stream_encoder));
+
+	if (!enc110)
+		return NULL;
+
+	if (dce110_stream_encoder_construct(enc110, ctx, bp, eng_id, regs))
+		return &enc110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, enc110);
+	return NULL;
+}
+
+static struct mem_input *dce100_mem_input_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_mem_input_reg_offsets *offset)
+{
+	struct dce110_mem_input *mem_input110 =
+		dm_alloc(ctx, sizeof(struct dce110_mem_input));
+
+	if (!mem_input110)
+		return NULL;
+
+	if (dce110_mem_input_construct(mem_input110,
+			ctx, inst, offset))
+		return &mem_input110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, mem_input110);
+	return NULL;
+}
+
+static void dce100_transform_destroy(struct transform **xfm)
+{
+	dm_free((*xfm)->ctx, TO_DCE110_TRANSFORM(*xfm));
+	*xfm = NULL;
+}
+
+static struct transform *dce100_transform_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_transform_reg_offsets *offsets)
+{
+	struct dce110_transform *transform =
+		dm_alloc(ctx, sizeof(struct dce110_transform));
+
+	if (!transform)
+		return NULL;
+
+	if (dce110_transform_construct(transform, ctx, inst, offsets))
+		return &transform->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, transform);
+	return NULL;
+}
+
+static struct input_pixel_processor *dce100_ipp_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_ipp_reg_offsets *offsets)
+{
+	struct dce110_ipp *ipp =
+		dm_alloc(ctx, sizeof(struct dce110_ipp));
+
+	if (!ipp)
+		return NULL;
+
+	if (dce110_ipp_construct(ipp, ctx, inst, offsets))
+		return &ipp->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, ipp);
+	return NULL;
+}
+
+struct link_encoder *dce100_link_encoder_create(
+	const struct encoder_init_data *enc_init_data)
+{
+	struct dce110_link_encoder *enc110 =
+		dm_alloc(
+			enc_init_data->ctx,
+			sizeof(struct dce110_link_encoder));
+
+	if (!enc110)
+		return NULL;
+
+	if (dce110_link_encoder_construct(
+			enc110,
+			enc_init_data,
+			&link_enc_regs[enc_init_data->transmitter],
+			&link_enc_aux_regs[enc_init_data->channel - 1],
+			&link_enc_bl_regs))
+		return &enc110->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(enc_init_data->ctx, enc110);
+	return NULL;
+}
+
+
+struct output_pixel_processor *dce100_opp_create(
+	struct dc_context *ctx,
+	uint32_t inst,
+	const struct dce110_opp_reg_offsets *offset)
+{
+	struct dce110_opp *opp =
+		dm_alloc(ctx, sizeof(struct dce110_opp));
+
+	if (!opp)
+		return NULL;
+
+	if (dce110_opp_construct(opp,
+			ctx, inst, offset))
+		return &opp->base;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, opp);
+	return NULL;
+}
+
+
+void dce100_opp_destroy(struct output_pixel_processor **opp)
+{
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_dx);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128_oem);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coeff128);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_1025);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.axis_x_256);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.coordinates_x);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_regamma);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_resulted);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_oem);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp)->regamma.rgb_user);
+	dm_free((*opp)->ctx, FROM_DCE11_OPP(*opp));
+	*opp = NULL;
+}
+
+struct clock_source *dce100_clock_source_create(
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_reg_offsets *offsets)
+{
+	struct dce110_clk_src *clk_src =
+		dm_alloc(ctx, sizeof(struct dce110_clk_src));
+
+	if (!clk_src)
+		return NULL;
+
+	if (dce110_clk_src_construct(clk_src, ctx, bios, id, offsets))
+		return &clk_src->base;
+
+	BREAK_TO_DEBUGGER();
+	return NULL;
+}
+
+void dce100_clock_source_destroy(struct clock_source **clk_src)
+{
+	dm_free((*clk_src)->ctx, TO_DCE110_CLK_SRC(*clk_src));
+	*clk_src = NULL;
+}
+
+void dce100_destruct_resource_pool(struct resource_pool *pool)
+{
+	unsigned int i;
+
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->opps[i] != NULL)
+			dce100_opp_destroy(&pool->opps[i]);
+
+		if (pool->transforms[i] != NULL)
+			dce100_transform_destroy(&pool->transforms[i]);
+
+		if (pool->ipps[i] != NULL)
+			dce110_ipp_destroy(&pool->ipps[i]);
+
+		if (pool->mis[i] != NULL) {
+			dm_free(pool->mis[i]->ctx,
+					TO_DCE110_MEM_INPUT(pool->mis[i]));
+			pool->mis[i] = NULL;
+		}
+
+		if (pool->timing_generators[i] != NULL)	{
+			dm_free(pool->timing_generators[i]->ctx,
+					DCE110TG_FROM_TG(pool->timing_generators[i]));
+			pool->timing_generators[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		if (pool->stream_enc[i] != NULL)
+			dm_free(pool->stream_enc[i]->ctx,
+				DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+	}
+
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] != NULL)
+			dce100_clock_source_destroy(&pool->clock_sources[i]);
+	}
+
+	for (i = 0; i < pool->audio_count; i++)	{
+		if (pool->audios[i] != NULL)
+			dal_audio_destroy(&pool->audios[i]);
+	}
+
+	if (pool->display_clock != NULL)
+		dal_display_clock_destroy(&pool->display_clock);
+
+	if (pool->scaler_filter != NULL)
+		dal_scaler_filter_destroy(&pool->scaler_filter);
+
+	if (pool->irqs != NULL)
+		dal_irq_service_destroy(&pool->irqs);
+
+	if (pool->adapter_srv != NULL)
+		dal_adapter_service_destroy(&pool->adapter_srv);
+}
+
+static struct clock_source *find_first_free_pll(
+		struct resource_context *res_ctx)
+{
+	if (res_ctx->clock_source_ref_count[DCE100_CLK_SRC_PLL0] == 0)
+		return res_ctx->pool.clock_sources[DCE100_CLK_SRC_PLL0];
+
+	if (res_ctx->clock_source_ref_count[DCE100_CLK_SRC_PLL1] == 0)
+		return res_ctx->pool.clock_sources[DCE100_CLK_SRC_PLL1];
+
+	return 0;
+}
+
+static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
+{
+	switch (crtc_id) {
+	case CONTROLLER_ID_D0:
+		return DTO_SOURCE_ID0;
+	case CONTROLLER_ID_D1:
+		return DTO_SOURCE_ID1;
+	case CONTROLLER_ID_D2:
+		return DTO_SOURCE_ID2;
+	case CONTROLLER_ID_D3:
+		return DTO_SOURCE_ID3;
+	case CONTROLLER_ID_D4:
+		return DTO_SOURCE_ID4;
+	case CONTROLLER_ID_D5:
+		return DTO_SOURCE_ID5;
+	default:
+		return DTO_SOURCE_UNKNOWN;
+	}
+}
+
+static void build_audio_output(
+	const struct core_stream *stream,
+	struct audio_output *audio_output)
+{
+	audio_output->engine_id = stream->stream_enc->id;
+
+	audio_output->signal = stream->signal;
+
+	/* audio_crtc_info  */
+
+	audio_output->crtc_info.h_total =
+		stream->public.timing.h_total;
+
+	/*
+	 * Audio packets are sent during actual CRTC blank physical signal, we
+	 * need to specify actual active signal portion
+	 */
+	audio_output->crtc_info.h_active =
+			stream->public.timing.h_addressable
+			+ stream->public.timing.h_border_left
+			+ stream->public.timing.h_border_right;
+
+	audio_output->crtc_info.v_active =
+			stream->public.timing.v_addressable
+			+ stream->public.timing.v_border_top
+			+ stream->public.timing.v_border_bottom;
+
+	audio_output->crtc_info.pixel_repetition = 1;
+
+	audio_output->crtc_info.interlaced =
+			stream->public.timing.flags.INTERLACE;
+
+	audio_output->crtc_info.refresh_rate =
+		(stream->public.timing.pix_clk_khz*1000)/
+		(stream->public.timing.h_total*stream->public.timing.v_total);
+
+	audio_output->crtc_info.color_depth =
+		stream->public.timing.display_color_depth;
+
+	audio_output->crtc_info.requested_pixel_clock =
+			stream->pix_clk_params.requested_pix_clk;
+
+	/*
+	 * TODO - Investigate why calculated pixel clk has to be
+	 * requested pixel clk
+	 */
+	audio_output->crtc_info.calculated_pixel_clock =
+			stream->pix_clk_params.requested_pix_clk;
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
+			stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+		audio_output->pll_info.dp_dto_source_clock_in_khz =
+			dal_display_clock_get_dp_ref_clk_frequency(
+				stream->dis_clk);
+	}
+
+	audio_output->pll_info.feed_back_divider =
+			stream->pll_settings.feedback_divider;
+
+	audio_output->pll_info.dto_source =
+		translate_to_dto_source(
+			stream->controller_idx + 1);
+
+	/* TODO hard code to enable for now. Need get from stream */
+	audio_output->pll_info.ss_enabled = true;
+
+	audio_output->pll_info.ss_percentage =
+			stream->pll_settings.ss_percentage;
+}
+
+static void get_pixel_clock_parameters(
+	const struct core_stream *stream,
+	struct pixel_clk_params *pixel_clk_params)
+{
+	pixel_clk_params->requested_pix_clk = stream->public.timing.pix_clk_khz;
+	pixel_clk_params->encoder_object_id = stream->sink->link->link_enc->id;
+	pixel_clk_params->signal_type = stream->sink->public.sink_signal;
+	pixel_clk_params->controller_id = stream->controller_idx + 1;
+	/* TODO: un-hardcode*/
+	pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
+		LINK_RATE_REF_FREQ_IN_KHZ;
+	pixel_clk_params->flags.ENABLE_SS = 0;
+	pixel_clk_params->color_depth =
+		stream->public.timing.display_color_depth;
+	pixel_clk_params->flags.DISPLAY_BLANKED = 1;
+}
+
+static enum dc_status build_stream_hw_param(struct core_stream *stream)
+{
+	/*TODO: unhardcode*/
+	stream->max_tmds_clk_from_edid_in_mhz = 0;
+	stream->max_hdmi_deep_color = COLOR_DEPTH_121212;
+	stream->max_hdmi_pixel_clock = 600000;
+
+	get_pixel_clock_parameters(stream, &stream->pix_clk_params);
+	stream->clock_source->funcs->get_pix_clk_dividers(
+		stream->clock_source,
+		&stream->pix_clk_params,
+		&stream->pll_settings);
+
+	build_audio_output(stream, &stream->audio_output);
+
+	return DC_OK;
+}
+
+static enum dc_status validate_mapped_resource(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	enum dc_status status = DC_OK;
+	uint8_t i, j;
+
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (context->target_flags[i].unchanged)
+			continue;
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct core_link *link = stream->sink->link;
+
+			if (!stream->tg->funcs->validate_timing(
+					stream->tg, &stream->public.timing))
+				return DC_FAIL_CONTROLLER_VALIDATE;
+
+			if (stream->signal == SIGNAL_TYPE_VIRTUAL)
+				return status;
+
+			status = build_stream_hw_param(stream);
+
+			if (status != DC_OK)
+				return status;
+
+			if (!link->link_enc->funcs->validate_output_with_stream(
+					link->link_enc,
+					stream))
+				return DC_FAIL_ENC_VALIDATE;
+
+			/* TODO: validate audio ASIC caps, encoder */
+
+			status = dc_link_validate_mode_timing(stream->sink,
+					link,
+					&stream->public.timing);
+
+			if (status != DC_OK)
+				return status;
+
+			build_info_frame(stream);
+		}
+	}
+
+	return DC_OK;
+}
+
+enum dc_status dce100_validate_bandwidth(
+	const struct dc *dc,
+	struct validate_context *context)
+{
+	/* TODO implement when needed but for now hardcode max value*/
+	context->bw_results.dispclk_khz = 681000;
+
+	return DC_OK;
+}
+
+static void set_target_unchanged(
+		struct validate_context *context,
+		uint8_t target_idx)
+{
+	uint8_t i;
+	struct core_target *target = context->targets[target_idx];
+
+	context->target_flags[target_idx].unchanged = true;
+	for (i = 0; i < target->public.stream_count; i++) {
+		struct core_stream *core_stream =
+			DC_STREAM_TO_CORE(target->public.streams[i]);
+		uint8_t index = core_stream->controller_idx;
+
+		context->res_ctx.controller_ctx[index].flags.unchanged = true;
+	}
+}
+
+static enum dc_status map_clock_resources(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	uint8_t i, j;
+
+	/* mark resources used for targets that are already active */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (!context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			reference_clock_source(
+				&context->res_ctx,
+				stream->clock_source);
+		}
+	}
+
+	/* acquire new resources */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			if (dc_is_dp_signal(stream->signal)
+				|| stream->signal == SIGNAL_TYPE_VIRTUAL)
+				stream->clock_source = context->res_ctx.
+					pool.clock_sources[DCE100_CLK_SRC_EXT];
+			else
+				stream->clock_source =
+					find_used_clk_src_for_sharing(
+							context, stream);
+			if (stream->clock_source == NULL)
+				stream->clock_source =
+					find_first_free_pll(&context->res_ctx);
+
+			if (stream->clock_source == NULL)
+				return DC_NO_CLOCK_SOURCE_RESOURCE;
+
+			reference_clock_source(
+					&context->res_ctx,
+					stream->clock_source);
+		}
+	}
+
+	return DC_OK;
+}
+
+enum dc_status dce100_validate_with_context(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count,
+		struct validate_context *context)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	uint8_t i, j;
+	struct dc_context *dc_ctx = dc->ctx;
+
+	for (i = 0; i < set_count; i++) {
+		context->targets[i] = DC_TARGET_TO_CORE(set[i].target);
+
+		for (j = 0; j < dc->current_context.target_count; j++)
+			if (dc->current_context.targets[j] == context->targets[i])
+				set_target_unchanged(context, i);
+
+		if (!context->target_flags[i].unchanged)
+			if (!logical_attach_surfaces_to_target(
+					(struct dc_surface **)set[i].surfaces,
+					set[i].surface_count,
+					&context->targets[i]->public)) {
+				DC_ERROR("Failed to attach surface to target!\n");
+				return DC_FAIL_ATTACH_SURFACES;
+			}
+	}
+
+	context->target_count = set_count;
+
+	context->res_ctx.pool = dc->res_pool;
+
+	result = map_resources(dc, context);
+
+	if (result == DC_OK)
+		result = map_clock_resources(dc, context);
+
+	if (result == DC_OK)
+		result = validate_mapped_resource(dc, context);
+
+	if (result == DC_OK)
+		build_scaling_params_for_context(dc, context);
+
+	if (result == DC_OK)
+		result = dce100_validate_bandwidth(dc, context);
+
+	return result;
+}
+
+static struct resource_funcs dce100_res_pool_funcs = {
+	.destruct = dce100_destruct_resource_pool,
+	.link_enc_create = dce100_link_encoder_create,
+	.link_enc_destroy = dce110_link_encoder_destroy,
+	.validate_with_context = dce100_validate_with_context,
+	.validate_bandwidth = dce100_validate_bandwidth
+};
+
+bool dce100_construct_resource_pool(
+	struct adapter_service *adapter_serv,
+	uint8_t num_virtual_links,
+	struct dc *dc,
+	struct resource_pool *pool)
+{
+	unsigned int i;
+	struct audio_init_data audio_init_data = { 0 };
+	struct dc_context *ctx = dc->ctx;
+
+	pool->adapter_srv = adapter_serv;
+	pool->funcs = &dce100_res_pool_funcs;
+
+	pool->stream_engines.engine.ENGINE_ID_DIGA = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGB = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGC = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGD = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGE = 1;
+	pool->stream_engines.engine.ENGINE_ID_DIGF = 1;
+
+	pool->clock_sources[DCE100_CLK_SRC_PLL0] = dce100_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_PLL0, &dce100_clk_src_reg_offsets[0]);
+	pool->clock_sources[DCE100_CLK_SRC_PLL1] = dce100_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_PLL1, &dce100_clk_src_reg_offsets[1]);
+	pool->clock_sources[DCE100_CLK_SRC_EXT] =  dce100_clock_source_create(
+		ctx, dal_adapter_service_get_bios_parser(adapter_serv),
+		CLOCK_SOURCE_ID_EXTERNAL, &dce100_clk_src_reg_offsets[0]);
+	pool->clk_src_count = DCE100_CLK_SRC_TOTAL;
+
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] == NULL) {
+			dm_error("DC: failed to create clock sources!\n");
+			BREAK_TO_DEBUGGER();
+			goto clk_src_create_fail;
+		}
+	}
+
+	pool->display_clock = dal_display_clock_dce110_create(ctx, adapter_serv);
+	if (pool->display_clock == NULL) {
+		dm_error("DC: failed to create display clock!\n");
+		BREAK_TO_DEBUGGER();
+		goto disp_clk_create_fail;
+	}
+
+	{
+		struct irq_service_init_data init_data;
+
+		init_data.ctx = dc->ctx;
+		pool->irqs = dal_irq_service_create(
+				dal_adapter_service_get_dce_version(
+					dc->res_pool.adapter_srv),
+				&init_data);
+		if (!pool->irqs)
+			goto irqs_create_fail;
+
+	}
+
+	pool->controller_count =
+		dal_adapter_service_get_func_controllers_num(adapter_serv);
+	pool->stream_enc_count = dal_adapter_service_get_stream_engines_num(
+			adapter_serv);
+	pool->scaler_filter = dal_scaler_filter_create(ctx);
+	if (pool->scaler_filter == NULL) {
+		BREAK_TO_DEBUGGER();
+		dm_error("DC: failed to create filter!\n");
+		goto filter_create_fail;
+	}
+
+	for (i = 0; i < pool->controller_count; i++) {
+		pool->timing_generators[i] = dce100_timing_generator_create(
+				adapter_serv, ctx, i, &dce100_tg_offsets[i]);
+		if (pool->timing_generators[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create tg!\n");
+			goto controller_create_fail;
+		}
+
+		pool->mis[i] = dce100_mem_input_create(ctx, i,
+				&dce100_mi_reg_offsets[i]);
+		if (pool->mis[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create memory input!\n");
+			goto controller_create_fail;
+		}
+
+		pool->ipps[i] = dce100_ipp_create(ctx, i,
+				&dce100_ipp_reg_offsets[i]);
+		if (pool->ipps[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create input pixel processor!\n");
+			goto controller_create_fail;
+		}
+
+		pool->transforms[i] = dce100_transform_create(
+					ctx, i, &dce100_xfm_offsets[i]);
+		if (pool->transforms[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create transform!\n");
+			goto controller_create_fail;
+		}
+		pool->transforms[i]->funcs->transform_set_scaler_filter(
+				pool->transforms[i],
+				pool->scaler_filter);
+
+		pool->opps[i] = dce100_opp_create(ctx, i, &dce100_opp_reg_offsets[i]);
+		if (pool->opps[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error(
+				"DC: failed to create output pixel processor!\n");
+			goto controller_create_fail;
+		}
+	}
+
+	audio_init_data.as = adapter_serv;
+	audio_init_data.ctx = ctx;
+	pool->audio_count = 0;
+	for (i = 0; i < pool->controller_count; i++) {
+		struct graphics_object_id obj_id;
+
+		obj_id = dal_adapter_service_enum_audio_object(adapter_serv, i);
+		if (false == dal_graphics_object_id_is_valid(obj_id)) {
+			/* no more valid audio objects */
+			break;
+		}
+
+		audio_init_data.audio_stream_id = obj_id;
+		pool->audios[i] = dal_audio_create(&audio_init_data);
+		if (pool->audios[i] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create DPPs!\n");
+			goto audio_create_fail;
+		}
+		pool->audio_count++;
+	}
+
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		/* TODO: rework fragile code*/
+		if (pool->stream_engines.u_all & 1 << i) {
+			pool->stream_enc[i] = dce100_stream_encoder_create(
+				i, dc->ctx,
+				dal_adapter_service_get_bios_parser(
+					adapter_serv),
+				&stream_enc_regs[i]);
+			if (pool->stream_enc[i] == NULL) {
+				BREAK_TO_DEBUGGER();
+				dm_error("DC: failed to create stream_encoder!\n");
+				goto stream_enc_create_fail;
+			}
+		}
+	}
+
+	for (i = 0; i < num_virtual_links; i++) {
+		pool->stream_enc[pool->stream_enc_count] =
+			virtual_stream_encoder_create(
+				dc->ctx, dal_adapter_service_get_bios_parser(
+								adapter_serv));
+		if (pool->stream_enc[pool->stream_enc_count] == NULL) {
+			BREAK_TO_DEBUGGER();
+			dm_error("DC: failed to create stream_encoder!\n");
+			goto stream_enc_create_fail;
+		}
+		pool->stream_enc_count++;
+	}
+
+	return true;
+
+stream_enc_create_fail:
+	for (i = 0; i < pool->stream_enc_count; i++) {
+		if (pool->stream_enc[i] != NULL)
+			dm_free(pool->stream_enc[i]->ctx,
+				DCE110STRENC_FROM_STRENC(pool->stream_enc[i]));
+	}
+
+audio_create_fail:
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->audios[i] != NULL)
+			dal_audio_destroy(&pool->audios[i]);
+	}
+
+controller_create_fail:
+	for (i = 0; i < pool->controller_count; i++) {
+		if (pool->opps[i] != NULL)
+			dce100_opp_destroy(&pool->opps[i]);
+
+		if (pool->transforms[i] != NULL)
+			dce100_transform_destroy(&pool->transforms[i]);
+
+		if (pool->ipps[i] != NULL)
+			dce110_ipp_destroy(&pool->ipps[i]);
+
+		if (pool->mis[i] != NULL) {
+			dm_free(pool->mis[i]->ctx,
+					TO_DCE110_MEM_INPUT(pool->mis[i]));
+			pool->mis[i] = NULL;
+		}
+
+		if (pool->timing_generators[i] != NULL)	{
+			dm_free(pool->timing_generators[i]->ctx,
+				DCE110TG_FROM_TG(pool->timing_generators[i]));
+			pool->timing_generators[i] = NULL;
+		}
+	}
+
+filter_create_fail:
+	dal_irq_service_destroy(&pool->irqs);
+
+irqs_create_fail:
+	dal_display_clock_destroy(&pool->display_clock);
+
+disp_clk_create_fail:
+clk_src_create_fail:
+	for (i = 0; i < pool->clk_src_count; i++) {
+		if (pool->clock_sources[i] != NULL)
+			dce100_clock_source_destroy(&pool->clock_sources[i]);
+	}
+
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h
new file mode 100644
index 000000000000..2a23d864831f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h
@@ -0,0 +1,43 @@
+/*
+* Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DCE100_RESOURCE_H_
+#define DCE100_RESOURCE_H_
+
+struct adapter_service;
+struct dc;
+struct resource_pool;
+struct dc_validation_set;
+
+
+bool dce100_construct_resource_pool(
+	struct adapter_service *adapter_serv,
+	uint8_t num_virtual_links,
+	struct dc *dc,
+	struct resource_pool *pool);
+
+void dce100_destruct_resource_pool(struct resource_pool *pool);
+
+#endif /* DCE100_RESOURCE_H_ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 23/26] drm/amd/dal: Add empty encoder programming for virtual HW
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (21 preceding siblings ...)
  2016-02-16 22:28   ` [PATCH v2 22/26] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
@ 2016-02-16 22:28   ` Harry Wentland
  2016-02-16 22:28   ` [PATCH v2 24/26] drm/amd/dal: Add display core Harry Wentland
                     ` (2 subsequent siblings)
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:28 UTC (permalink / raw)
  To: dri-devel

Adds empty encoder HW programming functions to support
enablement of virtual pipes (i.e. pipes without actual
display output).

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/virtual/Makefile        |   9 ++
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.c  | 133 +++++++++++++++++++++
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.h  |  35 ++++++
 .../amd/dal/dc/virtual/virtual_stream_encoder.c    | 124 +++++++++++++++++++
 .../amd/dal/dc/virtual/virtual_stream_encoder.h    |  39 ++++++
 5 files changed, 340 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h

diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/Makefile b/drivers/gpu/drm/amd/dal/dc/virtual/Makefile
new file mode 100644
index 000000000000..0e2cbc0bb532
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the virtual sub-component of DAL.
+# It provides the control and status of HW CRTC block.
+
+VIRTUAL = virtual_link_encoder.o virtual_stream_encoder.o
+
+AMD_DAL_VIRTUAL = $(addprefix $(AMDDALPATH)/dc/virtual/,$(VIRTUAL))
+
+AMD_DAL_FILES += $(AMD_DAL_VIRTUAL)
diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
new file mode 100644
index 000000000000..ade443d79c02
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services_types.h"
+
+#include "virtual_link_encoder.h"
+
+#define VIRTUAL_MAX_PIXEL_CLK_IN_KHZ 600000
+
+static bool virtual_link_encoder_validate_output_with_stream(
+	struct link_encoder *enc,
+	struct core_stream *stream) { return true; }
+
+static void virtual_link_encoder_hw_init(struct link_encoder *enc) {}
+
+static void virtual_link_encoder_setup(
+	struct link_encoder *enc,
+	enum signal_type signal) {}
+
+static void virtual_link_encoder_enable_tmds_output(
+	struct link_encoder *enc,
+	enum clock_source_id clock_source,
+	enum dc_color_depth color_depth,
+	bool hdmi,
+	bool dual_link,
+	uint32_t pixel_clock) {}
+
+static void virtual_link_encoder_enable_dp_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source) {}
+
+static void virtual_link_encoder_enable_dp_mst_output(
+	struct link_encoder *enc,
+	const struct link_settings *link_settings,
+	enum clock_source_id clock_source) {}
+
+static void virtual_link_encoder_disable_output(
+	struct link_encoder *link_enc,
+	enum signal_type signal) {}
+
+static void virtual_link_encoder_dp_set_lane_settings(
+	struct link_encoder *enc,
+	const struct link_training_settings *link_settings) {}
+
+static void virtual_link_encoder_dp_set_phy_pattern(
+	struct link_encoder *enc,
+	const struct encoder_set_dp_phy_pattern_param *param) {}
+
+static void virtual_link_encoder_update_mst_stream_allocation_table(
+	struct link_encoder *enc,
+	const struct link_mst_stream_allocation_table *table) {}
+
+static void virtual_link_encoder_set_lcd_backlight_level(
+	struct link_encoder *enc,
+	uint32_t level) {}
+
+static void virtual_link_encoder_edp_backlight_control(
+	struct link_encoder *enc,
+	bool enable) {}
+
+static void virtual_link_encoder_edp_power_control(
+	struct link_encoder *enc,
+	bool power_up) {}
+
+static void virtual_link_encoder_connect_dig_be_to_fe(
+	struct link_encoder *enc,
+	enum engine_id engine,
+	bool connect) {}
+
+static struct link_encoder_funcs virtual_lnk_enc_funcs = {
+	.validate_output_with_stream =
+		virtual_link_encoder_validate_output_with_stream,
+	.hw_init = virtual_link_encoder_hw_init,
+	.setup = virtual_link_encoder_setup,
+	.enable_tmds_output = virtual_link_encoder_enable_tmds_output,
+	.enable_dp_output = virtual_link_encoder_enable_dp_output,
+	.enable_dp_mst_output = virtual_link_encoder_enable_dp_mst_output,
+	.disable_output = virtual_link_encoder_disable_output,
+	.dp_set_lane_settings = virtual_link_encoder_dp_set_lane_settings,
+	.dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern,
+	.update_mst_stream_allocation_table =
+		virtual_link_encoder_update_mst_stream_allocation_table,
+	.set_lcd_backlight_level = virtual_link_encoder_set_lcd_backlight_level,
+	.backlight_control = virtual_link_encoder_edp_backlight_control,
+	.power_control = virtual_link_encoder_edp_power_control,
+	.connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe
+};
+
+bool virtual_link_encoder_construct(
+	struct link_encoder *enc, const struct encoder_init_data *init_data)
+{
+	enc->funcs = &virtual_lnk_enc_funcs;
+	enc->ctx = init_data->ctx;
+	enc->id = init_data->encoder;
+
+	enc->hpd_source = init_data->hpd_source;
+	enc->connector = init_data->connector;
+
+	enc->adapter_service = init_data->adapter_service;
+
+	enc->transmitter = init_data->transmitter;
+
+	enc->features.max_pixel_clock = VIRTUAL_MAX_PIXEL_CLK_IN_KHZ;
+
+	enc->output_signals = SIGNAL_TYPE_VIRTUAL;
+
+	enc->preferred_engine = ENGINE_ID_VIRTUAL;
+
+	return true;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
new file mode 100644
index 000000000000..c34bd0421c9b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_VIRTUAL_LINK_ENCODER_H__
+#define __DC_VIRTUAL_LINK_ENCODER_H__
+
+#include "inc/link_encoder.h"
+
+bool virtual_link_encoder_construct(
+	struct link_encoder *enc, const struct encoder_init_data *init_data);
+
+
+#endif /* __DC_VIRTUAL_LINK_ENCODER_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
new file mode 100644
index 000000000000..4f5271bec369
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "virtual_stream_encoder.h"
+
+static void virtual_stream_encoder_dp_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing) {}
+
+static void virtual_stream_encoder_hdmi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool enable_audio) {}
+
+static void virtual_stream_encoder_dvi_set_stream_attribute(
+	struct stream_encoder *enc,
+	struct dc_crtc_timing *crtc_timing,
+	bool is_dual_link) {}
+
+static void virtual_stream_encoder_set_mst_bandwidth(
+	struct stream_encoder *enc,
+	struct fixed31_32 avg_time_slots_per_mtp) {}
+
+static void virtual_stream_encoder_update_hdmi_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame) {}
+
+static void virtual_stream_encoder_stop_hdmi_info_packets(
+	struct stream_encoder *enc) {}
+
+static void virtual_stream_encoder_update_dp_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame) {}
+
+static void virtual_stream_encoder_stop_dp_info_packets(
+	struct stream_encoder *enc) {}
+
+static void virtual_stream_encoder_dp_blank(
+	struct stream_encoder *enc) {}
+
+static void virtual_stream_encoder_dp_unblank(
+	struct stream_encoder *enc,
+	const struct encoder_unblank_param *param) {}
+
+static struct stream_encoder_funcs virtual_str_enc_funcs = {
+	.dp_set_stream_attribute =
+		virtual_stream_encoder_dp_set_stream_attribute,
+	.hdmi_set_stream_attribute =
+		virtual_stream_encoder_hdmi_set_stream_attribute,
+	.dvi_set_stream_attribute =
+		virtual_stream_encoder_dvi_set_stream_attribute,
+	.set_mst_bandwidth =
+		virtual_stream_encoder_set_mst_bandwidth,
+	.update_hdmi_info_packets =
+		virtual_stream_encoder_update_hdmi_info_packets,
+	.stop_hdmi_info_packets =
+		virtual_stream_encoder_stop_hdmi_info_packets,
+	.update_dp_info_packets =
+		virtual_stream_encoder_update_dp_info_packets,
+	.stop_dp_info_packets =
+		virtual_stream_encoder_stop_dp_info_packets,
+	.dp_blank =
+		virtual_stream_encoder_dp_blank,
+	.dp_unblank =
+		virtual_stream_encoder_dp_unblank,
+};
+
+bool virtual_stream_encoder_construct(
+	struct stream_encoder *enc,
+	struct dc_context *ctx,
+	struct dc_bios *bp)
+{
+	if (!enc)
+		return false;
+	if (!bp)
+		return false;
+
+	enc->funcs = &virtual_str_enc_funcs;
+	enc->ctx = ctx;
+	enc->id = ENGINE_ID_VIRTUAL;
+	enc->bp = bp;
+
+	return true;
+}
+
+struct stream_encoder *virtual_stream_encoder_create(
+	struct dc_context *ctx, struct dc_bios *bp)
+{
+	struct stream_encoder *enc = dm_alloc(ctx, sizeof(*enc));
+
+	if (!enc)
+		return NULL;
+
+	if (virtual_stream_encoder_construct(enc, ctx, bp))
+		return enc;
+
+	BREAK_TO_DEBUGGER();
+	dm_free(ctx, enc);
+	return NULL;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h
new file mode 100644
index 000000000000..dce8425ea88e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_VIRTUAL_STREAM_ENCODER_H__
+#define __DC_VIRTUAL_STREAM_ENCODER_H__
+
+#include "inc/stream_encoder.h"
+
+struct stream_encoder *virtual_stream_encoder_create(
+	struct dc_context *ctx, struct dc_bios *bp);
+
+bool virtual_stream_encoder_construct(
+	struct stream_encoder *enc,
+	struct dc_context *ctx,
+	struct dc_bios *bp);
+
+#endif /* __DC_VIRTUAL_STREAM_ENCODER_H__ */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 24/26] drm/amd/dal: Add display core
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (22 preceding siblings ...)
  2016-02-16 22:28   ` [PATCH v2 23/26] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
@ 2016-02-16 22:28   ` Harry Wentland
  2016-02-16 22:28   ` [PATCH v2 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
  2016-02-16 22:28   ` [PATCH v2 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:28 UTC (permalink / raw)
  To: dri-devel

Adds a logical representation of our hardware. Provides ability to
- dc_validate_resources - validate a display configuration
- dc_commit_targets - commit a display configuration
- dc_commit_surfaces_to_target - update surfaces
- dc_link_detect - detect displays at link
- dc_resume - resume display HW
- dc_interrupt_set/ack - set and ack interrupts
- etc.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/Makefile               |   28 +
 drivers/gpu/drm/amd/dal/dc/core/dc.c              |  932 +++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c |   56 +
 drivers/gpu/drm/amd/dal/dc/core/dc_link.c         | 1644 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c     | 1151 ++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c      | 1728 +++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c    |  201 +++
 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c     | 1243 +++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c         |  116 ++
 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c       |  188 +++
 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c      |  123 ++
 drivers/gpu/drm/amd/dal/dc/core/dc_target.c       |  548 +++++++
 12 files changed, 7958 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_target.c

diff --git a/drivers/gpu/drm/amd/dal/dc/Makefile b/drivers/gpu/drm/amd/dal/dc/Makefile
new file mode 100644
index 000000000000..aed26eec81f9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/Makefile
@@ -0,0 +1,28 @@
+#
+# Makefile for Display Core (dc) component.
+#
+
+DC_LIBS = adapter asic_capability audio basics bios calcs \
+gpio gpu i2caux irq virtual
+
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+DC_LIBS += dce110
+endif
+
+ifdef CONFIG_DRM_AMD_DAL_DCE10_0
+DC_LIBS += dce100
+endif
+
+AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/dc/,$(DC_LIBS)))
+
+include $(AMD_DC)
+
+DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_target.o dc_sink.o dc_stream.o \
+dc_hw_sequencer.o dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o
+
+AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE))
+
+AMD_DAL_FILES += $(AMD_DISPLAY_CORE)
+
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c
new file mode 100644
index 000000000000..0b8f158c0ec2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ */
+
+#include "dm_services.h"
+
+#include "dc.h"
+
+#include "core_status.h"
+#include "core_types.h"
+#include "hw_sequencer.h"
+
+#include "resource.h"
+
+#include "adapter_service_interface.h"
+#include "clock_source.h"
+#include "dc_bios_types.h"
+
+#include "bandwidth_calcs.h"
+#include "include/irq_service_interface.h"
+#include "transform.h"
+#include "timing_generator.h"
+#include "virtual/virtual_link_encoder.h"
+
+#include "link_hwss.h"
+#include "link_encoder.h"
+
+#include "dc_link_ddc.h"
+
+/*******************************************************************************
+ * Private structures
+ ******************************************************************************/
+
+struct dc_target_sync_report {
+	uint32_t h_count;
+	uint32_t v_count;
+};
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static void destroy_links(struct dc *dc)
+{
+	uint32_t i;
+
+	for (i = 0; i < dc->link_count; i++) {
+		if (NULL != dc->links[i])
+			link_destroy(&dc->links[i]);
+	}
+}
+
+static bool create_links(struct dc *dc, const struct dc_init_data *init_params)
+{
+	int i;
+	int connectors_num;
+	struct dc_bios *dcb;
+
+	dc->link_count = 0;
+
+	dcb = dal_adapter_service_get_bios_parser(init_params->adapter_srv);
+
+	connectors_num = dcb->funcs->get_connectors_number(dcb);
+
+	if (connectors_num > ENUM_ID_COUNT) {
+		dm_error(
+			"DC: Number of connectors %d exceeds maximum of %d!\n",
+			connectors_num,
+			ENUM_ID_COUNT);
+		return false;
+	}
+
+	if (connectors_num == 0 && init_params->num_virtual_links == 0) {
+		dm_error("DC: Number of connectors can not be zero!\n");
+		return false;
+	}
+
+	dm_output_to_console(
+		"DC: %s: connectors_num: physical:%d, virtual:%d\n",
+		__func__,
+		connectors_num,
+		init_params->num_virtual_links);
+
+	for (i = 0; i < connectors_num; i++) {
+		struct link_init_data link_init_params = {0};
+		struct core_link *link;
+
+		link_init_params.ctx = init_params->ctx;
+		link_init_params.adapter_srv = init_params->adapter_srv;
+		link_init_params.connector_index = i;
+		link_init_params.link_index = dc->link_count;
+		link_init_params.dc = dc;
+		link = link_create(&link_init_params);
+
+		if (link) {
+			dc->links[dc->link_count] = link;
+			link->dc = dc;
+			++dc->link_count;
+		} else {
+			dm_error("DC: failed to create link!\n");
+		}
+	}
+
+	for (i = 0; i < init_params->num_virtual_links; i++) {
+		struct core_link *link = dm_alloc(
+			dc->ctx,
+			sizeof(*link));
+		struct encoder_init_data enc_init = {0};
+
+		if (link == NULL) {
+			BREAK_TO_DEBUGGER();
+			goto failed_alloc;
+		}
+
+		link->adapter_srv = init_params->adapter_srv;
+		link->ctx = init_params->ctx;
+		link->dc = dc;
+		link->public.connector_signal = SIGNAL_TYPE_VIRTUAL;
+		link->link_id.type = OBJECT_TYPE_CONNECTOR;
+		link->link_id.id = CONNECTOR_ID_VIRTUAL;
+		link->link_id.enum_id = ENUM_ID_1;
+		link->link_enc = dm_alloc(
+			dc->ctx,
+			sizeof(*link->link_enc));
+
+		enc_init.adapter_service = init_params->adapter_srv;
+		enc_init.ctx = init_params->ctx;
+		enc_init.channel = CHANNEL_ID_UNKNOWN;
+		enc_init.hpd_source = HPD_SOURCEID_UNKNOWN;
+		enc_init.transmitter = TRANSMITTER_UNKNOWN;
+		enc_init.connector = link->link_id;
+		enc_init.encoder.type = OBJECT_TYPE_ENCODER;
+		enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL;
+		enc_init.encoder.enum_id = ENUM_ID_1;
+		virtual_link_encoder_construct(link->link_enc, &enc_init);
+
+		link->public.link_index = dc->link_count;
+		dc->links[dc->link_count] = link;
+		dc->link_count++;
+	}
+
+	return true;
+
+failed_alloc:
+	return false;
+}
+
+
+static void init_hw(struct dc *dc)
+{
+	int i;
+	struct dc_bios *bp;
+	struct transform *xfm;
+
+	bp = dal_adapter_service_get_bios_parser(dc->res_pool.adapter_srv);
+	for(i = 0; i < dc->res_pool.controller_count; i++) {
+		xfm = dc->res_pool.transforms[i];
+
+		dc->hwss.enable_display_power_gating(
+				dc->ctx, i, bp,
+				PIPE_GATING_CONTROL_INIT);
+		dc->hwss.enable_display_power_gating(
+				dc->ctx, i, bp,
+				PIPE_GATING_CONTROL_DISABLE);
+
+		xfm->funcs->transform_power_up(xfm);
+		dc->hwss.enable_display_pipe_clock_gating(
+			dc->ctx,
+			true);
+	}
+
+	dc->hwss.clock_gating_power_up(dc->ctx, false);
+	bp->funcs->power_up(bp);
+	/***************************************/
+
+	for (i = 0; i < dc->link_count; i++) {
+		/****************************************/
+		/* Power up AND update implementation according to the
+		 * required signal (which may be different from the
+		 * default signal on connector). */
+		struct core_link *link = dc->links[i];
+		link->link_enc->funcs->hw_init(link->link_enc);
+	}
+
+	for(i = 0; i < dc->res_pool.controller_count; i++) {
+		struct timing_generator *tg = dc->res_pool.timing_generators[i];
+
+		tg->funcs->disable_vga(tg);
+
+		/* Blank controller using driver code instead of
+		 * command table. */
+		tg->funcs->set_blank(tg, true);
+	}
+
+	for(i = 0; i < dc->res_pool.audio_count; i++) {
+		struct audio *audio = dc->res_pool.audios[i];
+
+		if (dal_audio_power_up(audio) != AUDIO_RESULT_OK)
+			dm_error("Failed audio power up!\n");
+	}
+
+}
+
+static struct adapter_service *create_as(
+		struct dc_init_data *dc_init_data,
+		const struct dal_init_data *init)
+{
+	struct adapter_service *as = NULL;
+	struct as_init_data init_data;
+
+	dm_memset(&init_data, 0, sizeof(init_data));
+
+	init_data.ctx = dc_init_data->ctx;
+
+	/* BIOS parser init data */
+	init_data.bp_init_data.ctx = dc_init_data->ctx;
+	init_data.bp_init_data.bios = init->asic_id.atombios_base_address;
+
+	/* HW init data */
+	init_data.hw_init_data.chip_id = init->asic_id.chip_id;
+	init_data.hw_init_data.chip_family = init->asic_id.chip_family;
+	init_data.hw_init_data.pci_revision_id = init->asic_id.pci_revision_id;
+	init_data.hw_init_data.fake_paths_num = init->asic_id.fake_paths_num;
+	init_data.hw_init_data.feature_flags = init->asic_id.feature_flags;
+	init_data.hw_init_data.hw_internal_rev = init->asic_id.hw_internal_rev;
+	init_data.hw_init_data.runtime_flags = init->asic_id.runtime_flags;
+	init_data.hw_init_data.vram_width = init->asic_id.vram_width;
+	init_data.hw_init_data.vram_type = init->asic_id.vram_type;
+
+	/* bdf is BUS,DEVICE,FUNCTION*/
+	init_data.bdf_info = init->bdf_info;
+
+	init_data.display_param = &init->display_param;
+	init_data.vbios_override = init->vbios_override;
+	init_data.dce_environment = init->dce_environment;
+
+	as = dal_adapter_service_create(&init_data);
+
+	return as;
+}
+
+static void bw_calcs_data_update_from_pplib(struct dc *dc)
+{
+	struct dc_pp_clock_levels clks = {0};
+
+	/*do system clock*/
+	dm_pp_get_clock_levels_by_type(
+			dc->ctx,
+			DC_PP_CLOCK_TYPE_ENGINE_CLK,
+			&clks);
+	/* convert all the clock fro kHz to fix point mHz */
+	dc->bw_vbios.high_sclk = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels-1], 1000);
+	dc->bw_vbios.mid_sclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels>>1], 1000);
+	dc->bw_vbios.low_sclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[0], 1000);
+
+	/*do display clock*/
+	dm_pp_get_clock_levels_by_type(
+			dc->ctx,
+			DC_PP_CLOCK_TYPE_DISPLAY_CLK,
+			&clks);
+
+	dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels-1], 1000);
+	dc->bw_vbios.mid_voltage_max_dispclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels>>1], 1000);
+	dc->bw_vbios.low_voltage_max_dispclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[0], 1000);
+
+	/*do memory clock*/
+	dm_pp_get_clock_levels_by_type(
+			dc->ctx,
+			DC_PP_CLOCK_TYPE_MEMORY_CLK,
+			&clks);
+
+	dc->bw_vbios.low_yclk = bw_frc_to_fixed(
+		clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000);
+	dc->bw_vbios.mid_yclk = bw_frc_to_fixed(
+		clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER,
+		1000);
+	dc->bw_vbios.high_yclk = bw_frc_to_fixed(
+		clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER,
+		1000);
+}
+
+static bool construct(struct dc *dc, const struct dal_init_data *init_params)
+{
+	struct dal_logger *logger;
+	/* Tempory code
+	 * TODO: replace dal_init_data with dc_init_data when dal is removed
+	 */
+	struct dc_init_data dc_init_data = {0};
+
+	/* Create dc context */
+	/* A temp dc context is used only to allocate the memory for actual
+	 * dc context */
+	struct dc_context ctx = {0};
+	ctx.cgs_device = init_params->cgs_device;
+	ctx.dc = dc;
+
+	dc_init_data.ctx = dm_alloc(&ctx, sizeof(*dc_init_data.ctx));
+	if (!dc_init_data.ctx) {
+		dm_error("%s: failed to create ctx\n", __func__);
+		goto ctx_fail;
+	}
+	dc_init_data.ctx->driver_context = init_params->driver;
+	dc_init_data.ctx->cgs_device = init_params->cgs_device;
+	dc_init_data.num_virtual_links = init_params->num_virtual_links;
+	dc_init_data.ctx->dc = dc;
+
+	/* Create logger */
+	logger = dal_logger_create(dc_init_data.ctx);
+
+	if (!logger) {
+		/* can *not* call logger. call base driver 'print error' */
+		dm_error("%s: failed to create Logger!\n", __func__);
+		goto logger_fail;
+	}
+	dc_init_data.ctx->logger = logger;
+
+	/* Create adapter service */
+	dc_init_data.adapter_srv = create_as(&dc_init_data, init_params);
+
+	if (!dc_init_data.adapter_srv) {
+		dm_error("%s: create_as() failed!\n", __func__);
+		goto as_fail;
+	}
+
+	/* Initialize HW controlled by Adapter Service */
+	if (false == dal_adapter_service_initialize_hw_data(
+			dc_init_data.adapter_srv)) {
+		dm_error("%s: dal_adapter_service_initialize_hw_data()"\
+				"  failed!\n", __func__);
+		/* Note that AS exist, so have to destroy it.*/
+		goto as_fail;
+	}
+
+	dc->ctx = dc_init_data.ctx;
+
+	dc->ctx->dce_environment = dal_adapter_service_get_dce_environment(
+			dc_init_data.adapter_srv);
+
+	/* Create hardware sequencer */
+	if (!dc_construct_hw_sequencer(dc_init_data.adapter_srv, dc))
+		goto hwss_fail;
+
+	if (!dc_construct_resource_pool(
+		dc_init_data.adapter_srv, dc, dc_init_data.num_virtual_links))
+		goto construct_resource_fail;
+
+	if (!create_links(dc, &dc_init_data))
+		goto create_links_fail;
+
+	bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios);
+
+	bw_calcs_data_update_from_pplib(dc);
+
+	return true;
+
+	/**** error handling here ****/
+construct_resource_fail:
+create_links_fail:
+as_fail:
+	dal_logger_destroy(&dc_init_data.ctx->logger);
+logger_fail:
+hwss_fail:
+	dm_free(&ctx, dc_init_data.ctx);
+ctx_fail:
+	return false;
+}
+
+static void destruct(struct dc *dc)
+{
+	destroy_links(dc);
+	dc->res_pool.funcs->destruct(&dc->res_pool);
+	dal_logger_destroy(&dc->ctx->logger);
+	dm_free(dc->ctx, dc->ctx);
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+struct dc *dc_create(const struct dal_init_data *init_params)
+ {
+	struct dc_context ctx = {
+		.driver_context = init_params->driver,
+		.cgs_device = init_params->cgs_device
+	};
+	struct dc *dc = dm_alloc(&ctx, sizeof(*dc));
+
+	if (NULL == dc)
+		goto alloc_fail;
+
+	ctx.dc = dc;
+	if (false == construct(dc, init_params))
+		goto construct_fail;
+
+	/*TODO: separate HW and SW initialization*/
+	init_hw(dc);
+
+	return dc;
+
+construct_fail:
+	dm_free(&ctx, dc);
+
+alloc_fail:
+	return NULL;
+}
+
+void dc_destroy(struct dc **dc)
+{
+	struct dc_context ctx = *(*dc)->ctx;
+	destruct(*dc);
+	dm_free(&ctx, *dc);
+	*dc = NULL;
+}
+
+bool dc_validate_resources(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	struct validate_context *context;
+
+	context = dm_alloc(dc->ctx, sizeof(struct validate_context));
+	if(context == NULL)
+		goto context_alloc_fail;
+
+	result = dc->res_pool.funcs->validate_with_context(
+						dc, set, set_count, context);
+
+	dm_free(dc->ctx, context);
+context_alloc_fail:
+
+	return (result == DC_OK);
+
+}
+
+static void program_timing_sync(
+		struct dc_context *dc_ctx,
+		struct validate_context *ctx)
+{
+	uint8_t i;
+	uint8_t j;
+	uint8_t group_size = 0;
+	uint8_t tg_count = ctx->res_ctx.pool.controller_count;
+	struct timing_generator *tg_set[3];
+
+	for (i = 0; i < tg_count; i++) {
+		if (!ctx->res_ctx.controller_ctx[i].stream)
+			continue;
+
+		tg_set[0] = ctx->res_ctx.pool.timing_generators[i];
+		group_size = 1;
+
+		/* Add tg to the set, search rest of the tg's for ones with
+		 * same timing, add all tgs with same timing to the group
+		 */
+		for (j = i + 1; j < tg_count; j++) {
+			if (!ctx->res_ctx.controller_ctx[j].stream)
+				continue;
+
+			if (is_same_timing(
+				&ctx->res_ctx.controller_ctx[j].stream->public
+								.timing,
+				&ctx->res_ctx.controller_ctx[i].stream->public
+								.timing)) {
+				tg_set[group_size] =
+					ctx->res_ctx.pool.timing_generators[j];
+				group_size++;
+			}
+		}
+
+		/* Right now we limit to one timing sync group so if one is
+		 * found we break. A group has to be more than one tg.*/
+		if (group_size > 1)
+			break;
+	}
+
+	if(group_size > 1) {
+		dc_ctx->dc->hwss.enable_timing_synchronization(dc_ctx, group_size, tg_set);
+	}
+}
+
+static bool targets_changed(
+		struct dc *dc,
+		struct dc_target *targets[],
+		uint8_t target_count)
+{
+	uint8_t i;
+
+	if (target_count != dc->current_context.target_count)
+		return true;
+
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		if (&dc->current_context.targets[i]->public != targets[i])
+			return true;
+	}
+
+	return false;
+}
+
+bool dc_commit_targets(
+	struct dc *dc,
+	struct dc_target *targets[],
+	uint8_t target_count)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	struct validate_context *context;
+	struct dc_validation_set set[4];
+	uint8_t i;
+
+	if (false == targets_changed(dc, targets, target_count))
+		return DC_OK;
+
+	dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_INTERFACE_TRACE,
+				LOG_MINOR_COMPONENT_DC,
+				"%s: %d targets\n",
+				__func__,
+				target_count);
+
+	for (i = 0; i < target_count; i++) {
+		struct dc_target *target = targets[i];
+
+		dc_target_log(target,
+				dc->ctx->logger,
+				LOG_MAJOR_INTERFACE_TRACE,
+				LOG_MINOR_COMPONENT_DC);
+
+		set[i].target = targets[i];
+		set[i].surface_count = 0;
+
+	}
+
+	context = dm_alloc(dc->ctx, sizeof(struct validate_context));
+	if (context == NULL)
+		goto context_alloc_fail;
+
+	result = dc->res_pool.funcs->validate_with_context(dc, set, target_count, context);
+	if (result != DC_OK){
+		BREAK_TO_DEBUGGER();
+		goto fail;
+	}
+
+	pplib_apply_safe_state(dc);
+
+	if (!dal_adapter_service_is_in_accelerated_mode(
+						dc->res_pool.adapter_srv)) {
+		dc->hwss.enable_accelerated_mode(dc);
+	}
+
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		/*TODO: optimize this to happen only when necessary*/
+		dc_target_disable_memory_requests(
+				&dc->current_context.targets[i]->public);
+	}
+
+	if (result == DC_OK) {
+		dc->hwss.reset_hw_ctx(dc, context, target_count);
+
+		if (context->target_count > 0)
+			result = dc->hwss.apply_ctx_to_hw(dc, context);
+	}
+
+	for (i = 0; i < context->target_count; i++) {
+		struct dc_target *dc_target = &context->targets[i]->public;
+		if (context->targets[i]->status.surface_count > 0)
+			dc_target_enable_memory_requests(dc_target);
+	}
+
+	/* Release old targets */
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		dc_target_release(
+				&dc->current_context.targets[i]->public);
+		dc->current_context.targets[i] = NULL;
+	}
+	/* Retain new targets*/
+	for (i = 0; i < context->target_count; i++) {
+		dc_target_retain(&context->targets[i]->public);
+	}
+
+	dc->current_context = *context;
+
+	program_timing_sync(dc->ctx, context);
+
+	pplib_apply_display_requirements(dc, context);
+
+	/* TODO: disable unused plls*/
+fail:
+	dm_free(dc->ctx, context);
+
+context_alloc_fail:
+	return (result == DC_OK);
+}
+
+uint8_t dc_get_current_target_count(const struct dc *dc)
+{
+	return dc->current_context.target_count;
+}
+
+struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i)
+{
+	if (i < dc->current_context.target_count)
+		return &dc->current_context.targets[i]->public;
+	return NULL;
+}
+
+const struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index)
+{
+	return &dc->links[link_index]->public;
+}
+
+const struct graphics_object_id dc_get_link_id_at_index(
+	struct dc *dc, uint32_t link_index)
+{
+	return dc->links[link_index]->link_id;
+}
+
+const struct ddc_service *dc_get_ddc_at_index(
+	struct dc *dc, uint32_t link_index)
+{
+	return dc->links[link_index]->ddc;
+}
+
+const enum dc_irq_source dc_get_hpd_irq_source_at_index(
+	struct dc *dc, uint32_t link_index)
+{
+	return dc->links[link_index]->public.irq_source_hpd;
+}
+
+const struct audio **dc_get_audios(struct dc *dc)
+{
+	return (const struct audio **)dc->res_pool.audios;
+}
+
+void dc_get_caps(const struct dc *dc, struct dc_caps *caps)
+{
+	caps->max_targets = dc->res_pool.controller_count;
+	caps->max_links = dc->link_count;
+	caps->max_audios = dc->res_pool.audio_count;
+}
+
+void dc_flip_surface_addrs(struct dc* dc,
+		const struct dc_surface *const surfaces[],
+		struct dc_flip_addrs flip_addrs[],
+		uint32_t count)
+{
+	uint8_t i;
+	for (i = 0; i < count; i++) {
+		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
+		/*
+		 * TODO figure out a good way to keep track of address. Until
+		 * then we'll have to awkwardly bypass the "const" surface.
+		 */
+		surface->public.address = flip_addrs[i].address;
+		surface->public.flip_immediate = flip_addrs[i].flip_immediate;
+
+		dc->hwss.update_plane_address(
+			dc,
+			surface,
+			DC_TARGET_TO_CORE(surface->status.dc_target));
+	}
+}
+
+enum dc_irq_source dc_interrupt_to_irq_source(
+		struct dc *dc,
+		uint32_t src_id,
+		uint32_t ext_id)
+{
+	return dal_irq_service_to_irq_source(dc->res_pool.irqs, src_id, ext_id);
+}
+
+
+void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable)
+{
+	dal_irq_service_set(dc->res_pool.irqs, src, enable);
+}
+
+void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
+{
+	dal_irq_service_ack(dc->res_pool.irqs, src);
+}
+
+const struct dc_target *dc_get_target_on_irq_source(
+		const struct dc *dc,
+		enum dc_irq_source src)
+{
+	uint8_t i, j;
+	uint8_t crtc_idx;
+
+	switch (src) {
+	case DC_IRQ_SOURCE_VUPDATE1:
+	case DC_IRQ_SOURCE_VUPDATE2:
+	case DC_IRQ_SOURCE_VUPDATE3:
+	case DC_IRQ_SOURCE_VUPDATE4:
+	case DC_IRQ_SOURCE_VUPDATE5:
+	case DC_IRQ_SOURCE_VUPDATE6:
+		crtc_idx = src - DC_IRQ_SOURCE_VUPDATE1;
+		break;
+	case DC_IRQ_SOURCE_PFLIP1:
+	case DC_IRQ_SOURCE_PFLIP2:
+	case DC_IRQ_SOURCE_PFLIP3:
+	case DC_IRQ_SOURCE_PFLIP4:
+	case DC_IRQ_SOURCE_PFLIP5:
+	case DC_IRQ_SOURCE_PFLIP6:
+	case DC_IRQ_SOURCE_PFLIP_UNDERLAY0:
+		crtc_idx = src - DC_IRQ_SOURCE_PFLIP1;
+		break;
+	default:
+		dm_error("%s: invalid irq source: %d\n!" ,__func__, src);
+		return NULL;
+	}
+
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		struct core_target *target = dc->current_context.targets[i];
+
+		struct dc_target *dc_target;
+
+		if (NULL == target) {
+			dm_error("%s: 'dc_target' is NULL for irq source: %d\n!",
+					__func__, src);
+			continue;
+		}
+
+		dc_target = &target->public;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			const struct core_stream *stream =
+				DC_STREAM_TO_CORE(dc_target->streams[j]);
+			const uint8_t controller_idx = stream->controller_idx;
+
+			if (controller_idx == crtc_idx)
+				return dc_target;
+		}
+	}
+
+	return NULL;
+}
+
+void dc_set_power_state(
+	struct dc *dc,
+	enum dc_acpi_cm_power_state power_state,
+	enum dc_video_power_state video_power_state)
+{
+	dc->previous_power_state = dc->current_power_state;
+	dc->current_power_state = video_power_state;
+
+	switch (power_state) {
+	case DC_ACPI_CM_POWER_STATE_D0:
+		init_hw(dc);
+		break;
+	default:
+		/* NULL means "reset/release all DC targets" */
+		dc_commit_targets(dc, NULL, 0);
+
+		dc->hwss.power_down(dc);
+		break;
+	}
+
+}
+
+void dc_resume(const struct dc *dc)
+{
+	uint32_t i;
+
+	for (i = 0; i < dc->link_count; i++)
+		core_link_resume(dc->links[i]);
+}
+
+bool dc_read_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size)
+{
+	struct core_link *link =
+			DC_LINK_TO_LINK(dc_get_link_at_index(dc, link_index));
+
+	enum ddc_result r = dal_ddc_service_read_dpcd_data(
+			link->ddc,
+			address,
+			data,
+			size);
+	return r == DDC_RESULT_SUCESSFULL;
+}
+
+bool dc_write_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t size)
+{
+	struct core_link *link =
+			DC_LINK_TO_LINK(dc_get_link_at_index(dc, link_index));
+
+	enum ddc_result r = dal_ddc_service_write_dpcd_data(
+			link->ddc,
+			address,
+			data,
+			size);
+	return r == DDC_RESULT_SUCESSFULL;
+}
+
+bool dc_link_add_remote_sink(const struct dc_link *link, struct dc_sink *sink)
+{
+	struct core_link *core_link = DC_LINK_TO_LINK(link);
+	struct dc_link *dc_link = &core_link->public;
+
+	if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	dc_link->remote_sinks[link->sink_count] = sink;
+	dc_link->sink_count++;
+
+	return true;
+}
+
+void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink)
+{
+	struct core_link *core_link = DC_LINK_TO_LINK(link);
+	struct dc_link *dc_link = &core_link->public;
+
+	dc_link->local_sink = sink;
+
+	if (sink == NULL) {
+		dc_link->sink_count = 0;
+		dc_link->type = dc_connection_none;
+	} else {
+		dc_link->sink_count = 1;
+		dc_link->type = dc_connection_single;
+	}
+}
+
+void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink)
+{
+	int i;
+	struct core_link *core_link = DC_LINK_TO_LINK(link);
+	struct dc_link *dc_link = &core_link->public;
+
+	if (!link->sink_count) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	for (i = 0; i < dc_link->sink_count; i++) {
+		if (dc_link->remote_sinks[i] == sink) {
+			dc_sink_release(sink);
+			dc_link->remote_sinks[i] = NULL;
+
+			/* shrink array to remove empty place */
+			while (i < dc_link->sink_count - 1) {
+				dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1];
+				i++;
+			}
+
+			dc_link->sink_count--;
+			return;
+		}
+	}
+}
+
+uint8_t dc_get_dig_index(const struct dc_stream *stream)
+{
+
+	struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
+
+	switch (core_stream->stream_enc->id) {
+	case ENGINE_ID_DIGA:
+		return 0;
+	case ENGINE_ID_DIGB:
+		return 1;
+	case ENGINE_ID_DIGC:
+		return 2;
+	case ENGINE_ID_DIGD:
+		return 3;
+	case ENGINE_ID_DIGE:
+		return 4;
+	case ENGINE_ID_DIGF:
+		return 5;
+	case ENGINE_ID_DIGG:
+		return 6;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+enum gpio_ddc_line dc_get_ddc_line(
+		const struct dc_stream *stream)
+{
+
+	struct core_sink *core_sink = DC_SINK_TO_CORE(stream->sink);
+	struct ddc *ddc_line = dal_ddc_service_get_ddc_pin(
+			core_sink->link->ddc);
+
+	return dal_ddc_get_line(ddc_line);
+}
+
+enum signal_type dc_get_display_signal(
+		const struct dc_stream *stream)
+{
+	return stream->sink->sink_signal;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
new file mode 100644
index 000000000000..db4f1313e056
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "core_types.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce100/dce100_hw_sequencer.h"
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/dce110_hw_sequencer.h"
+#endif
+
+bool dc_construct_hw_sequencer(
+				struct adapter_service *adapter_serv,
+				struct dc *dc)
+{
+	enum dce_version dce_ver = dal_adapter_service_get_dce_version(adapter_serv);
+
+	switch (dce_ver)
+	{
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dce100_hw_sequencer_construct(dc);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dce110_hw_sequencer_construct(dc);
+#endif
+	default:
+		break;
+	}
+
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
new file mode 100644
index 000000000000..b0ef028ad0fc
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
@@ -0,0 +1,1644 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "dc.h"
+#include "core_dc.h"
+#include "adapter_service_interface.h"
+#include "grph_object_id.h"
+#include "gpio_service_interface.h"
+#include "core_status.h"
+#include "dc_link_dp.h"
+#include "dc_link_ddc.h"
+#include "link_hwss.h"
+#include "stream_encoder.h"
+#include "link_encoder.h"
+#include "hw_sequencer.h"
+#include "fixed31_32.h"
+
+
+#define LINK_INFO(...) \
+	dal_logger_write(dc_ctx->logger, \
+		LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_HOTPLUG, \
+		__VA_ARGS__)
+
+
+/*******************************************************************************
+ * Private structures
+ ******************************************************************************/
+
+enum {
+	LINK_RATE_REF_FREQ_IN_MHZ = 27,
+	PEAK_FACTOR_X1000 = 1006
+};
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static void destruct(struct core_link *link)
+{
+	if (link->ddc)
+		dal_ddc_service_destroy(&link->ddc);
+
+	if(link->link_enc)
+		link->ctx->dc->res_pool.funcs->link_enc_destroy(&link->link_enc);
+}
+
+/*
+ *  Function: program_hpd_filter
+ *
+ *  @brief
+ *     Programs HPD filter on associated HPD line
+ *
+ *  @param [in] delay_on_connect_in_ms: Connect filter timeout
+ *  @param [in] delay_on_disconnect_in_ms: Disconnect filter timeout
+ *
+ *  @return
+ *     true on success, false otherwise
+ */
+static bool program_hpd_filter(
+	const struct core_link *link)
+{
+	bool result = false;
+
+	struct irq *hpd;
+
+	int delay_on_connect_in_ms = 0;
+	int delay_on_disconnect_in_ms = 0;
+
+	/* Verify feature is supported */
+	switch (link->public.connector_signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		/* Program hpd filter */
+		delay_on_connect_in_ms = 500;
+		delay_on_disconnect_in_ms = 100;
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		/* Program hpd filter to allow DP signal to settle */
+		delay_on_connect_in_ms = 20;
+		delay_on_disconnect_in_ms = 0;
+		break;
+	case SIGNAL_TYPE_LVDS:
+	case SIGNAL_TYPE_EDP:
+	default:
+		/* Don't program hpd filter */
+		return false;
+	}
+
+	/* Obtain HPD handle */
+	hpd = dal_adapter_service_obtain_hpd_irq(
+		link->adapter_srv, link->link_id);
+
+	if (!hpd)
+		return result;
+
+	/* Setup HPD filtering */
+	if (dal_irq_open(hpd) == GPIO_RESULT_OK) {
+		struct gpio_hpd_config config;
+
+		config.delay_on_connect = delay_on_connect_in_ms;
+		config.delay_on_disconnect = delay_on_disconnect_in_ms;
+
+		dal_irq_setup_hpd_filter(hpd, &config);
+
+		dal_irq_close(hpd);
+
+		result = true;
+	} else {
+		ASSERT_CRITICAL(false);
+	}
+
+	/* Release HPD handle */
+	dal_adapter_service_release_irq(link->adapter_srv, hpd);
+
+	return result;
+}
+
+static bool detect_sink(struct core_link *link, enum dc_connection_type *type)
+{
+	uint32_t is_hpd_high = 0;
+	struct irq *hpd_pin;
+
+	/* todo: may need to lock gpio access */
+	hpd_pin = dal_adapter_service_obtain_hpd_irq(
+			link->adapter_srv,
+			link->link_id);
+	if (hpd_pin == NULL)
+		goto hpd_gpio_failure;
+
+	dal_irq_open(hpd_pin);
+	dal_irq_get_value(hpd_pin, &is_hpd_high);
+	dal_irq_close(hpd_pin);
+	dal_adapter_service_release_irq(
+		link->adapter_srv,
+		hpd_pin);
+
+	if (is_hpd_high) {
+		*type = dc_connection_single;
+		/* TODO: need to do the actual detection */
+	} else {
+		*type = dc_connection_none;
+	}
+
+	return true;
+
+hpd_gpio_failure:
+	return false;
+}
+
+
+enum ddc_transaction_type get_ddc_transaction_type(
+		enum signal_type sink_signal)
+{
+	enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE;
+
+
+	switch (sink_signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_LVDS:
+	case SIGNAL_TYPE_RGB:
+		transaction_type = DDC_TRANSACTION_TYPE_I2C;
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_EDP:
+		transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		/* MST does not use I2COverAux, but there is the
+		 * SPECIAL use case for "immediate dwnstrm device
+		 * access" (EPR#370830). */
+		transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+		break;
+
+	default:
+		break;
+	}
+
+
+	return transaction_type;
+}
+
+static enum signal_type get_basic_signal_type(
+	struct graphics_object_id encoder,
+	struct graphics_object_id downstream)
+{
+	if (downstream.type == OBJECT_TYPE_CONNECTOR) {
+		switch (downstream.id) {
+		case CONNECTOR_ID_SINGLE_LINK_DVII:
+			switch (encoder.id) {
+			case ENCODER_ID_INTERNAL_DAC1:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+			case ENCODER_ID_INTERNAL_DAC2:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+				return SIGNAL_TYPE_RGB;
+			default:
+				return SIGNAL_TYPE_DVI_SINGLE_LINK;
+			}
+		break;
+		case CONNECTOR_ID_DUAL_LINK_DVII:
+		{
+			switch (encoder.id) {
+			case ENCODER_ID_INTERNAL_DAC1:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+			case ENCODER_ID_INTERNAL_DAC2:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+				return SIGNAL_TYPE_RGB;
+			default:
+				return SIGNAL_TYPE_DVI_DUAL_LINK;
+			}
+		}
+		break;
+		case CONNECTOR_ID_SINGLE_LINK_DVID:
+			return SIGNAL_TYPE_DVI_SINGLE_LINK;
+		case CONNECTOR_ID_DUAL_LINK_DVID:
+			return SIGNAL_TYPE_DVI_DUAL_LINK;
+		case CONNECTOR_ID_VGA:
+			return SIGNAL_TYPE_RGB;
+		case CONNECTOR_ID_HDMI_TYPE_A:
+			return SIGNAL_TYPE_HDMI_TYPE_A;
+		case CONNECTOR_ID_LVDS:
+			return SIGNAL_TYPE_LVDS;
+		case CONNECTOR_ID_DISPLAY_PORT:
+			return SIGNAL_TYPE_DISPLAY_PORT;
+		case CONNECTOR_ID_EDP:
+			return SIGNAL_TYPE_EDP;
+		default:
+			return SIGNAL_TYPE_NONE;
+		}
+	} else if (downstream.type == OBJECT_TYPE_ENCODER) {
+		switch (downstream.id) {
+		case ENCODER_ID_EXTERNAL_NUTMEG:
+		case ENCODER_ID_EXTERNAL_TRAVIS:
+			return SIGNAL_TYPE_DISPLAY_PORT;
+		default:
+			return SIGNAL_TYPE_NONE;
+		}
+	}
+
+	return SIGNAL_TYPE_NONE;
+}
+
+/*
+ * @brief
+ * Check whether there is a dongle on DP connector
+ */
+static bool is_dp_sink_present(struct core_link *link)
+{
+	enum gpio_result gpio_result;
+	uint32_t clock_pin = 0;
+	uint32_t data_pin = 0;
+
+	struct ddc *ddc;
+
+	enum connector_id connector_id =
+		dal_graphics_object_id_get_connector_id(link->link_id);
+
+	bool present =
+		((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
+		(connector_id == CONNECTOR_ID_EDP));
+
+	ddc = dal_adapter_service_obtain_ddc(link->adapter_srv, link->link_id);
+
+	if (!ddc)
+		return present;
+
+	/* Open GPIO and set it to I2C mode */
+	/* Note: this GpioMode_Input will be converted
+	 * to GpioConfigType_I2cAuxDualMode in GPIO component,
+	 * which indicates we need additional delay */
+
+	if (GPIO_RESULT_OK != dal_ddc_open(
+		ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
+		dal_adapter_service_release_ddc(link->adapter_srv, ddc);
+
+		return present;
+	}
+
+	/* Read GPIO: DP sink is present if both clock and data pins are zero */
+	/* [anaumov] in DAL2, there was no check for GPIO failure */
+
+	gpio_result = dal_ddc_get_clock(ddc, &clock_pin);
+	ASSERT(gpio_result == GPIO_RESULT_OK);
+
+	if (gpio_result == GPIO_RESULT_OK)
+		if (link->link_enc->features.flags.bits.
+						DP_SINK_DETECT_POLL_DATA_PIN)
+			gpio_result = dal_ddc_get_data(ddc, &data_pin);
+
+	present = (gpio_result == GPIO_RESULT_OK) && !(clock_pin || data_pin);
+
+	dal_ddc_close(ddc);
+
+	dal_adapter_service_release_ddc(link->adapter_srv, ddc);
+
+	return present;
+}
+
+/*
+ * @brief
+ * Detect output sink type
+ */
+static enum signal_type link_detect_sink(struct core_link *link)
+{
+	enum signal_type result = get_basic_signal_type(
+		link->link_enc->id, link->link_id);
+
+	/* Internal digital encoder will detect only dongles
+	 * that require digital signal */
+
+	/* Detection mechanism is different
+	 * for different native connectors.
+	 * LVDS connector supports only LVDS signal;
+	 * PCIE is a bus slot, the actual connector needs to be detected first;
+	 * eDP connector supports only eDP signal;
+	 * HDMI should check straps for audio */
+
+	/* PCIE detects the actual connector on add-on board */
+
+	if (link->link_id.id == CONNECTOR_ID_PCIE) {
+		/* ZAZTODO implement PCIE add-on card detection */
+	}
+
+	switch (link->link_id.id) {
+	case CONNECTOR_ID_HDMI_TYPE_A: {
+		/* check audio support:
+		 * if native HDMI is not supported, switch to DVI */
+		union audio_support audio_support =
+			dal_adapter_service_get_audio_support(
+				link->adapter_srv);
+
+		if (!audio_support.bits.HDMI_AUDIO_NATIVE)
+			if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A)
+				result = SIGNAL_TYPE_DVI_SINGLE_LINK;
+	}
+	break;
+	case CONNECTOR_ID_DISPLAY_PORT: {
+
+		/* Check whether DP signal detected: if not -
+		 * we assume signal is DVI; it could be corrected
+		 * to HDMI after dongle detection */
+		if (!is_dp_sink_present(link))
+			result = SIGNAL_TYPE_DVI_SINGLE_LINK;
+	}
+	break;
+	default:
+	break;
+	}
+
+	return result;
+}
+
+static enum signal_type decide_signal_from_strap_and_dongle_type(
+		enum display_dongle_type dongle_type,
+		union audio_support *audio_support)
+{
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+
+	switch (dongle_type) {
+	case DISPLAY_DONGLE_DP_HDMI_DONGLE:
+		if (audio_support->bits.HDMI_AUDIO_ON_DONGLE)
+			signal =  SIGNAL_TYPE_HDMI_TYPE_A;
+		else
+			signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	case DISPLAY_DONGLE_DP_DVI_DONGLE:
+		signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE:
+		if (audio_support->bits.HDMI_AUDIO_NATIVE)
+			signal =  SIGNAL_TYPE_HDMI_TYPE_A;
+		else
+			signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	default:
+		signal = SIGNAL_TYPE_NONE;
+		break;
+	}
+
+	return signal;
+}
+
+static enum signal_type dp_passive_dongle_detection(
+		struct ddc_service *ddc,
+		struct display_sink_capability *sink_cap,
+		union audio_support *audio_support)
+{
+	/* TODO:These 2 functions should be protected for upstreaming purposes
+	 * in case hackers want to save 10 cents hdmi license fee
+	 */
+	dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
+						ddc, sink_cap);
+	return decide_signal_from_strap_and_dongle_type(
+			sink_cap->dongle_type,
+			audio_support);
+}
+
+static void link_disconnect_sink(struct core_link *link)
+{
+	if (link->public.local_sink) {
+		dc_sink_release(link->public.local_sink);
+		link->public.local_sink = NULL;
+	}
+
+	link->dpcd_sink_count = 0;
+}
+
+static enum dc_edid_status read_edid(
+	struct core_link *link,
+	struct core_sink *sink)
+{
+	uint32_t edid_retry = 3;
+	enum dc_edid_status edid_status;
+
+	/* some dongles read edid incorrectly the first time,
+	 * do check sum and retry to make sure read correct edid.
+	 */
+	do {
+		sink->public.dc_edid.length =
+				dal_ddc_service_edid_query(link->ddc);
+
+		if (0 == sink->public.dc_edid.length)
+			return EDID_NO_RESPONSE;
+
+		dal_ddc_service_get_edid_buf(link->ddc,
+				sink->public.dc_edid.raw_edid);
+		edid_status = dm_helpers_parse_edid_caps(
+				sink->ctx,
+				&sink->public.dc_edid,
+				&sink->public.edid_caps);
+		--edid_retry;
+		if (edid_status == EDID_BAD_CHECKSUM)
+			dal_logger_write(link->ctx->logger,
+					LOG_MAJOR_WARNING,
+					LOG_MINOR_DETECTION_EDID_PARSER,
+					"Bad EDID checksum, retry remain: %d\n",
+					edid_retry);
+	} while (edid_status == EDID_BAD_CHECKSUM && edid_retry > 0);
+
+	return edid_status;
+}
+
+static void detect_dp(
+	struct core_link *link,
+	struct display_sink_capability *sink_caps,
+	bool *converter_disable_audio,
+	union audio_support *audio_support,
+	bool boot)
+{
+	sink_caps->signal = link_detect_sink(link);
+	sink_caps->transaction_type =
+		get_ddc_transaction_type(sink_caps->signal);
+
+	if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
+		sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
+		detect_dp_sink_caps(link);
+
+		/* DP active dongles */
+		if (is_dp_active_dongle(link)) {
+			if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
+				link->public.type = dc_connection_none;
+				/*
+				 * active dongle unplug processing for short irq
+				 */
+				link_disconnect_sink(link);
+				return;
+			}
+
+			if (link->dpcd_caps.dongle_type !=
+			DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
+				*converter_disable_audio = true;
+			}
+		}
+		if (is_mst_supported(link)) {
+			sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
+
+			/*
+			 * This call will initiate MST topology discovery. Which
+			 * will detect MST ports and add new DRM connector DRM
+			 * framework. Then read EDID via remote i2c over aux. In
+			 * the end, will notify DRM detect result and save EDID
+			 * into DRM framework.
+			 *
+			 * .detect is called by .fill_modes.
+			 * .fill_modes is called by user mode ioctl
+			 * DRM_IOCTL_MODE_GETCONNECTOR.
+			 *
+			 * .get_modes is called by .fill_modes.
+			 *
+			 * call .get_modes, AMDGPU DM implementation will create
+			 * new dc_sink and add to dc_link. For long HPD plug
+			 * in/out, MST has its own handle.
+			 *
+			 * Therefore, just after dc_create, link->sink is not
+			 * created for MST until user mode app calls
+			 * DRM_IOCTL_MODE_GETCONNECTOR.
+			 *
+			 * Need check ->sink usages in case ->sink = NULL
+			 * TODO: s3 resume check
+			 */
+
+			if (dm_helpers_dp_mst_start_top_mgr(
+				link->ctx,
+				&link->public, boot)) {
+				link->public.type = dc_connection_mst_branch;
+			} else {
+				/* MST not supported */
+				sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
+			}
+		}
+	} else {
+		/* DP passive dongles */
+		sink_caps->signal = dp_passive_dongle_detection(link->ddc,
+				sink_caps,
+				audio_support);
+	}
+}
+
+bool dc_link_detect(const struct dc_link *dc_link, bool boot)
+{
+	struct core_link *link = DC_LINK_TO_LINK(dc_link);
+	struct dc_sink_init_data sink_init_data = { 0 };
+	struct display_sink_capability sink_caps = { 0 };
+	uint8_t i;
+	bool converter_disable_audio = false;
+	union audio_support audio_support =
+		dal_adapter_service_get_audio_support(
+			link->adapter_srv);
+	enum dc_edid_status edid_status;
+	struct dc_context *dc_ctx = link->ctx;
+	struct dc_sink *dc_sink;
+	struct core_sink *sink = NULL;
+	enum dc_connection_type new_connection_type = dc_connection_none;
+
+	if (link->public.connector_signal == SIGNAL_TYPE_VIRTUAL)
+		return false;
+
+	if (false == detect_sink(link, &new_connection_type)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	link_disconnect_sink(link);
+
+	if (new_connection_type != dc_connection_none) {
+		link->public.type = new_connection_type;
+
+		/* From Disconnected-to-Connected. */
+		switch (link->public.connector_signal) {
+		case SIGNAL_TYPE_HDMI_TYPE_A: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			if (audio_support.bits.HDMI_AUDIO_NATIVE)
+				sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+			else
+				sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+			break;
+		}
+
+		case SIGNAL_TYPE_DVI_SINGLE_LINK: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+			break;
+		}
+
+		case SIGNAL_TYPE_DVI_DUAL_LINK: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+			break;
+		}
+
+		case SIGNAL_TYPE_EDP: {
+			detect_dp_sink_caps(link);
+			sink_caps.transaction_type =
+				DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+			sink_caps.signal = SIGNAL_TYPE_EDP;
+			break;
+		}
+
+		case SIGNAL_TYPE_DISPLAY_PORT: {
+			detect_dp(
+				link,
+				&sink_caps,
+				&converter_disable_audio,
+				&audio_support, boot);
+
+			/* Active dongle downstream unplug */
+			if (link->public.type == dc_connection_none)
+				return true;
+
+			if (link->public.type == dc_connection_mst_branch) {
+				LINK_INFO("link=%d, mst branch is now Connected\n",
+					link->public.link_index);
+				return false;
+			}
+
+			break;
+		}
+
+		default:
+			DC_ERROR("Invalid connector type! signal:%d\n",
+				link->public.connector_signal);
+			return false;
+		} /* switch() */
+
+		if (link->dpcd_caps.sink_count.bits.SINK_COUNT)
+			link->dpcd_sink_count = link->dpcd_caps.sink_count.
+					bits.SINK_COUNT;
+			else
+				link->dpcd_sink_count = 1;
+
+
+		dal_ddc_service_set_transaction_type(
+						link->ddc,
+						sink_caps.transaction_type);
+
+		sink_init_data.link = &link->public;
+		sink_init_data.sink_signal = sink_caps.signal;
+		sink_init_data.dongle_max_pix_clk =
+			sink_caps.max_hdmi_pixel_clock;
+		sink_init_data.converter_disable_audio =
+			converter_disable_audio;
+
+		dc_sink = dc_sink_create(&sink_init_data);
+		if (!dc_sink) {
+			DC_ERROR("Failed to create sink!\n");
+			return false;
+		}
+
+		sink = DC_SINK_TO_CORE(dc_sink);
+		link->public.local_sink = &sink->public;
+
+		edid_status = read_edid(link, sink);
+
+		switch (edid_status) {
+		case EDID_BAD_CHECKSUM:
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_DETECTION_EDID_PARSER,
+				"EDID checksum invalid.\n");
+			break;
+		case EDID_NO_RESPONSE:
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_DETECTION_EDID_PARSER,
+				"No EDID read.\n");
+			return false;
+
+		default:
+			break;
+		}
+
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_DETECTION,
+			LOG_MINOR_DETECTION_EDID_PARSER,
+			"%s: "
+			"manufacturer_id = %X, "
+			"product_id = %X, "
+			"serial_number = %X, "
+			"manufacture_week = %d, "
+			"manufacture_year = %d, "
+			"display_name = %s, "
+			"speaker_flag = %d, "
+			"audio_mode_count = %d\n",
+			__func__,
+			sink->public.edid_caps.manufacturer_id,
+			sink->public.edid_caps.product_id,
+			sink->public.edid_caps.serial_number,
+			sink->public.edid_caps.manufacture_week,
+			sink->public.edid_caps.manufacture_year,
+			sink->public.edid_caps.display_name,
+			sink->public.edid_caps.speaker_flags,
+			sink->public.edid_caps.audio_mode_count);
+
+		for (i = 0; i < sink->public.edid_caps.audio_mode_count; i++) {
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_DETECTION,
+				LOG_MINOR_DETECTION_EDID_PARSER,
+				"%s: mode number = %d, "
+				"format_code = %d, "
+				"channel_count = %d, "
+				"sample_rate = %d, "
+				"sample_size = %d\n",
+				__func__,
+				i,
+				sink->public.edid_caps.audio_modes[i].format_code,
+				sink->public.edid_caps.audio_modes[i].channel_count,
+				sink->public.edid_caps.audio_modes[i].sample_rate,
+				sink->public.edid_caps.audio_modes[i].sample_size);
+		}
+
+	} else {
+		/* From Connected-to-Disconnected. */
+		if (link->public.type == dc_connection_mst_branch) {
+			LINK_INFO("link=%d, mst branch is now Disconnected\n",
+				link->public.link_index);
+			dm_helpers_dp_mst_stop_top_mgr(link->ctx, &link->public);
+		}
+
+		link->public.type = dc_connection_none;
+		sink_caps.signal = SIGNAL_TYPE_NONE;
+	}
+
+	LINK_INFO("link=%d, dc_sink_in=%p is now %s\n",
+		link->public.link_index, &sink->public,
+		(sink_caps.signal == SIGNAL_TYPE_NONE ?
+			"Disconnected":"Connected"));
+
+	return true;
+}
+
+static enum hpd_source_id get_hpd_line(
+		struct core_link *link,
+		struct adapter_service *as)
+{
+	struct irq *hpd;
+	enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN;
+
+	hpd = dal_adapter_service_obtain_hpd_irq(as, link->link_id);
+
+	if (hpd) {
+		switch (dal_irq_get_source(hpd)) {
+		case DC_IRQ_SOURCE_HPD1:
+			hpd_id = HPD_SOURCEID1;
+		break;
+		case DC_IRQ_SOURCE_HPD2:
+			hpd_id = HPD_SOURCEID2;
+		break;
+		case DC_IRQ_SOURCE_HPD3:
+			hpd_id = HPD_SOURCEID3;
+		break;
+		case DC_IRQ_SOURCE_HPD4:
+			hpd_id = HPD_SOURCEID4;
+		break;
+		case DC_IRQ_SOURCE_HPD5:
+			hpd_id = HPD_SOURCEID5;
+		break;
+		case DC_IRQ_SOURCE_HPD6:
+			hpd_id = HPD_SOURCEID6;
+		break;
+		default:
+			BREAK_TO_DEBUGGER();
+		break;
+		}
+
+		dal_adapter_service_release_irq(as, hpd);
+	}
+
+	return hpd_id;
+}
+
+static enum channel_id get_ddc_line(struct core_link *link, struct adapter_service *as)
+{
+	struct ddc *ddc;
+	enum channel_id channel = CHANNEL_ID_UNKNOWN;
+
+	ddc = dal_adapter_service_obtain_ddc(as, link->link_id);
+
+	if (ddc) {
+		switch (dal_ddc_get_line(ddc)) {
+		case GPIO_DDC_LINE_DDC1:
+			channel = CHANNEL_ID_DDC1;
+			break;
+		case GPIO_DDC_LINE_DDC2:
+			channel = CHANNEL_ID_DDC2;
+			break;
+		case GPIO_DDC_LINE_DDC3:
+			channel = CHANNEL_ID_DDC3;
+			break;
+		case GPIO_DDC_LINE_DDC4:
+			channel = CHANNEL_ID_DDC4;
+			break;
+		case GPIO_DDC_LINE_DDC5:
+			channel = CHANNEL_ID_DDC5;
+			break;
+		case GPIO_DDC_LINE_DDC6:
+			channel = CHANNEL_ID_DDC6;
+			break;
+		case GPIO_DDC_LINE_DDC_VGA:
+			channel = CHANNEL_ID_DDC_VGA;
+			break;
+		case GPIO_DDC_LINE_I2C_PAD:
+			channel = CHANNEL_ID_I2C_PAD;
+			break;
+		default:
+			BREAK_TO_DEBUGGER();
+			break;
+		}
+
+		dal_adapter_service_release_ddc(as, ddc);
+	}
+
+	return channel;
+}
+
+static enum transmitter translate_encoder_to_transmitter(
+	struct graphics_object_id encoder)
+{
+	switch (encoder.id) {
+	case ENCODER_ID_INTERNAL_UNIPHY:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_A;
+		case ENUM_ID_2:
+			return TRANSMITTER_UNIPHY_B;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_INTERNAL_UNIPHY1:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_C;
+		case ENUM_ID_2:
+			return TRANSMITTER_UNIPHY_D;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_INTERNAL_UNIPHY2:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_E;
+		case ENUM_ID_2:
+			return TRANSMITTER_UNIPHY_F;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_INTERNAL_UNIPHY3:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_G;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_EXTERNAL_NUTMEG:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_NUTMEG_CRT;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_EXTERNAL_TRAVIS:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_TRAVIS_CRT;
+		case ENUM_ID_2:
+			return TRANSMITTER_TRAVIS_LCD;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	default:
+		return TRANSMITTER_UNKNOWN;
+	}
+}
+
+
+static bool construct(
+	struct core_link *link,
+	const struct link_init_data *init_params)
+{
+	uint8_t i;
+	struct adapter_service *as = init_params->adapter_srv;
+	struct irq *hpd_gpio = NULL;
+	struct ddc_service_init_data ddc_service_init_data = { 0 };
+	struct dc_context *dc_ctx = init_params->ctx;
+	struct encoder_init_data enc_init_data = { 0 };
+	struct integrated_info info = {{{ 0 }}};
+
+	link->dc = init_params->dc;
+	link->adapter_srv = as;
+	link->ctx = dc_ctx;
+	link->public.link_index = init_params->link_index;
+
+	link->link_id = dal_adapter_service_get_connector_obj_id(
+			as,
+			init_params->connector_index);
+
+	if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
+		dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d!\n",
+				__func__, init_params->connector_index);
+		goto create_fail;
+	}
+
+	switch (link->link_id.id) {
+	case CONNECTOR_ID_HDMI_TYPE_A:
+		link->public.connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
+		break;
+	case CONNECTOR_ID_SINGLE_LINK_DVID:
+	case CONNECTOR_ID_SINGLE_LINK_DVII:
+		link->public.connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	case CONNECTOR_ID_DUAL_LINK_DVID:
+	case CONNECTOR_ID_DUAL_LINK_DVII:
+		link->public.connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+		break;
+	case CONNECTOR_ID_DISPLAY_PORT:
+		link->public.connector_signal =	SIGNAL_TYPE_DISPLAY_PORT;
+		hpd_gpio = dal_adapter_service_obtain_hpd_irq(
+					as,
+					link->link_id);
+
+		if (hpd_gpio != NULL) {
+			link->public.irq_source_hpd_rx =
+					dal_irq_get_rx_source(hpd_gpio);
+			dal_adapter_service_release_irq(
+					as, hpd_gpio);
+		}
+
+		break;
+	case CONNECTOR_ID_EDP:
+		link->public.connector_signal = SIGNAL_TYPE_EDP;
+		hpd_gpio = dal_adapter_service_obtain_hpd_irq(
+					as,
+					link->link_id);
+
+		if (hpd_gpio != NULL) {
+			link->public.irq_source_hpd_rx =
+					dal_irq_get_rx_source(hpd_gpio);
+			dal_adapter_service_release_irq(
+					as, hpd_gpio);
+		}
+		break;
+	default:
+		dal_logger_write(dc_ctx->logger,
+			LOG_MAJOR_WARNING, LOG_MINOR_TM_LINK_SRV,
+			"Unsupported Connector type:%d!\n", link->link_id.id);
+		goto create_fail;
+	}
+
+	/* TODO: #DAL3 Implement id to str function.*/
+	LINK_INFO("Connector[%d] description:"
+			"signal %d\n",
+			init_params->connector_index,
+			link->public.connector_signal);
+
+	hpd_gpio = dal_adapter_service_obtain_hpd_irq(as, link->link_id);
+
+	if (hpd_gpio != NULL) {
+		link->public.irq_source_hpd = dal_irq_get_source(hpd_gpio);
+		dal_adapter_service_release_irq(as, hpd_gpio);
+	}
+
+	ddc_service_init_data.as = as;
+	ddc_service_init_data.ctx = link->ctx;
+	ddc_service_init_data.id = link->link_id;
+	link->ddc = dal_ddc_service_create(&ddc_service_init_data);
+
+	if (NULL == link->ddc) {
+		DC_ERROR("Failed to create ddc_service!\n");
+		goto create_fail;
+	}
+
+	enc_init_data.adapter_service = as;
+	enc_init_data.ctx = dc_ctx;
+	enc_init_data.encoder = dal_adapter_service_get_src_obj(
+							as, link->link_id, 0);
+	enc_init_data.connector = link->link_id;
+	enc_init_data.channel = get_ddc_line(link, as);
+	enc_init_data.hpd_source = get_hpd_line(link, as);
+	enc_init_data.transmitter =
+			translate_encoder_to_transmitter(enc_init_data.encoder);
+	link->link_enc = dc_ctx->dc->res_pool.funcs->link_enc_create(
+								&enc_init_data);
+
+	if( link->link_enc == NULL) {
+		DC_ERROR("Failed to create link encoder!\n");
+		goto create_fail;
+	}
+
+	dal_adapter_service_get_integrated_info(as, &info);
+
+	for (i = 0; ; i++) {
+		if (!dal_adapter_service_get_device_tag(
+				as, link->link_id, i, &link->device_tag)) {
+			DC_ERROR("Failed to find device tag!\n");
+			goto create_fail;
+		}
+
+		/* Look for device tag that matches connector signal,
+		 * CRT for rgb, LCD for other supported signal tyes
+		 */
+		if (!dal_adapter_service_is_device_id_supported(
+						as, link->device_tag.dev_id))
+			continue;
+		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT
+			&& link->public.connector_signal != SIGNAL_TYPE_RGB)
+			continue;
+		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD
+			&& link->public.connector_signal == SIGNAL_TYPE_RGB)
+			continue;
+		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_WIRELESS
+			&& link->public.connector_signal != SIGNAL_TYPE_WIRELESS)
+			continue;
+		break;
+	}
+
+	/* Look for channel mapping corresponding to connector and device tag */
+	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
+		struct external_display_path *path =
+			&info.ext_disp_conn_info.path[i];
+		if (path->device_connector_id.enum_id == link->link_id.enum_id
+			&& path->device_connector_id.id == link->link_id.id
+			&& path->device_connector_id.type == link->link_id.type
+			&& path->device_acpi_enum
+					== link->device_tag.acpi_device) {
+			link->ddi_channel_mapping = path->channel_mapping;
+			break;
+		}
+	}
+
+	/*
+	 * TODO check if GPIO programmed correctly
+	 *
+	 * If GPIO isn't programmed correctly HPD might not rise or drain
+	 * fast enough, leading to bounces.
+	 */
+	program_hpd_filter(link);
+
+	return true;
+
+create_fail:
+	return false;
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+struct core_link *link_create(const struct link_init_data *init_params)
+{
+	struct core_link *link =
+			dm_alloc(init_params->ctx, sizeof(*link));
+
+	if (NULL == link)
+		goto alloc_fail;
+
+	if (false == construct(link, init_params))
+		goto construct_fail;
+
+	return link;
+
+construct_fail:
+	dm_free(init_params->ctx, link);
+
+alloc_fail:
+	return NULL;
+}
+
+void link_destroy(struct core_link **link)
+{
+	destruct(*link);
+	dm_free((*link)->ctx, *link);
+	*link = NULL;
+}
+
+static void dpcd_configure_panel_mode(
+	struct core_link *link,
+	enum dp_panel_mode panel_mode)
+{
+	union dpcd_edp_config edp_config_set;
+	bool panel_mode_edp = false;
+
+	dm_memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
+
+	if (DP_PANEL_MODE_DEFAULT != panel_mode) {
+
+		switch (panel_mode) {
+		case DP_PANEL_MODE_EDP:
+		case DP_PANEL_MODE_SPECIAL:
+			panel_mode_edp = true;
+			break;
+
+		default:
+			break;
+		}
+
+		/*set edp panel mode in receiver*/
+		core_link_read_dpcd(
+			link,
+			DPCD_ADDRESS_EDP_CONFIG_SET,
+			&edp_config_set.raw,
+			sizeof(edp_config_set.raw));
+
+		if (edp_config_set.bits.PANEL_MODE_EDP
+			!= panel_mode_edp) {
+			enum ddc_result result = DDC_RESULT_UNKNOWN;
+
+			edp_config_set.bits.PANEL_MODE_EDP =
+			panel_mode_edp;
+			result = core_link_write_dpcd(
+				link,
+				DPCD_ADDRESS_EDP_CONFIG_SET,
+				&edp_config_set.raw,
+				sizeof(edp_config_set.raw));
+
+			ASSERT(result == DDC_RESULT_SUCESSFULL);
+		}
+	}
+	dal_logger_write(link->ctx->logger, LOG_MAJOR_DETECTION,
+			LOG_MINOR_DETECTION_DP_CAPS,
+			"Link: %d eDP panel mode supported: %d "
+			"eDP panel mode enabled: %d \n",
+			link->public.link_index,
+			link->dpcd_caps.panel_mode_edp,
+			panel_mode_edp);
+}
+
+static enum dc_status enable_link_dp(struct core_stream *stream)
+{
+	enum dc_status status;
+	bool skip_video_pattern;
+	struct core_link *link = stream->sink->link;
+	struct link_settings link_settings = {0};
+	enum dp_panel_mode panel_mode;
+
+	/* get link settings for video mode timing */
+	decide_link_settings(stream, &link_settings);
+	dp_enable_link_phy(
+		stream->sink->link,
+		stream->signal,
+		&link_settings);
+
+	panel_mode = dp_get_panel_mode(link);
+	dpcd_configure_panel_mode(link, panel_mode);
+
+	skip_video_pattern = true;
+
+	if (link_settings.link_rate == LINK_RATE_LOW)
+			skip_video_pattern = false;
+
+	if (perform_link_training(link, &link_settings, skip_video_pattern)) {
+		link->cur_link_settings = link_settings;
+		status = DC_OK;
+	}
+	else
+		status = DC_ERROR_UNEXPECTED;
+
+	return status;
+}
+
+static enum dc_status enable_link_dp_mst(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+
+	/* sink signal type after MST branch is MST. Multiple MST sinks
+	 * share one link. Link DP PHY is enable or training only once.
+	 */
+	if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
+		return DC_OK;
+
+	return enable_link_dp(stream);
+}
+
+static void enable_link_hdmi(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+
+	/* enable video output */
+	/* here we need to specify that encoder output settings
+	 * need to be calculated as for the set mode,
+	 * it will lead to querying dynamic link capabilities
+	 * which should be done before enable output */
+	uint32_t normalized_pix_clk = stream->public.timing.pix_clk_khz;
+	switch (stream->public.timing.display_color_depth) {
+	case COLOR_DEPTH_888:
+		break;
+	case COLOR_DEPTH_101010:
+		normalized_pix_clk = (normalized_pix_clk * 30) / 24;
+		break;
+	case COLOR_DEPTH_121212:
+		normalized_pix_clk = (normalized_pix_clk * 36) / 24;
+		break;
+	case COLOR_DEPTH_161616:
+		normalized_pix_clk = (normalized_pix_clk * 48) / 24;
+		break;
+	default:
+		break;
+	}
+
+	if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		dal_ddc_service_write_scdc_data(
+			stream->sink->link->ddc,
+			normalized_pix_clk,
+			stream->public.timing.flags.LTE_340MCSC_SCRAMBLE);
+
+	dm_memset(&stream->sink->link->cur_link_settings, 0,
+			sizeof(struct link_settings));
+
+	link->link_enc->funcs->enable_tmds_output(
+			link->link_enc,
+			stream->clock_source->id,
+			stream->public.timing.display_color_depth,
+			stream->signal == SIGNAL_TYPE_HDMI_TYPE_A,
+			stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK,
+			stream->public.timing.pix_clk_khz);
+
+	if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		dal_ddc_service_read_scdc_data(link->ddc);
+}
+
+/****************************enable_link***********************************/
+static enum dc_status enable_link(struct core_stream *stream)
+{
+	enum dc_status status = DC_ERROR_UNEXPECTED;
+	switch (stream->signal) {
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_EDP:
+		status = enable_link_dp(stream);
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		status = enable_link_dp_mst(stream);
+		dm_sleep_in_milliseconds(stream->ctx, 200);
+		break;
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		enable_link_hdmi(stream);
+		status = DC_OK;
+		break;
+	case SIGNAL_TYPE_VIRTUAL:
+		status = DC_OK;
+		break;
+	default:
+		break;
+	}
+
+	if (stream->audio && status == DC_OK) {
+		/* notify audio driver for audio modes of monitor */
+		dal_audio_enable_azalia_audio_jack_presence(stream->audio,
+				stream->stream_enc->id);
+
+		/* un-mute audio */
+		dal_audio_unmute(stream->audio, stream->stream_enc->id,
+				stream->signal);
+	}
+
+	return status;
+}
+
+static void disable_link(struct core_stream *stream)
+{
+	/* TODO  dp_set_hw_test_pattern */
+
+	/* here we need to specify that encoder output settings
+	 * need to be calculated as for the set mode,
+	 * it will lead to querying dynamic link capabilities
+	 * which should be done before enable output */
+
+	if (dc_is_dp_signal(stream->signal)) {
+		/* SST DP, eDP */
+		if (dc_is_dp_sst_signal(stream->signal))
+			dp_disable_link_phy(
+					stream->sink->link, stream->signal);
+		else {
+			dp_disable_link_phy_mst(
+					stream->sink->link, stream);
+		}
+	} else {
+		struct link_encoder *encoder =
+				stream->sink->link->link_enc;
+
+		encoder->funcs->disable_output(encoder, stream->signal);
+	}
+}
+
+enum dc_status dc_link_validate_mode_timing(
+		const struct core_sink *sink,
+		struct core_link *link,
+		const struct dc_crtc_timing *timing)
+{
+	uint32_t max_pix_clk = sink->dongle_max_pix_clk;
+
+	if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk)
+		return DC_EXCEED_DONGLE_MAX_CLK;
+
+	switch (sink->public.sink_signal) {
+		case SIGNAL_TYPE_DISPLAY_PORT:
+			if(!dp_validate_mode_timing(
+					link,
+					timing))
+				return DC_NO_DP_LINK_BANDWIDTH;
+			break;
+
+		default:
+			break;
+	}
+
+	return DC_OK;
+}
+
+bool dc_link_set_backlight_level(const struct dc_link *public, uint32_t level)
+{
+	struct core_link *link = DC_LINK_TO_CORE(public);
+	struct dc_context *ctx = link->ctx;
+
+	dal_logger_write(ctx->logger, LOG_MAJOR_BACKLIGHT,
+			LOG_MINOR_BACKLIGHT_INTERFACE,
+			"New Backlight level: %d (0x%X)\n", level, level);
+
+	link->link_enc->funcs->set_lcd_backlight_level(link->link_enc, level);
+
+	return true;
+}
+
+void core_link_resume(struct core_link *link)
+{
+	if (link->public.connector_signal != SIGNAL_TYPE_VIRTUAL)
+		program_hpd_filter(link);
+}
+
+static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream)
+{
+	struct link_settings *link_settings =
+			&stream->sink->link->cur_link_settings;
+	uint32_t link_rate_in_mbps =
+			link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ;
+	struct fixed31_32 mbps = dal_fixed31_32_from_int(
+			link_rate_in_mbps * link_settings->lane_count);
+
+	return dal_fixed31_32_div_int(mbps, 54);
+}
+
+static int get_color_depth(struct core_stream *stream)
+{
+	switch (stream->pix_clk_params.color_depth) {
+	case COLOR_DEPTH_666: return 6;
+	case COLOR_DEPTH_888: return 8;
+	case COLOR_DEPTH_101010: return 10;
+	case COLOR_DEPTH_121212: return 12;
+	case COLOR_DEPTH_141414: return 14;
+	case COLOR_DEPTH_161616: return 16;
+	default: return 0;
+	}
+}
+
+static struct fixed31_32 get_pbn_from_timing(struct core_stream *stream)
+{
+	uint32_t bpc;
+	uint64_t kbps;
+	struct fixed31_32 peak_kbps;
+	uint32_t numerator;
+	uint32_t denominator;
+
+	bpc = get_color_depth(stream);
+	kbps = stream->pix_clk_params.requested_pix_clk * bpc * 3;
+
+	/*
+	 * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
+	 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
+	 * common multiplier to render an integer PBN for all link rate/lane
+	 * counts combinations
+	 * calculate
+	 * peak_kbps *= (1006/1000)
+	 * peak_kbps *= (64/54)
+	 * peak_kbps *= 8    convert to bytes
+	 */
+
+	numerator = 64 * PEAK_FACTOR_X1000;
+	denominator = 54 * 8 * 1000 * 1000;
+	kbps *= numerator;
+	peak_kbps = dal_fixed31_32_from_fraction(kbps, denominator);
+
+	return peak_kbps;
+}
+
+static void update_mst_stream_alloc_table(
+	struct core_link *link,
+	struct core_stream *stream,
+	const struct dp_mst_stream_allocation_table *proposed_table)
+{
+	struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = {
+			{ 0 } };
+	struct link_mst_stream_allocation *dc_alloc;
+
+	int i;
+	int j;
+
+	/* if DRM proposed_table has more than one new payload */
+	ASSERT(proposed_table->stream_count -
+			link->mst_stream_alloc_table.stream_count < 2);
+
+	/* copy proposed_table to core_link, add stream encoder */
+	for (i = 0; i < proposed_table->stream_count; i++) {
+
+		for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) {
+			dc_alloc =
+			&link->mst_stream_alloc_table.stream_allocations[j];
+
+			if (dc_alloc->vcp_id ==
+				proposed_table->stream_allocations[i].vcp_id) {
+
+				work_table[i] = *dc_alloc;
+				break; /* exit j loop */
+			}
+		}
+
+		/* new vcp_id */
+		if (j == link->mst_stream_alloc_table.stream_count) {
+			work_table[i].vcp_id =
+				proposed_table->stream_allocations[i].vcp_id;
+			work_table[i].slot_count =
+				proposed_table->stream_allocations[i].slot_count;
+			work_table[i].stream_enc = stream->stream_enc;
+		}
+	}
+
+	/* update link->mst_stream_alloc_table with work_table */
+	link->mst_stream_alloc_table.stream_count =
+			proposed_table->stream_count;
+	for (i = 0; i < MAX_CONTROLLER_NUM; i++)
+		link->mst_stream_alloc_table.stream_allocations[i] =
+				work_table[i];
+}
+
+/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table
+ * because stream_encoder is not exposed to dm
+ */
+static enum dc_status allocate_mst_payload(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+	struct link_encoder *link_encoder = link->link_enc;
+	struct stream_encoder *stream_encoder = stream->stream_enc;
+	struct dp_mst_stream_allocation_table proposed_table = {0};
+	struct fixed31_32 avg_time_slots_per_mtp;
+	struct fixed31_32 pbn;
+	struct fixed31_32 pbn_per_slot;
+	uint8_t i;
+
+	/* enable_link_dp_mst already check link->enabled_stream_count
+	 * and stream is in link->stream[]. This is called during set mode,
+	 * stream_enc is available.
+	 */
+
+	/* get calculate VC payload for stream: stream_alloc */
+	dm_helpers_dp_mst_write_payload_allocation_table(
+		stream->ctx,
+		&stream->public,
+		&proposed_table,
+		true);
+
+	update_mst_stream_alloc_table(link, stream, &proposed_table);
+
+	dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_MST,
+			LOG_MINOR_MST_PROGRAMMING,
+			"%s  "
+			"stream_count: %d: \n ",
+			__func__,
+			link->mst_stream_alloc_table.stream_count);
+
+	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
+		dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_MST,
+		LOG_MINOR_MST_PROGRAMMING,
+		"stream_enc[%d]: 0x%x      "
+		"stream[%d].vcp_id: %d      "
+		"stream[%d].slot_count: %d\n",
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
+	}
+
+	ASSERT(proposed_table.stream_count > 0);
+
+	/*
+	 * temporary fix. Unplug of MST chain happened (two displays),
+	 * table is empty on first reset mode, and cause 0 division in
+	 * avg_time_slots_per_mtp calculation
+	 */
+
+	/* to be removed or debugged */
+	if (proposed_table.stream_count == 0)
+		return DC_OK;
+
+	/* program DP source TX for payload */
+	link_encoder->funcs->update_mst_stream_allocation_table(
+		link_encoder,
+		&link->mst_stream_alloc_table);
+
+	/* send down message */
+	dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+			stream->ctx,
+			&stream->public);
+
+	dm_helpers_dp_mst_send_payload_allocation(
+			stream->ctx,
+			&stream->public,
+			true);
+
+	/* slot X.Y for only current stream */
+	pbn_per_slot = get_pbn_per_slot(stream);
+	pbn = get_pbn_from_timing(stream);
+	avg_time_slots_per_mtp = dal_fixed31_32_div(pbn, pbn_per_slot);
+
+
+
+	stream_encoder->funcs->set_mst_bandwidth(
+		stream_encoder,
+		avg_time_slots_per_mtp);
+
+	return DC_OK;
+
+}
+
+static enum dc_status deallocate_mst_payload(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+	struct link_encoder *link_encoder = link->link_enc;
+	struct stream_encoder *stream_encoder = stream->stream_enc;
+	struct dp_mst_stream_allocation_table proposed_table = {0};
+	struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0);
+	uint8_t i;
+	bool mst_mode = (link->public.type == dc_connection_mst_branch);
+
+	/* deallocate_mst_payload is called before disable link. When mode or
+	 * disable/enable monitor, new stream is created which is not in link
+	 * stream[] yet. For this, payload is not allocated yet, so de-alloc
+	 * should not done. For new mode set, map_resources will get engine
+	 * for new stream, so stream_enc->id should be validated until here.
+	 */
+
+	/* slot X.Y */
+	stream_encoder->funcs->set_mst_bandwidth(
+		stream_encoder,
+		avg_time_slots_per_mtp);
+
+	/* TODO: which component is responsible for remove payload table? */
+	if (mst_mode)
+		dm_helpers_dp_mst_write_payload_allocation_table(
+				stream->ctx,
+				&stream->public,
+				&proposed_table,
+				false);
+
+	update_mst_stream_alloc_table(link, stream, &proposed_table);
+
+	dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_MST,
+			LOG_MINOR_MST_PROGRAMMING,
+			"%s"
+			"stream_count: %d: ",
+			__func__,
+			link->mst_stream_alloc_table.stream_count);
+
+	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
+		dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_MST,
+		LOG_MINOR_MST_PROGRAMMING,
+		"stream_enc[%d]: 0x%x      "
+		"stream[%d].vcp_id: %d      "
+		"stream[%d].slot_count: %d\n",
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
+	}
+
+	link_encoder->funcs->update_mst_stream_allocation_table(
+		link_encoder,
+		&link->mst_stream_alloc_table);
+
+	if (mst_mode) {
+		dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+			stream->ctx,
+			&stream->public);
+
+		dm_helpers_dp_mst_send_payload_allocation(
+			stream->ctx,
+			&stream->public,
+			false);
+	}
+
+	return DC_OK;
+}
+
+void core_link_enable_stream(
+		struct core_link *link,
+		struct core_stream *stream)
+{
+	struct dc *dc = stream->ctx->dc;
+
+	if (DC_OK != enable_link(stream)) {
+			BREAK_TO_DEBUGGER();
+			return;
+	}
+
+	dc->hwss.enable_stream(stream);
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+		allocate_mst_payload(stream);
+}
+
+void core_link_disable_stream(
+		struct core_link *link,
+		struct core_stream *stream)
+{
+	struct dc *dc = stream->ctx->dc;
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+		deallocate_mst_payload(stream);
+
+	dc->hwss.disable_stream(stream);
+
+	disable_link(stream);
+
+}
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
new file mode 100644
index 000000000000..62b8c264a593
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
@@ -0,0 +1,1151 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "include/adapter_service_interface.h"
+#include "include/ddc_service_types.h"
+#include "include/grph_object_id.h"
+#include "include/dpcd_defs.h"
+#include "include/logger_interface.h"
+#include "include/vector.h"
+
+#include "dc_link_ddc.h"
+
+#define AUX_POWER_UP_WA_DELAY 500
+#define I2C_OVER_AUX_DEFER_WA_DELAY 70
+
+/* CV smart dongle slave address for retrieving supported HDTV modes*/
+#define CV_SMART_DONGLE_ADDRESS 0x20
+/* DVI-HDMI dongle slave address for retrieving dongle signature*/
+#define DVI_HDMI_DONGLE_ADDRESS 0x68
+static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G";
+struct dvi_hdmi_dongle_signature_data {
+	int8_t vendor[3];/* "AMD" */
+	uint8_t version[2];
+	uint8_t size;
+	int8_t id[11];/* "6140063500G"*/
+};
+/* DP-HDMI dongle slave address for retrieving dongle signature*/
+#define DP_HDMI_DONGLE_ADDRESS 0x40
+static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
+#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04
+
+struct dp_hdmi_dongle_signature_data {
+	int8_t id[15];/* "DP-HDMI ADAPTOR"*/
+	uint8_t eot;/* end of transmition '\x4' */
+};
+
+/* Address range from 0x00 to 0x1F.*/
+#define DP_ADAPTOR_TYPE2_SIZE 0x20
+#define DP_ADAPTOR_TYPE2_REG_ID 0x10
+#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D
+/* Identifies adaptor as Dual-mode adaptor */
+#define DP_ADAPTOR_TYPE2_ID 0xA0
+/* MHz*/
+#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600
+/* MHz*/
+#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25
+/* kHZ*/
+#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000
+/* kHZ*/
+#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000
+
+#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW
+
+enum edid_read_result {
+	EDID_READ_RESULT_EDID_MATCH = 0,
+	EDID_READ_RESULT_EDID_MISMATCH,
+	EDID_READ_RESULT_CHECKSUM_READ_ERR,
+	EDID_READ_RESULT_VENDOR_READ_ERR
+};
+
+/* SCDC Address defines (HDMI 2.0)*/
+#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3
+#define HDMI_SCDC_ADDRESS  0x54
+#define HDMI_SCDC_SINK_VERSION 0x01
+#define HDMI_SCDC_SOURCE_VERSION 0x02
+#define HDMI_SCDC_UPDATE_0 0x10
+#define HDMI_SCDC_TMDS_CONFIG 0x20
+#define HDMI_SCDC_SCRAMBLER_STATUS 0x21
+#define HDMI_SCDC_CONFIG_0 0x30
+#define HDMI_SCDC_STATUS_FLAGS 0x40
+#define HDMI_SCDC_ERR_DETECT 0x50
+#define HDMI_SCDC_TEST_CONFIG 0xC0
+
+
+union hdmi_scdc_update_read_data {
+	uint8_t byte[2];
+	struct {
+		uint8_t STATUS_UPDATE:1;
+		uint8_t CED_UPDATE:1;
+		uint8_t RR_TEST:1;
+		uint8_t RESERVED:5;
+		uint8_t RESERVED2:8;
+	} fields;
+};
+
+union hdmi_scdc_status_flags_data {
+	uint8_t byte[2];
+	struct {
+		uint8_t CLOCK_DETECTED:1;
+		uint8_t CH0_LOCKED:1;
+		uint8_t CH1_LOCKED:1;
+		uint8_t CH2_LOCKED:1;
+		uint8_t RESERVED:4;
+		uint8_t RESERVED2:8;
+	} fields;
+};
+
+union hdmi_scdc_ced_data {
+	uint8_t byte[7];
+	struct {
+		uint8_t CH0_8LOW:8;
+		uint8_t CH0_7HIGH:7;
+		uint8_t CH0_VALID:1;
+		uint8_t CH1_8LOW:8;
+		uint8_t CH1_7HIGH:7;
+		uint8_t CH1_VALID:1;
+		uint8_t CH2_8LOW:8;
+		uint8_t CH2_7HIGH:7;
+		uint8_t CH2_VALID:1;
+		uint8_t CHECKSUM:8;
+	} fields;
+};
+
+union hdmi_scdc_test_config_Data {
+	uint8_t byte;
+	struct {
+		uint8_t TEST_READ_REQUEST_DELAY:7;
+		uint8_t TEST_READ_REQUEST: 1;
+	} fields;
+};
+
+
+
+union ddc_wa {
+	struct {
+		uint32_t DP_SKIP_POWER_OFF:1;
+		uint32_t DP_AUX_POWER_UP_WA_DELAY:1;
+	} bits;
+	uint32_t raw;
+};
+
+struct ddc_flags {
+	uint8_t EDID_QUERY_DONE_ONCE:1;
+	uint8_t IS_INTERNAL_DISPLAY:1;
+	uint8_t FORCE_READ_REPEATED_START:1;
+	uint8_t EDID_STRESS_READ:1;
+
+};
+
+struct ddc_service {
+	struct ddc *ddc_pin;
+	struct ddc_flags flags;
+	union ddc_wa wa;
+	enum ddc_transaction_type transaction_type;
+	enum display_dongle_type dongle_type;
+	struct dp_receiver_id_info dp_receiver_id_info;
+	struct adapter_service *as;
+	struct dc_context *ctx;
+
+	uint32_t address;
+	uint32_t edid_buf_len;
+	uint8_t edid_buf[MAX_EDID_BUFFER_SIZE];
+};
+
+struct i2c_payloads {
+	struct vector payloads;
+};
+
+struct aux_payloads {
+	struct vector payloads;
+};
+
+struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count)
+{
+	struct i2c_payloads *payloads;
+
+	payloads = dm_alloc(ctx, sizeof(struct i2c_payloads));
+
+	if (!payloads)
+		return NULL;
+
+	if (dal_vector_construct(
+		&payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
+		return payloads;
+
+	dm_free(ctx, payloads);
+	return NULL;
+
+}
+
+struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
+{
+	return (struct i2c_payload *)p->payloads.container;
+}
+
+uint32_t  dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
+{
+	return p->payloads.count;
+}
+
+void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p)
+{
+	if (!p || !*p)
+		return;
+	dal_vector_destruct(&(*p)->payloads);
+	dm_free((*p)->payloads.ctx, *p);
+	*p = NULL;
+
+}
+
+struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count)
+{
+	struct aux_payloads *payloads;
+
+	payloads = dm_alloc(ctx, sizeof(struct aux_payloads));
+
+	if (!payloads)
+		return NULL;
+
+	if (dal_vector_construct(
+		&payloads->payloads, ctx, count, sizeof(struct aux_payloads)))
+		return payloads;
+
+	dm_free(ctx, payloads);
+	return NULL;
+}
+
+struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p)
+{
+	return (struct aux_payload *)p->payloads.container;
+}
+
+uint32_t  dal_ddc_aux_payloads_get_count(struct aux_payloads *p)
+{
+	return p->payloads.count;
+}
+
+
+void dal_ddc_aux_payloads_destroy(struct aux_payloads **p)
+{
+	if (!p || !*p)
+		return;
+
+	dal_vector_destruct(&(*p)->payloads);
+	dm_free((*p)->payloads.ctx, *p);
+	*p = NULL;
+}
+
+#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+void dal_ddc_i2c_payloads_add(
+	struct i2c_payloads *payloads,
+	uint32_t address,
+	uint32_t len,
+	uint8_t *data,
+	bool write)
+{
+	uint32_t payload_size = EDID_SEGMENT_SIZE;
+	uint32_t pos;
+
+	for (pos = 0; pos < len; pos += payload_size) {
+		struct i2c_payload payload = {
+			.write = write,
+			.address = address,
+			.length = DDC_MIN(payload_size, len - pos),
+			.data = data + pos };
+		dal_vector_append(&payloads->payloads, &payload);
+	}
+
+}
+
+void dal_ddc_aux_payloads_add(
+	struct aux_payloads *payloads,
+	uint32_t address,
+	uint32_t len,
+	uint8_t *data,
+	bool write)
+{
+	uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE;
+	uint32_t pos;
+
+	for (pos = 0; pos < len; pos += payload_size) {
+		struct aux_payload payload = {
+			.i2c_over_aux = true,
+			.write = write,
+			.address = address,
+			.length = DDC_MIN(payload_size, len - pos),
+			.data = data + pos };
+		dal_vector_append(&payloads->payloads, &payload);
+	}
+}
+
+
+static bool construct(
+	struct ddc_service *ddc_service,
+	struct ddc_service_init_data *init_data)
+{
+	enum connector_id connector_id =
+		dal_graphics_object_id_get_connector_id(init_data->id);
+
+	ddc_service->ctx = init_data->ctx;
+	ddc_service->as = init_data->as;
+	ddc_service->ddc_pin = dal_adapter_service_obtain_ddc(
+			init_data->as, init_data->id);
+
+	ddc_service->flags.EDID_QUERY_DONE_ONCE = false;
+
+	ddc_service->flags.FORCE_READ_REPEATED_START =
+		dal_adapter_service_is_feature_supported(
+			FEATURE_DDC_READ_FORCE_REPEATED_START);
+
+	ddc_service->flags.EDID_STRESS_READ =
+			dal_adapter_service_is_feature_supported(
+				FEATURE_EDID_STRESS_READ);
+
+
+	ddc_service->flags.IS_INTERNAL_DISPLAY =
+		connector_id == CONNECTOR_ID_EDP ||
+		connector_id == CONNECTOR_ID_LVDS;
+
+	ddc_service->wa.raw = 0;
+	return true;
+}
+
+struct ddc_service *dal_ddc_service_create(
+	struct ddc_service_init_data *init_data)
+{
+	struct ddc_service *ddc_service;
+
+	ddc_service = dm_alloc(init_data->ctx, sizeof(struct ddc_service));
+
+	if (!ddc_service)
+		return NULL;
+
+	if (construct(ddc_service, init_data))
+		return ddc_service;
+
+	dm_free(init_data->ctx, ddc_service);
+	return NULL;
+}
+
+static void destruct(struct ddc_service *ddc)
+{
+	if (ddc->ddc_pin)
+		dal_adapter_service_release_ddc(ddc->as, ddc->ddc_pin);
+}
+
+void dal_ddc_service_destroy(struct ddc_service **ddc)
+{
+	if (!ddc || !*ddc) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+	destruct(*ddc);
+	dm_free((*ddc)->ctx, *ddc);
+	*ddc = NULL;
+}
+
+enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc)
+{
+	return DDC_SERVICE_TYPE_CONNECTOR;
+}
+
+void dal_ddc_service_set_transaction_type(
+	struct ddc_service *ddc,
+	enum ddc_transaction_type type)
+{
+	ddc->transaction_type = type;
+}
+
+bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc)
+{
+	switch (ddc->transaction_type) {
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+void ddc_service_set_dongle_type(struct ddc_service *ddc,
+		enum display_dongle_type dongle_type)
+{
+	ddc->dongle_type = dongle_type;
+}
+
+static uint32_t defer_delay_converter_wa(
+	struct ddc_service *ddc,
+	uint32_t defer_delay)
+{
+	struct dp_receiver_id_info dp_rec_info = {0};
+
+	if (dal_ddc_service_get_dp_receiver_id_info(ddc, &dp_rec_info) &&
+		(dp_rec_info.branch_id == DP_BRANCH_DEVICE_ID_4) &&
+		!dm_strncmp(dp_rec_info.branch_name,
+			DP_DVI_CONVERTER_ID_4,
+			sizeof(dp_rec_info.branch_name)))
+		return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ?
+			defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY;
+
+	return defer_delay;
+
+}
+
+#define DP_TRANSLATOR_DELAY 5
+
+static uint32_t get_defer_delay(struct ddc_service *ddc)
+{
+	uint32_t defer_delay = 0;
+
+	switch (ddc->transaction_type) {
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
+		if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) ||
+			(DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) ||
+			(DISPLAY_DONGLE_DP_HDMI_CONVERTER ==
+				ddc->dongle_type)) {
+
+			defer_delay = DP_TRANSLATOR_DELAY;
+
+			defer_delay =
+				defer_delay_converter_wa(ddc, defer_delay);
+
+		} else /*sink has a delay different from an Active Converter*/
+			defer_delay = 0;
+		break;
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
+		defer_delay = DP_TRANSLATOR_DELAY;
+		break;
+	default:
+		break;
+	}
+	return defer_delay;
+}
+
+static bool i2c_read(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t *buffer,
+	uint32_t len)
+{
+	uint8_t offs_data = 0;
+	struct i2c_payload payloads[2] = {
+		{
+		.write = true,
+		.address = address,
+		.length = 1,
+		.data = &offs_data },
+		{
+		.write = false,
+		.address = address,
+		.length = len,
+		.data = buffer } };
+
+	struct i2c_command command = {
+		.payloads = payloads,
+		.number_of_payloads = 2,
+		.engine = DDC_I2C_COMMAND_ENGINE,
+		.speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) };
+
+	return dal_i2caux_submit_i2c_command(
+		dal_adapter_service_get_i2caux(ddc->as),
+		ddc->ddc_pin,
+		&command);
+}
+
+static uint8_t aux_read_edid_block(
+	struct ddc_service *ddc,
+	uint8_t address,
+	uint8_t index,
+	uint8_t *buf)
+{
+	struct aux_command cmd = {
+		.payloads = NULL,
+		.number_of_payloads = 0,
+		.defer_delay = get_defer_delay(ddc),
+		.max_defer_write_retry = 0 };
+
+	uint8_t retrieved = 0;
+	uint8_t base_offset =
+		(index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE;
+	uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT;
+
+	for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE;
+		retrieved += DEFAULT_AUX_MAX_DATA_SIZE) {
+
+		uint8_t offset = base_offset + retrieved;
+
+		struct aux_payload payloads[3] = {
+			{
+			.i2c_over_aux = true,
+			.write = true,
+			.address = DDC_EDID_SEGMENT_ADDRESS,
+			.length = 1,
+			.data = &segment },
+			{
+			.i2c_over_aux = true,
+			.write = true,
+			.address = address,
+			.length = 1,
+			.data = &offset },
+			{
+			.i2c_over_aux = true,
+			.write = false,
+			.address = address,
+			.length = DEFAULT_AUX_MAX_DATA_SIZE,
+			.data = &buf[retrieved] } };
+
+		if (segment == 0) {
+			cmd.payloads = &payloads[1];
+			cmd.number_of_payloads = 2;
+		} else {
+			cmd.payloads = payloads;
+			cmd.number_of_payloads = 3;
+		}
+
+		if (!dal_i2caux_submit_aux_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd))
+			/* cannot read, break*/
+			break;
+	}
+
+	/* Reset segment to 0. Needed by some panels */
+	if (0 != segment) {
+		struct aux_payload payloads[1] = { {
+			.i2c_over_aux = true,
+			.write = true,
+			.address = DDC_EDID_SEGMENT_ADDRESS,
+			.length = 1,
+			.data = &segment } };
+		bool result = false;
+
+		segment = 0;
+
+		cmd.number_of_payloads = ARRAY_SIZE(payloads);
+		cmd.payloads = payloads;
+
+		result = dal_i2caux_submit_aux_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd);
+
+		if (false == result)
+			dal_logger_write(
+				ddc->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE,
+				"%s: Writing of EDID Segment (0x30) failed!\n",
+				__func__);
+	}
+
+	return retrieved;
+}
+
+static uint8_t i2c_read_edid_block(
+	struct ddc_service *ddc,
+	uint8_t address,
+	uint8_t index,
+	uint8_t *buf)
+{
+	bool ret = false;
+	uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) *
+		DDC_EDID_BLOCK_SIZE;
+	uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT;
+
+	struct i2c_command cmd = {
+		.payloads = NULL,
+		.number_of_payloads = 0,
+		.engine = DDC_I2C_COMMAND_ENGINE,
+		.speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) };
+
+	struct i2c_payload payloads[3] = {
+		{
+		.write = true,
+		.address = DDC_EDID_SEGMENT_ADDRESS,
+		.length = 1,
+		.data = &segment },
+		{
+		.write = true,
+		.address = address,
+		.length = 1,
+		.data = &offset },
+		{
+		.write = false,
+		.address = address,
+		.length = DDC_EDID_BLOCK_SIZE,
+		.data = buf } };
+/*
+ * Some I2C engines don't handle stop/start between write-offset and read-data
+ * commands properly. For those displays, we have to force the newer E-DDC
+ * behavior of repeated-start which can be enabled by runtime parameter. */
+/* Originally implemented for OnLive using NXP receiver chip */
+
+	if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) {
+		/* base block, use use DDC2B, submit as 2 commands */
+		cmd.payloads = &payloads[1];
+		cmd.number_of_payloads = 1;
+
+		if (dal_i2caux_submit_i2c_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd)) {
+
+			cmd.payloads = &payloads[2];
+			cmd.number_of_payloads = 1;
+
+			ret = dal_i2caux_submit_i2c_command(
+				dal_adapter_service_get_i2caux(ddc->as),
+				ddc->ddc_pin,
+				&cmd);
+		}
+
+	} else {
+		/*
+		 * extension block use E-DDC, submit as 1 command
+		 * or if repeated-start is forced by runtime parameter
+		 */
+		if (segment != 0) {
+			/* include segment offset in command*/
+			cmd.payloads = payloads;
+			cmd.number_of_payloads = 3;
+		} else {
+			/* we are reading first segment,
+			 * segment offset is not required */
+			cmd.payloads = &payloads[1];
+			cmd.number_of_payloads = 2;
+		}
+
+		ret = dal_i2caux_submit_i2c_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd);
+	}
+
+	return ret ? DDC_EDID_BLOCK_SIZE : 0;
+}
+
+static uint32_t query_edid_block(
+	struct ddc_service *ddc,
+	uint8_t address,
+	uint8_t index,
+	uint8_t *buf,
+	uint32_t size)
+{
+	uint32_t size_retrieved = 0;
+
+	if (size < DDC_EDID_BLOCK_SIZE)
+		return 0;
+
+	if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
+
+		ASSERT(index < 2);
+		size_retrieved =
+			aux_read_edid_block(ddc, address, index, buf);
+	} else {
+		size_retrieved =
+			i2c_read_edid_block(ddc, address, index, buf);
+	}
+
+	return size_retrieved;
+}
+
+#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261
+#define DDC_TEST_ACK_ADDRESS 0x260
+#define DDC_DPCD_EDID_TEST_ACK 0x04
+#define DDC_DPCD_EDID_TEST_MASK 0x04
+#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218
+
+/* AG TODO GO throug DM callback here like for DPCD */
+
+static void write_dp_edid_checksum(
+	struct ddc_service *ddc,
+	uint8_t checksum)
+{
+	uint8_t dpcd_data;
+
+	dal_ddc_service_read_dpcd_data(
+		ddc,
+		DDC_DPCD_TEST_REQUEST_ADDRESS,
+		&dpcd_data,
+		1);
+
+	if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) {
+
+		dal_ddc_service_write_dpcd_data(
+			ddc,
+			DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS,
+			&checksum,
+			1);
+
+		dpcd_data = DDC_DPCD_EDID_TEST_ACK;
+
+		dal_ddc_service_write_dpcd_data(
+			ddc,
+			DDC_TEST_ACK_ADDRESS,
+			&dpcd_data,
+			1);
+	}
+}
+
+uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc)
+{
+	uint32_t bytes_read = 0;
+	uint32_t ext_cnt = 0;
+
+	uint8_t address;
+	uint32_t i;
+
+	for (address = DDC_EDID_ADDRESS_START;
+		address <= DDC_EDID_ADDRESS_END; ++address) {
+
+		bytes_read = query_edid_block(
+			ddc,
+			address,
+			0,
+			ddc->edid_buf,
+			sizeof(ddc->edid_buf) - bytes_read);
+
+		if (bytes_read != DDC_EDID_BLOCK_SIZE)
+			continue;
+
+		/* get the number of ext blocks*/
+		ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET];
+
+		/* EDID 2.0, need to read 1 more block because EDID2.0 is
+		 * 256 byte in size*/
+		if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] ==
+			DDC_EDID_20_SIGNATURE)
+				ext_cnt = 1;
+
+		for (i = 0; i < ext_cnt; i++) {
+			/* read additional ext blocks accordingly */
+			bytes_read += query_edid_block(
+					ddc,
+					address,
+					i+1,
+					&ddc->edid_buf[bytes_read],
+					sizeof(ddc->edid_buf) - bytes_read);
+		}
+
+		/*this is special code path for DP compliance*/
+		if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type)
+			write_dp_edid_checksum(
+				ddc,
+				ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) +
+				DDC_EDID1X_CHECKSUM_OFFSET]);
+
+		/*remembers the address where we fetch the EDID from
+		 * for later signature check use */
+		ddc->address = address;
+
+		break;/* already read edid, done*/
+	}
+
+	ddc->edid_buf_len = bytes_read;
+	return bytes_read;
+}
+
+uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc)
+{
+	return ddc->edid_buf_len;
+}
+
+void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf)
+{
+	dm_memmove(edid_buf,
+			ddc->edid_buf, ddc->edid_buf_len);
+}
+
+void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
+	struct ddc_service *ddc,
+	struct display_sink_capability *sink_cap)
+{
+	uint8_t i;
+	bool is_valid_hdmi_signature;
+	enum display_dongle_type *dongle = &sink_cap->dongle_type;
+	uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE];
+	bool is_type2_dongle = false;
+	struct dp_hdmi_dongle_signature_data *dongle_signature;
+
+	/* Assume we have no valid DP passive dongle connected */
+	*dongle = DISPLAY_DONGLE_NONE;
+	sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
+
+	/* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
+	if (!i2c_read(
+		ddc,
+		DP_HDMI_DONGLE_ADDRESS,
+		type2_dongle_buf,
+		sizeof(type2_dongle_buf))) {
+		dal_logger_write(ddc->ctx->logger,
+			LOG_MAJOR_DCS,
+			LOG_MINOR_DCS_DONGLE_DETECTION,
+			"Detected DP-DVI dongle.\n");
+		*dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
+		sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
+		return;
+	}
+
+	/* Check if Type 2 dongle.*/
+	if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID)
+		is_type2_dongle = true;
+
+	dongle_signature =
+		(struct dp_hdmi_dongle_signature_data *)type2_dongle_buf;
+
+	is_valid_hdmi_signature = true;
+
+	/* Check EOT */
+	if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) {
+		is_valid_hdmi_signature = false;
+	}
+
+	/* Check signature */
+	for (i = 0; i < sizeof(dongle_signature->id); ++i) {
+		/* If its not the right signature,
+		 * skip mismatch in subversion byte.*/
+		if (dongle_signature->id[i] !=
+			dp_hdmi_dongle_signature_str[i] && i != 3) {
+
+			if (is_type2_dongle) {
+				is_valid_hdmi_signature = false;
+				break;
+			}
+
+		}
+	}
+
+	if (is_type2_dongle) {
+		uint32_t max_tmds_clk =
+			type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK];
+
+		max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2;
+
+		if (0 == max_tmds_clk ||
+				max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK ||
+				max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) {
+			dal_logger_write(ddc->ctx->logger,
+				LOG_MAJOR_DCS,
+				LOG_MINOR_DCS_DONGLE_DETECTION,
+				"Invalid Maximum TMDS clock");
+			*dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
+		} else {
+			if (is_valid_hdmi_signature == true) {
+				*dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
+				dal_logger_write(ddc->ctx->logger,
+					LOG_MAJOR_DCS,
+					LOG_MINOR_DCS_DONGLE_DETECTION,
+					"Detected Type 2 DP-HDMI Maximum TMDS "
+					"clock, max TMDS clock: %d MHz",
+					max_tmds_clk);
+			} else {
+				*dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
+				dal_logger_write(ddc->ctx->logger,
+					LOG_MAJOR_DCS,
+					LOG_MINOR_DCS_DONGLE_DETECTION,
+					"Detected Type 2 DP-HDMI (no valid HDMI"
+					" signature) Maximum TMDS clock, max "
+					"TMDS clock: %d MHz",
+					max_tmds_clk);
+			}
+
+			/* Multiply by 1000 to convert to kHz. */
+			sink_cap->max_hdmi_pixel_clock =
+				max_tmds_clk * 1000;
+		}
+
+	} else {
+		if (is_valid_hdmi_signature == true) {
+			dal_logger_write(ddc->ctx->logger,
+				LOG_MAJOR_DCS,
+				LOG_MINOR_DCS_DONGLE_DETECTION,
+				"Detected Type 1 DP-HDMI dongle.\n");
+			*dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
+		} else {
+			dal_logger_write(ddc->ctx->logger,
+				LOG_MAJOR_DCS,
+				LOG_MINOR_DCS_DONGLE_DETECTION,
+				"Detected Type 1 DP-HDMI dongle (no valid HDMI "
+				"signature).\n");
+
+			*dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
+		}
+	}
+
+	return;
+}
+
+enum {
+	DP_SINK_CAP_SIZE =
+		DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1
+};
+
+bool dal_ddc_service_query_ddc_data(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t *write_buf,
+	uint32_t write_size,
+	uint8_t *read_buf,
+	uint32_t read_size)
+{
+	bool ret;
+	uint32_t payload_size =
+		dal_ddc_service_is_in_aux_transaction_mode(ddc) ?
+			DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE;
+
+	uint32_t write_payloads =
+		(write_size + payload_size - 1) / payload_size;
+
+	uint32_t read_payloads =
+		(read_size + payload_size - 1) / payload_size;
+
+	uint32_t payloads_num = write_payloads + read_payloads;
+
+	if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE)
+		return false;
+
+	/*TODO: len of payload data for i2c and aux is uint8!!!!,
+	 *  but we want to read 256 over i2c!!!!*/
+	if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
+
+		struct aux_payloads *payloads =
+			dal_ddc_aux_payloads_create(ddc->ctx, payloads_num);
+
+		struct aux_command command = {
+			.payloads = dal_ddc_aux_payloads_get(payloads),
+			.number_of_payloads = 0,
+			.defer_delay = get_defer_delay(ddc),
+			.max_defer_write_retry = 0 };
+
+		dal_ddc_aux_payloads_add(
+			payloads, address, write_size, write_buf, true);
+
+		dal_ddc_aux_payloads_add(
+			payloads, address, read_size, read_buf, false);
+
+		command.number_of_payloads =
+			dal_ddc_aux_payloads_get_count(payloads);
+
+		ret = dal_i2caux_submit_aux_command(
+				dal_adapter_service_get_i2caux(ddc->as),
+				ddc->ddc_pin,
+				&command);
+
+		dal_ddc_aux_payloads_destroy(&payloads);
+
+	} else {
+		struct i2c_payloads *payloads =
+			dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
+
+		struct i2c_command command = {
+			.payloads = dal_ddc_i2c_payloads_get(payloads),
+			.number_of_payloads = 0,
+			.engine = DDC_I2C_COMMAND_ENGINE,
+			.speed =
+				dal_adapter_service_get_sw_i2c_speed(ddc->as) };
+
+		dal_ddc_i2c_payloads_add(
+			payloads, address, write_size, write_buf, true);
+
+		dal_ddc_i2c_payloads_add(
+			payloads, address, read_size, read_buf, false);
+
+		command.number_of_payloads =
+			dal_ddc_i2c_payloads_get_count(payloads);
+
+		ret = dal_i2caux_submit_i2c_command(
+				dal_adapter_service_get_i2caux(ddc->as),
+				ddc->ddc_pin,
+				&command);
+
+		dal_ddc_i2c_payloads_destroy(&payloads);
+	}
+
+	return ret;
+}
+
+bool dal_ddc_service_get_dp_receiver_id_info(
+	struct ddc_service *ddc,
+	struct dp_receiver_id_info *info)
+{
+	if (!info)
+		return false;
+
+	*info = ddc->dp_receiver_id_info;
+	return true;
+}
+
+enum ddc_result dal_ddc_service_read_dpcd_data(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t len)
+{
+	struct aux_payload read_payload = {
+		.i2c_over_aux = false,
+		.write = false,
+		.address = address,
+		.length = len,
+		.data = data,
+	};
+	struct aux_command command = {
+		.payloads = &read_payload,
+		.number_of_payloads = 1,
+		.defer_delay = 0,
+		.max_defer_write_retry = 0,
+	};
+
+	if (len > DEFAULT_AUX_MAX_DATA_SIZE) {
+		BREAK_TO_DEBUGGER();
+		return DDC_RESULT_FAILED_INVALID_OPERATION;
+	}
+
+	if (dal_i2caux_submit_aux_command(
+		dal_adapter_service_get_i2caux(ddc->as),
+		ddc->ddc_pin,
+		&command))
+		return DDC_RESULT_SUCESSFULL;
+
+	return DDC_RESULT_FAILED_OPERATION;
+}
+
+enum ddc_result dal_ddc_service_write_dpcd_data(
+	struct ddc_service *ddc,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t len)
+{
+	struct aux_payload write_payload = {
+		.i2c_over_aux = false,
+		.write = true,
+		.address = address,
+		.length = len,
+		.data = (uint8_t *)data,
+	};
+	struct aux_command command = {
+		.payloads = &write_payload,
+		.number_of_payloads = 1,
+		.defer_delay = 0,
+		.max_defer_write_retry = 0,
+	};
+
+	if (len > DEFAULT_AUX_MAX_DATA_SIZE) {
+		BREAK_TO_DEBUGGER();
+		return DDC_RESULT_FAILED_INVALID_OPERATION;
+	}
+
+	if (dal_i2caux_submit_aux_command(
+		dal_adapter_service_get_i2caux(ddc->as),
+		ddc->ddc_pin,
+		&command))
+		return DDC_RESULT_SUCESSFULL;
+
+	return DDC_RESULT_FAILED_OPERATION;
+}
+
+/*test only function*/
+void dal_ddc_service_set_ddc_pin(
+	struct ddc_service *ddc_service,
+	struct ddc *ddc)
+{
+	ddc_service->ddc_pin = ddc;
+}
+
+struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service)
+{
+	return ddc_service->ddc_pin;
+}
+
+
+void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service)
+{
+	dm_memset(&ddc_service->dp_receiver_id_info,
+		0, sizeof(struct dp_receiver_id_info));
+}
+
+void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service,
+		uint32_t pix_clk,
+		bool lte_340_scramble)
+{
+	bool over_340_mhz = pix_clk > 340000 ? 1 : 0;
+	uint8_t slave_address = HDMI_SCDC_ADDRESS;
+	uint8_t offset = HDMI_SCDC_SINK_VERSION;
+	uint8_t sink_version = 0;
+	uint8_t write_buffer[2] = {0};
+	/*Lower than 340 Scramble bit from SCDC caps*/
+
+	dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
+			sizeof(offset), &sink_version, sizeof(sink_version));
+	if (sink_version == 1) {
+		/*Source Version = 1*/
+		write_buffer[0] = HDMI_SCDC_SOURCE_VERSION;
+		write_buffer[1] = 1;
+		dal_ddc_service_query_ddc_data(ddc_service, slave_address,
+				write_buffer, sizeof(write_buffer), NULL, 0);
+		/*Read Request from SCDC caps*/
+	}
+	write_buffer[0] = HDMI_SCDC_TMDS_CONFIG;
+
+	if (over_340_mhz) {
+		write_buffer[1] = 3;
+	} else if (lte_340_scramble) {
+		write_buffer[1] = 1;
+	} else {
+		write_buffer[1] = 0;
+	}
+	dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer,
+			sizeof(write_buffer), NULL, 0);
+}
+
+void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service)
+{
+	uint8_t slave_address = HDMI_SCDC_ADDRESS;
+	uint8_t offset = HDMI_SCDC_TMDS_CONFIG;
+	uint8_t tmds_config = 0;
+
+	dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
+			sizeof(offset), &tmds_config, sizeof(tmds_config));
+	if (tmds_config & 0x1) {
+		union hdmi_scdc_status_flags_data status_data = { {0} };
+		uint8_t scramble_status = 0;
+
+		offset = HDMI_SCDC_SCRAMBLER_STATUS;
+		dal_ddc_service_query_ddc_data(ddc_service, slave_address,
+				&offset, sizeof(offset), &scramble_status,
+				sizeof(scramble_status));
+		offset = HDMI_SCDC_STATUS_FLAGS;
+		dal_ddc_service_query_ddc_data(ddc_service, slave_address,
+				&offset, sizeof(offset), status_data.byte,
+				sizeof(status_data.byte));
+	}
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
new file mode 100644
index 000000000000..742ab756cb48
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
@@ -0,0 +1,1728 @@
+/* Copyright 2015 Advanced Micro Devices, Inc. */
+#include "dm_services.h"
+#include "dc.h"
+#include "dc_link_dp.h"
+#include "dm_helpers.h"
+
+#include "inc/core_types.h"
+#include "link_hwss.h"
+#include "dc_link_ddc.h"
+#include "core_status.h"
+#include "dpcd_defs.h"
+
+/* maximum pre emphasis level allowed for each voltage swing level*/
+static const enum pre_emphasis voltage_swing_to_pre_emphasis[] = {
+		PRE_EMPHASIS_LEVEL3,
+		PRE_EMPHASIS_LEVEL2,
+		PRE_EMPHASIS_LEVEL1,
+		PRE_EMPHASIS_DISABLED };
+
+enum {
+	POST_LT_ADJ_REQ_LIMIT = 6,
+	POST_LT_ADJ_REQ_TIMEOUT = 200
+};
+
+enum {
+	LINK_TRAINING_MAX_RETRY_COUNT = 5,
+	/* to avoid infinite loop where-in the receiver
+	 * switches between different VS
+	 */
+	LINK_TRAINING_MAX_CR_RETRY = 100
+};
+
+static const struct link_settings link_training_fallback_table[] = {
+/* 2160 Mbytes/sec*/
+{ LANE_COUNT_FOUR, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED },
+/* 1080 Mbytes/sec*/
+{ LANE_COUNT_FOUR, LINK_RATE_HIGH, LINK_SPREAD_DISABLED },
+/* 648 Mbytes/sec*/
+{ LANE_COUNT_FOUR, LINK_RATE_LOW, LINK_SPREAD_DISABLED },
+/* 1080 Mbytes/sec*/
+{ LANE_COUNT_TWO, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED },
+/* 540 Mbytes/sec*/
+{ LANE_COUNT_TWO, LINK_RATE_HIGH, LINK_SPREAD_DISABLED },
+/* 324 Mbytes/sec*/
+{ LANE_COUNT_TWO, LINK_RATE_LOW, LINK_SPREAD_DISABLED },
+/* 540 Mbytes/sec*/
+{ LANE_COUNT_ONE, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED },
+/* 270 Mbytes/sec*/
+{ LANE_COUNT_ONE, LINK_RATE_HIGH, LINK_SPREAD_DISABLED },
+/* 162 Mbytes/sec*/
+{ LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED } };
+
+static void wait_for_training_aux_rd_interval(
+	struct core_link* link,
+	uint32_t default_wait_in_micro_secs)
+{
+	uint8_t training_rd_interval;
+
+	/* overwrite the delay if rev > 1.1*/
+	if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
+		/* DP 1.2 or later - retrieve delay through
+		 * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */
+		core_link_read_dpcd(
+			link,
+			DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL,
+			&training_rd_interval,
+			sizeof(training_rd_interval));
+		default_wait_in_micro_secs = training_rd_interval ?
+			(training_rd_interval * 4000) :
+			default_wait_in_micro_secs;
+	}
+
+	dm_delay_in_microseconds(link->ctx, default_wait_in_micro_secs);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n wait = %d\n",
+		__func__,
+		default_wait_in_micro_secs);
+}
+
+static void dpcd_set_training_pattern(
+	struct core_link* link,
+	union dpcd_training_pattern dpcd_pattern)
+{
+	core_link_write_dpcd(
+		link,
+		DPCD_ADDRESS_TRAINING_PATTERN_SET,
+		&dpcd_pattern.raw,
+		1);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x pattern = %x\n",
+		__func__,
+		DPCD_ADDRESS_TRAINING_PATTERN_SET,
+		dpcd_pattern.bits.TRAINING_PATTERN_SET);
+}
+
+static void dpcd_set_link_settings(
+	struct core_link* link,
+	const struct link_training_settings *lt_settings)
+{
+	uint8_t rate = (uint8_t)
+	(lt_settings->link_settings.link_rate);
+
+	union down_spread_ctrl downspread = {{0}};
+	union lane_count_set lane_count_set = {{0}};
+	uint8_t link_set_buffer[2];
+
+
+	downspread.raw = (uint8_t)
+	(lt_settings->link_settings.link_spread);
+
+	lane_count_set.bits.LANE_COUNT_SET =
+	lt_settings->link_settings.lane_count;
+
+	lane_count_set.bits.ENHANCED_FRAMING = 1;
+
+	lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
+		link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
+
+	link_set_buffer[0] = rate;
+	link_set_buffer[1] = lane_count_set.raw;
+
+	core_link_write_dpcd(link, DPCD_ADDRESS_LINK_BW_SET,
+	link_set_buffer, 2);
+	core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL,
+	&downspread.raw, sizeof(downspread));
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
+		__func__,
+		DPCD_ADDRESS_LINK_BW_SET,
+		lt_settings->link_settings.link_rate,
+		DPCD_ADDRESS_LANE_COUNT_SET,
+		lt_settings->link_settings.lane_count,
+		DPCD_ADDRESS_DOWNSPREAD_CNTL,
+		lt_settings->link_settings.link_spread);
+
+}
+
+static enum dpcd_training_patterns
+	hw_training_pattern_to_dpcd_training_pattern(
+	struct core_link* link,
+	enum hw_dp_training_pattern pattern)
+{
+	enum dpcd_training_patterns dpcd_tr_pattern =
+	DPCD_TRAINING_PATTERN_VIDEOIDLE;
+
+	switch (pattern) {
+	case HW_DP_TRAINING_PATTERN_1:
+		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
+		break;
+	case HW_DP_TRAINING_PATTERN_2:
+		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
+		break;
+	case HW_DP_TRAINING_PATTERN_3:
+		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
+		break;
+	default:
+		ASSERT(0);
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_LINK_TRAINING,
+			"%s: Invalid HW Training pattern: %d\n",
+			__func__, pattern);
+		break;
+	}
+
+	return dpcd_tr_pattern;
+
+}
+
+static void dpcd_set_lt_pattern_and_lane_settings(
+	struct core_link* link,
+	const struct link_training_settings *lt_settings,
+	enum hw_dp_training_pattern pattern)
+{
+	union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
+	const uint32_t dpcd_base_lt_offset =
+	DPCD_ADDRESS_TRAINING_PATTERN_SET;
+	uint8_t dpcd_lt_buffer[5] = {0};
+	union dpcd_training_pattern dpcd_pattern = {{0}};
+	uint32_t lane;
+	uint32_t size_in_bytes;
+	bool edp_workaround = false; /* TODO link_prop.INTERNAL */
+
+	/*****************************************************************
+	* DpcdAddress_TrainingPatternSet
+	*****************************************************************/
+	dpcd_pattern.bits.TRAINING_PATTERN_SET =
+		hw_training_pattern_to_dpcd_training_pattern(link, pattern);
+
+	dpcd_lt_buffer[DPCD_ADDRESS_TRAINING_PATTERN_SET - dpcd_base_lt_offset]
+		= dpcd_pattern.raw;
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x pattern = %x\n",
+		__func__,
+		DPCD_ADDRESS_TRAINING_PATTERN_SET,
+		dpcd_pattern.bits.TRAINING_PATTERN_SET);
+
+
+	/*****************************************************************
+	* DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set
+	*****************************************************************/
+	for (lane = 0; lane <
+		(uint32_t)(lt_settings->link_settings.lane_count); lane++) {
+
+		dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
+		(uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING);
+		dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
+		(uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS);
+
+		dpcd_lane[lane].bits.MAX_SWING_REACHED =
+		(lt_settings->lane_settings[lane].VOLTAGE_SWING ==
+		VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
+		dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
+		(lt_settings->lane_settings[lane].PRE_EMPHASIS ==
+		PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
+	}
+
+	/* concatinate everything into one buffer*/
+
+	size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
+
+	 // 0x00103 - 0x00102
+	dm_memmove(
+		&dpcd_lt_buffer[DPCD_ADDRESS_LANE0_SET - dpcd_base_lt_offset],
+		dpcd_lane,
+		size_in_bytes);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n %x VS set = %x  PE set = %x \
+		max VS Reached = %x  max PE Reached = %x\n",
+		__func__,
+		DPCD_ADDRESS_LANE0_SET,
+		dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+		dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+		dpcd_lane[0].bits.MAX_SWING_REACHED,
+		dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+
+
+	if (edp_workaround) {
+		/* for eDP write in 2 parts because the 5-byte burst is
+		* causing issues on some eDP panels (EPR#366724)
+		*/
+		core_link_write_dpcd(
+			link,
+			DPCD_ADDRESS_TRAINING_PATTERN_SET,
+			&dpcd_pattern.raw,
+			sizeof(dpcd_pattern.raw) );
+
+		core_link_write_dpcd(
+			link,
+			DPCD_ADDRESS_LANE0_SET,
+			(uint8_t *)(dpcd_lane),
+			size_in_bytes);
+
+		} else
+		/* write it all in (1 + number-of-lanes)-byte burst*/
+			core_link_write_dpcd(
+				link,
+				dpcd_base_lt_offset,
+				dpcd_lt_buffer,
+				size_in_bytes + sizeof(dpcd_pattern.raw) );
+
+	link->ln_setting = lt_settings->lane_settings[0];
+}
+
+static bool is_cr_done(enum lane_count ln_count,
+	union lane_status *dpcd_lane_status)
+{
+	bool done = true;
+	uint32_t lane;
+	/*LANEx_CR_DONE bits All 1's?*/
+	for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
+		if (!dpcd_lane_status[lane].bits.CR_DONE_0)
+			done = false;
+	}
+	return done;
+
+}
+
+static bool is_ch_eq_done(enum lane_count ln_count,
+	union lane_status *dpcd_lane_status,
+	union lane_align_status_updated *lane_status_updated)
+{
+	bool done = true;
+	uint32_t lane;
+	if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE)
+		done = false;
+	else {
+		for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
+			if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 ||
+				!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
+				done = false;
+		}
+	}
+	return done;
+
+}
+
+static void update_drive_settings(
+		struct link_training_settings *dest,
+		struct link_training_settings src)
+{
+	uint32_t lane;
+	for (lane = 0; lane < src.link_settings.lane_count; lane++) {
+		dest->lane_settings[lane].VOLTAGE_SWING =
+			src.lane_settings[lane].VOLTAGE_SWING;
+		dest->lane_settings[lane].PRE_EMPHASIS =
+			src.lane_settings[lane].PRE_EMPHASIS;
+		dest->lane_settings[lane].POST_CURSOR2 =
+			src.lane_settings[lane].POST_CURSOR2;
+	}
+}
+
+static uint8_t get_nibble_at_index(const uint8_t *buf,
+	uint32_t index)
+{
+	uint8_t nibble;
+	nibble = buf[index / 2];
+
+	if (index % 2)
+		nibble >>= 4;
+	else
+		nibble &= 0x0F;
+
+	return nibble;
+}
+
+static enum pre_emphasis get_max_pre_emphasis_for_voltage_swing(
+	enum voltage_swing voltage)
+{
+	enum pre_emphasis pre_emphasis;
+	pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
+
+	if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
+		pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
+
+	return pre_emphasis;
+
+}
+
+static void find_max_drive_settings(
+	const struct link_training_settings *link_training_setting,
+	struct link_training_settings *max_lt_setting)
+{
+	uint32_t lane;
+	struct lane_settings max_requested;
+
+	max_requested.VOLTAGE_SWING =
+		link_training_setting->
+		lane_settings[0].VOLTAGE_SWING;
+	max_requested.PRE_EMPHASIS =
+		link_training_setting->
+		lane_settings[0].PRE_EMPHASIS;
+	/*max_requested.postCursor2 =
+	 * link_training_setting->laneSettings[0].postCursor2;*/
+
+	/* Determine what the maximum of the requested settings are*/
+	for (lane = 1; lane < link_training_setting->link_settings.lane_count;
+			lane++) {
+		if (link_training_setting->lane_settings[lane].VOLTAGE_SWING >
+			max_requested.VOLTAGE_SWING)
+
+			max_requested.VOLTAGE_SWING =
+			link_training_setting->
+			lane_settings[lane].VOLTAGE_SWING;
+
+
+		if (link_training_setting->lane_settings[lane].PRE_EMPHASIS >
+				max_requested.PRE_EMPHASIS)
+			max_requested.PRE_EMPHASIS =
+			link_training_setting->
+			lane_settings[lane].PRE_EMPHASIS;
+
+		/*
+		if (link_training_setting->laneSettings[lane].postCursor2 >
+		 max_requested.postCursor2)
+		{
+		max_requested.postCursor2 =
+		link_training_setting->laneSettings[lane].postCursor2;
+		}
+		*/
+	}
+
+	/* make sure the requested settings are
+	 * not higher than maximum settings*/
+	if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
+		max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
+
+	if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
+		max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
+	/*
+	if (max_requested.postCursor2 > PostCursor2_MaxLevel)
+	max_requested.postCursor2 = PostCursor2_MaxLevel;
+	*/
+
+	/* make sure the pre-emphasis matches the voltage swing*/
+	if (max_requested.PRE_EMPHASIS >
+		get_max_pre_emphasis_for_voltage_swing(
+			max_requested.VOLTAGE_SWING))
+		max_requested.PRE_EMPHASIS =
+		get_max_pre_emphasis_for_voltage_swing(
+			max_requested.VOLTAGE_SWING);
+
+	/*
+	 * Post Cursor2 levels are completely independent from
+	 * pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels
+	 * can only be applied to each allowable combination of voltage
+	 * swing and pre-emphasis levels */
+	 /* if ( max_requested.postCursor2 >
+	  *  getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing))
+	  *  max_requested.postCursor2 =
+	  *  getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing);
+	  */
+
+	max_lt_setting->link_settings.link_rate =
+		link_training_setting->link_settings.link_rate;
+	max_lt_setting->link_settings.lane_count =
+	link_training_setting->link_settings.lane_count;
+	max_lt_setting->link_settings.link_spread =
+		link_training_setting->link_settings.link_spread;
+
+	for (lane = 0; lane <
+		link_training_setting->link_settings.lane_count;
+		lane++) {
+		max_lt_setting->lane_settings[lane].VOLTAGE_SWING =
+			max_requested.VOLTAGE_SWING;
+		max_lt_setting->lane_settings[lane].PRE_EMPHASIS =
+			max_requested.PRE_EMPHASIS;
+		/*max_lt_setting->laneSettings[lane].postCursor2 =
+		 * max_requested.postCursor2;
+		 */
+	}
+
+}
+
+static void get_lane_status_and_drive_settings(
+	struct core_link* link,
+	const struct link_training_settings *link_training_setting,
+	union lane_status *ln_status,
+	union lane_align_status_updated *ln_status_updated,
+	struct link_training_settings *req_settings)
+{
+	uint8_t dpcd_buf[6] = {0};
+	union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {{{0}}};
+	struct link_training_settings request_settings = {{0}};
+	uint32_t lane;
+
+	dm_memset(req_settings, '\0', sizeof(struct link_training_settings));
+
+	core_link_read_dpcd(
+		link,
+		DPCD_ADDRESS_LANE_01_STATUS,
+		(uint8_t *)(dpcd_buf),
+		sizeof(dpcd_buf));
+
+
+	for (lane = 0; lane <
+		(uint32_t)(link_training_setting->link_settings.lane_count);
+		lane++) {
+
+		ln_status[lane].raw =
+			get_nibble_at_index(&dpcd_buf[0], lane);
+		dpcd_lane_adjust[lane].raw =
+			get_nibble_at_index(&dpcd_buf[4], lane);
+	}
+
+	ln_status_updated->raw = dpcd_buf[2];
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
+		__func__,
+		DPCD_ADDRESS_LANE_01_STATUS, dpcd_buf[0],
+		DPCD_ADDRESS_LANE_23_STATUS, dpcd_buf[1]);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
+		__func__,
+		DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1,
+		dpcd_buf[4],
+		DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3,
+		dpcd_buf[5]);
+
+	/*copy to req_settings*/
+	request_settings.link_settings.lane_count =
+		link_training_setting->link_settings.lane_count;
+	request_settings.link_settings.link_rate =
+		link_training_setting->link_settings.link_rate;
+	request_settings.link_settings.link_spread =
+		link_training_setting->link_settings.link_spread;
+
+	for (lane = 0; lane <
+		(uint32_t)(link_training_setting->link_settings.lane_count);
+		lane++) {
+
+		request_settings.lane_settings[lane].VOLTAGE_SWING =
+			(enum voltage_swing)(dpcd_lane_adjust[lane].bits.
+				VOLTAGE_SWING_LANE);
+		request_settings.lane_settings[lane].PRE_EMPHASIS =
+			(enum pre_emphasis)(dpcd_lane_adjust[lane].bits.
+				PRE_EMPHASIS_LANE);
+	}
+
+	/*Note: for postcursor2, read adjusted
+	 * postcursor2 settings from*/
+	/*DpcdAddress_AdjustRequestPostCursor2 =
+	 *0x020C (not implemented yet)*/
+
+	/* we find the maximum of the requested settings across all lanes*/
+	/* and set this maximum for all lanes*/
+	find_max_drive_settings(&request_settings, req_settings);
+
+	/* if post cursor 2 is needed in the future,
+	 * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C
+	 */
+
+}
+
+static void dpcd_set_lane_settings(
+	struct core_link* link,
+	const struct link_training_settings *link_training_setting)
+{
+	union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
+	uint32_t lane;
+
+	for (lane = 0; lane <
+		(uint32_t)(link_training_setting->
+		link_settings.lane_count);
+		lane++) {
+		dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
+			(uint8_t)(link_training_setting->
+			lane_settings[lane].VOLTAGE_SWING);
+		dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
+			(uint8_t)(link_training_setting->
+			lane_settings[lane].PRE_EMPHASIS);
+		dpcd_lane[lane].bits.MAX_SWING_REACHED =
+			(link_training_setting->
+			lane_settings[lane].VOLTAGE_SWING ==
+			VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
+		dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
+			(link_training_setting->
+			lane_settings[lane].PRE_EMPHASIS ==
+			PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
+	}
+
+	core_link_write_dpcd(link,
+		DPCD_ADDRESS_LANE0_SET,
+		(uint8_t *)(dpcd_lane),
+		link_training_setting->link_settings.lane_count);
+
+	/*
+	if (LTSettings.link.rate == LinkRate_High2)
+	{
+		DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0};
+		for ( uint32_t lane = 0;
+		lane < lane_count_DPMax; lane++)
+		{
+			dpcd_lane2[lane].bits.post_cursor2_set =
+			static_cast<unsigned char>(
+			LTSettings.laneSettings[lane].postCursor2);
+			dpcd_lane2[lane].bits.max_post_cursor2_reached = 0;
+		}
+		m_pDpcdAccessSrv->WriteDpcdData(
+		DpcdAddress_Lane0Set2,
+		reinterpret_cast<unsigned char*>(dpcd_lane2),
+		LTSettings.link.lanes);
+	}
+	*/
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x VS set = %x  PE set = %x \
+		max VS Reached = %x  max PE Reached = %x\n",
+		__func__,
+		DPCD_ADDRESS_LANE0_SET,
+		dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+		dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+		dpcd_lane[0].bits.MAX_SWING_REACHED,
+		dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+
+	link->ln_setting = link_training_setting->lane_settings[0];
+
+}
+
+static bool is_max_vs_reached(
+	const struct link_training_settings *lt_settings)
+{
+	uint32_t lane;
+	for (lane = 0; lane <
+		(uint32_t)(lt_settings->link_settings.lane_count);
+		lane++) {
+		if (lt_settings->lane_settings[lane].VOLTAGE_SWING
+			== VOLTAGE_SWING_MAX_LEVEL)
+			return true;
+	}
+	return false;
+
+}
+
+void set_drive_settings(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	/* program ASIC PHY settings*/
+	dp_set_hw_lane_settings(link, lt_settings);
+
+	/* Notify DP sink the PHY settings from source */
+	dpcd_set_lane_settings(link, lt_settings);
+}
+
+static bool perform_post_lt_adj_req_sequence(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	enum lane_count lane_count =
+	lt_settings->link_settings.lane_count;
+
+	uint32_t adj_req_count;
+	uint32_t adj_req_timer;
+	bool req_drv_setting_changed;
+	uint32_t lane;
+
+	req_drv_setting_changed = false;
+	for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
+	adj_req_count++) {
+
+		req_drv_setting_changed = false;
+
+		for (adj_req_timer = 0;
+			adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
+			adj_req_timer++) {
+
+			struct link_training_settings req_settings;
+			union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
+			union lane_align_status_updated
+				dpcd_lane_status_updated;
+
+			get_lane_status_and_drive_settings(
+			link,
+			lt_settings,
+			dpcd_lane_status,
+			&dpcd_lane_status_updated,
+			&req_settings);
+
+			if (dpcd_lane_status_updated.bits.
+					POST_LT_ADJ_REQ_IN_PROGRESS == 0)
+				return true;
+
+			if (!is_cr_done(lane_count, dpcd_lane_status))
+				return false;
+
+			if (!is_ch_eq_done(
+				lane_count,
+				dpcd_lane_status,
+				&dpcd_lane_status_updated))
+				return false;
+
+			for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
+
+				if (lt_settings->
+				lane_settings[lane].VOLTAGE_SWING !=
+				req_settings.lane_settings[lane].
+				VOLTAGE_SWING ||
+				lt_settings->lane_settings[lane].PRE_EMPHASIS !=
+				req_settings.lane_settings[lane].PRE_EMPHASIS) {
+
+					req_drv_setting_changed = true;
+					break;
+				}
+			}
+
+			if (req_drv_setting_changed) {
+				update_drive_settings(
+					lt_settings,req_settings);
+
+				set_drive_settings(link, lt_settings);
+				break;
+			}
+
+			dm_sleep_in_milliseconds(link->ctx, 1);
+		}
+
+		if (!req_drv_setting_changed) {
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_LINK_SERVICE,
+				"%s: Post Link Training Adjust Request Timed out\n",
+				__func__);
+
+			ASSERT(0);
+			return true;
+		}
+	}
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_WARNING,
+		LOG_MINOR_COMPONENT_LINK_SERVICE,
+		"%s: Post Link Training Adjust Request limit reached\n",
+		__func__);
+
+	ASSERT(0);
+	return true;
+
+}
+
+static bool perform_channel_equalization_sequence(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	struct link_training_settings req_settings;
+	enum hw_dp_training_pattern hw_tr_pattern;
+	uint32_t retries_ch_eq;
+	enum lane_count lane_count = lt_settings->link_settings.lane_count;
+	union lane_align_status_updated dpcd_lane_status_updated = {{0}};
+	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};;
+
+	/*TODO hw_tr_pattern = HW_DP_TRAINING_PATTERN_3;*/
+	hw_tr_pattern = HW_DP_TRAINING_PATTERN_2;
+
+	dp_set_hw_training_pattern(link, hw_tr_pattern);
+
+	for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
+		retries_ch_eq++) {
+
+		dp_set_hw_lane_settings(link, lt_settings);
+
+		/* 2. update DPCD*/
+		if (!retries_ch_eq)
+			/* EPR #361076 - write as a 5-byte burst,
+			 * but only for the 1-st iteration*/
+			dpcd_set_lt_pattern_and_lane_settings(
+				link,
+				lt_settings,
+				hw_tr_pattern);
+		else
+			dpcd_set_lane_settings(link, lt_settings);
+
+		/* 3. wait for receiver to lock-on*/
+		wait_for_training_aux_rd_interval(link, 400);
+
+		/* 4. Read lane status and requested
+		 * drive settings as set by the sink*/
+
+		get_lane_status_and_drive_settings(
+			link,
+			lt_settings,
+			dpcd_lane_status,
+			&dpcd_lane_status_updated,
+			&req_settings);
+
+		/* 5. check CR done*/
+		if (!is_cr_done(lane_count, dpcd_lane_status))
+			return false;
+
+		/* 6. check CHEQ done*/
+		if (is_ch_eq_done(lane_count,
+			dpcd_lane_status,
+			&dpcd_lane_status_updated))
+			return true;
+
+		/* 7. update VS/PE/PC2 in lt_settings*/
+		update_drive_settings(lt_settings, req_settings);
+	}
+
+	return false;
+
+}
+
+static bool perform_clock_recovery_sequence(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	uint32_t retries_cr;
+	uint32_t retry_count;
+	uint32_t lane;
+	struct link_training_settings req_settings;
+	enum lane_count lane_count =
+	lt_settings->link_settings.lane_count;
+	enum hw_dp_training_pattern hw_tr_pattern = HW_DP_TRAINING_PATTERN_1;
+	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
+	union lane_align_status_updated dpcd_lane_status_updated;
+
+	retries_cr = 0;
+	retry_count = 0;
+	/* initial drive setting (VS/PE/PC2)*/
+	for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
+		lt_settings->lane_settings[lane].VOLTAGE_SWING =
+		VOLTAGE_SWING_LEVEL0;
+		lt_settings->lane_settings[lane].PRE_EMPHASIS =
+		PRE_EMPHASIS_DISABLED;
+		lt_settings->lane_settings[lane].POST_CURSOR2 =
+		POST_CURSOR2_DISABLED;
+	}
+
+	dp_set_hw_training_pattern(link, hw_tr_pattern);
+
+	/* najeeb - The synaptics MST hub can put the LT in
+	* infinite loop by switching the VS
+	*/
+	/* between level 0 and level 1 continuously, here
+	* we try for CR lock for LinkTrainingMaxCRRetry count*/
+	while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
+	(retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
+
+		dm_memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
+		dm_memset(&dpcd_lane_status_updated, '\0',
+		sizeof(dpcd_lane_status_updated));
+
+		/* 1. call HWSS to set lane settings*/
+		dp_set_hw_lane_settings(
+				link,
+				lt_settings);
+
+		/* 2. update DPCD of the receiver*/
+		if (!retries_cr)
+			/* EPR #361076 - write as a 5-byte burst,
+			 * but only for the 1-st iteration.*/
+			dpcd_set_lt_pattern_and_lane_settings(
+					link,
+					lt_settings,
+					hw_tr_pattern);
+		else
+			dpcd_set_lane_settings(
+					link,
+					lt_settings);
+
+
+		/* 3. wait receiver to lock-on*/
+		wait_for_training_aux_rd_interval(
+				link,
+				100);
+
+		/* 4. Read lane status and requested drive
+		* settings as set by the sink
+		*/
+		get_lane_status_and_drive_settings(
+				link,
+				lt_settings,
+				dpcd_lane_status,
+				&dpcd_lane_status_updated,
+				&req_settings);
+
+
+		/* 5. check CR done*/
+		if (is_cr_done(lane_count, dpcd_lane_status))
+			return true;
+
+		/* 6. max VS reached*/
+		if (is_max_vs_reached(lt_settings))
+			return false;
+
+		/* 7. same voltage*/
+		/* Note: VS same for all lanes,
+		* so comparing first lane is sufficient*/
+		if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
+			req_settings.lane_settings[0].VOLTAGE_SWING)
+			retries_cr++;
+		else
+			retries_cr = 0;
+
+
+			/* 8. update VS/PE/PC2 in lt_settings*/
+			update_drive_settings(lt_settings, req_settings);
+
+			retry_count++;
+	}
+
+	if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
+		ASSERT(0);
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_LINK_SERVICE,
+			"%s: Link Training Error, could not \
+			 get CR after %d tries. \
+			Possibly voltage swing issue", __func__,
+			LINK_TRAINING_MAX_CR_RETRY);
+
+	}
+
+	return false;
+}
+
+ bool perform_link_training(
+	struct core_link *link,
+	const struct link_settings *link_setting,
+	bool skip_video_pattern)
+{
+	bool status;
+	union dpcd_training_pattern dpcd_pattern = {{0}};
+	union lane_count_set lane_count_set = {{0}};
+	const int8_t *link_rate = "Unknown";
+	struct link_training_settings lt_settings;
+
+	status = false;
+	dm_memset(&lt_settings, '\0', sizeof(lt_settings));
+
+	lt_settings.link_settings.link_rate = link_setting->link_rate;
+	lt_settings.link_settings.lane_count = link_setting->lane_count;
+
+	/*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/
+
+	/* TODO hard coded to SS for now
+	 * lt_settings.link_settings.link_spread =
+	 * dal_display_path_is_ss_supported(
+	 * path_mode->display_path) ?
+	 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
+	 * LINK_SPREAD_DISABLED;
+	 */
+	lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
+
+	/* 1. set link rate, lane count and spread*/
+	dpcd_set_link_settings(link, &lt_settings);
+
+	/* 2. perform link training (set link training done
+	 *  to false is done as well)*/
+	if (perform_clock_recovery_sequence(link, &lt_settings)) {
+
+		if (perform_channel_equalization_sequence(link, &lt_settings))
+			status = true;
+	}
+
+	if (status || !skip_video_pattern) {
+
+		/* 3. set training not in progress*/
+		dpcd_pattern.bits.TRAINING_PATTERN_SET =
+			DPCD_TRAINING_PATTERN_VIDEOIDLE;
+		dpcd_set_training_pattern(link, dpcd_pattern);
+
+		/* 4. mainlink output idle pattern*/
+		dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE);
+
+		/* 5. post training adjust if required*/
+		if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED
+			== 1) {
+			if (status == true) {
+				if (perform_post_lt_adj_req_sequence(
+					link, &lt_settings) == false)
+					status = false;
+			}
+
+			lane_count_set.bits.LANE_COUNT_SET =
+				lt_settings.link_settings.lane_count;
+			lane_count_set.bits.ENHANCED_FRAMING = 1;
+			lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
+
+			core_link_write_dpcd(
+				link,
+				DPCD_ADDRESS_LANE_COUNT_SET,
+				&lane_count_set.raw,
+				sizeof(lane_count_set));
+		}
+	}
+
+	/* 6. print status message*/
+	switch (lt_settings.link_settings.link_rate) {
+
+	case LINK_RATE_LOW:
+		link_rate = "Low";
+		break;
+	case LINK_RATE_HIGH:
+		link_rate = "High";
+		break;
+	case LINK_RATE_HIGH2:
+		link_rate = "High2";
+		break;
+	case LINK_RATE_RBR2:
+		link_rate = "RBR2";
+		break;
+	default:
+		break;
+	}
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_MST,
+		LOG_MINOR_MST_PROGRAMMING,
+		"Link training for %d lanes at %s rate %s with PE %d, VS %d\n",
+		lt_settings.link_settings.lane_count,
+		link_rate,
+		status ? "succeeded" : "failed",
+		lt_settings.lane_settings[0].PRE_EMPHASIS,
+		lt_settings.lane_settings[0].VOLTAGE_SWING);
+
+	return status;
+}
+
+/*TODO add more check to see if link support request link configuration */
+static bool is_link_setting_supported(
+	const struct link_settings *link_setting,
+	const struct link_settings *max_link_setting)
+{
+	if (link_setting->lane_count > max_link_setting->lane_count ||
+		link_setting->link_rate > max_link_setting->link_rate)
+		return false;
+	return true;
+}
+
+static const uint32_t get_link_training_fallback_table_len(
+	struct core_link *link)
+{
+	return ARRAY_SIZE(link_training_fallback_table);
+}
+
+static const struct link_settings *get_link_training_fallback_table(
+	struct core_link *link, uint32_t i)
+{
+	return &link_training_fallback_table[i];
+}
+
+static bool exceeded_limit_link_setting(const struct link_settings *link_setting,
+			const struct link_settings *limit_link_setting)
+{
+	return (link_setting->lane_count * link_setting->link_rate
+		 > limit_link_setting->lane_count * limit_link_setting->link_rate ?
+				 true : false);
+}
+
+
+bool dp_hbr_verify_link_cap(
+	struct core_link *link,
+	struct link_settings *known_limit_link_setting)
+{
+	struct link_settings max_link_cap = {0};
+	bool success;
+	bool skip_link_training;
+	const struct link_settings *cur;
+	bool skip_video_pattern;
+	uint32_t i;
+
+	success = false;
+	skip_link_training = false;
+
+	/* TODO confirm this is correct for cz */
+	max_link_cap.lane_count = LANE_COUNT_FOUR;
+	max_link_cap.link_rate = LINK_RATE_HIGH2;
+	max_link_cap.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
+
+	/* TODO implement override and monitor patch later */
+
+	/* try to train the link from high to low to
+	 * find the physical link capability
+	 */
+	/* disable PHY done possible by BIOS, will be done by driver itself */
+	dp_disable_link_phy(link, link->public.connector_signal);
+
+	for (i = 0; i < get_link_training_fallback_table_len(link) &&
+		!success; i++) {
+		cur = get_link_training_fallback_table(link, i);
+
+		if (known_limit_link_setting->lane_count != LANE_COUNT_UNKNOWN &&
+			exceeded_limit_link_setting(cur,
+					known_limit_link_setting))
+			continue;
+
+		if (!is_link_setting_supported(cur, &max_link_cap))
+			continue;
+
+		skip_video_pattern = true;
+		if (cur->link_rate == LINK_RATE_LOW)
+			skip_video_pattern = false;
+
+		dp_enable_link_phy(
+				link,
+				link->public.connector_signal,
+				cur);
+
+		if (skip_link_training)
+			success = true;
+		else {
+			uint8_t num_retries = 3;
+			uint8_t j;
+			uint8_t delay_between_retries = 10;
+
+			for (j = 0; j < num_retries; ++j) {
+				success = perform_link_training(
+					link,
+					cur,
+					skip_video_pattern);
+
+				if (success)
+					break;
+
+				dm_sleep_in_milliseconds(
+					link->ctx,
+					delay_between_retries);
+
+				delay_between_retries += 10;
+			}
+		}
+
+		if (success)
+			link->verified_link_cap = *cur;
+
+		/* always disable the link before trying another
+		 * setting or before returning we'll enable it later
+		 * based on the actual mode we're driving
+		 */
+		dp_disable_link_phy(link, link->public.connector_signal);
+	}
+
+	/* Link Training failed for all Link Settings
+	 *  (Lane Count is still unknown)
+	 */
+	if (!success) {
+		/* If all LT fails for all settings,
+		 * set verified = failed safe (1 lane low)
+		 */
+		link->verified_link_cap.lane_count = LANE_COUNT_ONE;
+		link->verified_link_cap.link_rate = LINK_RATE_LOW;
+
+		link->verified_link_cap.link_spread =
+		LINK_SPREAD_DISABLED;
+	}
+
+	link->max_link_setting = link->verified_link_cap;
+
+	return success;
+}
+
+static uint32_t bandwidth_in_kbps_from_timing(
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t bits_per_channel = 0;
+	uint32_t kbps;
+	switch (timing->display_color_depth) {
+
+	case COLOR_DEPTH_666:
+		bits_per_channel = 6;
+		break;
+	case COLOR_DEPTH_888:
+		bits_per_channel = 8;
+		break;
+	case COLOR_DEPTH_101010:
+		bits_per_channel = 10;
+		break;
+	case COLOR_DEPTH_121212:
+		bits_per_channel = 12;
+		break;
+	case COLOR_DEPTH_141414:
+		bits_per_channel = 14;
+		break;
+	case COLOR_DEPTH_161616:
+		bits_per_channel = 16;
+		break;
+	default:
+		break;
+	}
+	ASSERT(bits_per_channel != 0);
+
+	kbps = timing->pix_clk_khz;
+	kbps *= bits_per_channel;
+
+	if (timing->flags.Y_ONLY != 1)
+		/*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
+		kbps *= 3;
+
+	return kbps;
+
+}
+
+static uint32_t bandwidth_in_kbps_from_link_settings(
+	const struct link_settings *link_setting)
+{
+	uint32_t link_rate_in_kbps = link_setting->link_rate *
+		LINK_RATE_REF_FREQ_IN_KHZ;
+
+	uint32_t lane_count  = link_setting->lane_count;
+	uint32_t kbps = link_rate_in_kbps;
+	kbps *= lane_count;
+	kbps *= 8;   /* 8 bits per byte*/
+
+	return kbps;
+
+}
+
+bool dp_validate_mode_timing(
+	struct core_link *link,
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t req_bw;
+	uint32_t max_bw;
+
+	const struct link_settings *link_setting;
+
+	/*always DP fail safe mode*/
+	if (timing->pix_clk_khz == (uint32_t)25175 &&
+		timing->h_addressable == (uint32_t)640 &&
+		timing->v_addressable == (uint32_t)480)
+		return true;
+
+	/* For static validation we always use reported
+	 * link settings for other cases, when no modelist
+	 * changed we can use verified link setting*/
+	link_setting = &link->reported_link_cap;
+
+	/* TODO: DYNAMIC_VALIDATION needs to be implemented */
+	/*if (flags.DYNAMIC_VALIDATION == 1 &&
+		link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
+		link_setting = &link->verified_link_cap;
+	*/
+
+	req_bw = bandwidth_in_kbps_from_timing(timing);
+	max_bw = bandwidth_in_kbps_from_link_settings(link_setting);
+
+	if (req_bw < max_bw) {
+		/* remember the biggest mode here, during
+		 * initial link training (to get
+		 * verified_link_cap), LS sends event about
+		 * cannot train at reported cap to upper
+		 * layer and upper layer will re-enumerate modes.
+		 * this is not necessary if the lower
+		 * verified_link_cap is enough to drive
+		 * all the modes */
+
+		/* TODO: DYNAMIC_VALIDATION needs to be implemented */
+		/* if (flags.DYNAMIC_VALIDATION == 1)
+			dpsst->max_req_bw_for_verified_linkcap = dal_max(
+				dpsst->max_req_bw_for_verified_linkcap, req_bw); */
+		return true;
+	} else
+		return false;
+}
+
+void decide_link_settings(struct core_stream *stream,
+	struct link_settings *link_setting)
+{
+
+	const struct link_settings *cur_ls;
+	struct core_link* link;
+	uint32_t req_bw;
+	uint32_t link_bw;
+	uint32_t i;
+
+	req_bw = bandwidth_in_kbps_from_timing(
+			&stream->public.timing);
+
+	/* if preferred is specified through AMDDP, use it, if it's enough
+	 * to drive the mode
+	 */
+	link = stream->sink->link;
+
+	if ((link->reported_link_cap.lane_count != LANE_COUNT_UNKNOWN) &&
+		(link->reported_link_cap.link_rate <=
+				link->verified_link_cap.link_rate)) {
+
+		link_bw = bandwidth_in_kbps_from_link_settings(
+				&link->reported_link_cap);
+
+		if (req_bw < link_bw) {
+			*link_setting = link->reported_link_cap;
+			return;
+		}
+	}
+
+	/* search for first suitable setting for the requested
+	 * bandwidth
+	 */
+	for (i = 0; i < get_link_training_fallback_table_len(link); i++) {
+
+		cur_ls = get_link_training_fallback_table(link, i);
+
+		link_bw =
+				bandwidth_in_kbps_from_link_settings(
+				cur_ls);
+
+		if (req_bw < link_bw) {
+			if (is_link_setting_supported(
+				cur_ls,
+				&link->max_link_setting)) {
+				*link_setting = *cur_ls;
+				return;
+			}
+		}
+	}
+
+	BREAK_TO_DEBUGGER();
+	ASSERT(link->verified_link_cap.lane_count !=
+		LANE_COUNT_UNKNOWN);
+
+	*link_setting = link->verified_link_cap;
+}
+
+/*************************Short Pulse IRQ***************************/
+
+static bool hpd_rx_irq_check_link_loss_status(
+	struct core_link *link,
+	union hpd_irq_data *hpd_irq_dpcd_data)
+{
+	uint8_t irq_reg_rx_power_state;
+	enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
+	union lane_status lane_status;
+	uint32_t lane;
+	bool sink_status_changed;
+	bool return_code;
+
+	sink_status_changed = false;
+	return_code = false;
+
+	if (link->cur_link_settings.lane_count == 0)
+		return return_code;
+	/*1. Check that we can handle interrupt: Not in FS DOS,
+	 *  Not in "Display Timeout" state, Link is trained.
+	 */
+
+	dpcd_result = core_link_read_dpcd(link,
+		DPCD_ADDRESS_POWER_STATE,
+		&irq_reg_rx_power_state,
+		sizeof(irq_reg_rx_power_state));
+
+	if (dpcd_result != DC_OK) {
+		irq_reg_rx_power_state = DP_PWR_STATE_D0;
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_HPD_IRQ,
+			"%s: DPCD read failed to obtain power state.\n",
+			__func__);
+	}
+
+	if (irq_reg_rx_power_state == DP_PWR_STATE_D0) {
+
+		/*2. Check that Link Status changed, before re-training.*/
+
+		/*parse lane status*/
+		for (lane = 0;
+			lane < link->cur_link_settings.lane_count;
+			lane++) {
+
+			/* check status of lanes 0,1
+			 * changed DpcdAddress_Lane01Status (0x202)*/
+			lane_status.raw = get_nibble_at_index(
+				&hpd_irq_dpcd_data->bytes.lane01_status.raw,
+				lane);
+
+			if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
+				!lane_status.bits.CR_DONE_0 ||
+				!lane_status.bits.SYMBOL_LOCKED_0) {
+				/* if one of the channel equalization, clock
+				 * recovery or symbol lock is dropped
+				 * consider it as (link has been
+				 * dropped) dp sink status has changed*/
+				sink_status_changed = true;
+				break;
+			}
+
+		}
+
+		/* Check interlane align.*/
+		if (sink_status_changed ||
+			!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.
+			INTERLANE_ALIGN_DONE) {
+
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_HPD_IRQ,
+				"%s: Link Status changed.\n",
+				__func__);
+
+			return_code = true;
+		}
+	}
+
+	return return_code;
+}
+
+static enum dc_status read_hpd_rx_irq_data(
+	struct core_link *link,
+	union hpd_irq_data *irq_data)
+{
+	/* The HW reads 16 bytes from 200h on HPD,
+	 * but if we get an AUX_DEFER, the HW cannot retry
+	 * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
+	 * fail, so we now explicitly read 6 bytes which is
+	 * the req from the above mentioned test cases.
+	 */
+	return core_link_read_dpcd(
+	link,
+	DPCD_ADDRESS_SINK_COUNT,
+	irq_data->raw,
+	sizeof(union hpd_irq_data));
+}
+
+static bool allow_hpd_rx_irq(const struct core_link *link)
+{
+	/*
+	 * Don't handle RX IRQ unless one of following is met:
+	 * 1) The link is established (cur_link_settings != unknown)
+	 * 2) We kicked off MST detection
+	 * 3) We know we're dealing with an active dongle
+	 */
+
+	if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
+		(link->public.type == dc_connection_mst_branch) ||
+		is_dp_active_dongle(link))
+		return true;
+
+	return false;
+}
+
+bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link)
+{
+	struct core_link *link = DC_LINK_TO_LINK(dc_link);
+	union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}};
+	enum dc_status result = DDC_RESULT_UNKNOWN;
+	bool status = false;
+	/* For use cases related to down stream connection status change,
+	 * PSR and device auto test, refer to function handle_sst_hpd_irq
+	 * in DAL2.1*/
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_HPD_IRQ,
+		"%s: Got short pulse HPD on link %d\n",
+		__func__, link->public.link_index);
+
+	if (!allow_hpd_rx_irq(link)) {
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_HPD_IRQ,
+			"%s: skipping HPD handling on %d\n",
+			__func__, link->public.link_index);
+		return false;
+	}
+
+	 /* All the "handle_hpd_irq_xxx()" methods
+	 * should be called only after
+	 * dal_dpsst_ls_read_hpd_irq_data
+	 * Order of calls is important too
+	 */
+	result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
+
+	if (result != DC_OK) {
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_HPD_IRQ,
+			"%s: DPCD read failed to obtain irq data\n",
+			__func__);
+		return false;
+	}
+
+	/* check if we have MST msg and return since we poll for it */
+	if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY ||
+		hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY)
+		return false;
+
+
+	/* For now we only handle 'Downstream port status' case. */
+	/* If we got sink count changed it means Downstream port status changed,
+	 * then DM should call DC to do the detection. */
+	if (hpd_rx_irq_check_link_loss_status(
+		link,
+		&hpd_irq_dpcd_data)) {
+		perform_link_training(link, &link->cur_link_settings, true);
+		status = false;
+	}
+
+	if (hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
+				!= link->dpcd_sink_count)
+		status = true;
+
+	/* reasons for HPD RX:
+	 * 1. Link Loss - ie Re-train the Link
+	 * 2. MST sideband message
+	 * 3. Automated Test - ie. Internal Commit
+	 * 4. CP (copy protection) - (not interesting for DM???)
+	 * 5. DRR
+	 * 6. Downstream Port status changed -ie. Detect - this the only one
+	 * which is interesting for DM because it must call dc_link_detect.
+	 */
+	return status;
+}
+
+/*query dpcd for version and mst cap addresses*/
+bool is_mst_supported(struct core_link *link)
+{
+	bool mst          = false;
+	enum dc_status st = DC_OK;
+	union dpcd_rev rev;
+	union mstm_cap cap;
+
+	rev.raw  = 0;
+	cap.raw  = 0;
+
+	st = core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, &rev.raw,
+			sizeof(rev));
+
+	if (st == DC_OK && rev.raw >= DPCD_REV_12) {
+
+		st = core_link_read_dpcd(link, DPCD_ADDRESS_MSTM_CAP,
+				&cap.raw, sizeof(cap));
+		if (st == DC_OK && cap.bits.MST_CAP == 1)
+			mst = true;
+	}
+	return mst;
+
+}
+
+bool is_dp_active_dongle(const struct core_link *link)
+{
+	enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type;
+
+	return (dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) ||
+			(dongle_type == DISPLAY_DONGLE_DP_DVI_CONVERTER) ||
+			(dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER);
+}
+
+static void get_active_converter_info(
+	uint8_t data, struct core_link *link)
+{
+	union dp_downstream_port_present ds_port = { .byte = data };
+
+	/* decode converter info*/
+	if (!ds_port.fields.PORT_PRESENT) {
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
+		ddc_service_set_dongle_type(link->ddc,
+				link->dpcd_caps.dongle_type);
+		return;
+	}
+
+	switch (ds_port.fields.PORT_TYPE) {
+	case DOWNSTREAM_VGA:
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
+		break;
+	case DOWNSTREAM_DVI_HDMI:
+		/* At this point we don't know is it DVI or HDMI,
+		 * assume DVI.*/
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
+		break;
+	default:
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
+		break;
+	}
+
+	if (link->dpcd_caps.dpcd_rev.raw >= DCS_DPCD_REV_11) {
+		uint8_t det_caps[4];
+		union dwnstream_port_caps_byte0 *port_caps =
+			(union dwnstream_port_caps_byte0 *)det_caps;
+		core_link_read_dpcd(link, DPCD_ADDRESS_DWN_STRM_PORT0_CAPS,
+				det_caps, sizeof(det_caps));
+
+		switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
+		case DOWN_STREAM_DETAILED_VGA:
+			link->dpcd_caps.dongle_type =
+				DISPLAY_DONGLE_DP_VGA_CONVERTER;
+			break;
+		case DOWN_STREAM_DETAILED_DVI:
+			link->dpcd_caps.dongle_type =
+				DISPLAY_DONGLE_DP_DVI_CONVERTER;
+			break;
+		case DOWN_STREAM_DETAILED_HDMI:
+			link->dpcd_caps.dongle_type =
+				DISPLAY_DONGLE_DP_HDMI_CONVERTER;
+
+			if (ds_port.fields.DETAILED_CAPS) {
+
+				union dwnstream_port_caps_byte3_hdmi
+					hdmi_caps = {.raw = det_caps[3] };
+
+				link->dpcd_caps.is_dp_hdmi_s3d_converter =
+					hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
+			}
+			break;
+		}
+	}
+	ddc_service_set_dongle_type(link->ddc,
+			link->dpcd_caps.dongle_type);
+}
+
+static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data,
+		int length)
+{
+	int retry = 0;
+	struct dp_device_vendor_id dp_id;
+	union dp_downstream_port_present ds_port = { 0 };
+
+	if (!link->dpcd_caps.dpcd_rev.raw) {
+		do {
+			dp_receiver_power_ctrl(link, true);
+			core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV,
+							dpcd_data, length);
+			link->dpcd_caps.dpcd_rev.raw = dpcd_data[
+				DPCD_ADDRESS_DPCD_REV -
+				DPCD_ADDRESS_DPCD_REV];
+		} while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
+	}
+
+	ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT -
+				 DPCD_ADDRESS_DPCD_REV];
+
+	get_active_converter_info(ds_port.byte, link);
+
+	/* read IEEE branch device id */
+	core_link_read_dpcd(link, DPCD_ADDRESS_BRANCH_DEVICE_ID_START,
+			(uint8_t *)&dp_id, sizeof(dp_id));
+	link->dpcd_caps.branch_dev_id =
+			(dp_id.ieee_oui[0] << 16) +
+			(dp_id.ieee_oui[1] << 8) +
+			dp_id.ieee_oui[2];
+
+	if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
+		switch (link->dpcd_caps.branch_dev_id) {
+		/* Some active dongles (DP-VGA, DP-DLDVI converters) power down
+		 * all internal circuits including AUX communication preventing
+		 * reading DPCD table and EDID (spec violation).
+		 * Encoder will skip DP RX power down on disable_output to
+		 * keep receiver powered all the time.*/
+		case DP_BRANCH_DEVICE_ID_1:
+		case DP_BRANCH_DEVICE_ID_4:
+			link->wa_flags.dp_keep_receiver_powered = true;
+			break;
+
+		/* TODO: May need work around for other dongles. */
+		default:
+			link->wa_flags.dp_keep_receiver_powered = false;
+			break;
+		}
+	} else
+		link->wa_flags.dp_keep_receiver_powered = false;
+}
+
+static void retrieve_link_cap(struct core_link *link)
+{
+	uint8_t dpcd_data[
+			DPCD_ADDRESS_EDP_CONFIG_CAP -
+			DPCD_ADDRESS_DPCD_REV + 1];
+
+	union down_stream_port_count down_strm_port_count;
+	union edp_configuration_cap edp_config_cap;
+	union max_down_spread max_down_spread;
+	union dp_downstream_port_present ds_port = { 0 };
+
+	dm_memset(dpcd_data, '\0', sizeof(dpcd_data));
+	dm_memset(&down_strm_port_count,
+		'\0', sizeof(union down_stream_port_count));
+	dm_memset(&edp_config_cap, '\0',
+		sizeof(union edp_configuration_cap));
+	dm_memset(&max_down_spread, '\0',
+		sizeof(union max_down_spread));
+
+	core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV,
+			dpcd_data, sizeof(dpcd_data));
+	link->dpcd_caps.dpcd_rev.raw = dpcd_data[
+		DPCD_ADDRESS_DPCD_REV -
+		DPCD_ADDRESS_DPCD_REV];
+
+	ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT -
+				 DPCD_ADDRESS_DPCD_REV];
+
+	get_active_converter_info(ds_port.byte, link);
+
+	dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
+
+	link->dpcd_caps.allow_invalid_MSA_timing_param =
+		down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
+
+	link->dpcd_caps.max_ln_count.raw = dpcd_data[
+		DPCD_ADDRESS_MAX_LANE_COUNT - DPCD_ADDRESS_DPCD_REV];
+
+	max_down_spread.raw = dpcd_data[
+		DPCD_ADDRESS_MAX_DOWNSPREAD - DPCD_ADDRESS_DPCD_REV];
+
+	link->reported_link_cap.lane_count =
+		link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
+	link->reported_link_cap.link_rate = dpcd_data[
+		DPCD_ADDRESS_MAX_LINK_RATE - DPCD_ADDRESS_DPCD_REV];
+	link->reported_link_cap.link_spread =
+		max_down_spread.bits.MAX_DOWN_SPREAD ?
+		LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
+
+	edp_config_cap.raw = dpcd_data[
+		DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV];
+	link->dpcd_caps.panel_mode_edp =
+		edp_config_cap.bits.ALT_SCRAMBLER_RESET;
+
+	link->edp_revision = DPCD_EDP_REVISION_EDP_UNKNOWN;
+
+	/* read sink count */
+	core_link_read_dpcd(link,
+			DPCD_ADDRESS_SINK_COUNT,
+			&link->dpcd_caps.sink_count.raw,
+			sizeof(link->dpcd_caps.sink_count.raw));
+
+	/* Display control registers starting at DPCD 700h are only valid and
+	 * enabled if this eDP config cap bit is set. */
+	if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) {
+		/* Read the Panel's eDP revision at DPCD 700h. */
+		core_link_read_dpcd(link,
+			DPCD_ADDRESS_EDP_REV,
+			(uint8_t *)(&link->edp_revision),
+			sizeof(link->edp_revision));
+	}
+	/* TODO: Confirm if need retrieve_psr_link_cap */
+}
+
+void detect_dp_sink_caps(struct core_link *link)
+{
+	retrieve_link_cap(link);
+
+	/* dc init_hw has power encoder using default
+	 * signal for connector. For native DP, no
+	 * need to power up encoder again. If not native
+	 * DP, hw_init may need check signal or power up
+	 * encoder here.
+	 */
+
+	if (is_mst_supported(link)) {
+		link->verified_link_cap = link->reported_link_cap;
+	} else {
+		dp_hbr_verify_link_cap(link,
+			&link->reported_link_cap);
+	}
+	/* TODO save sink caps in link->sink */
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
new file mode 100644
index 000000000000..39aa734680c6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
@@ -0,0 +1,201 @@
+/* Copyright 2015 Advanced Micro Devices, Inc. */
+
+#include "dm_services.h"
+#include "dc.h"
+#include "inc/core_dc.h"
+#include "include/ddc_service_types.h"
+#include "include/i2caux_interface.h"
+#include "link_hwss.h"
+#include "hw_sequencer.h"
+#include "dc_link_ddc.h"
+#include "dm_helpers.h"
+#include "dce110/dce110_link_encoder.h"
+#include "dce110/dce110_stream_encoder.h"
+
+
+enum dc_status core_link_read_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t size)
+{
+	if (!dm_helper_dp_read_dpcd(link->ctx,
+			&link->public,
+			address, data, size))
+			return DC_ERROR_UNEXPECTED;
+
+	return DC_OK;
+}
+
+enum dc_status core_link_write_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t size)
+{
+	if (!dm_helper_dp_write_dpcd(link->ctx,
+			&link->public,
+			address, data, size))
+				return DC_ERROR_UNEXPECTED;
+
+	return DC_OK;
+}
+
+void dp_receiver_power_ctrl(struct core_link *link, bool on)
+{
+	uint8_t state;
+
+	state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
+
+	core_link_write_dpcd(link, DPCD_ADDRESS_POWER_STATE, &state,
+			sizeof(state));
+}
+
+void dp_enable_link_phy(
+	struct core_link *link,
+	enum signal_type signal,
+	const struct link_settings *link_settings)
+{
+	struct link_encoder *link_enc = link->link_enc;
+
+	if (dc_is_dp_sst_signal(signal)) {
+		if (signal == SIGNAL_TYPE_EDP) {
+			link_enc->funcs->power_control(link_enc, true);
+			link_enc->funcs->backlight_control(link_enc, true);
+		}
+
+		link_enc->funcs->enable_dp_output(
+						link_enc,
+						link_settings,
+						CLOCK_SOURCE_ID_EXTERNAL);
+	} else {
+		link_enc->funcs->enable_dp_mst_output(
+						link_enc,
+						link_settings,
+						CLOCK_SOURCE_ID_EXTERNAL);
+	}
+
+	dp_receiver_power_ctrl(link, true);
+}
+
+void dp_disable_link_phy(struct core_link *link, enum signal_type signal)
+{
+	if (!link->wa_flags.dp_keep_receiver_powered)
+		dp_receiver_power_ctrl(link, false);
+
+	if (signal == SIGNAL_TYPE_EDP)
+		link->link_enc->funcs->backlight_control(link->link_enc, false);
+
+	link->link_enc->funcs->disable_output(link->link_enc, signal);
+
+	/* Clear current link setting.*/
+	dm_memset(&link->cur_link_settings, 0,
+			sizeof(link->cur_link_settings));
+}
+
+void dp_disable_link_phy_mst(struct core_link *link, struct core_stream *stream)
+{
+	/* MST disable link only when no stream use the link */
+	if (link->mst_stream_alloc_table.stream_count > 0)
+		return;
+
+	dp_disable_link_phy(link, stream->signal);
+}
+
+bool dp_set_hw_training_pattern(
+	struct core_link *link,
+	enum hw_dp_training_pattern pattern)
+{
+	enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
+	struct encoder_set_dp_phy_pattern_param pattern_param = {0};
+	struct link_encoder *encoder = link->link_enc;
+
+	switch (pattern) {
+	case HW_DP_TRAINING_PATTERN_1:
+		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
+		break;
+	case HW_DP_TRAINING_PATTERN_2:
+		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
+		break;
+	case HW_DP_TRAINING_PATTERN_3:
+		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
+		break;
+	default:
+		break;
+	}
+
+	pattern_param.dp_phy_pattern = test_pattern;
+	pattern_param.custom_pattern = NULL;
+	pattern_param.custom_pattern_size = 0;
+	pattern_param.dp_panel_mode = dp_get_panel_mode(link);
+
+	encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
+
+	return true;
+}
+
+
+void dp_set_hw_lane_settings(
+	struct core_link *link,
+	const struct link_training_settings *link_settings)
+{
+	struct link_encoder *encoder = link->link_enc;
+
+	/* call Encoder to set lane settings */
+	encoder->funcs->dp_set_lane_settings(encoder, link_settings);
+}
+
+enum dp_panel_mode dp_get_panel_mode(struct core_link *link)
+{
+	/* We need to explicitly check that connector
+	 * is not DP. Some Travis_VGA get reported
+	 * by video bios as DP.
+	 */
+	if (link->public.connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
+
+		switch (link->dpcd_caps.branch_dev_id) {
+		case DP_BRANCH_DEVICE_ID_2:
+			if (strncmp(
+				link->dpcd_caps.branch_dev_name,
+				DP_VGA_LVDS_CONVERTER_ID_2,
+				sizeof(
+				link->dpcd_caps.
+				branch_dev_name)) == 0) {
+				return DP_PANEL_MODE_SPECIAL;
+			}
+			break;
+		case DP_BRANCH_DEVICE_ID_3:
+			if (strncmp(link->dpcd_caps.branch_dev_name,
+				DP_VGA_LVDS_CONVERTER_ID_3,
+				sizeof(
+				link->dpcd_caps.
+				branch_dev_name)) == 0) {
+				return DP_PANEL_MODE_SPECIAL;
+			}
+			break;
+		default:
+			break;
+		}
+
+		if (link->dpcd_caps.panel_mode_edp) {
+			return DP_PANEL_MODE_EDP;
+		}
+	}
+
+	return DP_PANEL_MODE_DEFAULT;
+}
+
+void dp_set_hw_test_pattern(
+	struct core_link *link,
+	enum dp_test_pattern test_pattern)
+{
+	struct encoder_set_dp_phy_pattern_param pattern_param = {0};
+	struct link_encoder *encoder = link->link_enc;
+
+	pattern_param.dp_phy_pattern = test_pattern;
+	pattern_param.custom_pattern = NULL;
+	pattern_param.custom_pattern_size = 0;
+	pattern_param.dp_panel_mode = dp_get_panel_mode(link);
+
+	encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
new file mode 100644
index 000000000000..8cb756e99bfd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
@@ -0,0 +1,1243 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+#include "link_encoder.h"
+#include "stream_encoder.h"
+#include "opp.h"
+#include "transform.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce100/dce100_resource.h"
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/dce110_resource.h"
+#endif
+
+bool dc_construct_resource_pool(struct adapter_service *adapter_serv,
+				struct dc *dc,
+				uint8_t num_virtual_links)
+{
+	enum dce_version dce_ver = dal_adapter_service_get_dce_version(adapter_serv);
+
+	switch (dce_ver) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dce100_construct_resource_pool(
+			adapter_serv, num_virtual_links, dc, &dc->res_pool);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dce110_construct_resource_pool(
+			adapter_serv, num_virtual_links, dc, &dc->res_pool);
+#endif
+	default:
+		break;
+	}
+
+	return false;
+}
+
+void unreference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.clk_src_count; i++) {
+		if (res_ctx->pool.clock_sources[i] == clock_source) {
+			res_ctx->clock_source_ref_count[i]--;
+
+		if (res_ctx->clock_source_ref_count[i] == 0)
+			clock_source->funcs->cs_power_down(clock_source);
+		}
+	}
+
+
+}
+
+void reference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.clk_src_count; i++) {
+		if (res_ctx->pool.clock_sources[i] == clock_source) {
+			res_ctx->clock_source_ref_count[i]++;
+		}
+	}
+}
+
+bool is_same_timing(
+	const struct dc_crtc_timing *timing1,
+	const struct dc_crtc_timing *timing2)
+{
+	return dm_memcmp(timing1, timing2, sizeof(struct dc_crtc_timing)) == 0;
+}
+
+static bool is_sharable_clk_src(
+	const struct core_stream *stream_with_clk_src,
+	const struct core_stream *stream)
+{
+	enum clock_source_id id = stream_with_clk_src->clock_source->id;
+
+	if (stream_with_clk_src->clock_source == NULL)
+		return false;
+
+	if (id == CLOCK_SOURCE_ID_EXTERNAL)
+		return false;
+
+	/* Sharing dual link is not working */
+	if (stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK ||
+			stream_with_clk_src->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
+			return false;
+
+	if(!is_same_timing(
+		&stream_with_clk_src->public.timing, &stream->public.timing))
+		return false;
+
+	return true;
+}
+
+struct clock_source *find_used_clk_src_for_sharing(
+					struct validate_context *context,
+					struct core_stream *stream)
+{
+	uint8_t i, j;
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *clock_source_stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			if (clock_source_stream->clock_source == NULL)
+				continue;
+
+			if (is_sharable_clk_src(clock_source_stream, stream))
+				return clock_source_stream->clock_source;
+		}
+	}
+
+	return NULL;
+}
+
+static enum pixel_format convert_pixel_format_to_dalsurface(
+		enum surface_pixel_format surface_pixel_format)
+{
+	enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+
+	switch (surface_pixel_format) {
+	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
+		dal_pixel_format = PIXEL_FORMAT_INDEX8;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+		dal_pixel_format = PIXEL_FORMAT_RGB565;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+		dal_pixel_format = PIXEL_FORMAT_RGB565;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
+		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+		dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+		dal_pixel_format = PIXEL_FORMAT_FP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+		dal_pixel_format = PIXEL_FORMAT_FP16;
+		break;
+
+
+	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+		dal_pixel_format = PIXEL_FORMAT_420BPP12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+		dal_pixel_format = PIXEL_FORMAT_420BPP12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCb:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCr:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb1555:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_CrYCb565:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb4444:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA5551:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb8888:
+		dal_pixel_format = PIXEL_FORMAT_444BPP32;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb2101010:
+		dal_pixel_format = PIXEL_FORMAT_444BPP32;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA1010102:
+		dal_pixel_format = PIXEL_FORMAT_444BPP32;
+		break;
+	default:
+		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+		break;
+	}
+	return dal_pixel_format;
+}
+
+static void calculate_viewport(
+		const struct dc_surface *surface,
+		struct core_stream *stream)
+{
+	const struct rect src = surface->src_rect;
+	const struct rect clip = surface->clip_rect;
+	const struct rect dst = surface->dst_rect;
+
+	/* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
+	 * num_pixels = clip.num_pix * scl_ratio
+	 */
+	stream->viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width;
+	stream->viewport.width = clip.width * src.width / dst.width;
+
+	stream->viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height;
+	stream->viewport.height = clip.height * src.height / dst.height;
+
+	/* Minimum viewport such that 420/422 chroma vp is non 0 */
+	if (stream->viewport.width < 2)
+	{
+		stream->viewport.width = 2;
+	}
+	if (stream->viewport.height < 2)
+	{
+		stream->viewport.height = 2;
+	}
+}
+
+static void calculate_overscan(
+		const struct dc_surface *surface,
+		struct core_stream *stream)
+{
+	stream->overscan.left = stream->public.dst.x;
+	if (stream->public.src.x < surface->clip_rect.x)
+		stream->overscan.left += (surface->clip_rect.x
+			- stream->public.src.x) * stream->public.dst.width
+			/ stream->public.src.width;
+
+	stream->overscan.right = stream->public.timing.h_addressable
+		- stream->public.dst.x - stream->public.dst.width;
+	if (stream->public.src.x + stream->public.src.width
+		> surface->clip_rect.x + surface->clip_rect.width)
+		stream->overscan.right = stream->public.timing.h_addressable -
+			dal_fixed31_32_floor(dal_fixed31_32_div(
+				dal_fixed31_32_from_int(
+						stream->viewport.width),
+						stream->ratios.horz)) -
+						stream->overscan.left;
+
+
+	stream->overscan.top = stream->public.dst.y;
+	if (stream->public.src.y < surface->clip_rect.y)
+		stream->overscan.top += (surface->clip_rect.y
+			- stream->public.src.y) * stream->public.dst.height
+			/ stream->public.src.height;
+
+	stream->overscan.bottom = stream->public.timing.v_addressable
+		- stream->public.dst.y - stream->public.dst.height;
+	if (stream->public.src.y + stream->public.src.height
+		> surface->clip_rect.y + surface->clip_rect.height)
+		stream->overscan.bottom = stream->public.timing.v_addressable -
+			dal_fixed31_32_floor(dal_fixed31_32_div(
+				dal_fixed31_32_from_int(
+						stream->viewport.height),
+						stream->ratios.vert)) -
+						stream->overscan.top;
+
+
+	/* TODO: Add timing overscan to finalize overscan calculation*/
+}
+
+static void calculate_scaling_ratios(
+		const struct dc_surface *surface,
+		struct core_stream *stream)
+{
+	const uint32_t in_w = stream->public.src.width;
+	const uint32_t in_h = stream->public.src.height;
+	const uint32_t out_w = stream->public.dst.width;
+	const uint32_t out_h = stream->public.dst.height;
+
+	stream->ratios.horz = dal_fixed31_32_from_fraction(
+					surface->src_rect.width,
+					surface->dst_rect.width);
+	stream->ratios.vert = dal_fixed31_32_from_fraction(
+					surface->src_rect.height,
+					surface->dst_rect.height);
+
+	if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE)
+		stream->ratios.horz.value *= 2;
+	else if (surface->stereo_format
+					== PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
+		stream->ratios.vert.value *= 2;
+
+	stream->ratios.vert.value = div64_s64(stream->ratios.vert.value * in_h,
+			out_h);
+	stream->ratios.horz.value = div64_s64(stream->ratios.horz.value * in_w ,
+			out_w);
+
+	stream->ratios.horz_c = stream->ratios.horz;
+	stream->ratios.vert_c = stream->ratios.vert;
+
+	if (stream->format == PIXEL_FORMAT_420BPP12) {
+		stream->ratios.horz_c.value /= 2;
+		stream->ratios.vert_c.value /= 2;
+	} else if (stream->format == PIXEL_FORMAT_422BPP16) {
+		stream->ratios.horz_c.value /= 2;
+	}
+}
+
+/*TODO: per pipe not per stream*/
+void build_scaling_params(
+	const struct dc_surface *surface,
+	struct core_stream *stream)
+{
+	/* Important: scaling ratio calculation requires pixel format,
+	 * overscan calculation requires scaling ratios and viewport
+	 * and lb depth/taps calculation requires overscan. Call sequence
+	 * is therefore important */
+	stream->format = convert_pixel_format_to_dalsurface(surface->format);
+
+	calculate_viewport(surface, stream);
+
+	calculate_scaling_ratios(surface, stream);
+
+	calculate_overscan(surface, stream);
+
+	/* Check if scaling is required update taps if not */
+	if (dal_fixed31_32_u2d19(stream->ratios.horz) == 1 << 19)
+		stream->taps.h_taps = 1;
+	else
+		stream->taps.h_taps = surface->scaling_quality.h_taps;
+
+	if (dal_fixed31_32_u2d19(stream->ratios.horz_c) == 1 << 19)
+		stream->taps.h_taps_c = 1;
+	else
+		stream->taps.h_taps_c = surface->scaling_quality.h_taps_c;
+
+	if (dal_fixed31_32_u2d19(stream->ratios.vert) == 1 << 19)
+		stream->taps.v_taps = 1;
+	else
+		stream->taps.v_taps = surface->scaling_quality.v_taps;
+
+	if (dal_fixed31_32_u2d19(stream->ratios.vert_c) == 1 << 19)
+		stream->taps.v_taps_c = 1;
+	else
+		stream->taps.v_taps_c = surface->scaling_quality.v_taps_c;
+
+	dal_logger_write(stream->ctx->logger,
+				LOG_MAJOR_DCP,
+				LOG_MINOR_DCP_SCALER,
+				"%s: Overscan:\n bot:%d left:%d right:%d "
+				"top:%d\nViewport:\nheight:%d width:%d x:%d "
+				"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
+				"y:%d\n",
+				__func__,
+				stream->overscan.bottom,
+				stream->overscan.left,
+				stream->overscan.right,
+				stream->overscan.top,
+				stream->viewport.height,
+				stream->viewport.width,
+				stream->viewport.x,
+				stream->viewport.y,
+				surface->dst_rect.height,
+				surface->dst_rect.width,
+				surface->dst_rect.x,
+				surface->dst_rect.y);
+}
+
+void build_scaling_params_for_context(
+	const struct dc *dc,
+	struct validate_context *context)
+{
+	uint8_t i, j, k;
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		if (context->target_flags[i].unchanged)
+			continue;
+		for (j = 0; j < target->status.surface_count; j++) {
+			const struct dc_surface *surface =
+				target->status.surfaces[j];
+			for (k = 0; k < target->public.stream_count; k++) {
+				struct core_stream *stream =
+					DC_STREAM_TO_CORE(
+						target->public.streams[k]);
+
+				build_scaling_params(surface, stream);
+			}
+		}
+	}
+}
+
+bool logical_attach_surfaces_to_target(
+		struct dc_surface *surfaces[],
+		uint8_t surface_count,
+		struct dc_target *dc_target)
+{
+	uint8_t i;
+	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+
+	if (surface_count > MAX_SURFACE_NUM) {
+		dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
+			surface_count, MAX_SURFACE_NUM);
+		return false;
+	}
+
+	for (i = 0; i < target->status.surface_count; i++)
+		dc_surface_release(target->status.surfaces[i]);
+
+	for (i = 0; i < surface_count; i++) {
+		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
+		surface->status.dc_target = &target->public;
+		target->status.surfaces[i] = surfaces[i];
+		dc_surface_retain(target->status.surfaces[i]);
+	}
+	target->status.surface_count = surface_count;
+
+	return true;
+}
+
+static uint32_t get_min_vblank_time_us(const struct validate_context *context)
+{
+	uint8_t i, j;
+	uint32_t min_vertical_blank_time = -1;
+
+	for (i = 0; i < context->target_count; i++) {
+		const struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			const struct dc_stream *stream =
+						target->public.streams[j];
+			uint32_t vertical_blank_in_pixels = 0;
+			uint32_t vertical_blank_time = 0;
+
+			vertical_blank_in_pixels = stream->timing.h_total *
+				(stream->timing.v_total
+					- stream->timing.v_addressable);
+			vertical_blank_time = vertical_blank_in_pixels
+				* 1000 / stream->timing.pix_clk_khz;
+			if (min_vertical_blank_time > vertical_blank_time)
+				min_vertical_blank_time = vertical_blank_time;
+		}
+	}
+	return min_vertical_blank_time;
+}
+
+static void fill_display_configs(
+	const struct validate_context *context,
+	struct dc_pp_display_configuration *pp_display_cfg)
+{
+	uint8_t i, j;
+	uint8_t num_cfgs = 0;
+
+	for (i = 0; i < context->target_count; i++) {
+		const struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			const struct core_stream *stream =
+			DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct dc_pp_single_disp_config *cfg =
+					&pp_display_cfg->disp_configs[num_cfgs];
+
+			num_cfgs++;
+			cfg->signal = stream->signal;
+			cfg->pipe_idx = stream->opp->inst;
+			cfg->src_height = stream->public.src.height;
+			cfg->src_width = stream->public.src.width;
+			cfg->ddi_channel_mapping =
+				stream->sink->link->ddi_channel_mapping.raw;
+			cfg->transmitter =
+				stream->sink->link->link_enc->transmitter;
+			cfg->link_settings =
+					stream->sink->link->cur_link_settings;
+			cfg->sym_clock = stream->public.timing.pix_clk_khz;
+			switch (stream->public.timing.display_color_depth) {
+			case COLOR_DEPTH_101010:
+				cfg->sym_clock = (cfg->sym_clock * 30) / 24;
+				break;
+			case COLOR_DEPTH_121212:
+				cfg->sym_clock = (cfg->sym_clock * 36) / 24;
+				break;
+			case COLOR_DEPTH_161616:
+				cfg->sym_clock = (cfg->sym_clock * 48) / 24;
+				break;
+			default:
+				break;
+			}
+			/* TODO: unhardcode*/
+			cfg->v_refresh = 60;
+		}
+	}
+	pp_display_cfg->display_count = num_cfgs;
+}
+
+void pplib_apply_safe_state(
+	const struct dc *dc)
+{
+	dm_pp_apply_safe_state(dc->ctx);
+}
+
+void pplib_apply_display_requirements(
+	const struct dc *dc,
+	const struct validate_context *context)
+{
+	struct dc_pp_display_configuration pp_display_cfg = { 0 };
+
+	pp_display_cfg.all_displays_in_sync =
+		context->bw_results.all_displays_in_sync;
+	pp_display_cfg.nb_pstate_switch_disable =
+			context->bw_results.nbp_state_change_enable == false;
+	pp_display_cfg.cpu_cc6_disable =
+			context->bw_results.cpuc_state_change_enable == false;
+	pp_display_cfg.cpu_pstate_disable =
+			context->bw_results.cpup_state_change_enable == false;
+	pp_display_cfg.cpu_pstate_separation_time =
+			context->bw_results.required_blackout_duration_us;
+
+	pp_display_cfg.min_memory_clock_khz = context->bw_results.required_yclk
+		/ MEMORY_TYPE_MULTIPLIER;
+	pp_display_cfg.min_engine_clock_khz = context->bw_results.required_sclk;
+	pp_display_cfg.min_engine_clock_deep_sleep_khz
+			= context->bw_results.required_sclk_deep_sleep;
+
+	pp_display_cfg.avail_mclk_switch_time_us =
+						get_min_vblank_time_us(context);
+	pp_display_cfg.avail_mclk_switch_time_in_disp_active_us = 0;
+
+	pp_display_cfg.disp_clk_khz = context->bw_results.dispclk_khz;
+
+	fill_display_configs(context, &pp_display_cfg);
+
+	/* TODO: is this still applicable?*/
+	if (pp_display_cfg.display_count == 1) {
+		const struct dc_crtc_timing *timing =
+			&context->targets[0]->public.streams[0]->timing;
+
+		pp_display_cfg.crtc_index =
+			pp_display_cfg.disp_configs[0].pipe_idx;
+		pp_display_cfg.line_time_in_us = timing->h_total * 1000
+							/ timing->pix_clk_khz;
+	}
+
+	dm_pp_apply_display_requirements(dc->ctx, &pp_display_cfg);
+}
+
+/* Maximum TMDS single link pixel clock 165MHz */
+#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
+
+static void attach_stream_to_controller(
+		struct resource_context *res_ctx,
+		struct core_stream *stream)
+{
+	res_ctx->controller_ctx[stream->controller_idx].stream = stream;
+}
+
+static void set_stream_engine_in_use(
+		struct resource_context *res_ctx,
+		struct stream_encoder *stream_enc)
+{
+	int i;
+
+	for (i = 0; i < res_ctx->pool.stream_enc_count; i++) {
+		if (res_ctx->pool.stream_enc[i] == stream_enc)
+			res_ctx->is_stream_enc_acquired[i] = true;
+	}
+}
+
+/* TODO: release audio object */
+static void set_audio_in_use(
+		struct resource_context *res_ctx,
+		struct audio *audio)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.audio_count; i++) {
+		if (res_ctx->pool.audios[i] == audio) {
+			res_ctx->is_audio_acquired[i] = true;
+		}
+	}
+}
+
+static bool assign_first_free_controller(
+		struct resource_context *res_ctx,
+		struct core_stream *stream)
+{
+	uint8_t i;
+	for (i = 0; i < res_ctx->pool.controller_count; i++) {
+		if (!res_ctx->controller_ctx[i].stream) {
+			stream->tg = res_ctx->pool.timing_generators[i];
+			stream->mi = res_ctx->pool.mis[i];
+			stream->ipp = res_ctx->pool.ipps[i];
+			stream->xfm = res_ctx->pool.transforms[i];
+			stream->opp = res_ctx->pool.opps[i];
+			stream->controller_idx = i;
+			stream->dis_clk = res_ctx->pool.display_clock;
+			return true;
+		}
+	}
+	return false;
+}
+
+static struct stream_encoder *find_first_free_match_stream_enc_for_link(
+		struct resource_context *res_ctx,
+		struct core_link *link)
+{
+	uint8_t i;
+	int8_t j = -1;
+	const struct dc_sink *sink = NULL;
+
+	for (i = 0; i < res_ctx->pool.stream_enc_count; i++) {
+		if (!res_ctx->is_stream_enc_acquired[i] &&
+					res_ctx->pool.stream_enc[i]) {
+			/* Store first available for MST second display
+			 * in daisy chain use case */
+			j = i;
+			if (res_ctx->pool.stream_enc[i]->id ==
+					link->link_enc->preferred_engine)
+				return res_ctx->pool.stream_enc[i];
+		}
+	}
+
+	/*
+	 * below can happen in cases when stream encoder is acquired:
+	 * 1) for second MST display in chain, so preferred engine already
+	 * acquired;
+	 * 2) for another link, which preferred engine already acquired by any
+	 * MST configuration.
+	 *
+	 * If signal is of DP type and preferred engine not found, return last available
+	 *
+	 * TODO - This is just a patch up and a generic solution is
+	 * required for non DP connectors.
+	 */
+
+	sink = link->public.local_sink ? link->public.local_sink : link->public.remote_sinks[0];
+
+	if (sink && j >= 0 &&  dc_is_dp_signal(sink->sink_signal))
+		return res_ctx->pool.stream_enc[j];
+
+	return NULL;
+}
+
+static struct audio *find_first_free_audio(struct resource_context *res_ctx)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.audio_count; i++) {
+		if (res_ctx->is_audio_acquired[i] == false) {
+			return res_ctx->pool.audios[i];
+		}
+	}
+
+	return 0;
+}
+
+static bool check_timing_change(struct core_stream *cur_stream,
+		struct core_stream *new_stream)
+{
+	if (cur_stream == NULL)
+		return true;
+
+	/* If sink pointer changed, it means this is a hotplug, we should do
+	 * full hw setting.
+	 */
+	if (cur_stream->sink != new_stream->sink)
+		return true;
+
+	return !is_same_timing(
+					&cur_stream->public.timing,
+					&new_stream->public.timing);
+}
+
+static void set_stream_signal(struct core_stream *stream)
+{
+	struct dc_sink *dc_sink = (struct dc_sink *)stream->public.sink;
+
+	/* For asic supports dual link DVI, we should adjust signal type
+	 * based on timing pixel clock. If pixel clock more than 165Mhz,
+	 * signal is dual link, otherwise, single link.
+	 */
+	if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
+			dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) {
+		if (stream->public.timing.pix_clk_khz >
+			TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
+			dc_sink->sink_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+		else
+			dc_sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+	}
+
+	stream->signal = dc_sink->sink_signal;
+}
+
+enum dc_status map_resources(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	uint8_t i, j;
+
+	/* mark resources used for targets that are already active */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (!context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			attach_stream_to_controller(
+				&context->res_ctx,
+				stream);
+
+			set_stream_engine_in_use(
+				&context->res_ctx,
+				stream->stream_enc);
+
+			reference_clock_source(
+				&context->res_ctx,
+				stream->clock_source);
+
+			if (stream->audio) {
+				set_audio_in_use(&context->res_ctx,
+					stream->audio);
+			}
+		}
+	}
+
+	/* acquire new resources */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct core_stream *curr_stream;
+
+			if (!assign_first_free_controller(
+					&context->res_ctx, stream))
+				return DC_NO_CONTROLLER_RESOURCE;
+
+			attach_stream_to_controller(&context->res_ctx, stream);
+
+			set_stream_signal(stream);
+
+			curr_stream =
+				dc->current_context.res_ctx.controller_ctx
+				[stream->controller_idx].stream;
+			context->res_ctx.controller_ctx[stream->controller_idx]
+			.flags.timing_changed =
+				check_timing_change(curr_stream, stream);
+
+			stream->stream_enc =
+				find_first_free_match_stream_enc_for_link(
+					&context->res_ctx,
+					stream->sink->link);
+
+			if (!stream->stream_enc)
+				return DC_NO_STREAM_ENG_RESOURCE;
+
+			set_stream_engine_in_use(
+					&context->res_ctx,
+					stream->stream_enc);
+
+			/* TODO: Add check if ASIC support and EDID audio */
+			if (!stream->sink->converter_disable_audio &&
+						dc_is_audio_capable_signal(
+						stream->signal)) {
+				stream->audio = find_first_free_audio(
+						&context->res_ctx);
+
+				if (!stream->audio)
+					return DC_NO_STREAM_AUDIO_RESOURCE;
+
+				set_audio_in_use(&context->res_ctx,
+						stream->audio);
+			}
+		}
+	}
+
+	return DC_OK;
+}
+
+static enum ds_color_space build_default_color_space(
+		struct core_stream *stream)
+{
+	enum ds_color_space color_space =
+			DS_COLOR_SPACE_SRGB_FULLRANGE;
+	struct dc_crtc_timing *timing = &stream->public.timing;
+
+	switch (stream->signal) {
+	/* TODO: implement other signal color space setting */
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	{
+		uint32_t pix_clk_khz;
+
+		if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 &&
+			timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) {
+			if (timing->timing_standard ==
+					TIMING_STANDARD_CEA770 &&
+				timing->timing_standard ==
+						TIMING_STANDARD_CEA861)
+				color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+
+			pix_clk_khz = timing->pix_clk_khz / 10;
+			if (timing->h_addressable == 640 &&
+				timing->v_addressable == 480 &&
+				(pix_clk_khz == 2520 || pix_clk_khz == 2517))
+				color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+		} else {
+			if (timing->timing_standard ==
+					TIMING_STANDARD_CEA770 ||
+					timing->timing_standard ==
+					TIMING_STANDARD_CEA861) {
+
+				color_space =
+					(timing->pix_clk_khz > PIXEL_CLOCK) ?
+						DS_COLOR_SPACE_YCBCR709 :
+						DS_COLOR_SPACE_YCBCR601;
+			}
+		}
+		break;
+	}
+	default:
+		switch (timing->pixel_encoding) {
+		case PIXEL_ENCODING_YCBCR422:
+		case PIXEL_ENCODING_YCBCR444:
+			if (timing->pix_clk_khz > PIXEL_CLOCK)
+				color_space = DS_COLOR_SPACE_YCBCR709;
+			else
+				color_space = DS_COLOR_SPACE_YCBCR601;
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+	return color_space;
+}
+
+static void translate_info_frame(const struct hw_info_frame *hw_info_frame,
+	struct encoder_info_frame *encoder_info_frame)
+{
+	dm_memset(
+		encoder_info_frame, 0, sizeof(struct encoder_info_frame));
+
+	/* For gamut we recalc checksum */
+	if (hw_info_frame->gamut_packet.valid) {
+		uint8_t chk_sum = 0;
+		uint8_t *ptr;
+		uint8_t i;
+
+		dm_memmove(
+						&encoder_info_frame->gamut,
+						&hw_info_frame->gamut_packet,
+						sizeof(struct hw_info_packet));
+
+		/*start of the Gamut data. */
+		ptr = &encoder_info_frame->gamut.sb[3];
+
+		for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++)
+			chk_sum += ptr[i];
+
+		encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum);
+	}
+
+	if (hw_info_frame->avi_info_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->avi,
+						&hw_info_frame->avi_info_packet,
+						sizeof(struct hw_info_packet));
+	}
+
+	if (hw_info_frame->vendor_info_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->vendor,
+						&hw_info_frame->vendor_info_packet,
+						sizeof(struct hw_info_packet));
+	}
+
+	if (hw_info_frame->spd_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->spd,
+						&hw_info_frame->spd_packet,
+						sizeof(struct hw_info_packet));
+	}
+
+	if (hw_info_frame->vsc_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->vsc,
+						&hw_info_frame->vsc_packet,
+						sizeof(struct hw_info_packet));
+	}
+}
+
+static void set_avi_info_frame(struct hw_info_packet *info_packet,
+		struct core_stream *stream)
+{
+	enum ds_color_space color_space = DS_COLOR_SPACE_UNKNOWN;
+	struct info_frame info_frame = { {0} };
+	uint32_t pixel_encoding = 0;
+	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
+	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
+	bool itc = false;
+	uint8_t cn0_cn1 = 0;
+	uint8_t *check_sum = NULL;
+	uint8_t byte_index = 0;
+
+	if (info_packet == NULL)
+		return;
+
+	color_space = build_default_color_space(stream);
+
+	/* Initialize header */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.header.
+			info_frame_type = INFO_FRAME_AVI;
+	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
+	* not be used in HDMI 2.0 (Section 10.1) */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.header.version =
+			INFO_FRAME_VERSION_2;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.header.length =
+			INFO_FRAME_SIZE_AVI;
+
+	/* IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
+	* according to HDMI 2.0 spec (Section 10.1)
+	* Add "case PixelEncoding_YCbCr420:    pixelEncoding = 3; break;"
+	* when YCbCr 4:2:0 is supported by DAL hardware. */
+
+	switch (stream->public.timing.pixel_encoding) {
+	case PIXEL_ENCODING_YCBCR422:
+		pixel_encoding = 1;
+		break;
+
+	case PIXEL_ENCODING_YCBCR444:
+		pixel_encoding = 2;
+		break;
+
+	case PIXEL_ENCODING_RGB:
+	default:
+		pixel_encoding = 0;
+	}
+
+	/* Y0_Y1_Y2 : The pixel encoding */
+	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 =
+		pixel_encoding;
+
+
+	/* A0 = 1 Active Format Information valid */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.A0 =
+		ACTIVE_FORMAT_VALID;
+
+	/* B0, B1 = 3; Bar info data is valid */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 =
+		BAR_INFO_BOTH_VALID;
+
+	info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 =
+			PICTURE_SCALING_UNIFORM;
+
+	/* S0, S1 : Underscan / Overscan */
+	/* TODO: un-hardcode scan type */
+	scan_type = SCANNING_TYPE_UNDERSCAN;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type;
+
+	/* C0, C1 : Colorimetry */
+	if (color_space == DS_COLOR_SPACE_YCBCR709)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_ITU709;
+	else if (color_space == DS_COLOR_SPACE_YCBCR601)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_ITU601;
+	else
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_NO_DATA;
+
+
+	/* TODO: un-hardcode aspect ratio */
+	aspect = stream->public.timing.aspect_ratio;
+
+	switch (aspect) {
+	case ASPECT_RATIO_4_3:
+	case ASPECT_RATIO_16_9:
+		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect;
+		break;
+
+	case ASPECT_RATIO_NO_DATA:
+	case ASPECT_RATIO_64_27:
+	case ASPECT_RATIO_256_135:
+	default:
+		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0;
+	}
+
+	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 =
+			ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
+
+	/* TODO: un-hardcode cn0_cn1 and itc */
+	cn0_cn1 = 0;
+	itc = false;
+
+	if (itc) {
+		info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1;
+		info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 =
+			cn0_cn1;
+	}
+
+	/* TODO: un-hardcode q0_q1 */
+	if (color_space == DS_COLOR_SPACE_SRGB_FULLRANGE)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
+						RGB_QUANTIZATION_FULL_RANGE;
+	else if (color_space == DS_COLOR_SPACE_SRGB_LIMITEDRANGE)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
+						RGB_QUANTIZATION_LIMITED_RANGE;
+	else
+		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
+						RGB_QUANTIZATION_DEFAULT_RANGE;
+
+	/* TODO : We should handle YCC quantization,
+	 * but we do not have matrix calculation */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
+					YYC_QUANTIZATION_LIMITED_RANGE;
+
+	info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 =
+					stream->public.timing.vic;
+
+	/* pixel repetition
+	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
+	 * repetition start from 1 */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0;
+
+	/* Bar Info
+	 * barTop:    Line Number of End of Top Bar.
+	 * barBottom: Line Number of Start of Bottom Bar.
+	 * barLeft:   Pixel Number of End of Left Bar.
+	 * barRight:  Pixel Number of Start of Right Bar. */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top =
+			stream->public.timing.v_border_top;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom =
+		(stream->public.timing.v_border_top
+			- stream->public.timing.v_border_bottom + 1);
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left =
+			stream->public.timing.h_border_left;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right =
+		(stream->public.timing.h_total
+			- stream->public.timing.h_border_right + 1);
+
+	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
+	check_sum =
+		&info_frame.
+		avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
+	*check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI
+			+ INFO_FRAME_VERSION_2;
+
+	for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++)
+		*check_sum += info_frame.avi_info_packet.info_packet_hdmi.
+				packet_raw_data.sb[byte_index];
+
+	/* one byte complement */
+	*check_sum = (uint8_t) (0x100 - *check_sum);
+
+	/* Store in hw_path_mode */
+	info_packet->hb0 =
+		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0;
+	info_packet->hb1 =
+		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1;
+	info_packet->hb2 =
+		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2;
+
+	for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++)
+		info_packet->sb[byte_index] = info_frame.avi_info_packet.
+		info_packet_hdmi.packet_raw_data.sb[byte_index];
+
+	info_packet->valid = true;
+}
+
+static void set_vendor_info_packet(struct core_stream *stream,
+		struct hw_info_packet *info_packet)
+{
+	uint32_t length = 0;
+	bool hdmi_vic_mode = false;
+	uint8_t checksum = 0;
+	uint32_t i = 0;
+	enum dc_timing_3d_format format;
+
+	ASSERT_CRITICAL(stream != NULL);
+	ASSERT_CRITICAL(info_packet != NULL);
+
+	format = stream->public.timing.timing_3d_format;
+
+	/* Can be different depending on packet content */
+	length = 5;
+
+	if (stream->public.timing.hdmi_vic != 0
+			&& stream->public.timing.h_total >= 3840
+			&& stream->public.timing.v_total >= 2160)
+		hdmi_vic_mode = true;
+
+	/* According to HDMI 1.4a CTS, VSIF should be sent
+	 * for both 3D stereo and HDMI VIC modes.
+	 * For all other modes, there is no VSIF sent.  */
+
+	if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
+		return;
+
+	/* 24bit IEEE Registration identifier (0x000c03). LSB first. */
+	info_packet->sb[1] = 0x03;
+	info_packet->sb[2] = 0x0C;
+	info_packet->sb[3] = 0x00;
+
+	/*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
+	 * The value for HDMI_Video_Format are:
+	 * 0x0 (0b000) - No additional HDMI video format is presented in this
+	 * packet
+	 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
+	 * parameter follows
+	 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
+	 * potentially 3D_Ext_Data follows
+	 * 0x3..0x7 (0b011..0b111) - reserved for future use */
+	if (format != TIMING_3D_FORMAT_NONE)
+		info_packet->sb[4] = (2 << 5);
+	else if (hdmi_vic_mode)
+		info_packet->sb[4] = (1 << 5);
+
+	/* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
+	 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
+	 * The value for 3D_Structure are:
+	 * 0x0 - Frame Packing
+	 * 0x1 - Field Alternative
+	 * 0x2 - Line Alternative
+	 * 0x3 - Side-by-Side (full)
+	 * 0x4 - L + depth
+	 * 0x5 - L + depth + graphics + graphics-depth
+	 * 0x6 - Top-and-Bottom
+	 * 0x7 - Reserved for future use
+	 * 0x8 - Side-by-Side (Half)
+	 * 0x9..0xE - Reserved for future use
+	 * 0xF - Not used */
+	switch (format) {
+	case TIMING_3D_FORMAT_HW_FRAME_PACKING:
+	case TIMING_3D_FORMAT_SW_FRAME_PACKING:
+		info_packet->sb[5] = (0x0 << 4);
+		break;
+
+	case TIMING_3D_FORMAT_SIDE_BY_SIDE:
+	case TIMING_3D_FORMAT_SBS_SW_PACKED:
+		info_packet->sb[5] = (0x8 << 4);
+		length = 6;
+		break;
+
+	case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
+	case TIMING_3D_FORMAT_TB_SW_PACKED:
+		info_packet->sb[5] = (0x6 << 4);
+		break;
+
+	default:
+		break;
+	}
+
+	/*PB5: If PB4 is set to 0x1 (extended resolution format)
+	 * fill PB5 with the correct HDMI VIC code */
+	if (hdmi_vic_mode)
+		info_packet->sb[5] = stream->public.timing.hdmi_vic;
+
+	/* Header */
+	info_packet->hb0 = 0x81; /* VSIF packet type. */
+	info_packet->hb1 = 0x01; /* Version */
+
+	/* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
+	info_packet->hb2 = (uint8_t) (length);
+
+	/* Calculate checksum */
+	checksum = 0;
+	checksum += info_packet->hb0;
+	checksum += info_packet->hb1;
+	checksum += info_packet->hb2;
+
+	for (i = 1; i <= length; i++)
+		checksum += info_packet->sb[i];
+
+	info_packet->sb[0] = (uint8_t) (0x100 - checksum);
+
+	info_packet->valid = true;
+}
+
+void build_info_frame(struct core_stream *stream)
+{
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+	struct hw_info_frame info_frame = { { 0 } };
+
+	/* default all packets to invalid */
+	info_frame.avi_info_packet.valid = false;
+	info_frame.gamut_packet.valid = false;
+	info_frame.vendor_info_packet.valid = false;
+	info_frame.spd_packet.valid = false;
+	info_frame.vsc_packet.valid = false;
+
+	signal = stream->sink->public.sink_signal;
+
+	/* HDMi and DP have different info packets*/
+	if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+		set_avi_info_frame(&info_frame.avi_info_packet,
+				stream);
+		set_vendor_info_packet(stream, &info_frame.vendor_info_packet);
+	}
+
+	translate_info_frame(&info_frame,
+			&stream->encoder_info_frame);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c b/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
new file mode 100644
index 000000000000..c5a770e61812
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "core_types.h"
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+
+struct sink {
+	struct core_sink protected;
+	int ref_count;
+};
+
+#define DC_SINK_TO_SINK(dc_sink) \
+			container_of(dc_sink, struct sink, protected.public)
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+
+static void destruct(struct sink *sink)
+{
+
+}
+
+static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params)
+{
+
+	struct core_link *core_link = DC_LINK_TO_LINK(init_params->link);
+
+	sink->protected.public.sink_signal = init_params->sink_signal;
+	sink->protected.link = core_link;
+	sink->protected.ctx = core_link->ctx;
+	sink->protected.dongle_max_pix_clk = init_params->dongle_max_pix_clk;
+	sink->protected.converter_disable_audio =
+			init_params->converter_disable_audio;
+
+	return true;
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+void dc_sink_retain(const struct dc_sink *dc_sink)
+{
+	struct sink *sink = DC_SINK_TO_SINK(dc_sink);
+
+	++sink->ref_count;
+}
+
+void dc_sink_release(const struct dc_sink *dc_sink)
+{
+	struct core_sink *core_sink = DC_SINK_TO_CORE(dc_sink);
+	struct sink *sink = DC_SINK_TO_SINK(dc_sink);
+
+	--sink->ref_count;
+
+	if (sink->ref_count == 0) {
+		destruct(sink);
+		dm_free(core_sink->ctx, sink);
+	}
+}
+
+struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params)
+{
+	struct core_link *core_link = DC_LINK_TO_LINK(init_params->link);
+
+	struct sink *sink = dm_alloc(core_link->ctx, sizeof(*sink));
+
+	if (NULL == sink)
+		goto alloc_fail;
+
+	if (false == construct(sink, init_params))
+		goto construct_fail;
+
+	/* TODO should we move this outside to where the assignment actually happens? */
+	dc_sink_retain(&sink->protected.public);
+
+	return &sink->protected.public;
+
+construct_fail:
+	dm_free(core_link->ctx, sink);
+
+alloc_fail:
+	return NULL;
+}
+
+/*******************************************************************************
+ * Protected functions - visible only inside of DC (not visible in DM)
+ ******************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c b/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
new file mode 100644
index 000000000000..d7012bcda10a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dc.h"
+#include "core_types.h"
+#include "resource.h"
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+
+struct stream {
+	struct core_stream protected;
+	int ref_count;
+};
+
+#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected.public)
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static void build_bit_depth_reduction_params(
+		const struct core_stream *stream,
+		struct bit_depth_reduction_params *fmt_bit_depth)
+{
+	dm_memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
+
+	/*TODO: Need to un-hardcode, refer to function with same name
+	 * in dal2 hw_sequencer*/
+
+	fmt_bit_depth->flags.TRUNCATE_ENABLED = 0;
+	fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 0;
+	fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 0;
+
+	/* Diagnostics need consistent CRC of the image, that means
+	 * dithering should not be enabled for Diagnostics. */
+	if (IS_DIAG_DC(stream->ctx->dce_environment) == false) {
+
+		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
+		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
+
+		/* frame random is on by default */
+		fmt_bit_depth->flags.FRAME_RANDOM = 1;
+		/* apply RGB dithering */
+		fmt_bit_depth->flags.RGB_RANDOM = true;
+	}
+
+	return;
+}
+
+static void setup_pixel_encoding(
+	struct clamping_and_pixel_encoding_params *clamping)
+{
+	/*TODO: Need to un-hardcode, refer to function with same name
+		 * in dal2 hw_sequencer*/
+
+	clamping->pixel_encoding = PIXEL_ENCODING_RGB;
+
+	return;
+}
+
+static bool construct(struct core_stream *stream,
+	const struct dc_sink *dc_sink_data)
+{
+	uint32_t i = 0;
+
+	stream->sink = DC_SINK_TO_CORE(dc_sink_data);
+	stream->ctx = stream->sink->ctx;
+	stream->public.sink = dc_sink_data;
+
+	dc_sink_retain(dc_sink_data);
+
+	build_bit_depth_reduction_params(stream, &stream->bit_depth_params);
+	setup_pixel_encoding(&stream->clamping);
+
+	/* Copy audio modes */
+	/* TODO - Remove this translation */
+	for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++)
+	{
+		stream->public.audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count;
+		stream->public.audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code;
+		stream->public.audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate;
+		stream->public.audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size;
+	}
+	stream->public.audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count;
+	stream->public.audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency;
+	stream->public.audio_info.video_latency = dc_sink_data->edid_caps.video_latency;
+	dm_memmove(
+		stream->public.audio_info.display_name,
+		dc_sink_data->edid_caps.display_name,
+		AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
+	stream->public.audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id;
+	stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id;
+	stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags;
+
+	/* TODO - Unhardcode port_id */
+	stream->public.audio_info.port_id[0] = 0x5558859e;
+	stream->public.audio_info.port_id[1] = 0xd989449;
+
+	/* EDID CAP translation for HDMI 2.0 */
+	stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
+	return true;
+}
+
+static void destruct(struct core_stream *stream)
+{
+	dc_sink_release(&stream->sink->public);
+}
+
+void dc_stream_retain(struct dc_stream *dc_stream)
+{
+	struct stream *stream = DC_STREAM_TO_STREAM(dc_stream);
+	stream->ref_count++;
+}
+
+void dc_stream_release(struct dc_stream *public)
+{
+	struct stream *stream = DC_STREAM_TO_STREAM(public);
+	struct core_stream *protected = DC_STREAM_TO_CORE(public);
+	struct dc_context *ctx = protected->ctx;
+	stream->ref_count--;
+
+	if (stream->ref_count == 0) {
+		destruct(protected);
+		dm_free(ctx, stream);
+	}
+}
+
+struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink)
+{
+	struct core_sink *sink = DC_SINK_TO_CORE(dc_sink);
+	struct stream *stream;
+
+	if (sink == NULL)
+		goto alloc_fail;
+
+	stream = dm_alloc(sink->ctx, sizeof(struct stream));
+
+	if (NULL == stream)
+		goto alloc_fail;
+
+	if (false == construct(&stream->protected, dc_sink))
+			goto construct_fail;
+
+	dc_stream_retain(&stream->protected.public);
+
+	return &stream->protected.public;
+
+construct_fail:
+	dm_free(sink->ctx, stream);
+
+alloc_fail:
+	return NULL;
+}
+
+void dc_update_stream(const struct dc_stream *dc_stream,
+		struct rect *src,
+		struct rect *dst)
+{
+	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
+
+	stream->public.src = *src;
+	stream->public.dst = *dst;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
new file mode 100644
index 000000000000..1a9ee8f97757
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/* DC interface (public) */
+#include "dm_services.h"
+#include "dc.h"
+
+/* DC core (private) */
+#include "core_dc.h"
+#include "inc/transform.h"
+
+/*******************************************************************************
+ * Private structures
+ ******************************************************************************/
+struct surface {
+	struct core_surface protected;
+	enum dc_irq_source irq_source;
+	int ref_count;
+};
+
+#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public)
+#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected)
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static bool construct(struct dc_context *ctx, struct surface *surface)
+{
+	uint32_t i;
+	struct gamma_ramp *gamma =
+			&surface->protected.public.gamma_correction;
+
+	/* construct gamma default value. */
+	for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) {
+		gamma->gamma_ramp_rgb256x3x16.red[i] =
+				(unsigned short) (i << 8);
+		gamma->gamma_ramp_rgb256x3x16.green[i] =
+				(unsigned short) (i << 8);
+		gamma->gamma_ramp_rgb256x3x16.blue[i] =
+				(unsigned short) (i << 8);
+	}
+	gamma->type = GAMMA_RAMP_TYPE_RGB256;
+	gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
+
+	surface->protected.ctx = ctx;
+	return true;
+}
+
+static void destruct(struct surface *surface)
+{
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+void enable_surface_flip_reporting(struct dc_surface *dc_surface,
+		uint32_t controller_id)
+{
+	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
+	surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1;
+	/*register_flip_interrupt(surface);*/
+}
+
+struct dc_surface *dc_create_surface(const struct dc *dc)
+{
+	struct surface *surface = dm_alloc(dc->ctx, sizeof(*surface));
+
+	if (NULL == surface)
+		goto alloc_fail;
+
+	if (false == construct(dc->ctx, surface))
+		goto construct_fail;
+
+	dc_surface_retain(&surface->protected.public);
+
+	return &surface->protected.public;
+
+construct_fail:
+	dm_free(dc->ctx, surface);
+
+alloc_fail:
+	return NULL;
+}
+
+void dc_surface_retain(const struct dc_surface *dc_surface)
+{
+	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
+
+	++surface->ref_count;
+}
+
+void dc_surface_release(const struct dc_surface *dc_surface)
+{
+	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
+	--surface->ref_count;
+
+	if (surface->ref_count == 0) {
+		destruct(surface);
+		dm_free(surface->protected.ctx, surface);
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
new file mode 100644
index 000000000000..e93e73d13448
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
@@ -0,0 +1,548 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "core_types.h"
+#include "hw_sequencer.h"
+#include "resource.h"
+#include "ipp.h"
+#include "timing_generator.h"
+
+#define COEFF_RANGE	3
+#define REGAMMA_COEFF_A0	31308
+#define REGAMMA_COEFF_A1	12920
+#define REGAMMA_COEFF_A2	55
+#define REGAMMA_COEFF_A3	55
+#define REGAMMA_COEFF_GAMMA	2400
+
+struct target {
+	struct core_target protected;
+	int ref_count;
+};
+
+#define DC_TARGET_TO_TARGET(dc_target) \
+	container_of(dc_target, struct target, protected.public)
+#define CORE_TARGET_TO_TARGET(core_target) \
+	container_of(core_target, struct target, protected)
+
+static void construct(
+	struct core_target *target,
+	struct dc_context *ctx,
+	struct dc_stream *dc_streams[],
+	uint8_t stream_count)
+{
+	uint8_t i;
+	for (i = 0; i < stream_count; i++) {
+		target->public.streams[i] = dc_streams[i];
+		dc_stream_retain(dc_streams[i]);
+	}
+
+	target->ctx = ctx;
+	target->public.stream_count = stream_count;
+}
+
+static void destruct(struct core_target *core_target)
+{
+	int i;
+
+	for (i = 0; i < core_target->status.surface_count; i++) {
+		dc_surface_release(core_target->status.surfaces[i]);
+		core_target->status.surfaces[i] = NULL;
+	}
+	for (i = 0; i < core_target->public.stream_count; i++) {
+		dc_stream_release(
+			(struct dc_stream *)core_target->public.streams[i]);
+		core_target->public.streams[i] = NULL;
+	}
+}
+
+void dc_target_retain(struct dc_target *dc_target)
+{
+	struct target *target = DC_TARGET_TO_TARGET(dc_target);
+
+	target->ref_count++;
+}
+
+void dc_target_release(struct dc_target *dc_target)
+{
+	struct target *target = DC_TARGET_TO_TARGET(dc_target);
+	struct core_target *protected = DC_TARGET_TO_CORE(dc_target);
+
+	ASSERT(target->ref_count > 0);
+	target->ref_count--;
+	if (target->ref_count == 0) {
+		destruct(protected);
+		dm_free(protected->ctx, target);
+	}
+}
+
+const struct dc_target_status *dc_target_get_status(
+					const struct dc_target* dc_target)
+{
+	struct core_target* target = DC_TARGET_TO_CORE(dc_target);
+	return &target->status;
+}
+
+struct dc_target *dc_create_target_for_streams(
+		struct dc_stream *dc_streams[],
+		uint8_t stream_count)
+{
+	struct core_stream *stream;
+	struct target *target;
+
+	if (0 == stream_count)
+		goto target_alloc_fail;
+
+	stream = DC_STREAM_TO_CORE(dc_streams[0]);
+
+	target = dm_alloc(stream->ctx, sizeof(struct target));
+
+	if (NULL == target)
+		goto target_alloc_fail;
+
+	construct(&target->protected, stream->ctx, dc_streams, stream_count);
+
+	dc_target_retain(&target->protected.public);
+
+	return &target->protected.public;
+
+
+target_alloc_fail:
+	return NULL;
+}
+
+static void build_gamma_params(
+		enum pixel_format pixel_format,
+		struct gamma_parameters *gamma_param)
+{
+	uint32_t i;
+
+	/* translate parameters */
+	gamma_param->surface_pixel_format = pixel_format;
+
+	gamma_param->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW;
+	gamma_param->degamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW;
+
+	gamma_param->selected_gamma_lut = GRAPHICS_GAMMA_LUT_REGAMMA;
+
+	/* TODO support non-legacy gamma */
+	gamma_param->disable_adjustments = false;
+	gamma_param->flag.bits.config_is_changed = 0;
+	gamma_param->flag.bits.regamma_update = 1;
+	gamma_param->flag.bits.gamma_update = 1;
+
+	/* Set regamma */
+	gamma_param->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 1;
+	gamma_param->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 1;
+	gamma_param->regamma.features.bits.GAMMA_RAMP_ARRAY = 0;
+	gamma_param->regamma.features.bits.APPLY_DEGAMMA = 0;
+
+	for (i = 0; i < COEFF_RANGE; i++) {
+		gamma_param->regamma.gamma_coeff.a0[i] = REGAMMA_COEFF_A0;
+		gamma_param->regamma.gamma_coeff.a1[i] = REGAMMA_COEFF_A1;
+		gamma_param->regamma.gamma_coeff.a2[i] = REGAMMA_COEFF_A2;
+		gamma_param->regamma.gamma_coeff.a3[i] = REGAMMA_COEFF_A3;
+		gamma_param->regamma.gamma_coeff.gamma[i] = REGAMMA_COEFF_GAMMA;
+	}
+}
+
+
+static bool program_gamma(
+		struct dc_context *ctx,
+		struct dc_surface *surface,
+		struct input_pixel_processor *ipp,
+		struct output_pixel_processor *opp)
+{
+	struct gamma_parameters *gamma_param;
+	bool result= false;
+
+	gamma_param = dm_alloc(ctx, sizeof(struct gamma_parameters));
+
+	if (!gamma_param)
+		goto gamma_param_fail;
+
+	build_gamma_params(surface->format, gamma_param);
+
+	result = ctx->dc->hwss.set_gamma_ramp(ipp, opp,
+			&surface->gamma_correction,
+			gamma_param);
+
+	dm_free(ctx, gamma_param);
+
+gamma_param_fail:
+	return result;
+}
+
+static bool validate_surface_address(
+		struct dc_plane_address address)
+{
+	bool is_valid_address = false;
+
+	switch (address.type) {
+	case PLN_ADDR_TYPE_GRAPHICS:
+		if (address.grph.addr.quad_part != 0)
+			is_valid_address = true;
+		break;
+	case PLN_ADDR_TYPE_GRPH_STEREO:
+		if ((address.grph_stereo.left_addr.quad_part != 0) &&
+			(address.grph_stereo.right_addr.quad_part != 0)) {
+			is_valid_address = true;
+		}
+		break;
+	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
+	default:
+		/* not supported */
+		BREAK_TO_DEBUGGER();
+		break;
+	}
+
+	return is_valid_address;
+}
+
+bool dc_commit_surfaces_to_target(
+		struct dc *dc,
+		struct dc_surface *new_surfaces[],
+		uint8_t new_surface_count,
+		struct dc_target *dc_target)
+
+{
+	int i, j;
+	uint32_t prev_disp_clk = dc->current_context.bw_results.dispclk_khz;
+	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+
+	int current_enabled_surface_count = 0;
+	int new_enabled_surface_count = 0;
+
+	if (!dal_adapter_service_is_in_accelerated_mode(
+						dc->res_pool.adapter_srv) ||
+			dc->current_context.target_count == 0) {
+		return false;
+	}
+
+	for (i = 0; i < dc->current_context.target_count; i++)
+		if (target == dc->current_context.targets[i])
+			break;
+
+	/* Cannot commit surface to a target that is not commited */
+	if (i == dc->current_context.target_count)
+		return false;
+
+	for (i = 0; i < target->status.surface_count; i++)
+		if (target->status.surfaces[i]->visible)
+			current_enabled_surface_count++;
+
+	for (i = 0; i < new_surface_count; i++)
+		if (new_surfaces[i]->visible)
+			new_enabled_surface_count++;
+
+	dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_INTERFACE_TRACE,
+				LOG_MINOR_COMPONENT_DC,
+				"%s: commit %d surfaces to target 0x%x\n",
+				__func__,
+				new_surface_count,
+				dc_target);
+
+
+	if (!logical_attach_surfaces_to_target(
+						new_surfaces,
+						new_surface_count,
+						dc_target)) {
+		BREAK_TO_DEBUGGER();
+		goto unexpected_fail;
+	}
+
+	for (i = 0; i < new_surface_count; i++)
+		for (j = 0; j < target->public.stream_count; j++)
+			build_scaling_params(
+				new_surfaces[i],
+				DC_STREAM_TO_CORE(target->public.streams[j]));
+
+	if (dc->res_pool.funcs->validate_bandwidth(dc, &dc->current_context)
+								!= DC_OK) {
+		BREAK_TO_DEBUGGER();
+		goto unexpected_fail;
+	}
+
+	if (prev_disp_clk < dc->current_context.bw_results.dispclk_khz) {
+		dc->hwss.program_bw(dc, &dc->current_context);
+		pplib_apply_display_requirements(dc, &dc->current_context);
+	}
+
+	if (current_enabled_surface_count > 0 && new_enabled_surface_count == 0)
+		dc_target_disable_memory_requests(dc_target);
+
+	for (i = 0; i < new_surface_count; i++) {
+		struct dc_surface *surface = new_surfaces[i];
+		struct core_surface *core_surface = DC_SURFACE_TO_CORE(surface);
+		bool is_valid_address =
+				validate_surface_address(surface->address);
+
+		dal_logger_write(dc->ctx->logger,
+					LOG_MAJOR_INTERFACE_TRACE,
+					LOG_MINOR_COMPONENT_DC,
+					"0x%x:",
+					surface);
+
+		program_gamma(dc->ctx, surface,
+			DC_STREAM_TO_CORE(target->public.streams[0])->ipp,
+			DC_STREAM_TO_CORE(target->public.streams[0])->opp);
+
+		dc->hwss.set_plane_config(dc, core_surface, target);
+
+		if (is_valid_address)
+			dc->hwss.update_plane_address(dc, core_surface, target);
+	}
+
+	if (current_enabled_surface_count == 0 && new_enabled_surface_count > 0)
+		dc_target_enable_memory_requests(dc_target);
+
+	/* Lower display clock if necessary */
+	if (prev_disp_clk > dc->current_context.bw_results.dispclk_khz) {
+		dc->hwss.program_bw(dc, &dc->current_context);
+		pplib_apply_display_requirements(dc, &dc->current_context);
+	}
+
+	return true;
+
+unexpected_fail:
+	for (i = 0; i < new_surface_count; i++) {
+		target->status.surfaces[i] = NULL;
+	}
+	target->status.surface_count = 0;
+
+	return false;
+}
+
+bool dc_target_is_connected_to_sink(
+		const struct dc_target * dc_target,
+		const struct dc_sink *dc_sink)
+{
+	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+	uint8_t i;
+	for (i = 0; i < target->public.stream_count; i++) {
+		if (target->public.streams[i]->sink == dc_sink)
+			return true;
+	}
+	return false;
+}
+
+void dc_target_enable_memory_requests(struct dc_target *target)
+{
+	uint8_t i;
+	struct core_target *core_target = DC_TARGET_TO_CORE(target);
+	for (i = 0; i < core_target->public.stream_count; i++) {
+		struct timing_generator *tg =
+			DC_STREAM_TO_CORE(core_target->public.streams[i])->tg;
+
+		if (!tg->funcs->set_blank(tg, false)) {
+			dm_error("DC: failed to unblank crtc!\n");
+			BREAK_TO_DEBUGGER();
+		}
+	}
+}
+
+void dc_target_disable_memory_requests(struct dc_target *target)
+{
+	uint8_t i;
+	struct core_target *core_target = DC_TARGET_TO_CORE(target);
+	for (i = 0; i < core_target->public.stream_count; i++) {
+	struct timing_generator *tg =
+		DC_STREAM_TO_CORE(core_target->public.streams[i])->tg;
+
+		if (NULL == tg) {
+			dm_error("DC: timing generator is NULL!\n");
+			BREAK_TO_DEBUGGER();
+			continue;
+		}
+
+		if (false == tg->funcs->set_blank(tg, true)) {
+			dm_error("DC: failed to blank crtc!\n");
+			BREAK_TO_DEBUGGER();
+		}
+	}
+}
+
+/**
+ * Update the cursor attributes and set cursor surface address
+ */
+bool dc_target_set_cursor_attributes(
+	struct dc_target *dc_target,
+	const struct dc_cursor_attributes *attributes)
+{
+	struct core_target *core_target;
+	struct input_pixel_processor *ipp;
+
+	if (NULL == dc_target) {
+		dm_error("DC: dc_target is NULL!\n");
+			return false;
+
+	}
+
+	core_target = DC_TARGET_TO_CORE(dc_target);
+	ipp = DC_STREAM_TO_CORE(core_target->public.streams[0])->ipp;
+
+	if (NULL == ipp) {
+		dm_error("DC: input pixel processor is NULL!\n");
+		return false;
+	}
+
+	if (true == ipp->funcs->ipp_cursor_set_attributes(ipp, attributes))
+		return true;
+
+	return false;
+}
+
+bool dc_target_set_cursor_position(
+	struct dc_target *dc_target,
+	const struct dc_cursor_position *position)
+{
+	struct core_target *core_target;
+	struct input_pixel_processor *ipp;
+
+	if (NULL == dc_target) {
+		dm_error("DC: dc_target is NULL!\n");
+		return false;
+	}
+
+	if (NULL == position) {
+		dm_error("DC: cursor position is NULL!\n");
+		return false;
+	}
+
+	core_target = DC_TARGET_TO_CORE(dc_target);
+	ipp = DC_STREAM_TO_CORE(core_target->public.streams[0])->ipp;
+
+	if (NULL == ipp) {
+		dm_error("DC: input pixel processor is NULL!\n");
+		return false;
+	}
+
+
+	if (true == ipp->funcs->ipp_cursor_set_position(ipp, position))
+		return true;
+
+	return false;
+}
+
+/* TODO: #flip temporary to make flip work */
+uint8_t dc_target_get_link_index(const struct dc_target *dc_target)
+{
+	const struct core_target *target = CONST_DC_TARGET_TO_CORE(dc_target);
+	const struct core_sink *sink =
+		DC_SINK_TO_CORE(target->public.streams[0]->sink);
+
+	return sink->link->public.link_index;
+}
+
+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target)
+{
+	struct core_target *core_target = DC_TARGET_TO_CORE(dc_target);
+	struct timing_generator *tg =
+		DC_STREAM_TO_CORE(core_target->public.streams[0])->tg;
+
+	return tg->funcs->get_frame_count(tg);
+}
+
+enum dc_irq_source dc_target_get_irq_src(
+	const struct dc_target *dc_target, const enum irq_type irq_type)
+{
+	struct core_target *core_target = DC_TARGET_TO_CORE(dc_target);
+
+	/* #TODO - Remove the assumption that the controller is always in the
+	 * first stream of a core target */
+	struct core_stream *stream =
+		DC_STREAM_TO_CORE(core_target->public.streams[0]);
+	uint8_t controller_idx = stream->controller_idx;
+
+	/* Get controller id */
+	enum controller_id crtc_id = controller_idx + 1;
+
+	/* Calculate controller offset */
+	unsigned int offset = crtc_id - CONTROLLER_ID_D0;
+	unsigned int base = irq_type;
+
+	/* Calculate irq source */
+	enum dc_irq_source src = base + offset;
+
+	return src;
+}
+
+void dc_target_log(
+	const struct dc_target *dc_target,
+	struct dal_logger *dal_logger,
+	enum log_major log_major,
+	enum log_minor log_minor)
+{
+	int i;
+
+	const struct core_target *core_target =
+			CONST_DC_TARGET_TO_CORE(dc_target);
+
+	dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"core_target 0x%x: surface_count=%d, stream_count=%d\n",
+			core_target,
+			core_target->status.surface_count,
+			core_target->public.stream_count);
+
+	for (i = 0; i < core_target->public.stream_count; i++) {
+		const struct core_stream *core_stream =
+			DC_STREAM_TO_CORE(core_target->public.streams[i]);
+
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n",
+			core_stream,
+			core_stream->public.src.x,
+			core_stream->public.src.y,
+			core_stream->public.src.width,
+			core_stream->public.src.height,
+			core_stream->public.dst.x,
+			core_stream->public.dst.y,
+			core_stream->public.dst.width,
+			core_stream->public.dst.height);
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"\tpix_clk_khz: %d, h_total: %d, v_total: %d\n",
+			core_stream->public.timing.pix_clk_khz,
+			core_stream->public.timing.h_total,
+			core_stream->public.timing.v_total);
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"\tsink name: %s, serial: %d\n",
+			core_stream->sink->public.edid_caps.display_name,
+			core_stream->sink->public.edid_caps.serial_number);
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"\tlink: %d\n",
+			core_stream->sink->link->public.link_index);
+	}
+}
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 25/26] drm/amd/dal: Adding amdgpu_dm for dal
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (23 preceding siblings ...)
  2016-02-16 22:28   ` [PATCH v2 24/26] drm/amd/dal: Add display core Harry Wentland
@ 2016-02-16 22:28   ` Harry Wentland
  2016-02-16 22:28   ` [PATCH v2 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:28 UTC (permalink / raw)
  To: dri-devel

Implements DRM's atomic KMS interfaces using DC.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile         |   17 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c      | 1468 +++++++++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h      |  168 ++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c  |  474 ++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c  |  820 +++++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h  |  122 +
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c    |  480 ++++
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h    |   36 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c |  457 ++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c    | 2577 ++++++++++++++++++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h    |  100 +
 drivers/gpu/drm/amd/dal/dc/dm_services.h           |   17 -
 12 files changed, 6719 insertions(+), 17 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h

diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
new file mode 100644
index 000000000000..0f365c65342e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the 'dm' sub-component of DAL.
+# It provides the control and status of dm blocks.
+
+
+
+AMDGPUDM = amdgpu_dm_types.o amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o
+
+ifneq ($(CONFIG_DRM_AMD_DAL),)
+AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o
+endif
+
+subdir-ccflags-y += -I$(FULL_AMD_DAL_PATH)/dc
+
+AMDGPU_DM = $(addprefix $(AMDDALPATH)/amdgpu_dm/,$(AMDGPUDM))
+
+AMD_DAL_FILES += $(AMDGPU_DM)
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
new file mode 100644
index 000000000000..0ceb505355e8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
@@ -0,0 +1,1468 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services_types.h"
+#include "dc.h"
+
+#include "vid.h"
+#include "amdgpu.h"
+#include "atom.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_types.h"
+
+#include "amd_shared.h"
+#include "amdgpu_dm_irq.h"
+#include "dm_helpers.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+#include "dce/dce_11_0_enum.h"
+#include "ivsrcid/ivsrcid_vislands30.h"
+
+#include "oss/oss_3_0_d.h"
+#include "oss/oss_3_0_sh_mask.h"
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_dp_mst_helper.h>
+
+/* TODO: Remove when mc access work around is removed */
+static const u32 crtc_offsets[] =
+{
+	CRTC0_REGISTER_OFFSET,
+	CRTC1_REGISTER_OFFSET,
+	CRTC2_REGISTER_OFFSET,
+	CRTC3_REGISTER_OFFSET,
+	CRTC4_REGISTER_OFFSET,
+	CRTC5_REGISTER_OFFSET,
+	CRTC6_REGISTER_OFFSET
+};
+/* TODO: End of when Remove mc access work around is removed */
+
+/* Define variables here
+ * These values will be passed to DAL for feature enable purpose
+ * Disable ALL for HDMI light up
+ * TODO: follow up if need this mechanism*/
+struct dal_override_parameters display_param = {
+	.bool_param_enable_mask = 0,
+	.bool_param_values = 0,
+	.int_param_values[DAL_PARAM_MAX_COFUNC_NON_DP_DISPLAYS] = DAL_PARAM_INVALID_INT,
+	.int_param_values[DAL_PARAM_DRR_SUPPORT] = DAL_PARAM_INVALID_INT,
+};
+
+/* Debug facilities */
+#define AMDGPU_DM_NOT_IMPL(fmt, ...) \
+	DRM_INFO("DM_NOT_IMPL: " fmt, ##__VA_ARGS__)
+
+/*
+ * dm_vblank_get_counter
+ *
+ * @brief
+ * Get counter for number of vertical blanks
+ *
+ * @param
+ * struct amdgpu_device *adev - [in] desired amdgpu device
+ * int disp_idx - [in] which CRTC to get the counter from
+ *
+ * @return
+ * Counter for vertical blanks
+ */
+static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
+{
+	if (crtc >= adev->mode_info.num_crtc)
+		return 0;
+	else {
+		struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
+
+		if (NULL == acrtc->target) {
+			DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc);
+			return 0;
+		}
+
+		return dc_target_get_vblank_counter(acrtc->target);
+	}
+}
+
+static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
+					u32 *vbl, u32 *position)
+{
+	if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
+		return -EINVAL;
+
+/* TODO: #DAL3 Implement scanoutpos
+	dal_get_crtc_scanoutpos(adev->dm.dal, crtc, vbl, position);
+*/
+	return 0;
+}
+
+static u32 dm_hpd_get_gpio_reg(struct amdgpu_device *adev)
+{
+	return mmDC_GPIO_HPD_A;
+}
+
+
+static bool dm_is_display_hung(struct amdgpu_device *adev)
+{
+	/* TODO: #DAL3 need to replace
+	u32 crtc_hung = 0;
+	u32 i, j, tmp;
+
+	crtc_hung = dal_get_connected_targets_vector(adev->dm.dal);
+
+	for (j = 0; j < 10; j++) {
+		for (i = 0; i < adev->mode_info.num_crtc; i++) {
+			if (crtc_hung & (1 << i)) {
+				int32_t vpos1, hpos1;
+				int32_t vpos2, hpos2;
+
+				tmp = dal_get_crtc_scanoutpos(
+					adev->dm.dal,
+					i,
+					&vpos1,
+					&hpos1);
+				udelay(10);
+				tmp = dal_get_crtc_scanoutpos(
+					adev->dm.dal,
+					i,
+					&vpos2,
+					&hpos2);
+
+				if (hpos1 != hpos2 && vpos1 != vpos2)
+					crtc_hung &= ~(1 << i);
+			}
+		}
+
+		if (crtc_hung == 0)
+			return false;
+	}
+*/
+	return true;
+}
+
+/* TODO: Remove mc access work around*/
+static void dm_stop_mc_access(struct amdgpu_device *adev,
+				     struct amdgpu_mode_mc_save *save)
+{
+
+	u32 crtc_enabled, tmp;
+	int i;
+
+	save->vga_render_control = RREG32(mmVGA_RENDER_CONTROL);
+	save->vga_hdp_control = RREG32(mmVGA_HDP_CONTROL);
+
+	/* disable VGA render */
+	tmp = RREG32(mmVGA_RENDER_CONTROL);
+	tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0);
+	WREG32(mmVGA_RENDER_CONTROL, tmp);
+
+	/* blank the display controllers */
+	for (i = 0; i < adev->mode_info.num_crtc; i++) {
+		crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
+					     CRTC_CONTROL, CRTC_MASTER_EN);
+		if (crtc_enabled) {
+#if 0
+			u32 frame_count;
+			int j;
+
+			save->crtc_enabled[i] = true;
+			tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN) == 0) {
+				amdgpu_display_vblank_wait(adev, i);
+				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+				tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
+				WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			}
+			/* wait for the next frame */
+			frame_count = amdgpu_display_vblank_get_counter(adev, i);
+			for (j = 0; j < adev->usec_timeout; j++) {
+				if (amdgpu_display_vblank_get_counter(adev, i) != frame_count)
+					break;
+				udelay(1);
+			}
+			tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK) == 0) {
+				tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
+				WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK) == 0) {
+				tmp = REG_SET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK, 1);
+				WREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+			}
+#else
+			/* XXX this is a hack to avoid strange behavior with EFI on certain systems */
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+			tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
+			tmp = REG_SET_FIELD(tmp, CRTC_CONTROL, CRTC_MASTER_EN, 0);
+			WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			save->crtc_enabled[i] = false;
+			/* ***** */
+#endif
+		} else {
+			save->crtc_enabled[i] = false;
+		}
+	}
+}
+
+
+static void dm_resume_mc_access(struct amdgpu_device *adev,
+				       struct amdgpu_mode_mc_save *save)
+{
+
+	u32 tmp, frame_count;
+	int i, j;
+
+	/* update crtc base addresses */
+	for (i = 0; i < adev->mode_info.num_crtc; i++) {
+		WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
+		       upper_32_bits(adev->mc.vram_start));
+		WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
+		       upper_32_bits(adev->mc.vram_start));
+		WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i],
+		       (u32)adev->mc.vram_start);
+		WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
+		       (u32)adev->mc.vram_start);
+
+		if (save->crtc_enabled[i]) {
+			tmp = RREG32(mmCRTC_MASTER_UPDATE_MODE + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, CRTC_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 3) {
+				tmp = REG_SET_FIELD(tmp, CRTC_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 3);
+				WREG32(mmCRTC_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK)) {
+				tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
+				WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp);
+			}
+			tmp = RREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+			if (REG_GET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK)) {
+				tmp = REG_SET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK, 0);
+				WREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+			}
+			for (j = 0; j < adev->usec_timeout; j++) {
+				tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+				if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING) == 0)
+					break;
+				udelay(1);
+			}
+			tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]);
+			tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 0);
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+			WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			/* wait for the next frame */
+			frame_count = amdgpu_display_vblank_get_counter(adev, i);
+			for (j = 0; j < adev->usec_timeout; j++) {
+				if (amdgpu_display_vblank_get_counter(adev, i) != frame_count)
+					break;
+				udelay(1);
+			}
+		}
+	}
+
+	WREG32(mmVGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start));
+	WREG32(mmVGA_MEMORY_BASE_ADDRESS, lower_32_bits(adev->mc.vram_start));
+
+	/* Unlock vga access */
+	WREG32(mmVGA_HDP_CONTROL, save->vga_hdp_control);
+	mdelay(1);
+	WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control);
+}
+
+/* End of TODO: Remove mc access work around*/
+
+static bool dm_is_idle(void *handle)
+{
+	/* XXX todo */
+	return true;
+}
+
+static int dm_wait_for_idle(void *handle)
+{
+	/* XXX todo */
+	return 0;
+}
+
+static void dm_print_status(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	dev_info(adev->dev, "DCE 10.x registers\n");
+	/* XXX todo */
+}
+
+static int dm_soft_reset(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	u32 srbm_soft_reset = 0, tmp;
+
+	if (dm_is_display_hung(adev))
+		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK;
+
+	if (srbm_soft_reset) {
+		dm_print_status(adev);
+
+		tmp = RREG32(mmSRBM_SOFT_RESET);
+		tmp |= srbm_soft_reset;
+		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
+		WREG32(mmSRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmSRBM_SOFT_RESET);
+
+		udelay(50);
+
+		tmp &= ~srbm_soft_reset;
+		WREG32(mmSRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmSRBM_SOFT_RESET);
+
+		/* Wait a little for things to settle down */
+		udelay(50);
+		dm_print_status(adev);
+	}
+	return 0;
+}
+
+static struct amdgpu_crtc *get_crtc_by_target(
+	struct amdgpu_device *adev,
+	const struct dc_target *dc_target)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_crtc *crtc;
+	struct amdgpu_crtc *amdgpu_crtc;
+
+	/*
+	 * following if is check inherited from both functions where this one is
+	 * used now. Need to be checked why it could happen.
+	 */
+	if (dc_target == NULL)
+		return adev->mode_info.crtcs[0];
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+		if (amdgpu_crtc->target == dc_target)
+			return amdgpu_crtc;
+	}
+
+	return NULL;
+}
+
+static void dm_pflip_high_irq(void *interrupt_params)
+{
+	struct amdgpu_flip_work *works;
+	struct amdgpu_crtc *amdgpu_crtc;
+	struct common_irq_params *irq_params = interrupt_params;
+	struct amdgpu_device *adev = irq_params->adev;
+	unsigned long flags;
+	const struct dc *dc = irq_params->adev->dm.dc;
+	const struct dc_target *dc_target =
+			dc_get_target_on_irq_source(dc, irq_params->irq_src);
+
+	amdgpu_crtc = get_crtc_by_target(adev, dc_target);
+
+	/* IRQ could occur when in initial stage */
+	if(amdgpu_crtc == NULL)
+		return;
+
+	spin_lock_irqsave(&adev->ddev->event_lock, flags);
+	works = amdgpu_crtc->pflip_works;
+	if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
+		DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
+						 "AMDGPU_FLIP_SUBMITTED(%d)\n",
+						 amdgpu_crtc->pflip_status,
+						 AMDGPU_FLIP_SUBMITTED);
+		spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+		return;
+	}
+
+	/* page flip completed. clean up */
+	amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
+	amdgpu_crtc->pflip_works = NULL;
+
+	/* wakeup usersapce */
+	if(works->event)
+		drm_send_vblank_event(
+			adev->ddev,
+			amdgpu_crtc->crtc_id,
+			works->event);
+
+	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+
+	drm_crtc_vblank_put(&amdgpu_crtc->base);
+	queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
+}
+
+static void dm_crtc_high_irq(void *interrupt_params)
+{
+	struct common_irq_params *irq_params = interrupt_params;
+	struct amdgpu_device *adev = irq_params->adev;
+	const struct dc *dc = irq_params->adev->dm.dc;
+	const struct dc_target *dc_target =
+			dc_get_target_on_irq_source(dc, irq_params->irq_src);
+	uint8_t crtc_index = 0;
+	struct amdgpu_crtc *acrtc = get_crtc_by_target(adev, dc_target);
+
+	if (acrtc)
+		crtc_index = acrtc->crtc_id;
+
+	drm_handle_vblank(adev->ddev, crtc_index);
+
+}
+
+static int dm_set_clockgating_state(void *handle,
+		  enum amd_clockgating_state state)
+{
+	return 0;
+}
+
+static int dm_set_powergating_state(void *handle,
+		  enum amd_powergating_state state)
+{
+	return 0;
+}
+
+/* Prototypes of private functions */
+static int dm_early_init(void* handle);
+
+static void hotplug_notify_work_func(struct work_struct *work)
+{
+	struct amdgpu_display_manager *dm = container_of(work, struct amdgpu_display_manager, mst_hotplug_work);
+	struct drm_device *dev = dm->ddev;
+
+	drm_kms_helper_hotplug_event(dev);
+}
+
+/* Init display KMS
+ *
+ * Returns 0 on success
+ */
+int amdgpu_dm_init(struct amdgpu_device *adev)
+{
+	struct dal_init_data init_data;
+	struct drm_device *ddev = adev->ddev;
+	adev->dm.ddev = adev->ddev;
+	adev->dm.adev = adev;
+
+	/* Zero all the fields */
+	memset(&init_data, 0, sizeof(init_data));
+
+	/* initialize DAL's lock (for SYNC context use) */
+	spin_lock_init(&adev->dm.dal_lock);
+
+	/* initialize DAL's mutex */
+	mutex_init(&adev->dm.dal_mutex);
+
+	if(amdgpu_dm_irq_init(adev)) {
+		DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
+		goto error;
+	}
+
+	if (ddev->pdev) {
+		init_data.bdf_info.DEVICE_NUMBER = PCI_SLOT(ddev->pdev->devfn);
+		init_data.bdf_info.FUNCTION_NUMBER =
+			PCI_FUNC(ddev->pdev->devfn);
+		if (ddev->pdev->bus)
+			init_data.bdf_info.BUS_NUMBER = ddev->pdev->bus->number;
+	}
+
+	init_data.display_param = display_param;
+
+	init_data.asic_id.chip_family = adev->family;
+
+	init_data.asic_id.pci_revision_id = adev->rev_id;
+	init_data.asic_id.hw_internal_rev = adev->external_rev_id;
+
+	init_data.asic_id.vram_width = adev->mc.vram_width;
+	/* TODO: initialize init_data.asic_id.vram_type here!!!! */
+	init_data.asic_id.atombios_base_address =
+		adev->mode_info.atom_context->bios;
+	init_data.asic_id.runtime_flags.flags.bits.SKIP_POWER_DOWN_ON_RESUME = 1;
+
+	if (adev->asic_type == CHIP_CARRIZO)
+		init_data.asic_id.runtime_flags.flags.bits.GNB_WAKEUP_SUPPORTED = 1;
+
+	init_data.driver = adev;
+
+	adev->dm.cgs_device = amdgpu_cgs_create_device(adev);
+
+	if (!adev->dm.cgs_device) {
+		DRM_ERROR("amdgpu: failed to create cgs device.\n");
+		goto error;
+	}
+
+	init_data.cgs_device = adev->dm.cgs_device;
+
+	adev->dm.dal = NULL;
+
+	/* enable gpu scaling in DAL */
+	init_data.display_param.bool_param_enable_mask |=
+		1 << DAL_PARAM_ENABLE_GPU_SCALING;
+	init_data.display_param.bool_param_values |=
+		1 << DAL_PARAM_ENABLE_GPU_SCALING;
+
+	init_data.dce_environment = DCE_ENV_PRODUCTION_DRV;
+
+	/* Display Core create. */
+	adev->dm.dc = dc_create(&init_data);
+
+	INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func);
+
+	if (amdgpu_dm_initialize_drm_device(adev)) {
+		DRM_ERROR(
+		"amdgpu: failed to initialize sw for display support.\n");
+		goto error;
+	}
+
+	/* Update the actual used number of crtc */
+	adev->mode_info.num_crtc = adev->dm.display_indexes_num;
+
+	/* TODO: Add_display_info? */
+
+	/* TODO use dynamic cursor width */
+	adev->ddev->mode_config.cursor_width = 128;
+	adev->ddev->mode_config.cursor_height = 128;
+
+	if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) {
+		DRM_ERROR(
+		"amdgpu: failed to initialize sw for display support.\n");
+		goto error;
+	}
+
+	DRM_INFO("KMS initialized.\n");
+
+	return 0;
+error:
+	amdgpu_dm_fini(adev);
+
+	return -1;
+}
+
+void amdgpu_dm_fini(struct amdgpu_device *adev)
+{
+	amdgpu_dm_destroy_drm_device(&adev->dm);
+	/*
+	 * TODO: pageflip, vlank interrupt
+	 *
+	 * amdgpu_dm_irq_fini(adev);
+	 */
+
+	if (adev->dm.cgs_device) {
+		amdgpu_cgs_destroy_device(adev->dm.cgs_device);
+		adev->dm.cgs_device = NULL;
+	}
+
+	/* DC Destroy TODO: Replace destroy DAL */
+	{
+		dc_destroy(&adev->dm.dc);
+	}
+	return;
+}
+
+/* moved from amdgpu_dm_kms.c */
+void amdgpu_dm_destroy()
+{
+}
+
+static int dm_sw_init(void *handle)
+{
+	return 0;
+}
+
+static int dm_sw_fini(void *handle)
+{
+	return 0;
+}
+
+
+static void detect_link_for_all_connectors(struct drm_device *dev)
+{
+	struct amdgpu_connector *aconnector;
+	struct drm_connector *connector;
+
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		   aconnector = to_amdgpu_connector(connector);
+		   if (aconnector->dc_link->type == dc_connection_mst_branch) {
+			   DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n",
+						aconnector, aconnector->base.base.id);
+
+				if (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) < 0) {
+					DRM_ERROR("DM_MST: Failed to start MST\n");
+					((struct dc_link *)aconnector->dc_link)->type = dc_connection_single;
+				}
+		   }
+	}
+
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+}
+
+
+static int dm_hw_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	/* Create DAL display manager */
+	amdgpu_dm_init(adev);
+
+	amdgpu_dm_hpd_init(adev);
+
+	detect_link_for_all_connectors(adev->ddev);
+
+
+
+	return 0;
+}
+
+static int dm_hw_fini(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	amdgpu_dm_hpd_fini(adev);
+
+	amdgpu_dm_irq_fini(adev);
+
+	return 0;
+}
+
+static int dm_display_suspend(struct drm_device *ddev)
+{
+	struct drm_mode_config *config = &ddev->mode_config;
+	struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
+	struct drm_atomic_state *state;
+	struct drm_crtc *crtc;
+	unsigned crtc_mask = 0;
+	int ret = 0;
+
+	if (WARN_ON(!ctx))
+		return 0;
+
+	lockdep_assert_held(&ctx->ww_ctx);
+
+	state = drm_atomic_state_alloc(ddev);
+	if (WARN_ON(!state))
+		return -ENOMEM;
+
+	state->acquire_ctx = ctx;
+	state->allow_modeset = true;
+
+	/* Set all active crtcs to inactive, to turn off displays*/
+	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
+		struct drm_crtc_state *crtc_state =
+			drm_atomic_get_crtc_state(state, crtc);
+
+		ret = PTR_ERR_OR_ZERO(crtc_state);
+		if (ret)
+			goto free;
+
+		if (!crtc_state->active)
+			continue;
+
+		crtc_state->active = false;
+		crtc_mask |= (1 << drm_crtc_index(crtc));
+	}
+
+	if (crtc_mask) {
+		ret = drm_atomic_commit(state);
+
+		/* In case of failure, revert everything we did*/
+		if (!ret) {
+			list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head)
+				if (crtc_mask & (1 << drm_crtc_index(crtc)))
+					crtc->state->active = true;
+
+			return ret;
+		}
+	}
+
+free:
+	if (ret) {
+		DRM_ERROR("Suspending crtc's failed with %i\n", ret);
+		drm_atomic_state_free(state);
+		return ret;
+	}
+
+	return 0;
+}
+static int dm_suspend(void *handle)
+{
+	struct amdgpu_device *adev = handle;
+	struct amdgpu_display_manager *dm = &adev->dm;
+	struct drm_device *ddev = adev->ddev;
+	int ret = 0;
+
+	drm_modeset_lock_all(ddev);
+	ret = dm_display_suspend(ddev);
+	drm_modeset_unlock_all(ddev);
+
+	if (ret)
+		goto fail;
+
+	dc_set_power_state(
+		dm->dc,
+		DC_ACPI_CM_POWER_STATE_D3,
+		DC_VIDEO_POWER_SUSPEND);
+
+	amdgpu_dm_irq_suspend(adev);
+fail:
+	return ret;
+}
+
+static int dm_display_resume(struct drm_device *ddev)
+{
+	int ret = 0;
+	struct drm_connector *connector;
+
+	struct drm_atomic_state *state = drm_atomic_state_alloc(ddev);
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+
+	if (!state)
+		return ENOMEM;
+
+	state->acquire_ctx = ddev->mode_config.acquire_ctx;
+
+	/* Construct an atomic state to restore previous display setting*/
+	/* Attach crtcs to drm_atomic_state*/
+	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
+		struct drm_crtc_state *crtc_state =
+			drm_atomic_get_crtc_state(state, crtc);
+
+		ret = PTR_ERR_OR_ZERO(crtc_state);
+		if (ret)
+			goto err;
+
+		/* force a restore */
+		crtc_state->mode_changed = true;
+	}
+
+	/* Attach planes to drm_atomic_state*/
+	list_for_each_entry(plane, &ddev->mode_config.plane_list, head) {
+		ret = PTR_ERR_OR_ZERO(drm_atomic_get_plane_state(state, plane));
+		if (ret)
+			goto err;
+	}
+
+	/* Attach connectors to drm_atomic_state*/
+	list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
+		ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(state, connector));
+		if (ret)
+			goto err;
+	}
+
+	/* Call commit internally with the state we just constructed */
+	ret = drm_atomic_commit(state);
+	if (!ret)
+		return 0;
+
+err:
+	DRM_ERROR("Restoring old state failed with %i\n", ret);
+	drm_atomic_state_free(state);
+
+	return ret;
+}
+
+static int dm_resume(void *handle)
+{
+	struct amdgpu_device *adev = handle;
+	struct drm_device *ddev = adev->ddev;
+	struct amdgpu_display_manager *dm = &adev->dm;
+	struct amdgpu_connector *aconnector;
+	struct drm_connector *connector;
+	int ret = 0;
+
+	/* power on hardware */
+	dc_set_power_state(
+		dm->dc,
+		DC_ACPI_CM_POWER_STATE_D0,
+		DC_VIDEO_POWER_ON);
+
+	/* Do detection*/
+	list_for_each_entry(connector,
+			&ddev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		dc_link_detect(aconnector->dc_link, false);
+		aconnector->dc_sink = NULL;
+		amdgpu_dm_update_connector_after_detect(aconnector);
+	}
+
+
+	drm_modeset_lock_all(ddev);
+	ret = dm_display_resume(ddev);
+	drm_modeset_unlock_all(ddev);
+
+	drm_kms_helper_hotplug_event(ddev);
+
+	/* program HPD filter*/
+	dc_resume(dm->dc);
+	/* resume IRQ */
+	amdgpu_dm_irq_resume(adev);
+
+	return ret;
+}
+const struct amd_ip_funcs amdgpu_dm_funcs = {
+	.early_init = dm_early_init,
+	.late_init = NULL,
+	.sw_init = dm_sw_init,
+	.sw_fini = dm_sw_fini,
+	.hw_init = dm_hw_init,
+	.hw_fini = dm_hw_fini,
+	.suspend = dm_suspend,
+	.resume = dm_resume,
+	.is_idle = dm_is_idle,
+	.wait_for_idle = dm_wait_for_idle,
+	.soft_reset = dm_soft_reset,
+	.print_status = dm_print_status,
+	.set_clockgating_state = dm_set_clockgating_state,
+	.set_powergating_state = dm_set_powergating_state,
+};
+
+/* TODO: it is temporary non-const, should fixed later */
+static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
+	.atomic_check = amdgpu_dm_atomic_check,
+	.atomic_commit = amdgpu_dm_atomic_commit
+};
+
+
+void amdgpu_dm_update_connector_after_detect(
+	struct amdgpu_connector *aconnector)
+{
+	struct drm_connector *connector = &aconnector->base;
+	struct drm_device *dev = connector->dev;
+	const struct dc_sink *sink;
+
+	/* MST handled by drm_mst framework */
+	if (aconnector->mst_mgr.mst_state == true)
+		return;
+
+	sink = aconnector->dc_link->local_sink;
+
+	/*
+	 * TODO: temporary guard to look for proper fix
+	 * if this sink is MST sink, we should not do anything
+	 */
+	if (sink && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+		return;
+
+	if (aconnector->dc_sink == sink) {
+		/* We got a DP short pulse (Link Loss, DP CTS, etc...).
+		 * Do nothing!! */
+		DRM_INFO("DCHPD: connector_id=%d: dc_sink didn't change.\n",
+				aconnector->connector_id);
+		return;
+	}
+
+	DRM_INFO("DCHPD: connector_id=%d: Old sink=%p New sink=%p\n",
+		aconnector->connector_id, aconnector->dc_sink, sink);
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/* 1. Update status of the drm connector
+	 * 2. Send an event and let userspace tell us what to do */
+	if (sink) {
+		/* TODO: check if we still need the S3 mode update workaround.
+		 * If yes, put it here. */
+
+		aconnector->dc_sink = sink;
+		if (sink->dc_edid.length == 0)
+			aconnector->edid = NULL;
+		else {
+			aconnector->edid =
+				(struct edid *) sink->dc_edid.raw_edid;
+			drm_mode_connector_update_edid_property(connector,
+					aconnector->edid);
+		}
+	} else {
+		drm_mode_connector_update_edid_property(connector, NULL);
+		aconnector->num_modes = 0;
+		aconnector->dc_sink = NULL;
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void handle_hpd_irq(void *param)
+{
+	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
+	struct drm_connector *connector = &aconnector->base;
+	struct drm_device *dev = connector->dev;
+
+	/* In case of failure or MST no need to update connector status or notify the OS
+	 * since (for MST case) MST does this in it's own context.
+	 */
+	if (dc_link_detect(aconnector->dc_link, false)) {
+		amdgpu_dm_update_connector_after_detect(aconnector);
+		drm_kms_helper_hotplug_event(dev);
+	}
+}
+
+static void handle_hpd_rx_irq(void *param)
+{
+	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
+	struct drm_connector *connector = &aconnector->base;
+	struct drm_device *dev = connector->dev;
+	bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
+
+	if (dc_link_handle_hpd_rx_irq(aconnector->dc_link) &&
+			!is_mst_root_connector) {
+		/* Downstream Port status changed. */
+		if (dc_link_detect(aconnector->dc_link, false)) {
+			amdgpu_dm_update_connector_after_detect(aconnector);
+			drm_kms_helper_hotplug_event(dev);
+		}
+	}
+
+	if (is_mst_root_connector)
+		dm_helpers_dp_mst_handle_mst_hpd_rx_irq(param);
+}
+
+static void register_hpd_handlers(struct amdgpu_device *adev)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_connector *connector;
+	struct amdgpu_connector *aconnector;
+	const struct dc_link *dc_link;
+	struct dc_interrupt_params int_params = {0};
+
+	int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
+	int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
+
+	list_for_each_entry(connector,
+			&dev->mode_config.connector_list, head)	{
+
+		aconnector = to_amdgpu_connector(connector);
+		dc_link = aconnector->dc_link;
+
+		int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
+		int_params.irq_source = dc_link->irq_source_hpd;
+
+		amdgpu_dm_irq_register_interrupt(adev, &int_params,
+				handle_hpd_irq,
+				(void *) aconnector);
+
+		if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+
+			/* Also register for DP short pulse (hpd_rx). */
+			int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
+			int_params.irq_source =	dc_link->irq_source_hpd_rx;
+
+			amdgpu_dm_irq_register_interrupt(adev, &int_params,
+					handle_hpd_rx_irq,
+					(void *) aconnector);
+		}
+	}
+}
+
+/* Register IRQ sources and initialize IRQ callbacks */
+static int dce110_register_irq_handlers(struct amdgpu_device *adev)
+{
+	struct dc *dc = adev->dm.dc;
+	struct common_irq_params *c_irq_params;
+	struct dc_interrupt_params int_params = {0};
+	int r;
+	int i;
+	struct dc_caps caps = { 0 };
+
+	dc_get_caps(dc, &caps);
+
+	int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
+	int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
+
+	/* Actions of amdgpu_irq_add_id():
+	 * 1. Register a set() function with base driver.
+	 *    Base driver will call set() function to enable/disable an
+	 *    interrupt in DC hardware.
+	 * 2. Register amdgpu_dm_irq_handler().
+	 *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
+	 *    coming from DC hardware.
+	 *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
+	 *    for acknowledging and handling. */
+
+	for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT;
+			i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) {
+		r = amdgpu_irq_add_id(adev, i, &adev->crtc_irq);
+		if (r) {
+			DRM_ERROR("Failed to add crtc irq id!\n");
+			return r;
+		}
+
+		int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+		int_params.irq_source =
+			dc_interrupt_to_irq_source(dc, i, 0);
+
+		c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
+
+		c_irq_params->adev = adev;
+		c_irq_params->irq_src = int_params.irq_source;
+
+		amdgpu_dm_irq_register_interrupt(adev, &int_params,
+				dm_crtc_high_irq, c_irq_params);
+	}
+
+	for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP;
+			i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) {
+		r = amdgpu_irq_add_id(adev, i, &adev->pageflip_irq);
+		if (r) {
+			DRM_ERROR("Failed to add page flip irq id!\n");
+			return r;
+		}
+
+		int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+		int_params.irq_source =
+			dc_interrupt_to_irq_source(dc, i, 0);
+
+		c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST];
+
+		c_irq_params->adev = adev;
+		c_irq_params->irq_src = int_params.irq_source;
+
+		amdgpu_dm_irq_register_interrupt(adev, &int_params,
+				dm_pflip_high_irq, c_irq_params);
+
+	}
+
+	/* HPD */
+	r = amdgpu_irq_add_id(adev, VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A,
+			&adev->hpd_irq);
+	if (r) {
+		DRM_ERROR("Failed to add hpd irq id!\n");
+		return r;
+	}
+
+	register_hpd_handlers(adev);
+
+	return 0;
+}
+
+static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
+{
+	int r;
+
+	adev->mode_info.mode_config_initialized = true;
+
+	amdgpu_dm_mode_funcs.fb_create =
+		amdgpu_mode_funcs.fb_create;
+	amdgpu_dm_mode_funcs.output_poll_changed =
+		amdgpu_mode_funcs.output_poll_changed;
+
+	adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs;
+
+	adev->ddev->mode_config.max_width = 16384;
+	adev->ddev->mode_config.max_height = 16384;
+
+	adev->ddev->mode_config.preferred_depth = 24;
+	adev->ddev->mode_config.prefer_shadow = 1;
+
+	adev->ddev->mode_config.fb_base = adev->mc.aper_base;
+
+	r = amdgpu_modeset_create_props(adev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
+	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
+{
+	struct amdgpu_display_manager *dm = bl_get_data(bd);
+
+	if (dc_link_set_backlight_level(dm->backlight_link,
+			bd->props.brightness))
+		return 0;
+	else
+		return 1;
+}
+
+static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static const struct backlight_ops amdgpu_dm_backlight_ops = {
+	.get_brightness = amdgpu_dm_backlight_get_brightness,
+	.update_status	= amdgpu_dm_backlight_update_status,
+};
+
+void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
+{
+	char bl_name[16];
+	struct backlight_properties props = { 0 };
+
+	props.max_brightness = AMDGPU_MAX_BL_LEVEL;
+	props.type = BACKLIGHT_RAW;
+
+	snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
+			dm->adev->ddev->primary->index);
+
+	dm->backlight_dev = backlight_device_register(bl_name,
+			dm->adev->ddev->dev,
+			dm,
+			&amdgpu_dm_backlight_ops,
+			&props);
+
+	if (NULL == dm->backlight_dev)
+		DRM_ERROR("DM: Backlight registration failed!\n");
+	else
+		DRM_INFO("DM: Registered Backlight device: %s\n", bl_name);
+}
+
+#endif
+
+/* In this architecture, the association
+ * connector -> encoder -> crtc
+ * id not really requried. The crtc and connector will hold the
+ * display_index as an abstraction to use with DAL component
+ *
+ * Returns 0 on success
+ */
+int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+{
+	struct amdgpu_display_manager *dm = &adev->dm;
+	uint32_t i;
+	struct amdgpu_connector *aconnector;
+	struct amdgpu_encoder *aencoder;
+	struct amdgpu_crtc *acrtc;
+	struct dc_caps caps = { 0 };
+	uint32_t link_cnt;
+
+	dc_get_caps(dm->dc, &caps);
+	link_cnt = caps.max_links;
+
+	if (amdgpu_dm_mode_config_init(dm->adev)) {
+		DRM_ERROR("DM: Failed to initialize mode config\n");
+		return -1;
+	}
+
+	for (i = 0; i < caps.max_targets; i++) {
+		acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL);
+		if (!acrtc)
+			goto fail;
+
+		if (amdgpu_dm_crtc_init(
+			dm,
+			acrtc,
+			i)) {
+			DRM_ERROR("KMS: Failed to initialize crtc\n");
+			kfree(acrtc);
+			goto fail;
+		}
+	}
+
+	dm->display_indexes_num = caps.max_targets;
+
+	/* loops over all connectors on the board */
+	for (i = 0; i < link_cnt; i++) {
+
+		if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) {
+			DRM_ERROR(
+				"KMS: Cannot support more than %d display indexes\n",
+					AMDGPU_DM_MAX_DISPLAY_INDEX);
+			continue;
+		}
+
+		aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
+		if (!aconnector)
+			goto fail;
+
+		aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL);
+		if (!aencoder) {
+			goto fail_free_connector;
+		}
+
+		if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) {
+			DRM_ERROR("KMS: Failed to initialize encoder\n");
+			goto fail_free_encoder;
+		}
+
+		if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) {
+			DRM_ERROR("KMS: Failed to initialize connector\n");
+			goto fail_free_connector;
+		}
+
+		if (dc_link_detect(dc_get_link_at_index(dm->dc, i), true))
+			amdgpu_dm_update_connector_after_detect(
+				aconnector);
+	}
+
+	/* Software is initialized. Now we can register interrupt handlers. */
+	switch (adev->asic_type) {
+	case CHIP_TONGA:
+	case CHIP_FIJI:
+	case CHIP_CARRIZO:
+		if (dce110_register_irq_handlers(dm->adev)) {
+			DRM_ERROR("DM: Failed to initialize IRQ\n");
+			return -1;
+		}
+		break;
+	default:
+		DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type);
+		return -1;
+	}
+
+	drm_mode_config_reset(dm->ddev);
+
+	return 0;
+fail_free_encoder:
+	kfree(aencoder);
+fail_free_connector:
+	kfree(aconnector);
+fail:
+	return -1;
+}
+
+void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
+{
+	drm_mode_config_cleanup(dm->ddev);
+	return;
+}
+
+/******************************************************************************
+ * amdgpu_display_funcs functions
+ *****************************************************************************/
+
+
+static void dm_set_vga_render_state(struct amdgpu_device *adev,
+					   bool render)
+{
+	u32 tmp;
+
+	/* Lockout access through VGA aperture*/
+	tmp = RREG32(mmVGA_HDP_CONTROL);
+	if (render)
+		tmp = REG_SET_FIELD(tmp, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE, 0);
+	else
+		tmp = REG_SET_FIELD(tmp, VGA_HDP_CONTROL, VGA_MEMORY_DISABLE, 1);
+	WREG32(mmVGA_HDP_CONTROL, tmp);
+
+	/* disable VGA render */
+	tmp = RREG32(mmVGA_RENDER_CONTROL);
+	if (render)
+		tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 1);
+	else
+		tmp = REG_SET_FIELD(tmp, VGA_RENDER_CONTROL, VGA_VSTATUS_CNTL, 0);
+	WREG32(mmVGA_RENDER_CONTROL, tmp);
+}
+
+/**
+ * dm_bandwidth_update - program display watermarks
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Calculate and program the display watermarks and line buffer allocation.
+ */
+static void dm_bandwidth_update(struct amdgpu_device *adev)
+{
+	AMDGPU_DM_NOT_IMPL("%s\n", __func__);
+}
+
+static void dm_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder,
+				     u8 level)
+{
+	/* TODO: translate amdgpu_encoder to display_index and call DAL */
+	AMDGPU_DM_NOT_IMPL("%s\n", __func__);
+}
+
+static u8 dm_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder)
+{
+	/* TODO: translate amdgpu_encoder to display_index and call DAL */
+	AMDGPU_DM_NOT_IMPL("%s\n", __func__);
+	return 0;
+}
+
+/******************************************************************************
+ * Page Flip functions
+ ******************************************************************************/
+
+void amdgpu_dm_flip_cleanup(
+	struct amdgpu_device *adev,
+	struct amdgpu_crtc *acrtc)
+{
+	int r;
+	struct amdgpu_flip_work *works = acrtc->pflip_works;
+
+	acrtc->pflip_works = NULL;
+	acrtc->pflip_status = AMDGPU_FLIP_NONE;
+
+	if (works) {
+		if(works->event)
+			drm_send_vblank_event(
+				adev->ddev,
+				acrtc->crtc_id,
+				works->event);
+
+		r = amdgpu_bo_reserve(works->old_rbo, false);
+		if (likely(r == 0)) {
+			r = amdgpu_bo_unpin(works->old_rbo);
+			if (unlikely(r != 0)) {
+				DRM_ERROR("failed to unpin buffer after flip\n");
+			}
+			amdgpu_bo_unreserve(works->old_rbo);
+		} else
+			DRM_ERROR("failed to reserve buffer after flip\n");
+
+		amdgpu_bo_unref(&works->old_rbo);
+		kfree(works->shared);
+		kfree(works);
+	}
+}
+
+/**
+ * dm_page_flip - called by amdgpu_flip_work_func(), which is triggered
+ * 			via DRM IOCTL, by user mode.
+ *
+ * @adev: amdgpu_device pointer
+ * @crtc_id: crtc to cleanup pageflip on
+ * @crtc_base: new address of the crtc (GPU MC address)
+ *
+ * Does the actual pageflip (surface address update).
+ */
+static void dm_page_flip(struct amdgpu_device *adev,
+			int crtc_id, u64 crtc_base)
+{
+	struct amdgpu_crtc *acrtc;
+	struct dc_target *target;
+	struct dc_flip_addrs addr = { {0} };
+
+	/*
+	 * TODO risk of concurrency issues
+	 *
+	 * This should guarded by the dal_mutex but we can't do this since the
+	 * caller uses a spin_lock on event_lock.
+	 *
+	 * If we wait on the dal_mutex a second page flip interrupt might come,
+	 * spin on the event_lock, disabling interrupts while it does so. At
+	 * this point the core can no longer be pre-empted and return to the
+	 * thread that waited on the dal_mutex and we're deadlocked.
+	 *
+	 * With multiple cores the same essentially happens but might just take
+	 * a little longer to lock up all cores.
+	 *
+	 * The reason we should lock on dal_mutex is so that we can be sure
+	 * nobody messes with acrtc->target after we read and check its value.
+	 *
+	 * We might be able to fix our concurrency issues with a work queue
+	 * where we schedule all work items (mode_set, page_flip, etc.) and
+	 * execute them one by one. Care needs to be taken to still deal with
+	 * any potential concurrency issues arising from interrupt calls.
+	 */
+
+	acrtc = adev->mode_info.crtcs[crtc_id];
+	target = acrtc->target;
+
+	/*
+	 * Received a page flip call after the display has been reset.
+	 * Just return in this case. Everything should be clean-up on reset.
+	 */
+	if (!target)
+		return;
+
+	addr.address.grph.addr.low_part = lower_32_bits(crtc_base);
+	addr.address.grph.addr.high_part = upper_32_bits(crtc_base);
+
+	dc_flip_surface_addrs(
+			adev->dm.dc,
+			dc_target_get_status(target)->surfaces,
+			&addr, 1);
+}
+
+static const struct amdgpu_display_funcs display_funcs = {
+	.set_vga_render_state = dm_set_vga_render_state,
+	.bandwidth_update = dm_bandwidth_update, /* called unconditionally */
+	.vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */
+	.vblank_wait = NULL, /* not called anywhere */
+	.is_display_hung = dm_is_display_hung,/* called unconditionally */
+	.backlight_set_level =
+		dm_set_backlight_level,/* called unconditionally */
+	.backlight_get_level =
+		dm_get_backlight_level,/* called unconditionally */
+	.hpd_sense = NULL,/* called unconditionally */
+	.hpd_set_polarity = NULL, /* called unconditionally */
+	.hpd_get_gpio_reg = dm_hpd_get_gpio_reg,/* called unconditionally */
+	.page_flip = dm_page_flip, /* called unconditionally */
+	.page_flip_get_scanoutpos =
+		dm_crtc_get_scanoutpos,/* called unconditionally */
+	.add_encoder = NULL, /* VBIOS parsing. DAL does it. */
+	.add_connector = NULL, /* VBIOS parsing. DAL does it. */
+	.stop_mc_access = dm_stop_mc_access, /* called unconditionally */
+	.resume_mc_access = dm_resume_mc_access, /* called unconditionally */
+};
+
+static void set_display_funcs(struct amdgpu_device *adev)
+{
+	if (adev->mode_info.funcs == NULL)
+		adev->mode_info.funcs = &display_funcs;
+}
+
+static int dm_early_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	set_display_funcs(adev);
+	amdgpu_dm_set_irq_funcs(adev);
+
+	switch (adev->asic_type) {
+	case CHIP_FIJI:
+	case CHIP_TONGA:
+		adev->mode_info.num_crtc = 6;
+		adev->mode_info.num_hpd = 6;
+		adev->mode_info.num_dig = 7;
+		break;
+	case CHIP_CARRIZO:
+		adev->mode_info.num_crtc = 3;
+		adev->mode_info.num_hpd = 6;
+		adev->mode_info.num_dig = 9;
+		break;
+	default:
+		DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type);
+		return -EINVAL;
+	}
+
+	/* Note: Do NOT change adev->audio_endpt_rreg and
+	 * adev->audio_endpt_wreg because they are initialised in
+	 * amdgpu_device_init() */
+
+
+
+	return 0;
+}
+
+
+bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm)
+{
+	/* TODO */
+	return true;
+}
+
+bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm)
+{
+	/* TODO */
+	return true;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
new file mode 100644
index 000000000000..c4ae90b31523
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AMDGPU_DM_H__
+#define __AMDGPU_DM_H__
+
+/*
+#include "linux/switch.h"
+*/
+
+/*
+ * This file contains the definition for amdgpu_display_manager
+ * and its API for amdgpu driver's use.
+ * This component provides all the display related functionality
+ * and this is the only component that calls DAL API.
+ * The API contained here intended for amdgpu driver use.
+ * The API that is called directly from KMS framework is located
+ * in amdgpu_dm_kms.h file
+ */
+
+#define AMDGPU_DM_MAX_DISPLAY_INDEX 31
+/*
+#include "include/amdgpu_dal_power_if.h"
+#include "amdgpu_dm_irq.h"
+*/
+
+#include "irq_types.h"
+
+/* Forward declarations */
+struct amdgpu_device;
+struct drm_device;
+struct amdgpu_dm_irq_handler_data;
+
+struct amdgpu_dm_prev_state {
+	struct drm_framebuffer *fb;
+	int32_t x;
+	int32_t y;
+	struct drm_display_mode mode;
+};
+
+struct common_irq_params {
+	struct amdgpu_device *adev;
+	enum dc_irq_source irq_src;
+};
+
+struct irq_list_head {
+	struct list_head head;
+	/* In case this interrupt needs post-processing, 'work' will be queued*/
+	struct work_struct work;
+};
+
+struct amdgpu_display_manager {
+	struct dal *dal;
+	struct dc *dc;
+	void *cgs_device;
+	/* lock to be used when DAL is called from SYNC IRQ context */
+	spinlock_t dal_lock;
+
+	struct amdgpu_device *adev;	/*AMD base driver*/
+	struct drm_device *ddev;	/*DRM base driver*/
+	u16 display_indexes_num;
+
+	struct amdgpu_dm_prev_state prev_state;
+
+	/*
+	 * 'irq_source_handler_table' holds a list of handlers
+	 * per (DAL) IRQ source.
+	 *
+	 * Each IRQ source may need to be handled at different contexts.
+	 * By 'context' we mean, for example:
+	 * - The ISR context, which is the direct interrupt handler.
+	 * - The 'deferred' context - this is the post-processing of the
+	 *	interrupt, but at a lower priority.
+	 *
+	 * Note that handlers are called in the same order as they were
+	 * registered (FIFO).
+	 */
+	struct irq_list_head irq_handler_list_low_tab[DAL_IRQ_SOURCES_NUMBER];
+	struct list_head irq_handler_list_high_tab[DAL_IRQ_SOURCES_NUMBER];
+
+	struct common_irq_params
+	pflip_params[DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1];
+
+	struct common_irq_params
+	vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1];
+
+	/* this spin lock synchronizes access to 'irq_handler_list_table' */
+	spinlock_t irq_handler_list_table_lock;
+
+	/* Timer-related data. */
+	struct list_head timer_handler_list;
+	struct workqueue_struct *timer_workqueue;
+
+	/* Use dal_mutex for any activity which is NOT syncronized by
+	 * DRM mode setting locks.
+	 * For example: amdgpu_dm_hpd_low_irq() calls into DAL *without*
+	 * DRM mode setting locks being acquired. This is where dal_mutex
+	 * is acquired before calling into DAL. */
+	struct mutex dal_mutex;
+
+	struct backlight_device *backlight_dev;
+
+	const struct dc_link *backlight_link;
+
+	struct work_struct mst_hotplug_work;
+};
+
+
+/* basic init/fini API */
+int amdgpu_dm_init(struct amdgpu_device *adev);
+
+void amdgpu_dm_fini(struct amdgpu_device *adev);
+
+void amdgpu_dm_destroy(void);
+
+/* initializes drm_device display related structures, based on the information
+ * provided by DAL. The drm strcutures are: drm_crtc, drm_connector,
+ * drm_encoder, drm_mode_config
+ *
+ * Returns 0 on success
+ */
+int amdgpu_dm_initialize_drm_device(
+	struct amdgpu_device *adev);
+
+/* removes and deallocates the drm structures, created by the above function */
+void amdgpu_dm_destroy_drm_device(
+	struct amdgpu_display_manager *dm);
+
+/* Locking/Mutex */
+bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm);
+
+bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm);
+
+/* Register "Backlight device" accessible by user-mode. */
+void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm);
+
+void amdgpu_dm_flip_cleanup(
+	struct amdgpu_device *adev,
+	struct amdgpu_crtc *acrtc);
+
+extern const struct amd_ip_funcs amdgpu_dm_funcs;
+
+void amdgpu_dm_update_connector_after_detect(
+	struct amdgpu_connector *aconnector);
+
+#endif /* __AMDGPU_DM_H__ */
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
new file mode 100644
index 000000000000..39c5c98fe918
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/acpi.h>
+#include <linux/version.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/amdgpu_drm.h>
+#include <drm/drm_edid.h>
+
+#include "dm_services.h"
+#include "amdgpu.h"
+#include "dc.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_irq.h"
+#include "amdgpu_dm_types.h"
+
+/* dm_helpers_parse_edid_caps
+ *
+ * Parse edid caps
+ *
+ * @edid:	[in] pointer to edid
+ *  edid_caps:	[in] pointer to edid caps
+ * @return
+ *	void
+ * */
+enum dc_edid_status dm_helpers_parse_edid_caps(
+		struct dc_context *ctx,
+		const struct dc_edid *edid,
+		struct dc_edid_caps *edid_caps)
+{
+	struct edid *edid_buf = (struct edid *) edid->raw_edid;
+	struct cea_sad *sads;
+	int sad_count = -1;
+	int sadb_count = -1;
+	int i = 0;
+	int j = 0;
+	uint8_t *sadb = NULL;
+
+	enum dc_edid_status result = EDID_OK;
+
+	if (!edid_caps || !edid)
+		return EDID_BAD_INPUT;
+
+	if (!drm_edid_is_valid(edid_buf))
+		result = EDID_BAD_CHECKSUM;
+
+	edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] |
+					((uint16_t) edid_buf->mfg_id[1])<<8;
+	edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] |
+					((uint16_t) edid_buf->prod_code[1])<<8;
+	edid_caps->serial_number = edid_buf->serial;
+	edid_caps->manufacture_week = edid_buf->mfg_week;
+	edid_caps->manufacture_year = edid_buf->mfg_year;
+
+	/* One of the four detailed_timings stores the monitor name. It's
+	 * stored in an array of length 13. */
+	for (i = 0; i < 4; i++) {
+		if (edid_buf->detailed_timings[i].data.other_data.type == 0xfc) {
+			while (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] && j < 13) {
+				if (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] == '\n')
+					break;
+
+				edid_caps->display_name[j] =
+					edid_buf->detailed_timings[i].data.other_data.data.str.str[j];
+				j++;
+			}
+		}
+	}
+
+	sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
+	if (sad_count <= 0) {
+		DRM_INFO("SADs count is: %d, don't need to read it\n",
+				sad_count);
+		return result;
+	}
+
+	edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT;
+	for (i = 0; i < edid_caps->audio_mode_count; ++i) {
+		struct cea_sad *sad = &sads[i];
+
+		edid_caps->audio_modes[i].format_code = sad->format;
+		edid_caps->audio_modes[i].channel_count = sad->channels;
+		edid_caps->audio_modes[i].sample_rate = sad->freq;
+		edid_caps->audio_modes[i].sample_size = sad->byte2;
+	}
+
+	sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb);
+
+	if (sadb_count < 0) {
+		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count);
+		sadb_count = 0;
+	}
+
+	if (sadb_count)
+		edid_caps->speaker_flags = sadb[0];
+	else
+		edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION;
+
+	kfree(sads);
+	kfree(sadb);
+
+	return result;
+}
+
+static struct amdgpu_connector *get_connector_for_sink(
+	struct drm_device *dev,
+	const struct dc_sink *sink)
+{
+	struct drm_connector *connector;
+	struct amdgpu_connector *aconnector = NULL;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		if (aconnector->dc_sink == sink)
+			break;
+	}
+
+	return aconnector;
+}
+
+static struct amdgpu_connector *get_connector_for_link(
+	struct drm_device *dev,
+	const struct dc_link *link)
+{
+	struct drm_connector *connector;
+	struct amdgpu_connector *aconnector = NULL;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		if (aconnector->dc_link == link)
+			break;
+	}
+
+	return aconnector;
+}
+
+
+static void get_payload_table(
+		struct amdgpu_connector *aconnector,
+		struct dp_mst_stream_allocation_table *proposed_table)
+{
+	int i;
+	struct drm_dp_mst_topology_mgr *mst_mgr =
+			&aconnector->mst_port->mst_mgr;
+
+	mutex_lock(&mst_mgr->payload_lock);
+
+	proposed_table->stream_count = 0;
+
+	/* number of active streams */
+	for (i = 0; i < mst_mgr->max_payloads; i++) {
+		if (mst_mgr->payloads[i].num_slots == 0)
+			break; /* end of vcp_id table */
+
+		ASSERT(mst_mgr->payloads[i].payload_state !=
+				DP_PAYLOAD_DELETE_LOCAL);
+
+		if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL ||
+			mst_mgr->payloads[i].payload_state ==
+					DP_PAYLOAD_REMOTE) {
+
+			struct dp_mst_stream_allocation *sa =
+					&proposed_table->stream_allocations[
+						proposed_table->stream_count];
+
+			sa->slot_count = mst_mgr->payloads[i].num_slots;
+			sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi;
+			proposed_table->stream_count++;
+		}
+	}
+
+	mutex_unlock(&mst_mgr->payload_lock);
+}
+
+/*
+ * Writes payload allocation table in immediate downstream device.
+ */
+bool dm_helpers_dp_mst_write_payload_allocation_table(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		struct dp_mst_stream_allocation_table *proposed_table,
+		bool enable)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
+	struct drm_dp_mst_port *mst_port;
+	int slots = 0;
+	bool ret;
+	int clock;
+	int bpp = 0;
+	int pbn = 0;
+
+	aconnector = get_connector_for_sink(dev, stream->sink);
+
+	if (!aconnector->mst_port)
+		return false;
+
+	mst_mgr = &aconnector->mst_port->mst_mgr;
+
+	if (!mst_mgr->mst_state)
+		return false;
+
+	mst_port = aconnector->port;
+
+	if (enable) {
+		clock = stream->timing.pix_clk_khz;
+
+		switch (stream->timing.display_color_depth) {
+
+		case COLOR_DEPTH_666:
+			bpp = 6;
+			break;
+		case COLOR_DEPTH_888:
+			bpp = 8;
+			break;
+		case COLOR_DEPTH_101010:
+			bpp = 10;
+			break;
+		case COLOR_DEPTH_121212:
+			bpp = 12;
+			break;
+		case COLOR_DEPTH_141414:
+			bpp = 14;
+			break;
+		case COLOR_DEPTH_161616:
+			bpp = 16;
+			break;
+		default:
+			ASSERT(bpp != 0);
+			break;
+		}
+
+		bpp = bpp * 3;
+
+		/* TODO need to know link rate */
+
+		pbn = drm_dp_calc_pbn_mode(clock, bpp);
+
+		ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, &slots);
+
+		if (!ret)
+			return false;
+
+	} else {
+		drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port);
+	}
+
+	ret = drm_dp_update_payload_part1(mst_mgr);
+
+	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
+	 * AUX message. The sequence is slot 1-63 allocated sequence for each
+	 * stream. AMD ASIC stream slot allocation should follow the same
+	 * sequence. copy DRM MST allocation to dc */
+
+	get_payload_table(aconnector, proposed_table);
+
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/*
+ * Polls for ACT (allocation change trigger) handled and sends
+ * ALLOCATE_PAYLOAD message.
+ */
+bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+		struct dc_context *ctx,
+		const struct dc_stream *stream)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
+	int ret;
+
+	aconnector = get_connector_for_sink(dev, stream->sink);
+
+	if (!aconnector->mst_port)
+		return false;
+
+	mst_mgr = &aconnector->mst_port->mst_mgr;
+
+	if (!mst_mgr->mst_state)
+		return false;
+
+	ret = drm_dp_check_act_status(mst_mgr);
+
+	if (ret)
+		return false;
+
+	return true;
+}
+
+bool dm_helpers_dp_mst_send_payload_allocation(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		bool enable)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
+	struct drm_dp_mst_port *mst_port;
+	int ret;
+
+	aconnector = get_connector_for_sink(dev, stream->sink);
+
+	mst_port = aconnector->port;
+
+	if (!aconnector->mst_port)
+		return false;
+
+	mst_mgr = &aconnector->mst_port->mst_mgr;
+
+	if (!mst_mgr->mst_state)
+		return false;
+
+	ret = drm_dp_update_payload_part2(mst_mgr);
+
+	if (ret)
+		return false;
+
+	if (!enable)
+		drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port);
+
+	return true;
+}
+
+void dm_helpers_dp_mst_handle_mst_hpd_rx_irq(void *param)
+{
+	uint8_t esi[8] = { 0 };
+	uint8_t dret;
+	bool new_irq_handled = true;
+	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
+
+	/* DPCD 0x2002 - 0x2008 for down stream IRQ from MST, eDP etc. */
+	dret = drm_dp_dpcd_read(
+		&aconnector->dm_dp_aux.aux,
+		DP_SINK_COUNT_ESI, esi, 8);
+
+	while ((dret == 8) && new_irq_handled) {
+		uint8_t retry;
+
+		DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+
+		/* handle HPD short pulse irq */
+		drm_dp_mst_hpd_irq(&aconnector->mst_mgr, esi, &new_irq_handled);
+
+		if (new_irq_handled) {
+			/* ACK at DPCD to notify down stream */
+			for (retry = 0; retry < 3; retry++) {
+				uint8_t wret;
+
+				wret = drm_dp_dpcd_write(
+					&aconnector->dm_dp_aux.aux,
+					DP_SINK_COUNT_ESI + 1,
+					&esi[1],
+					3);
+				if (wret == 3)
+					break;
+			}
+
+			/* check if there is new irq to be handle */
+			dret = drm_dp_dpcd_read(
+				&aconnector->dm_dp_aux.aux,
+				DP_SINK_COUNT_ESI, esi, 8);
+		}
+	}
+}
+
+bool dm_helpers_dp_mst_start_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		bool boot)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	if (boot) {
+		DRM_INFO("DM_MST: Differing MST start on aconnector: %p [id: %d]\n",
+					aconnector, aconnector->base.base.id);
+		return true;
+	}
+
+	DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n",
+			aconnector, aconnector->base.base.id);
+
+	return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0);
+}
+
+void dm_helpers_dp_mst_stop_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n",
+			aconnector, aconnector->base.base.id);
+
+	if (aconnector->mst_mgr.mst_state == true)
+		drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false);
+}
+
+bool dm_helper_dp_read_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size) {
+
+
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	if (!aconnector) {
+		DRM_ERROR("Failed to found connector for link!");
+		return false;
+	}
+
+	return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address,
+			data, size) > 0;
+}
+
+bool dm_helper_dp_write_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t size) {
+
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	if (!aconnector) {
+		DRM_ERROR("Failed to found connector for link!");
+		return false;
+	}
+
+	return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux,
+			address, (uint8_t *)data, size) > 0;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
new file mode 100644
index 000000000000..9b5fd7063a0b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <drm/drmP.h>
+
+#include "dm_services_types.h"
+#include "dc.h"
+
+#include "amdgpu.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_irq.h"
+
+
+/******************************************************************************
+ * Private declarations.
+ *****************************************************************************/
+
+struct handler_common_data {
+	struct list_head list;
+	interrupt_handler handler;
+	void *handler_arg;
+
+	/* DM which this handler belongs to */
+	struct amdgpu_display_manager *dm;
+};
+
+struct amdgpu_dm_irq_handler_data {
+	struct handler_common_data hcd;
+	/* DAL irq source which registered for this interrupt. */
+	enum dc_irq_source irq_source;
+};
+
+struct amdgpu_dm_timer_handler_data {
+	struct handler_common_data hcd;
+	struct delayed_work d_work;
+};
+
+
+#define DM_IRQ_TABLE_LOCK(adev, flags) \
+	spin_lock_irqsave(&adev->dm.irq_handler_list_table_lock, flags)
+
+#define DM_IRQ_TABLE_UNLOCK(adev, flags) \
+	spin_unlock_irqrestore(&adev->dm.irq_handler_list_table_lock, flags)
+
+/******************************************************************************
+ * Private functions.
+ *****************************************************************************/
+
+static void init_handler_common_data(
+	struct handler_common_data *hcd,
+	void (*ih)(void *),
+	void *args,
+	struct amdgpu_display_manager *dm)
+{
+	hcd->handler = ih;
+	hcd->handler_arg = args;
+	hcd->dm = dm;
+}
+
+/**
+ * dm_irq_work_func - Handle an IRQ outside of the interrupt handler proper.
+ *
+ * @work: work struct
+ */
+static void dm_irq_work_func(struct work_struct *work)
+{
+	struct list_head *entry;
+	struct irq_list_head *irq_list_head =
+		container_of(work, struct irq_list_head, work);
+	struct list_head *handler_list = &irq_list_head->head;
+	struct amdgpu_dm_irq_handler_data *handler_data;
+
+	list_for_each(entry, handler_list) {
+		handler_data =
+			list_entry(
+				entry,
+				struct amdgpu_dm_irq_handler_data,
+				hcd.list);
+
+		DRM_DEBUG_KMS("DM_IRQ: work_func: for dal_src=%d\n",
+				handler_data->irq_source);
+
+		DRM_DEBUG_KMS("DM_IRQ: schedule_work: for dal_src=%d\n",
+			handler_data->irq_source);
+
+		handler_data->hcd.handler(handler_data->hcd.handler_arg);
+	}
+
+	/* Call a DAL subcomponent which registered for interrupt notification
+	 * at INTERRUPT_LOW_IRQ_CONTEXT.
+	 * (The most common use is HPD interrupt) */
+}
+
+/**
+ * Remove a handler and return a pointer to hander list from which the
+ * handler was removed.
+ */
+static struct list_head *remove_irq_handler(
+	struct amdgpu_device *adev,
+	void *ih,
+	const struct dc_interrupt_params *int_params)
+{
+	struct list_head *hnd_list;
+	struct list_head *entry, *tmp;
+	struct amdgpu_dm_irq_handler_data *handler;
+	unsigned long irq_table_flags;
+	bool handler_removed = false;
+	enum dc_irq_source irq_source;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	irq_source = int_params->irq_source;
+
+	switch (int_params->int_context) {
+	case INTERRUPT_HIGH_IRQ_CONTEXT:
+		hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source];
+		break;
+	case INTERRUPT_LOW_IRQ_CONTEXT:
+	default:
+		hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head;
+		break;
+	}
+
+	list_for_each_safe(entry, tmp, hnd_list) {
+
+		handler = list_entry(entry, struct amdgpu_dm_irq_handler_data,
+				hcd.list);
+
+		if (ih == handler) {
+			/* Found our handler. Remove it from the list. */
+			list_del(&handler->hcd.list);
+			handler_removed = true;
+			break;
+		}
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	if (handler_removed == false) {
+		/* Not necessarily an error - caller may not
+		 * know the context. */
+		return NULL;
+	}
+
+	kfree(handler);
+
+	DRM_DEBUG_KMS(
+	"DM_IRQ: removed irq handler: %p for: dal_src=%d, irq context=%d\n",
+		ih, int_params->irq_source, int_params->int_context);
+
+	return hnd_list;
+}
+
+/* If 'handler_in == NULL' then remove ALL handlers. */
+static void remove_timer_handler(
+	struct amdgpu_device *adev,
+	struct amdgpu_dm_timer_handler_data *handler_in)
+{
+	struct amdgpu_dm_timer_handler_data *handler_temp;
+	struct list_head *handler_list;
+	struct list_head *entry, *tmp;
+	unsigned long irq_table_flags;
+	bool handler_removed = false;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	handler_list = &adev->dm.timer_handler_list;
+
+	list_for_each_safe(entry, tmp, handler_list) {
+		/* Note that list_for_each_safe() guarantees that
+		 * handler_temp is NOT null. */
+		handler_temp = list_entry(entry,
+				struct amdgpu_dm_timer_handler_data, hcd.list);
+
+		if (handler_in == NULL || handler_in == handler_temp) {
+			list_del(&handler_temp->hcd.list);
+			DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+			DRM_DEBUG_KMS("DM_IRQ: removing timer handler: %p\n",
+					handler_temp);
+
+			if (handler_in == NULL) {
+				/* Since it is still in the queue, it must
+				 * be cancelled. */
+				cancel_delayed_work_sync(&handler_temp->d_work);
+			}
+
+			kfree(handler_temp);
+			handler_removed = true;
+
+			DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+		}
+
+		if (handler_in == NULL) {
+			/* Remove ALL handlers. */
+			continue;
+		}
+
+		if (handler_in == handler_temp) {
+			/* Remove a SPECIFIC handler.
+			 * Found our handler - we can stop here. */
+			break;
+		}
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	if (handler_in != NULL && handler_removed == false) {
+		DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n",
+				handler_in);
+	}
+}
+
+/**
+ * dm_timer_work_func - Handle a timer.
+ *
+ * @work: work struct
+ */
+static void dm_timer_work_func(
+	struct work_struct *work)
+{
+	struct amdgpu_dm_timer_handler_data *handler_data =
+		container_of(work, struct amdgpu_dm_timer_handler_data,
+				d_work.work);
+
+	DRM_DEBUG_KMS("DM_IRQ: work_func: handler_data=%p\n", handler_data);
+
+	/* Call a DAL subcomponent which registered for timer notification. */
+	handler_data->hcd.handler(handler_data->hcd.handler_arg);
+
+	/* We support only "single shot" timers. That means we must delete
+	 * the handler after it was called. */
+	remove_timer_handler(handler_data->hcd.dm->adev, handler_data);
+}
+
+static bool validate_irq_registration_params(
+	struct dc_interrupt_params *int_params,
+	void (*ih)(void *))
+{
+	if (NULL == int_params || NULL == ih) {
+		DRM_ERROR("DM_IRQ: invalid input!\n");
+		return false;
+	}
+
+	if (int_params->int_context >= INTERRUPT_CONTEXT_NUMBER) {
+		DRM_ERROR("DM_IRQ: invalid context: %d!\n",
+				int_params->int_context);
+		return false;
+	}
+
+	if (!DAL_VALID_IRQ_SRC_NUM(int_params->irq_source)) {
+		DRM_ERROR("DM_IRQ: invalid irq_source: %d!\n",
+				int_params->irq_source);
+		return false;
+	}
+
+	return true;
+}
+
+static bool validate_irq_unregistration_params(
+	enum dc_irq_source irq_source,
+	irq_handler_idx handler_idx)
+{
+	if (DAL_INVALID_IRQ_HANDLER_IDX == handler_idx) {
+		DRM_ERROR("DM_IRQ: invalid handler_idx==NULL!\n");
+		return false;
+	}
+
+	if (!DAL_VALID_IRQ_SRC_NUM(irq_source)) {
+		DRM_ERROR("DM_IRQ: invalid irq_source:%d!\n", irq_source);
+		return false;
+	}
+
+	return true;
+}
+/******************************************************************************
+ * Public functions.
+ *
+ * Note: caller is responsible for input validation.
+ *****************************************************************************/
+
+void *amdgpu_dm_irq_register_interrupt(
+	struct amdgpu_device *adev,
+	struct dc_interrupt_params *int_params,
+	void (*ih)(void *),
+	void *handler_args)
+{
+	struct list_head *hnd_list;
+	struct amdgpu_dm_irq_handler_data *handler_data;
+	unsigned long irq_table_flags;
+	enum dc_irq_source irq_source;
+
+	if (false == validate_irq_registration_params(int_params, ih))
+		return DAL_INVALID_IRQ_HANDLER_IDX;
+
+	handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL);
+	if (!handler_data) {
+		DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n");
+		return DAL_INVALID_IRQ_HANDLER_IDX;
+	}
+
+	memset(handler_data, 0, sizeof(*handler_data));
+
+	init_handler_common_data(&handler_data->hcd, ih, handler_args,
+			&adev->dm);
+
+	irq_source = int_params->irq_source;
+
+	handler_data->irq_source = irq_source;
+
+	/* Lock the list, add the handler. */
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	switch (int_params->int_context) {
+	case INTERRUPT_HIGH_IRQ_CONTEXT:
+		hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source];
+		break;
+	case INTERRUPT_LOW_IRQ_CONTEXT:
+	default:
+		hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head;
+		break;
+	}
+
+	list_add_tail(&handler_data->hcd.list, hnd_list);
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	/* This pointer will be stored by code which requested interrupt
+	 * registration.
+	 * The same pointer will be needed in order to unregister the
+	 * interrupt. */
+
+	DRM_DEBUG_KMS(
+		"DM_IRQ: added irq handler: %p for: dal_src=%d, irq context=%d\n",
+		handler_data,
+		irq_source,
+		int_params->int_context);
+
+	return handler_data;
+}
+
+void amdgpu_dm_irq_unregister_interrupt(
+	struct amdgpu_device *adev,
+	enum dc_irq_source irq_source,
+	void *ih)
+{
+	struct list_head *handler_list;
+	struct dc_interrupt_params int_params;
+	int i;
+
+	if (false == validate_irq_unregistration_params(irq_source, ih))
+		return;
+
+	memset(&int_params, 0, sizeof(int_params));
+
+	int_params.irq_source = irq_source;
+
+	for (i = 0; i < INTERRUPT_CONTEXT_NUMBER; i++) {
+
+		int_params.int_context = i;
+
+		handler_list = remove_irq_handler(adev, ih, &int_params);
+
+		if (handler_list != NULL)
+			break;
+	}
+
+	if (handler_list == NULL) {
+		/* If we got here, it means we searched all irq contexts
+		 * for this irq source, but the handler was not found. */
+		DRM_ERROR(
+		"DM_IRQ: failed to find irq handler:%p for irq_source:%d!\n",
+			ih, irq_source);
+	}
+}
+
+int amdgpu_dm_irq_init(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct irq_list_head *lh;
+
+	DRM_DEBUG_KMS("DM_IRQ\n");
+
+	spin_lock_init(&adev->dm.irq_handler_list_table_lock);
+
+	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+		/* low context handler list init */
+		lh = &adev->dm.irq_handler_list_low_tab[src];
+		INIT_LIST_HEAD(&lh->head);
+		INIT_WORK(&lh->work, dm_irq_work_func);
+
+		/* high context handler init */
+		INIT_LIST_HEAD(&adev->dm.irq_handler_list_high_tab[src]);
+	}
+
+	INIT_LIST_HEAD(&adev->dm.timer_handler_list);
+
+	/* allocate and initialize the workqueue for DM timer */
+	adev->dm.timer_workqueue = create_singlethread_workqueue(
+			"dm_timer_queue");
+	if (adev->dm.timer_workqueue == NULL) {
+		DRM_ERROR("DM_IRQ: unable to create timer queue!\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void amdgpu_dm_irq_register_timer(
+	struct amdgpu_device *adev,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *args)
+{
+	unsigned long jf_delay;
+	struct list_head *handler_list;
+	struct amdgpu_dm_timer_handler_data *handler_data;
+	unsigned long irq_table_flags;
+
+	handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL);
+	if (!handler_data) {
+		DRM_ERROR("DM_IRQ: failed to allocate timer handler!\n");
+		return;
+	}
+
+	memset(handler_data, 0, sizeof(*handler_data));
+
+	init_handler_common_data(&handler_data->hcd, ih, args, &adev->dm);
+
+	INIT_DELAYED_WORK(&handler_data->d_work, dm_timer_work_func);
+
+	/* Lock the list, add the handler. */
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	handler_list = &adev->dm.timer_handler_list;
+
+	list_add_tail(&handler_data->hcd.list, handler_list);
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	jf_delay = usecs_to_jiffies(int_params->micro_sec_interval);
+
+	queue_delayed_work(adev->dm.timer_workqueue, &handler_data->d_work,
+			jf_delay);
+
+	DRM_DEBUG_KMS("DM_IRQ: added handler:%p with micro_sec_interval=%u\n",
+			handler_data, int_params->micro_sec_interval);
+	return;
+}
+
+/* DM IRQ and timer resource release */
+void amdgpu_dm_irq_fini(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct irq_list_head *lh;
+	DRM_DEBUG_KMS("DM_IRQ: releasing resources.\n");
+
+	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+
+		/* The handler was removed from the table,
+		 * it means it is safe to flush all the 'work'
+		 * (because no code can schedule a new one). */
+		lh = &adev->dm.irq_handler_list_low_tab[src];
+		flush_work(&lh->work);
+	}
+
+	/* Cancel ALL timers and release handlers (if any). */
+	remove_timer_handler(adev, NULL);
+	/* Release the queue itself. */
+	destroy_workqueue(adev->dm.timer_workqueue);
+}
+
+int amdgpu_dm_irq_suspend(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct list_head *hnd_list_h;
+	struct list_head *hnd_list_l;
+	unsigned long irq_table_flags;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	DRM_DEBUG_KMS("DM_IRQ: suspend\n");
+
+	/* disable HW interrupt */
+	for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+		hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
+		hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
+		if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
+			dc_interrupt_set(adev->dm.dc, src, false);
+
+		DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+		flush_work(&adev->dm.irq_handler_list_low_tab[src].work);
+
+		DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	return 0;
+}
+
+int amdgpu_dm_irq_resume(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct list_head *hnd_list_h, *hnd_list_l;
+	unsigned long irq_table_flags;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	DRM_DEBUG_KMS("DM_IRQ: resume\n");
+
+	/* re-enable HW interrupt */
+	for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+		hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
+		hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
+		if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
+			dc_interrupt_set(adev->dm.dc, src, true);
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	return 0;
+}
+
+
+/**
+ * amdgpu_dm_irq_schedule_work - schedule all work items registered for the
+ * "irq_source".
+ */
+static void amdgpu_dm_irq_schedule_work(
+	struct amdgpu_device *adev,
+	enum dc_irq_source irq_source)
+{
+	unsigned long irq_table_flags;
+	struct work_struct *work = NULL;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	if (!list_empty(&adev->dm.irq_handler_list_low_tab[irq_source].head))
+		work = &adev->dm.irq_handler_list_low_tab[irq_source].work;
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	if (work) {
+		if (!schedule_work(work))
+			DRM_INFO("amdgpu_dm_irq_schedule_work FAILED src %d\n",
+						irq_source);
+	}
+
+}
+
+/** amdgpu_dm_irq_immediate_work
+ *  Callback high irq work immediately, don't send to work queue
+ */
+static void amdgpu_dm_irq_immediate_work(
+	struct amdgpu_device *adev,
+	enum dc_irq_source irq_source)
+{
+	struct amdgpu_dm_irq_handler_data *handler_data;
+	struct list_head *entry;
+	unsigned long irq_table_flags;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	list_for_each(
+		entry,
+		&adev->dm.irq_handler_list_high_tab[irq_source]) {
+
+		handler_data =
+			list_entry(
+				entry,
+				struct amdgpu_dm_irq_handler_data,
+				hcd.list);
+
+		/* Call a subcomponent which registered for immediate
+		 * interrupt notification */
+		handler_data->hcd.handler(handler_data->hcd.handler_arg);
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+}
+
+/*
+ * amdgpu_dm_irq_handler
+ *
+ * Generic IRQ handler, calls all registered high irq work immediately, and
+ * schedules work for low irq
+ */
+int amdgpu_dm_irq_handler(
+		struct amdgpu_device *adev,
+		struct amdgpu_irq_src *source,
+		struct amdgpu_iv_entry *entry)
+{
+
+	enum dc_irq_source src =
+		dc_interrupt_to_irq_source(
+			adev->dm.dc,
+			entry->src_id,
+			entry->src_data);
+
+	dc_interrupt_ack(adev->dm.dc, src);
+
+	/* Call high irq work immediately */
+	amdgpu_dm_irq_immediate_work(adev, src);
+	/*Schedule low_irq work */
+	amdgpu_dm_irq_schedule_work(adev, src);
+
+	return 0;
+}
+
+static enum dc_irq_source amdgpu_dm_hpd_to_dal_irq_source(unsigned type)
+{
+	switch (type) {
+	case AMDGPU_HPD_1:
+		return DC_IRQ_SOURCE_HPD1;
+	case AMDGPU_HPD_2:
+		return DC_IRQ_SOURCE_HPD2;
+	case AMDGPU_HPD_3:
+		return DC_IRQ_SOURCE_HPD3;
+	case AMDGPU_HPD_4:
+		return DC_IRQ_SOURCE_HPD4;
+	case AMDGPU_HPD_5:
+		return DC_IRQ_SOURCE_HPD5;
+	case AMDGPU_HPD_6:
+		return DC_IRQ_SOURCE_HPD6;
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev,
+					struct amdgpu_irq_src *source,
+					unsigned type,
+					enum amdgpu_interrupt_state state)
+{
+	enum dc_irq_source src = amdgpu_dm_hpd_to_dal_irq_source(type);
+	bool st = (state == AMDGPU_IRQ_STATE_ENABLE);
+
+	dc_interrupt_set(adev->dm.dc, src, st);
+	return 0;
+}
+
+static inline int dm_irq_state(
+	struct amdgpu_device *adev,
+	struct amdgpu_irq_src *source,
+	unsigned crtc_id,
+	enum amdgpu_interrupt_state state,
+	const enum irq_type dal_irq_type,
+	const char *func)
+{
+	bool st;
+	enum dc_irq_source irq_source;
+
+	struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc_id];
+
+	if (!acrtc->target) {
+		DRM_INFO(
+			"%s: target is null for crtc %d, talk to David R\n",
+			func,
+			crtc_id);
+		WARN_ON(true);
+		return 0;
+	}
+
+	irq_source = dc_target_get_irq_src(acrtc->target, dal_irq_type);
+
+	st = (state == AMDGPU_IRQ_STATE_ENABLE);
+
+	dc_interrupt_set(adev->dm.dc, irq_source, st);
+	return 0;
+}
+
+static int amdgpu_dm_set_pflip_irq_state(struct amdgpu_device *adev,
+					struct amdgpu_irq_src *source,
+					unsigned crtc_id,
+					enum amdgpu_interrupt_state state)
+{
+	return dm_irq_state(
+		adev,
+		source,
+		crtc_id,
+		state,
+		IRQ_TYPE_PFLIP,
+		__func__);
+}
+
+static int amdgpu_dm_set_crtc_irq_state(struct amdgpu_device *adev,
+					struct amdgpu_irq_src *source,
+					unsigned crtc_id,
+					enum amdgpu_interrupt_state state)
+{
+	return dm_irq_state(
+		adev,
+		source,
+		crtc_id,
+		state,
+		IRQ_TYPE_VUPDATE,
+		__func__);
+}
+
+static const struct amdgpu_irq_src_funcs dm_crtc_irq_funcs = {
+	.set = amdgpu_dm_set_crtc_irq_state,
+	.process = amdgpu_dm_irq_handler,
+};
+
+static const struct amdgpu_irq_src_funcs dm_pageflip_irq_funcs = {
+	.set = amdgpu_dm_set_pflip_irq_state,
+	.process = amdgpu_dm_irq_handler,
+};
+
+static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = {
+	.set = amdgpu_dm_set_hpd_irq_state,
+	.process = amdgpu_dm_irq_handler,
+};
+
+void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev)
+{
+	adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST;
+	adev->crtc_irq.funcs = &dm_crtc_irq_funcs;
+
+	adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST;
+	adev->pageflip_irq.funcs = &dm_pageflip_irq_funcs;
+
+	adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
+	adev->hpd_irq.funcs = &dm_hpd_irq_funcs;
+}
+
+/*
+ * amdgpu_dm_hpd_init - hpd setup callback.
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Setup the hpd pins used by the card (evergreen+).
+ * Enable the pin, set the polarity, and enable the hpd interrupts.
+ */
+void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct amdgpu_connector *amdgpu_connector =
+				to_amdgpu_connector(connector);
+
+		const struct dc_link *dc_link = amdgpu_connector->dc_link;
+
+		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+			connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+			/* don't try to enable hpd on eDP or LVDS avoid breaking
+			 * the aux dp channel on imac and help (but not
+			 * completely fix)
+			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+			 * also avoid interrupt storms during dpms.
+			 */
+			continue;
+		}
+
+		dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, true);
+
+		if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+			dc_interrupt_set(adev->dm.dc,
+					dc_link->irq_source_hpd_rx,
+					true);
+		}
+	}
+}
+
+/**
+ * amdgpu_dm_hpd_fini - hpd tear down callback.
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Tear down the hpd pins used by the card (evergreen+).
+ * Disable the hpd interrupts.
+ */
+void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct amdgpu_connector *amdgpu_connector =
+				to_amdgpu_connector(connector);
+		const struct dc_link *dc_link = amdgpu_connector->dc_link;
+
+		dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, false);
+
+		if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+			dc_interrupt_set(adev->dm.dc,
+					dc_link->irq_source_hpd_rx,
+					false);
+		}
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
new file mode 100644
index 000000000000..afedb50897bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION 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 __AMDGPU_DM_IRQ_H__
+#define __AMDGPU_DM_IRQ_H__
+
+#include "irq_types.h" /* DAL irq definitions */
+
+/*
+ * Display Manager IRQ-related interfaces (for use by DAL).
+ */
+
+/**
+ * amdgpu_dm_irq_init - Initialize internal structures of 'amdgpu_dm_irq'.
+ *
+ * This function should be called exactly once - during DM initialization.
+ *
+ * Returns:
+ *	0 - success
+ *	non-zero - error
+ */
+int amdgpu_dm_irq_init(
+	struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_fini - deallocate internal structures of 'amdgpu_dm_irq'.
+ *
+ * This function should be called exactly once - during DM destruction.
+ *
+ */
+void amdgpu_dm_irq_fini(
+	struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_register_interrupt - register irq handler for Display block.
+ *
+ * @adev: AMD DRM device
+ * @int_params: parameters for the irq
+ * @ih: pointer to the irq hander function
+ * @handler_args: arguments which will be passed to ih
+ *
+ * Returns:
+ * 	IRQ Handler Index on success.
+ * 	NULL on failure.
+ *
+ * Cannot be called from an interrupt handler.
+ */
+void *amdgpu_dm_irq_register_interrupt(
+		struct amdgpu_device *adev,
+		struct dc_interrupt_params *int_params,
+		void (*ih)(void *),
+		void *handler_args);
+
+/**
+ * amdgpu_dm_irq_unregister_interrupt - unregister handler which was registered
+ *	by amdgpu_dm_irq_register_interrupt().
+ *
+ * @adev: AMD DRM device.
+ * @ih_index: irq handler index which was returned by
+ *	amdgpu_dm_irq_register_interrupt
+ */
+void amdgpu_dm_irq_unregister_interrupt(
+		struct amdgpu_device *adev,
+		enum dc_irq_source irq_source,
+		void *ih_index);
+
+void amdgpu_dm_irq_register_timer(
+	struct amdgpu_device *adev,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *args);
+
+/**
+ * amdgpu_dm_irq_handler
+ * Generic IRQ handler, calls all registered high irq work immediately, and
+ * schedules work for low irq
+ */
+int amdgpu_dm_irq_handler(
+		struct amdgpu_device *adev,
+		struct amdgpu_irq_src *source,
+		struct amdgpu_iv_entry *entry);
+
+void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev);
+
+void amdgpu_dm_hpd_init(struct amdgpu_device *adev);
+void amdgpu_dm_hpd_fini(struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_suspend - disable ASIC interrupt during suspend.
+ *
+ */
+int amdgpu_dm_irq_suspend(
+	struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_resume - enable ASIC interrupt during resume.
+ *
+ */
+int amdgpu_dm_irq_resume(
+	struct amdgpu_device *adev);
+
+#endif /* __AMDGPU_DM_IRQ_H__ */
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
new file mode 100644
index 000000000000..22ba13080cf1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/version.h>
+#include <drm/drm_atomic_helper.h>
+#include "dm_services.h"
+#include "amdgpu.h"
+#include "amdgpu_dm_types.h"
+#include "amdgpu_dm_mst_types.h"
+
+#include "dc.h"
+#include "dm_helpers.h"
+
+
+/* #define TRACE_DPCD */
+
+#ifdef TRACE_DPCD
+#define SIDE_BAND_MSG(address) (address >= DP_SIDEBAND_MSG_DOWN_REQ_BASE && address < DP_SINK_COUNT_ESI)
+
+static inline char *side_band_msg_type_to_str(uint32_t address)
+{
+	static char str[10] = {0};
+
+	if (address < DP_SIDEBAND_MSG_UP_REP_BASE)
+		strcpy(str, "DOWN_REQ");
+	else if (address < DP_SIDEBAND_MSG_DOWN_REP_BASE)
+		strcpy(str, "UP_REP");
+	else if (address < DP_SIDEBAND_MSG_UP_REQ_BASE)
+		strcpy(str, "DOWN_REP");
+	else
+		strcpy(str, "UP_REQ");
+
+	return str;
+}
+
+void log_dpcd(uint8_t type,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size,
+		bool res)
+{
+	DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n",
+			(type == DP_AUX_NATIVE_READ) ||
+			(type == DP_AUX_I2C_READ) ?
+					"Read" : "Write",
+			address,
+			SIDE_BAND_MSG(address) ?
+					side_band_msg_type_to_str(address) : "Nop",
+			res ? "OK" : "Fail");
+
+	if (res) {
+		print_hex_dump(KERN_INFO, "Body: ", DUMP_PREFIX_NONE, 16, 1, data, size, false);
+	}
+}
+#endif
+
+static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
+{
+	struct pci_dev *pdev = to_pci_dev(aux->dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct amdgpu_device *adev = drm_dev->dev_private;
+	struct dc *dc = adev->dm.dc;
+	bool res;
+
+	switch (msg->request) {
+	case DP_AUX_NATIVE_READ:
+		res = dc_read_dpcd(
+			dc,
+			TO_DM_AUX(aux)->link_index,
+			msg->address,
+			msg->buffer,
+			msg->size);
+		break;
+	case DP_AUX_NATIVE_WRITE:
+		res = dc_write_dpcd(
+			dc,
+			TO_DM_AUX(aux)->link_index,
+			msg->address,
+			msg->buffer,
+			msg->size);
+		break;
+	default:
+		return 0;
+	}
+
+#ifdef TRACE_DPCD
+	log_dpcd(msg->request,
+			msg->address,
+			msg->buffer,
+			msg->size,
+			res);
+#endif
+
+	return msg->size;
+}
+
+static enum drm_connector_status
+dm_dp_mst_detect(struct drm_connector *connector, bool force)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+	struct amdgpu_connector *master = aconnector->mst_port;
+
+	enum drm_connector_status status =
+		drm_dp_mst_detect_port(
+			connector,
+			&master->mst_mgr,
+			aconnector->port);
+
+	if (status == connector_status_disconnected && aconnector->edid) {
+		kfree(aconnector->edid);
+		aconnector->edid = NULL;
+	}
+
+	/*
+	 * we do not want to make this connector connected until we have edid on
+	 * it
+	 */
+	if (status == connector_status_connected &&
+		!aconnector->port->cached_edid)
+		status = connector_status_disconnected;
+
+	return status;
+}
+
+static void
+dm_dp_mst_connector_destroy(struct drm_connector *connector)
+{
+	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+	struct amdgpu_encoder *amdgpu_encoder = amdgpu_connector->mst_encoder;
+
+	drm_encoder_cleanup(&amdgpu_encoder->base);
+	kfree(amdgpu_encoder);
+	drm_connector_cleanup(connector);
+	kfree(amdgpu_connector);
+}
+
+static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = dm_dp_mst_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = dm_dp_mst_connector_destroy,
+	.reset = amdgpu_dm_connector_funcs_reset,
+	.atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
+	.atomic_destroy_state = amdgpu_dm_connector_atomic_destroy_state,
+	.atomic_set_property = amdgpu_dm_connector_atomic_set_property
+};
+
+static struct dc_sink *dm_dp_mst_add_mst_sink(
+		const struct dc_link *dc_link,
+		uint8_t *edid,
+		uint16_t len)
+{
+	struct dc_sink *dc_sink;
+	struct dc_sink_init_data init_params = {
+			.link = dc_link,
+			.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST};
+	enum dc_edid_status edid_status;
+
+	if (len > MAX_EDID_BUFFER_SIZE) {
+		DRM_ERROR("Max EDID buffer size breached!\n");
+		return NULL;
+	}
+
+	if (!dc_link) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	/*
+	 * TODO make dynamic-ish?
+	 * dc_link->connector_signal;
+	 */
+
+	dc_sink = dc_sink_create(&init_params);
+
+	if (!dc_sink)
+		return NULL;
+
+	dm_memmove(dc_sink->dc_edid.raw_edid, edid, len);
+	dc_sink->dc_edid.length = len;
+
+	if (!dc_link_add_remote_sink(
+			dc_link,
+			dc_sink))
+		goto fail_add_sink;
+
+	edid_status = dm_helpers_parse_edid_caps(
+			NULL,
+			&dc_sink->dc_edid,
+			&dc_sink->edid_caps);
+	if (edid_status != EDID_OK)
+		goto fail;
+
+	/* dc_sink_retain(&core_sink->public); */
+
+	return dc_sink;
+fail:
+	dc_link_remove_remote_sink(dc_link, dc_sink);
+fail_add_sink:
+	return NULL;
+}
+
+static int dm_dp_mst_get_modes(struct drm_connector *connector)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+	struct amdgpu_connector *master = aconnector->mst_port;
+	struct edid *edid;
+	const struct dc_sink *sink;
+	int ret = 0;
+
+	if (!aconnector->edid) {
+		edid = drm_dp_mst_get_edid(connector, &master->mst_mgr, aconnector->port);
+
+		if (!edid) {
+			drm_mode_connector_update_edid_property(
+				&aconnector->base,
+				NULL);
+
+			return ret;
+		}
+
+		aconnector->edid = edid;
+
+		if (aconnector->dc_sink)
+			dc_link_remove_remote_sink(
+				aconnector->dc_link,
+				aconnector->dc_sink);
+
+		sink = dm_dp_mst_add_mst_sink(
+			aconnector->dc_link,
+			(uint8_t *)edid,
+			(edid->extensions + 1) * EDID_LENGTH);
+		aconnector->dc_sink = sink;
+	} else
+		edid = aconnector->edid;
+
+	DRM_DEBUG_KMS("edid retrieved %p\n", edid);
+
+	drm_mode_connector_update_edid_property(
+		&aconnector->base,
+		aconnector->edid);
+
+	ret = drm_add_edid_modes(&aconnector->base, aconnector->edid);
+
+	drm_edid_to_eld(&aconnector->base, aconnector->edid);
+
+	return ret;
+}
+
+static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
+{
+	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+
+	return &amdgpu_connector->mst_encoder->base;
+}
+
+static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = {
+	.get_modes = dm_dp_mst_get_modes,
+	.mode_valid = amdgpu_dm_connector_mode_valid,
+	.best_encoder = dm_mst_best_encoder,
+};
+
+static struct amdgpu_encoder *
+dm_dp_create_fake_mst_encoder(struct amdgpu_connector *connector)
+{
+	struct drm_device *dev = connector->base.dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct amdgpu_encoder *amdgpu_encoder;
+	struct drm_encoder *encoder;
+	const struct drm_connector_helper_funcs *connector_funcs =
+		connector->base.helper_private;
+	struct drm_encoder *enc_master =
+		connector_funcs->best_encoder(&connector->base);
+
+	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
+	amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
+	if (!amdgpu_encoder)
+		return NULL;
+
+	encoder = &amdgpu_encoder->base;
+	encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
+
+	drm_encoder_init(
+		dev,
+		&amdgpu_encoder->base,
+		NULL,
+		DRM_MODE_ENCODER_DPMST,
+		NULL);
+
+	drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
+
+	return amdgpu_encoder;
+}
+
+static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
+							 struct drm_dp_mst_port *port,
+							 const char *pathprop)
+{
+	struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr);
+	struct drm_device *dev = master->base.dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct amdgpu_connector *aconnector;
+	struct drm_connector *connector;
+
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		if (aconnector->mst_port == master
+				&& !aconnector->port) {
+			DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n",
+						aconnector, connector->base.id, aconnector->mst_port);
+
+			aconnector->port = port;
+			drm_mode_connector_set_path_property(connector, pathprop);
+
+			drm_modeset_unlock(&dev->mode_config.connection_mutex);
+			return &aconnector->base;
+		}
+	}
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+
+	aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
+	if (!aconnector)
+		return NULL;
+
+	connector = &aconnector->base;
+	aconnector->port = port;
+	aconnector->mst_port = master;
+
+	if (drm_connector_init(
+		dev,
+		connector,
+		&dm_dp_mst_connector_funcs,
+		DRM_MODE_CONNECTOR_DisplayPort)) {
+		kfree(aconnector);
+		return NULL;
+	}
+	drm_connector_helper_add(connector, &dm_dp_mst_connector_helper_funcs);
+
+	amdgpu_dm_connector_init_helper(
+		&adev->dm,
+		aconnector,
+		DRM_MODE_CONNECTOR_DisplayPort,
+		master->dc_link,
+		master->connector_id);
+
+	aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
+
+	/*
+	 * TODO: understand why this one is needed
+	 */
+	drm_object_attach_property(
+		&connector->base,
+		dev->mode_config.path_property,
+		0);
+	drm_object_attach_property(
+		&connector->base,
+		dev->mode_config.tile_property,
+		0);
+
+	drm_mode_connector_set_path_property(connector, pathprop);
+
+	/*
+	 * Initialize connector state before adding the connectror to drm and
+	 * framebuffer lists
+	 */
+	amdgpu_dm_connector_funcs_reset(connector);
+
+	DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n",
+			aconnector, connector->base.id, aconnector->mst_port);
+
+	DRM_DEBUG_KMS(":%d\n", connector->base.id);
+
+	return connector;
+}
+
+static void dm_dp_destroy_mst_connector(
+	struct drm_dp_mst_topology_mgr *mgr,
+	struct drm_connector *connector)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+
+	DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n",
+				aconnector, connector->base.id, aconnector->mst_port);
+
+	aconnector->port = NULL;
+	if (aconnector->dc_sink) {
+		dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink);
+		aconnector->dc_sink = NULL;
+	}
+}
+
+static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr);
+	struct drm_device *dev = master->base.dev;
+	struct amdgpu_device *adev = dev->dev_private;
+
+	schedule_work(&adev->dm.mst_hotplug_work);
+}
+
+static void dm_dp_mst_register_connector(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	int i;
+
+	drm_modeset_lock_all(dev);
+	if (adev->mode_info.rfbdev) {
+		/*Do not add if already registered in past*/
+		for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) {
+			if (adev->mode_info.rfbdev->helper.connector_info[i]->connector
+					== connector) {
+				drm_modeset_unlock_all(dev);
+				return;
+			}
+		}
+
+		drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector);
+	}
+	else
+		DRM_ERROR("adev->mode_info.rfbdev is NULL\n");
+
+	drm_modeset_unlock_all(dev);
+
+	drm_connector_register(connector);
+
+}
+
+struct drm_dp_mst_topology_cbs dm_mst_cbs = {
+	.add_connector = dm_dp_add_mst_connector,
+	.destroy_connector = dm_dp_destroy_mst_connector,
+	.hotplug = dm_dp_mst_hotplug,
+	.register_connector = dm_dp_mst_register_connector
+};
+
+
+void amdgpu_dm_initialize_mst_connector(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector)
+{
+	aconnector->dm_dp_aux.aux.name = "dmdc";
+	aconnector->dm_dp_aux.aux.dev = dm->adev->dev;
+	aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
+	aconnector->dm_dp_aux.link_index = aconnector->connector_id;
+
+	drm_dp_aux_register(&aconnector->dm_dp_aux.aux);
+	aconnector->mst_mgr.cbs = &dm_mst_cbs;
+	drm_dp_mst_topology_mgr_init(
+		&aconnector->mst_mgr,
+		dm->adev->dev,
+		&aconnector->dm_dp_aux.aux,
+		16,
+		4,
+		aconnector->connector_id);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
new file mode 100644
index 000000000000..6130d62ac65c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AMDGPU_DM_MST_TYPES_H__
+#define __DAL_AMDGPU_DM_MST_TYPES_H__
+
+struct amdgpu_display_manager;
+struct amdgpu_connector;
+
+void amdgpu_dm_initialize_mst_connector(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
new file mode 100644
index 000000000000..b1552700d9e0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/acpi.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/amdgpu_drm.h>
+#include "dm_services.h"
+#include "amdgpu.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_irq.h"
+#include "amdgpu_dm_types.h"
+#include "amdgpu_pm.h"
+
+/*
+#include "logger_interface.h"
+#include "acpimethod_atif.h"
+#include "amdgpu_powerplay.h"
+#include "amdgpu_notifications.h"
+*/
+
+/* if the pointer is not NULL, the allocated memory is zeroed */
+void *dm_alloc(struct dc_context *ctx, uint32_t size)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+
+/* Reallocate memory. The contents will remain unchanged.*/
+void *dm_realloc(struct dc_context *ctx, const void *ptr, uint32_t size)
+{
+	return krealloc(ptr, size, GFP_KERNEL);
+}
+
+void dm_memmove(void *dst, const void *src, uint32_t size)
+{
+	memmove(dst, src, size);
+}
+
+void dm_free(struct dc_context *ctx, void *p)
+{
+	kfree(p);
+}
+
+void dm_memset(void *p, int32_t c, uint32_t count)
+{
+	memset(p, c, count);
+}
+
+int32_t dm_memcmp(const void *p1, const void *p2, uint32_t count)
+{
+	return memcmp(p1, p2, count);
+}
+
+int32_t dm_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count)
+{
+	return strncmp(p1, p2, count);
+}
+
+void dm_sleep_in_milliseconds(struct dc_context *ctx, uint32_t milliseconds)
+{
+	if (milliseconds >= 20)
+		msleep(milliseconds);
+	else
+		usleep_range(milliseconds*1000, milliseconds*1000+1);
+}
+
+void dal_delay_in_nanoseconds(uint32_t nanoseconds)
+{
+	ndelay(nanoseconds);
+}
+
+void dm_delay_in_microseconds(struct dc_context *ctx, uint32_t microseconds)
+{
+	udelay(microseconds);
+}
+
+/******************************************************************************
+ * IRQ Interfaces.
+ *****************************************************************************/
+
+void dal_register_timer_interrupt(
+	struct dc_context *ctx,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *args)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+
+	if (!adev || !int_params) {
+		DRM_ERROR("DM_IRQ: invalid input!\n");
+		return;
+	}
+
+	if (int_params->int_context != INTERRUPT_LOW_IRQ_CONTEXT) {
+		/* only low irq ctx is supported. */
+		DRM_ERROR("DM_IRQ: invalid context: %d!\n",
+				int_params->int_context);
+		return;
+	}
+
+	amdgpu_dm_irq_register_timer(adev, int_params, ih, args);
+}
+
+void dal_isr_acquire_lock(struct dc_context *ctx)
+{
+	/*TODO*/
+}
+
+void dal_isr_release_lock(struct dc_context *ctx)
+{
+	/*TODO*/
+}
+
+/******************************************************************************
+ * End-of-IRQ Interfaces.
+ *****************************************************************************/
+
+bool dm_get_platform_info(struct dc_context *ctx,
+			struct platform_info_params *params)
+{
+	/*TODO*/
+	return false;
+}
+
+/**** power component interfaces ****/
+
+bool dm_pp_pre_dce_clock_change(
+		struct dc_context *ctx,
+		struct dal_to_power_info *input,
+		struct power_to_dal_info *output)
+{
+	/*TODO*/
+	return false;
+}
+
+bool dm_pp_apply_safe_state(
+		const struct dc_context *ctx)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+
+	if (adev->pm.dpm_enabled) {
+		/* TODO: Does this require PreModeChange event to PPLIB? */
+	}
+
+	return true;
+#else
+	return false;
+#endif
+}
+
+bool dm_pp_apply_display_requirements(
+		const struct dc_context *ctx,
+		const struct dc_pp_display_configuration *pp_display_cfg)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+
+	if (adev->pm.dpm_enabled) {
+
+		memset(&adev->pm.pm_display_cfg, 0,
+				sizeof(adev->pm.pm_display_cfg));
+
+		adev->pm.pm_display_cfg.cpu_cc6_disable =
+			pp_display_cfg->cpu_cc6_disable;
+
+		adev->pm.pm_display_cfg.cpu_pstate_disable =
+			pp_display_cfg->cpu_pstate_disable;
+
+		adev->pm.pm_display_cfg.cpu_pstate_separation_time =
+			pp_display_cfg->cpu_pstate_separation_time;
+
+		adev->pm.pm_display_cfg.nb_pstate_switch_disable =
+			pp_display_cfg->nb_pstate_switch_disable;
+
+		adev->pm.pm_display_cfg.num_display =
+				pp_display_cfg->display_count;
+		adev->pm.pm_display_cfg.num_path_including_non_display =
+				pp_display_cfg->display_count;
+
+		adev->pm.pm_display_cfg.min_core_set_clock =
+				pp_display_cfg->min_engine_clock_khz/10;
+		adev->pm.pm_display_cfg.min_core_set_clock_in_sr =
+				pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
+		adev->pm.pm_display_cfg.min_mem_set_clock =
+				pp_display_cfg->min_memory_clock_khz/10;
+
+		adev->pm.pm_display_cfg.multi_monitor_in_sync =
+				pp_display_cfg->all_displays_in_sync;
+		adev->pm.pm_display_cfg.min_vblank_time =
+				pp_display_cfg->avail_mclk_switch_time_us;
+
+		adev->pm.pm_display_cfg.display_clk =
+				pp_display_cfg->disp_clk_khz/10;
+
+		adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency =
+				pp_display_cfg->avail_mclk_switch_time_in_disp_active_us;
+
+		adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index;
+		adev->pm.pm_display_cfg.line_time_in_us =
+				pp_display_cfg->line_time_in_us;
+
+		adev->pm.pm_display_cfg.crossfire_display_index = -1;
+		adev->pm.pm_display_cfg.min_bus_bandwidth = 0;
+
+		/* TODO: complete implementation of
+		 * amd_powerplay_display_configuration_change().
+		 * Follow example of:
+		 * PHM_StoreDALConfigurationData - powerplay\hwmgr\hardwaremanager.c
+		 * PP_IRI_DisplayConfigurationChange - powerplay\eventmgr\iri.c */
+		amd_powerplay_display_configuration_change(
+				adev->powerplay.pp_handle,
+				&adev->pm.pm_display_cfg);
+
+		/* TODO: replace by a separate call to 'apply display cfg'? */
+		amdgpu_pm_compute_clocks(adev);
+	}
+
+	return true;
+#else
+	return false;
+#endif
+}
+
+bool dc_service_get_system_clocks_range(
+		const struct dc_context *ctx,
+		struct dal_system_clock_range *sys_clks)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+#endif
+
+	/* Default values, in case PPLib is not compiled-in. */
+	sys_clks->max_mclk = 80000;
+	sys_clks->min_mclk = 80000;
+
+	sys_clks->max_sclk = 60000;
+	sys_clks->min_sclk = 30000;
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	if (adev->pm.dpm_enabled) {
+		sys_clks->max_mclk = amdgpu_dpm_get_mclk(adev, false);
+		sys_clks->min_mclk = amdgpu_dpm_get_mclk(adev, true);
+
+		sys_clks->max_sclk = amdgpu_dpm_get_sclk(adev, false);
+		sys_clks->min_sclk = amdgpu_dpm_get_sclk(adev, true);
+	}
+#endif
+
+	return true;
+}
+
+static void get_default_clock_levels(
+		enum dc_pp_clock_type clk_type,
+		struct dc_pp_clock_levels *clks)
+{
+	uint32_t disp_clks_in_khz[6] = {
+			300000, 400000, 496560, 626090, 685720, 757900 };
+	uint32_t sclks_in_khz[6] = {
+			300000, 360000, 423530, 514290, 626090, 720000 };
+	uint32_t mclks_in_khz[2] = { 333000, 800000 };
+
+	switch (clk_type) {
+	case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
+		clks->num_levels = 6;
+		dm_memmove(clks->clocks_in_khz, disp_clks_in_khz,
+				sizeof(disp_clks_in_khz));
+		break;
+	case DC_PP_CLOCK_TYPE_ENGINE_CLK:
+		clks->num_levels = 6;
+		dm_memmove(clks->clocks_in_khz, sclks_in_khz,
+				sizeof(sclks_in_khz));
+		break;
+	case DC_PP_CLOCK_TYPE_MEMORY_CLK:
+		clks->num_levels = 2;
+		dm_memmove(clks->clocks_in_khz, mclks_in_khz,
+				sizeof(mclks_in_khz));
+		break;
+	default:
+		clks->num_levels = 0;
+		break;
+	}
+}
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+static enum amd_pp_clock_type dc_to_pp_clock_type(
+		enum dc_pp_clock_type dc_pp_clk_type)
+{
+	enum amd_pp_clock_type amd_pp_clk_type = 0;
+
+	switch (dc_pp_clk_type) {
+	case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
+		amd_pp_clk_type = amd_pp_disp_clock;
+		break;
+	case DC_PP_CLOCK_TYPE_ENGINE_CLK:
+		amd_pp_clk_type = amd_pp_sys_clock;
+		break;
+	case DC_PP_CLOCK_TYPE_MEMORY_CLK:
+		amd_pp_clk_type = amd_pp_mem_clock;
+		break;
+	default:
+		DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
+				dc_pp_clk_type);
+		break;
+	}
+
+	return amd_pp_clk_type;
+}
+
+static void pp_to_dc_clock_levels(
+		const struct amd_pp_clocks *pp_clks,
+		struct dc_pp_clock_levels *dc_clks,
+		enum dc_pp_clock_type dc_clk_type)
+{
+	uint32_t i;
+
+	if (pp_clks->count > DC_PP_MAX_CLOCK_LEVELS) {
+		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
+				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
+				pp_clks->count,
+				DC_PP_MAX_CLOCK_LEVELS);
+
+		dc_clks->num_levels = DC_PP_MAX_CLOCK_LEVELS;
+	} else
+		dc_clks->num_levels = pp_clks->count;
+
+	DRM_INFO("DM_PPLIB: values for %s clock\n",
+			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
+
+	for (i = 0; i < dc_clks->num_levels; i++) {
+		DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
+		/* translate 10kHz to kHz */
+		dc_clks->clocks_in_khz[i] = pp_clks->clock[i] * 10;
+	}
+}
+#endif
+
+bool dm_pp_get_clock_levels_by_type(
+		const struct dc_context *ctx,
+		enum dc_pp_clock_type clk_type,
+		struct dc_pp_clock_levels *dc_clks)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+	void *pp_handle = adev->powerplay.pp_handle;
+	struct amd_pp_clocks pp_clks = { 0 };
+	struct amd_pp_simple_clock_info validation_clks = { 0 };
+	uint32_t i;
+
+	if (amd_powerplay_get_clock_by_type(pp_handle,
+			dc_to_pp_clock_type(clk_type), &pp_clks)) {
+		/* Error in pplib. Provide default values. */
+		get_default_clock_levels(clk_type, dc_clks);
+		return true;
+	}
+
+	pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
+
+	if (amd_powerplay_get_display_mode_validation_clocks(pp_handle,
+			&validation_clks)) {
+		/* Error in pplib. Provide default values. */
+		DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
+		validation_clks.engine_max_clock = 72000;
+		validation_clks.memory_max_clock = 80000;
+		validation_clks.level = 0;
+	}
+
+	DRM_INFO("DM_PPLIB: Validation clocks:\n");
+	DRM_INFO("DM_PPLIB:    engine_max_clock: %d\n",
+			validation_clks.engine_max_clock);
+	DRM_INFO("DM_PPLIB:    memory_max_clock: %d\n",
+			validation_clks.memory_max_clock);
+	DRM_INFO("DM_PPLIB:    level           : %d\n",
+			validation_clks.level);
+
+	/* Translate 10 kHz to kHz. */
+	validation_clks.engine_max_clock *= 10;
+	validation_clks.memory_max_clock *= 10;
+
+	/* Determine the highest non-boosted level from the Validation Clocks */
+	if (clk_type == DC_PP_CLOCK_TYPE_ENGINE_CLK) {
+		for (i = 0; i < dc_clks->num_levels; i++) {
+			if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
+				/* This clock is higher the validation clock.
+				 * Than means the previous one is the highest
+				 * non-boosted one. */
+				DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
+						dc_clks->num_levels, i + 1);
+				dc_clks->num_levels = i;
+				break;
+			}
+		}
+	} else if (clk_type == DC_PP_CLOCK_TYPE_MEMORY_CLK) {
+		for (i = 0; i < dc_clks->num_levels; i++) {
+			if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
+				DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
+						dc_clks->num_levels, i + 1);
+				dc_clks->num_levels = i;
+				break;
+			}
+		}
+	}
+#else
+	get_default_clock_levels(clk_type, dc_clks);
+#endif
+	return true;
+}
+
+/**** end of power component interfaces ****/
+
+
+/* Calls to notification */
+
+void dal_notify_setmode_complete(struct dc_context *ctx,
+	uint32_t h_total,
+	uint32_t v_total,
+	uint32_t h_active,
+	uint32_t v_active,
+	uint32_t pix_clk_in_khz)
+{
+	/*TODO*/
+}
+/* End of calls to notification */
+
+long dm_get_pid(void)
+{
+	return current->pid;
+}
+
+long dm_get_tgid(void)
+{
+	return current->tgid;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
new file mode 100644
index 000000000000..7643f751fcc6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
@@ -0,0 +1,2577 @@
+/*
+ * Copyright 2012-13 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic.h>
+
+#include "amdgpu.h"
+#include "amdgpu_pm.h"
+#include "dm_services_types.h"
+
+// We need to #undef FRAME_SIZE and DEPRECATED because they conflict
+// with ptrace-abi.h's #define's of them.
+#undef FRAME_SIZE
+#undef DEPRECATED
+
+#include "dc.h"
+
+#include "amdgpu_dm_types.h"
+#include "amdgpu_dm_mst_types.h"
+
+struct dm_connector_state {
+	struct drm_connector_state base;
+
+	enum amdgpu_rmx_type scaling;
+	uint8_t underscan_vborder;
+	uint8_t underscan_hborder;
+	bool underscan_enable;
+};
+
+#define to_dm_connector_state(x)\
+	container_of((x), struct dm_connector_state, base)
+
+#define AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET 1
+#define MAX_TARGET_NUM 6
+
+void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+	kfree(encoder);
+}
+
+static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
+	.destroy = amdgpu_dm_encoder_destroy,
+};
+
+static void dm_set_cursor(
+	struct amdgpu_crtc *amdgpu_crtc,
+	uint64_t gpu_addr,
+	uint32_t width,
+	uint32_t height)
+{
+	struct dc_cursor_attributes attributes;
+	amdgpu_crtc->cursor_width = width;
+	amdgpu_crtc->cursor_height = height;
+
+	attributes.address.high_part = upper_32_bits(gpu_addr);
+	attributes.address.low_part  = lower_32_bits(gpu_addr);
+	attributes.width             = width-1;
+	attributes.height            = height-1;
+	attributes.x_hot             = 0;
+	attributes.y_hot             = 0;
+	attributes.color_format      = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA;
+	attributes.rotation_angle    = 0;
+	attributes.attribute_flags.value = 0;
+
+	if (!dc_target_set_cursor_attributes(
+				amdgpu_crtc->target,
+				&attributes)) {
+		DRM_ERROR("DC failed to set cursor attributes\n");
+	}
+}
+
+static int dm_crtc_unpin_cursor_bo_old(
+	struct amdgpu_crtc *amdgpu_crtc)
+{
+	struct amdgpu_bo *robj;
+	int ret = 0;
+
+	if (NULL != amdgpu_crtc && NULL != amdgpu_crtc->cursor_bo) {
+		robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
+
+		ret = amdgpu_bo_reserve(robj, false);
+
+		if (likely(ret == 0)) {
+			ret = amdgpu_bo_unpin(robj);
+
+			if (unlikely(ret != 0)) {
+				DRM_ERROR(
+					"%s: unpin failed (ret=%d), bo %p\n",
+					__func__,
+					ret,
+					amdgpu_crtc->cursor_bo);
+			}
+
+			amdgpu_bo_unreserve(robj);
+		} else {
+			DRM_ERROR(
+				"%s: reserve failed (ret=%d), bo %p\n",
+				__func__,
+				ret,
+				amdgpu_crtc->cursor_bo);
+		}
+
+		drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo);
+		amdgpu_crtc->cursor_bo = NULL;
+	}
+
+	return ret;
+}
+
+static int dm_crtc_pin_cursor_bo_new(
+	struct drm_crtc *crtc,
+	struct drm_file *file_priv,
+	uint32_t handle,
+	struct amdgpu_bo **ret_obj)
+{
+	struct amdgpu_crtc *amdgpu_crtc;
+	struct amdgpu_bo *robj;
+	struct drm_gem_object *obj;
+	int ret = -EINVAL;
+
+	if (NULL != crtc) {
+		struct drm_device *dev = crtc->dev;
+		struct amdgpu_device *adev = dev->dev_private;
+		uint64_t gpu_addr;
+
+		amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+		obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+
+		if (!obj) {
+			DRM_ERROR(
+				"Cannot find cursor object %x for crtc %d\n",
+				handle,
+				amdgpu_crtc->crtc_id);
+			goto release;
+		}
+		robj = gem_to_amdgpu_bo(obj);
+
+		ret  = amdgpu_bo_reserve(robj, false);
+
+		if (unlikely(ret != 0)) {
+			drm_gem_object_unreference_unlocked(obj);
+		DRM_ERROR("dm_crtc_pin_cursor_bo_new ret %x, handle %x\n",
+				 ret, handle);
+			goto release;
+		}
+
+		ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, 0,
+						adev->mc.visible_vram_size,
+						&gpu_addr);
+
+		if (ret == 0) {
+			amdgpu_crtc->cursor_addr = gpu_addr;
+			*ret_obj  = robj;
+		}
+		amdgpu_bo_unreserve(robj);
+		if (ret)
+			drm_gem_object_unreference_unlocked(obj);
+
+	}
+release:
+
+	return ret;
+}
+
+static int dm_crtc_cursor_set(
+	struct drm_crtc *crtc,
+	struct drm_file *file_priv,
+	uint32_t handle,
+	uint32_t width,
+	uint32_t height)
+{
+	struct amdgpu_bo *new_cursor_bo;
+	struct dc_cursor_position position;
+
+	int ret;
+
+	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+	ret		= EINVAL;
+	new_cursor_bo	= NULL;
+
+	DRM_DEBUG_KMS(
+	"%s: crtc_id=%d with handle %d and size %d to %d, bo_object %p\n",
+		__func__,
+		amdgpu_crtc->crtc_id,
+		handle,
+		width,
+		height,
+		amdgpu_crtc->cursor_bo);
+
+	if (!handle) {
+		/* turn off cursor */
+		position.enable = false;
+		position.x = 0;
+		position.y = 0;
+		position.hot_spot_enable = false;
+
+		if (amdgpu_crtc->target) {
+			/*set cursor visible false*/
+			dc_target_set_cursor_position(
+				amdgpu_crtc->target,
+				&position);
+		}
+		/*unpin old cursor buffer and update cache*/
+		ret = dm_crtc_unpin_cursor_bo_old(amdgpu_crtc);
+		goto release;
+
+	}
+
+	if ((width > amdgpu_crtc->max_cursor_width) ||
+		(height > amdgpu_crtc->max_cursor_height)) {
+		DRM_ERROR(
+			"%s: bad cursor width or height %d x %d\n",
+			__func__,
+			width,
+			height);
+		goto release;
+	}
+	/*try to pin new cursor bo*/
+	ret = dm_crtc_pin_cursor_bo_new(crtc, file_priv, handle, &new_cursor_bo);
+	/*if map not successful then return an error*/
+	if (ret)
+		goto release;
+
+	/*program new cursor bo to hardware*/
+	dm_set_cursor(amdgpu_crtc, amdgpu_crtc->cursor_addr, width, height);
+
+	/*un map old, not used anymore cursor bo ,
+	 * return memory and mapping back */
+	dm_crtc_unpin_cursor_bo_old(amdgpu_crtc);
+
+	/*assign new cursor bo to our internal cache*/
+	amdgpu_crtc->cursor_bo = &new_cursor_bo->gem_base;
+
+release:
+	return ret;
+
+}
+
+static int dm_crtc_cursor_move(struct drm_crtc *crtc,
+				     int x, int y)
+{
+	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+	int xorigin = 0, yorigin = 0;
+	struct dc_cursor_position position;
+
+	/* avivo cursor are offset into the total surface */
+	x += crtc->primary->state->src_x >> 16;
+	y += crtc->primary->state->src_y >> 16;
+
+	/*
+	 * TODO: for cursor debugging unguard the following
+	 */
+#if 0
+	DRM_DEBUG_KMS(
+		"%s: x %d y %d c->x %d c->y %d\n",
+		__func__,
+		x,
+		y,
+		crtc->x,
+		crtc->y);
+#endif
+
+	if (x < 0) {
+		xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1);
+		x = 0;
+	}
+	if (y < 0) {
+		yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1);
+		y = 0;
+	}
+
+	position.enable = true;
+	position.x = x;
+	position.y = y;
+
+	position.hot_spot_enable = true;
+	position.x_origin = xorigin;
+	position.y_origin = yorigin;
+
+	if (!dc_target_set_cursor_position(
+				amdgpu_crtc->target,
+				&position)) {
+		DRM_ERROR("DC failed to set cursor position\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void dm_crtc_cursor_reset(struct drm_crtc *crtc)
+{
+	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+	DRM_DEBUG_KMS(
+		"%s: with cursor_bo %p\n",
+		__func__,
+		amdgpu_crtc->cursor_bo);
+
+	if (amdgpu_crtc->cursor_bo && amdgpu_crtc->target) {
+		dm_set_cursor(
+		amdgpu_crtc,
+		amdgpu_crtc->cursor_addr,
+		amdgpu_crtc->cursor_width,
+		amdgpu_crtc->cursor_height);
+	}
+}
+static bool fill_rects_from_plane_state(
+	const struct drm_plane_state *state,
+	struct dc_surface *surface)
+{
+	surface->src_rect.x = state->src_x >> 16;
+	surface->src_rect.y = state->src_y >> 16;
+	/*we ignore for now mantissa and do not to deal with floating pixels :(*/
+	surface->src_rect.width = state->src_w >> 16;
+
+	if (surface->src_rect.width == 0)
+		return false;
+
+	surface->src_rect.height = state->src_h >> 16;
+	if (surface->src_rect.height == 0)
+		return false;
+
+	surface->dst_rect.x = state->crtc_x;
+	surface->dst_rect.y = state->crtc_y;
+
+	if (state->crtc_w == 0)
+		return false;
+
+	surface->dst_rect.width = state->crtc_w;
+
+	if (state->crtc_h == 0)
+		return false;
+
+	surface->dst_rect.height = state->crtc_h;
+
+	surface->clip_rect = surface->dst_rect;
+
+	switch (state->rotation) {
+	case BIT(DRM_ROTATE_0):
+		surface->rotation = ROTATION_ANGLE_0;
+		break;
+	case BIT(DRM_ROTATE_90):
+		surface->rotation = ROTATION_ANGLE_90;
+		break;
+	case BIT(DRM_ROTATE_180):
+		surface->rotation = ROTATION_ANGLE_180;
+		break;
+	case BIT(DRM_ROTATE_270):
+		surface->rotation = ROTATION_ANGLE_270;
+		break;
+	default:
+		surface->rotation = ROTATION_ANGLE_0;
+		break;
+	}
+
+	return true;
+}
+static bool get_fb_info(
+	const struct amdgpu_framebuffer *amdgpu_fb,
+	uint64_t *tiling_flags,
+	uint64_t *fb_location)
+{
+	struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj);
+	int r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r != 0)){
+		DRM_ERROR("Unable to reserve buffer\n");
+		return false;
+	}
+
+
+	if (fb_location)
+		*fb_location = amdgpu_bo_gpu_offset(rbo);
+
+	if (tiling_flags)
+		amdgpu_bo_get_tiling_flags(rbo, tiling_flags);
+
+	amdgpu_bo_unreserve(rbo);
+
+	return true;
+}
+static void fill_plane_attributes_from_fb(
+	struct dc_surface *surface,
+	const struct amdgpu_framebuffer *amdgpu_fb)
+{
+	uint64_t tiling_flags;
+	uint64_t fb_location;
+	const struct drm_framebuffer *fb = &amdgpu_fb->base;
+
+	get_fb_info(
+		amdgpu_fb,
+		&tiling_flags,
+		&fb_location);
+
+	surface->address.type                = PLN_ADDR_TYPE_GRAPHICS;
+	surface->address.grph.addr.low_part  = lower_32_bits(fb_location);
+	surface->address.grph.addr.high_part = upper_32_bits(fb_location);
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_C8:
+		surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS;
+		break;
+	case DRM_FORMAT_RGB565:
+		surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565;
+		break;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+		surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888;
+		break;
+	default:
+		DRM_ERROR("Unsupported screen depth %d\n", fb->bits_per_pixel);
+		return;
+	}
+
+	memset(&surface->tiling_info, 0, sizeof(surface->tiling_info));
+
+	if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1)
+	{
+		unsigned bankw, bankh, mtaspect, tile_split, num_banks;
+
+		bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
+		bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
+		mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
+		tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
+		num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
+
+
+		/* XXX fix me for VI */
+		surface->tiling_info.num_banks = num_banks;
+		surface->tiling_info.array_mode =
+				DC_ARRAY_2D_TILED_THIN1;
+		surface->tiling_info.tile_split = tile_split;
+		surface->tiling_info.bank_width = bankw;
+		surface->tiling_info.bank_height = bankh;
+		surface->tiling_info.tile_aspect = mtaspect;
+		surface->tiling_info.tile_mode =
+				DC_ADDR_SURF_MICRO_TILING_DISPLAY;
+	} else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE)
+			== DC_ARRAY_1D_TILED_THIN1) {
+		surface->tiling_info.array_mode = DC_ARRAY_1D_TILED_THIN1;
+	}
+
+	surface->tiling_info.pipe_config =
+			AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
+
+	surface->plane_size.grph.surface_size.x = 0;
+	surface->plane_size.grph.surface_size.y = 0;
+	surface->plane_size.grph.surface_size.width = fb->width;
+	surface->plane_size.grph.surface_size.height = fb->height;
+	surface->plane_size.grph.surface_pitch =
+		fb->pitches[0] / (fb->bits_per_pixel / 8);
+
+	surface->visible = true;
+	surface->scaling_quality.h_taps_c = 2;
+	surface->scaling_quality.v_taps_c = 2;
+
+	/* TODO: unhardcode */
+	surface->colorimetry.limited_range = false;
+	surface->colorimetry.color_space = SURFACE_COLOR_SPACE_SRGB;
+	surface->scaling_quality.h_taps = 2;
+	surface->scaling_quality.v_taps = 2;
+	surface->stereo_format = PLANE_STEREO_FORMAT_NONE;
+
+}
+
+#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256
+
+static void fill_gamma_from_crtc(
+	const struct drm_crtc *crtc,
+	struct dc_surface *dc_surface)
+{
+	int i;
+	struct gamma_ramp *gamma;
+	uint16_t *red, *green, *blue;
+	int end = (crtc->gamma_size > NUM_OF_RAW_GAMMA_RAMP_RGB_256) ?
+			NUM_OF_RAW_GAMMA_RAMP_RGB_256 : crtc->gamma_size;
+
+	red = crtc->gamma_store;
+	green = red + crtc->gamma_size;
+	blue = green + crtc->gamma_size;
+
+	gamma = &dc_surface->gamma_correction;
+
+	for (i = 0; i < end; i++) {
+		gamma->gamma_ramp_rgb256x3x16.red[i] =
+				(unsigned short) red[i];
+		gamma->gamma_ramp_rgb256x3x16.green[i] =
+				(unsigned short) green[i];
+		gamma->gamma_ramp_rgb256x3x16.blue[i] =
+				(unsigned short) blue[i];
+	}
+
+	gamma->type = GAMMA_RAMP_RBG256X3X16;
+	gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
+}
+
+static void fill_plane_attributes(
+			struct dc_surface *surface,
+			struct drm_plane_state *state)
+{
+	const struct amdgpu_framebuffer *amdgpu_fb =
+		to_amdgpu_framebuffer(state->fb);
+	const struct drm_crtc *crtc = state->crtc;
+
+	fill_rects_from_plane_state(state, surface);
+	fill_plane_attributes_from_fb(
+		surface,
+		amdgpu_fb);
+
+	/* In case of gamma set, update gamma value */
+	if (crtc->mode.private_flags &
+		AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET) {
+		fill_gamma_from_crtc(crtc, surface);
+	}
+}
+
+/*****************************************************************************/
+
+struct amdgpu_connector *aconnector_from_drm_crtc_id(
+		const struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+	struct amdgpu_connector *aconnector;
+
+	list_for_each_entry(connector,
+			&dev->mode_config.connector_list, head)	{
+
+		aconnector = to_amdgpu_connector(connector);
+
+		if (aconnector->base.state->crtc != &acrtc->base)
+			continue;
+
+		/* Found the connector */
+		return aconnector;
+	}
+
+	/* If we get here, not found. */
+	return NULL;
+}
+
+static void calculate_stream_scaling_settings(
+		const struct drm_display_mode *mode,
+		const struct dc_stream *stream,
+		struct dm_connector_state *dm_state)
+{
+	enum amdgpu_rmx_type rmx_type;
+
+	struct rect src = { 0 }; /* viewport in target space*/
+	struct rect dst = { 0 }; /* stream addressable area */
+
+	/* Full screen scaling by default */
+	src.width = mode->hdisplay;
+	src.height = mode->vdisplay;
+	dst.width = stream->timing.h_addressable;
+	dst.height = stream->timing.v_addressable;
+
+	rmx_type = dm_state->scaling;
+	if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) {
+		if (src.width * dst.height <
+				src.height * dst.width) {
+			/* height needs less upscaling/more downscaling */
+			dst.width = src.width *
+					dst.height / src.height;
+		} else {
+			/* width needs less upscaling/more downscaling */
+			dst.height = src.height *
+					dst.width / src.width;
+		}
+	} else if (rmx_type == RMX_CENTER) {
+		dst = src;
+	}
+
+	dst.x = (stream->timing.h_addressable - dst.width) / 2;
+	dst.y = (stream->timing.v_addressable - dst.height) / 2;
+
+	if (dm_state->underscan_enable) {
+		dst.x += dm_state->underscan_hborder / 2;
+		dst.y += dm_state->underscan_vborder / 2;
+		dst.width -= dm_state->underscan_hborder;
+		dst.height -= dm_state->underscan_vborder;
+	}
+
+	dc_update_stream(stream, &src, &dst);
+
+	DRM_DEBUG_KMS("Destination Rectangle x:%d  y:%d  width:%d  height:%d\n",
+			dst.x, dst.y, dst.width, dst.height);
+
+}
+
+static void dm_dc_surface_commit(
+		struct dc *dc,
+		struct drm_crtc *crtc,
+		struct dm_connector_state *dm_state)
+{
+	struct dc_surface *dc_surface;
+	const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+	struct dc_target *dc_target = acrtc->target;
+
+	if (!dc_target) {
+		dm_error(
+			"%s: Failed to obtain target on crtc (%d)!\n",
+			__func__,
+			acrtc->crtc_id);
+		goto fail;
+	}
+
+	dc_surface = dc_create_surface(dc);
+
+	if (!dc_surface) {
+		dm_error(
+			"%s: Failed to create a surface!\n",
+			__func__);
+		goto fail;
+	}
+
+	calculate_stream_scaling_settings(&crtc->state->mode,
+			dc_target->streams[0],
+			dm_state);
+
+	/* Surface programming */
+	fill_plane_attributes(dc_surface, crtc->primary->state);
+	if (crtc->mode.private_flags &
+		AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET) {
+		/* reset trigger of gamma */
+		crtc->mode.private_flags &=
+			~AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET;
+	}
+
+	if (false == dc_commit_surfaces_to_target(
+			dc,
+			&dc_surface,
+			1,
+			dc_target)) {
+		dm_error(
+			"%s: Failed to attach surface!\n",
+			__func__);
+	}
+
+	dc_surface_release(dc_surface);
+fail:
+	return;
+}
+
+static enum dc_color_depth convert_color_depth_from_display_info(
+		const struct drm_connector *connector)
+{
+	uint32_t bpc = connector->display_info.bpc;
+
+	/* Limited color depth to 8bit
+	 * TODO: Still need to handle deep color*/
+	if (bpc > 8)
+		bpc = 8;
+
+	switch (bpc) {
+	case 0:
+		/* Temporary Work around, DRM don't parse color depth for
+		 * EDID revision before 1.4
+		 * TODO: Fix edid parsing
+		 */
+		return COLOR_DEPTH_888;
+	case 6:
+		return COLOR_DEPTH_666;
+	case 8:
+		return COLOR_DEPTH_888;
+	case 10:
+		return COLOR_DEPTH_101010;
+	case 12:
+		return COLOR_DEPTH_121212;
+	case 14:
+		return COLOR_DEPTH_141414;
+	case 16:
+		return COLOR_DEPTH_161616;
+	default:
+		return COLOR_DEPTH_UNDEFINED;
+	}
+}
+
+static enum dc_aspect_ratio get_aspect_ratio(
+		const struct drm_display_mode *mode_in)
+{
+	int32_t width = mode_in->crtc_hdisplay * 9;
+	int32_t height = mode_in->crtc_vdisplay * 16;
+	if ((width - height) < 10 && (width - height) > -10)
+		return ASPECT_RATIO_16_9;
+	else
+		return ASPECT_RATIO_4_3;
+}
+
+/*****************************************************************************/
+
+static void dc_timing_from_drm_display_mode(
+	struct dc_crtc_timing *timing_out,
+	const struct drm_display_mode *mode_in,
+	const struct drm_connector *connector)
+{
+	memset(timing_out, 0, sizeof(struct dc_crtc_timing));
+
+	timing_out->h_border_left = 0;
+	timing_out->h_border_right = 0;
+	timing_out->v_border_top = 0;
+	timing_out->v_border_bottom = 0;
+	/* TODO: un-hardcode */
+	timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
+	timing_out->timing_standard = TIMING_STANDARD_HDMI;
+	timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
+	timing_out->display_color_depth = convert_color_depth_from_display_info(
+			connector);
+	timing_out->scan_type = SCANNING_TYPE_NODATA;
+	timing_out->hdmi_vic = 0;
+	timing_out->vic = drm_match_cea_mode(mode_in);
+
+	timing_out->h_addressable = mode_in->crtc_hdisplay;
+	timing_out->h_total = mode_in->crtc_htotal;
+	timing_out->h_sync_width =
+		mode_in->crtc_hsync_end - mode_in->crtc_hsync_start;
+	timing_out->h_front_porch =
+		mode_in->crtc_hsync_start - mode_in->crtc_hdisplay;
+	timing_out->v_total = mode_in->crtc_vtotal;
+	timing_out->v_addressable = mode_in->crtc_vdisplay;
+	timing_out->v_front_porch =
+		mode_in->crtc_vsync_start - mode_in->crtc_vdisplay;
+	timing_out->v_sync_width =
+		mode_in->crtc_vsync_end - mode_in->crtc_vsync_start;
+	timing_out->pix_clk_khz = mode_in->crtc_clock;
+	timing_out->aspect_ratio = get_aspect_ratio(mode_in);
+}
+
+static void fill_audio_info(
+	struct audio_info *audio_info,
+	const struct drm_connector *drm_connector,
+	const struct dc_sink *dc_sink)
+{
+	int i = 0;
+	int cea_revision = 0;
+	const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps;
+
+	audio_info->manufacture_id = edid_caps->manufacturer_id;
+	audio_info->product_id = edid_caps->product_id;
+
+	cea_revision = drm_connector->display_info.cea_rev;
+
+	while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS &&
+		edid_caps->display_name[i]) {
+		audio_info->display_name[i] = edid_caps->display_name[i];
+		i++;
+	}
+
+	if(cea_revision >= 3) {
+		audio_info->mode_count = edid_caps->audio_mode_count;
+
+		for (i = 0; i < audio_info->mode_count; ++i) {
+			audio_info->modes[i].format_code =
+					(enum audio_format_code)
+					(edid_caps->audio_modes[i].format_code);
+			audio_info->modes[i].channel_count =
+					edid_caps->audio_modes[i].channel_count;
+			audio_info->modes[i].sample_rates.all =
+					edid_caps->audio_modes[i].sample_rate;
+			audio_info->modes[i].sample_size =
+					edid_caps->audio_modes[i].sample_size;
+		}
+	}
+
+	audio_info->flags.all = edid_caps->speaker_flags;
+
+	/* TODO: We only check for the progressive mode, check for interlace mode too */
+	if(drm_connector->latency_present[0]) {
+		audio_info->video_latency = drm_connector->video_latency[0];
+		audio_info->audio_latency = drm_connector->audio_latency[0];
+	}
+
+	/* TODO: For DP, video and audio latency should be calculated from DPCD caps */
+
+}
+
+/*TODO: move these defines elsewhere*/
+#define DAL_MAX_CONTROLLERS 4
+
+static void copy_crtc_timing_for_drm_display_mode(
+		const struct drm_display_mode *src_mode,
+		struct drm_display_mode *dst_mode)
+{
+	dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay;
+	dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay;
+	dst_mode->crtc_clock = src_mode->crtc_clock;
+	dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start;
+	dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end;
+	dst_mode->crtc_hsync_start=  src_mode->crtc_hsync_start;
+	dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end;
+	dst_mode->crtc_htotal = src_mode->crtc_htotal;
+	dst_mode->crtc_hskew = src_mode->crtc_hskew;
+	dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start;;
+	dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end;;
+	dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start;;
+	dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end;;
+	dst_mode->crtc_vtotal = src_mode->crtc_vtotal;;
+}
+
+static void decide_crtc_timing_for_drm_display_mode(
+		struct drm_display_mode *drm_mode,
+		const struct drm_display_mode *native_mode,
+		bool scale_enabled)
+{
+	if (scale_enabled) {
+		copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode);
+	} else if (native_mode->clock == drm_mode->clock &&
+			native_mode->htotal == drm_mode->htotal &&
+			native_mode->vtotal == drm_mode->vtotal) {
+		copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode);
+	} else {
+		/* no scaling nor amdgpu inserted, no need to patch */
+	}
+}
+
+
+static struct dc_target *create_target_for_sink(
+		const struct amdgpu_connector *aconnector,
+		struct drm_display_mode *drm_mode)
+{
+	struct drm_display_mode *preferred_mode = NULL;
+	const struct drm_connector *drm_connector;
+	struct dm_connector_state *dm_state;
+	struct dc_target *target = NULL;
+	struct dc_stream *stream;
+	struct drm_display_mode mode = *drm_mode;
+	bool native_mode_found = false;
+
+	if (NULL == aconnector) {
+		DRM_ERROR("aconnector is NULL!\n");
+		goto drm_connector_null;
+	}
+
+	drm_connector = &aconnector->base;
+	dm_state = to_dm_connector_state(drm_connector->state);
+	stream = dc_create_stream_for_sink(aconnector->dc_sink);
+
+	if (NULL == stream) {
+		DRM_ERROR("Failed to create stream for sink!\n");
+		goto stream_create_fail;
+	}
+
+	list_for_each_entry(preferred_mode, &aconnector->base.modes, head) {
+		/* Search for preferred mode */
+		if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) {
+			native_mode_found = true;
+			break;
+		}
+	}
+	if (!native_mode_found)
+		preferred_mode = list_first_entry_or_null(
+				&aconnector->base.modes,
+				struct drm_display_mode,
+				head);
+	if (NULL == preferred_mode) {
+		DRM_ERROR("No preferred mode found\n");
+		goto stream_create_fail;
+	}
+
+	decide_crtc_timing_for_drm_display_mode(
+			&mode, preferred_mode,
+			dm_state->scaling != RMX_OFF);
+
+	dc_timing_from_drm_display_mode(&stream->timing,
+			&mode, &aconnector->base);
+
+	fill_audio_info(
+		&stream->audio_info,
+		drm_connector,
+		aconnector->dc_sink);
+
+	target = dc_create_target_for_streams(&stream, 1);
+	dc_stream_release(stream);
+
+	if (NULL == target) {
+		DRM_ERROR("Failed to create target with streams!\n");
+		goto target_create_fail;
+	}
+
+drm_connector_null:
+target_create_fail:
+stream_create_fail:
+	return target;
+}
+
+void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct amdgpu_crtc *dm_crtc = to_amdgpu_crtc(crtc);
+
+	drm_crtc_cleanup(crtc);
+	destroy_workqueue(dm_crtc->pflip_queue);
+	kfree(crtc);
+}
+
+static void amdgpu_dm_atomic_crtc_gamma_set(
+		struct drm_crtc *crtc,
+		u16 *red,
+		u16 *green,
+		u16 *blue,
+		uint32_t start,
+		uint32_t size)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_property *prop = dev->mode_config.prop_crtc_id;
+
+	crtc->state->mode.private_flags |= AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET;
+
+	drm_atomic_helper_crtc_set_property(crtc, prop, 0);
+}
+
+static int dm_crtc_funcs_atomic_set_property(
+	struct drm_crtc *crtc,
+	struct drm_crtc_state *crtc_state,
+	struct drm_property *property,
+	uint64_t val)
+{
+	struct drm_plane_state *plane_state;
+
+	crtc_state->planes_changed = true;
+
+	/*
+	 * Bit of magic done here. We need to ensure
+	 * that planes get update after mode is set.
+	 * So, we need to add primary plane to state,
+	 * and this way atomic_update would be called
+	 * for it
+	 */
+	plane_state =
+		drm_atomic_get_plane_state(
+			crtc_state->state,
+			crtc->primary);
+
+	if (!plane_state)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Implemented only the options currently availible for the driver */
+static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
+	.reset = drm_atomic_helper_crtc_reset,
+	.cursor_set = dm_crtc_cursor_set,
+	.cursor_move = dm_crtc_cursor_move,
+	.destroy = amdgpu_dm_crtc_destroy,
+	.gamma_set = amdgpu_dm_atomic_crtc_gamma_set,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.atomic_set_property = dm_crtc_funcs_atomic_set_property
+};
+
+static enum drm_connector_status
+amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
+{
+	bool connected;
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+
+	/* Notes:
+	 * 1. This interface is NOT called in context of HPD irq.
+	 * 2. This interface *is called* in context of user-mode ioctl. Which
+	 * makes it a bad place for *any* MST-related activit. */
+
+	connected = (NULL != aconnector->dc_sink);
+
+	return (connected ? connector_status_connected :
+			connector_status_disconnected);
+}
+
+int amdgpu_dm_connector_atomic_set_property(
+	struct drm_connector *connector,
+	struct drm_connector_state *connector_state,
+	struct drm_property *property,
+	uint64_t val)
+{
+	struct drm_device *dev = connector->dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct dm_connector_state *dm_old_state =
+		to_dm_connector_state(connector->state);
+	struct dm_connector_state *dm_new_state =
+		to_dm_connector_state(connector_state);
+
+	if (property == dev->mode_config.scaling_mode_property) {
+		struct drm_crtc_state *new_crtc_state;
+		struct drm_crtc *crtc;
+		int i;
+		enum amdgpu_rmx_type rmx_type;
+
+		switch (val) {
+		case DRM_MODE_SCALE_CENTER:
+			rmx_type = RMX_CENTER;
+			break;
+		case DRM_MODE_SCALE_ASPECT:
+			rmx_type = RMX_ASPECT;
+			break;
+		case DRM_MODE_SCALE_FULLSCREEN:
+			rmx_type = RMX_FULL;
+			break;
+		case DRM_MODE_SCALE_NONE:
+		default:
+			rmx_type = RMX_OFF;
+			break;
+		}
+
+		if (dm_old_state->scaling == rmx_type)
+			return 0;
+
+		dm_new_state->scaling = rmx_type;
+
+		for_each_crtc_in_state(
+			connector_state->state,
+			crtc,
+			new_crtc_state,
+			i) {
+
+			if (crtc == connector_state->crtc) {
+				struct drm_plane_state *plane_state;
+
+				new_crtc_state->mode_changed = true;
+
+				/*
+				 * Bit of magic done here. We need to ensure
+				 * that planes get update after mode is set.
+				 * So, we need to add primary plane to state,
+				 * and this way atomic_update would be called
+				 * for it
+				 */
+				plane_state =
+					drm_atomic_get_plane_state(
+						connector_state->state,
+						crtc->primary);
+
+				if (!plane_state)
+					return -EINVAL;
+			}
+		}
+
+		return 0;
+	} else if (property == adev->mode_info.underscan_hborder_property) {
+		dm_new_state->underscan_hborder = val;
+		return 0;
+	} else if (property == adev->mode_info.underscan_vborder_property) {
+		dm_new_state->underscan_vborder = val;
+		return 0;
+	} else if (property == adev->mode_info.underscan_property) {
+		struct drm_crtc_state *new_crtc_state;
+		struct drm_crtc *crtc;
+		int i;
+
+		dm_new_state->underscan_enable = val;
+
+		for_each_crtc_in_state(
+			connector_state->state,
+			crtc,
+			new_crtc_state,
+			i) {
+
+			if (crtc == connector_state->crtc) {
+				struct drm_plane_state *plane_state;
+
+				/*
+				 * Bit of magic done here. We need to ensure
+				 * that planes get update after mode is set.
+				 * So, we need to add primary plane to state,
+				 * and this way atomic_update would be called
+				 * for it
+				 */
+				plane_state =
+					drm_atomic_get_plane_state(
+						connector_state->state,
+						crtc->primary);
+
+				if (!plane_state)
+					return -EINVAL;
+			}
+		}
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+void amdgpu_dm_connector_destroy(struct drm_connector *connector)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+	const struct dc_link *link = aconnector->dc_link;
+	struct amdgpu_device *adev = connector->dev->dev_private;
+	struct amdgpu_display_manager *dm = &adev->dm;
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
+	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+	if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) {
+		amdgpu_dm_register_backlight_device(dm);
+
+		if (dm->backlight_dev) {
+			backlight_device_unregister(dm->backlight_dev);
+			dm->backlight_dev = NULL;
+		}
+
+	}
+#endif
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
+{
+	struct dm_connector_state *state =
+		to_dm_connector_state(connector->state);
+
+	kfree(state);
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+
+	if (state) {
+		state->scaling = RMX_OFF;
+		state->underscan_enable = false;
+		state->underscan_hborder = 0;
+		state->underscan_vborder = 0;
+
+		connector->state = &state->base;
+		connector->state->connector = connector;
+	}
+}
+
+struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state(
+	struct drm_connector *connector)
+{
+	struct dm_connector_state *state =
+		to_dm_connector_state(connector->state);
+
+	struct dm_connector_state *new_state =
+		kzalloc(sizeof(*new_state), GFP_KERNEL);
+
+	if (new_state) {
+		*new_state = *state;
+
+		return &new_state->base;
+	}
+
+	return NULL;
+}
+
+void amdgpu_dm_connector_atomic_destroy_state(
+	struct drm_connector *connector,
+	struct drm_connector_state *state)
+{
+	struct dm_connector_state *dm_state =
+		to_dm_connector_state(state);
+
+	__drm_atomic_helper_connector_destroy_state(connector, state);
+
+	kfree(dm_state);
+}
+
+static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = amdgpu_dm_connector_funcs_reset,
+	.detect = amdgpu_dm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = drm_atomic_helper_connector_set_property,
+	.destroy = amdgpu_dm_connector_destroy,
+	.atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
+	.atomic_destroy_state = amdgpu_dm_connector_atomic_destroy_state,
+	.atomic_set_property = amdgpu_dm_connector_atomic_set_property
+};
+
+static struct drm_encoder *best_encoder(struct drm_connector *connector)
+{
+	int enc_id = connector->encoder_ids[0];
+	struct drm_mode_object *obj;
+	struct drm_encoder *encoder;
+
+	DRM_DEBUG_KMS("Finding the best encoder\n");
+
+	/* pick the encoder ids */
+	if (enc_id) {
+		obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
+		if (!obj) {
+			DRM_ERROR("Couldn't find a matching encoder for our connector\n");
+			return NULL;
+		}
+		encoder = obj_to_encoder(obj);
+		return encoder;
+	}
+	DRM_ERROR("No encoder id\n");
+	return NULL;
+}
+
+static int get_modes(struct drm_connector *connector)
+{
+	return amdgpu_dm_connector_get_modes(connector);
+}
+
+int amdgpu_dm_connector_mode_valid(
+		struct drm_connector *connector,
+		struct drm_display_mode *mode)
+{
+	int result = MODE_ERROR;
+	const struct dc_sink *dc_sink =
+			to_amdgpu_connector(connector)->dc_sink;
+	struct amdgpu_device *adev = connector->dev->dev_private;
+	struct dc_validation_set val_set = { 0 };
+	/* TODO: Unhardcode stream count */
+	struct dc_stream *streams[1];
+	struct dc_target *target;
+
+	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+			(mode->flags & DRM_MODE_FLAG_DBLSCAN))
+		return result;
+
+	if (NULL == dc_sink) {
+		DRM_ERROR("dc_sink is NULL!\n");
+		goto stream_create_fail;
+	}
+
+	streams[0] = dc_create_stream_for_sink(dc_sink);
+
+	if (NULL == streams[0]) {
+		DRM_ERROR("Failed to create stream for sink!\n");
+		goto stream_create_fail;
+	}
+
+	drm_mode_set_crtcinfo(mode, 0);
+	dc_timing_from_drm_display_mode(&streams[0]->timing, mode, connector);
+
+	target = dc_create_target_for_streams(streams, 1);
+	val_set.target = target;
+
+	if (NULL == val_set.target) {
+		DRM_ERROR("Failed to create target with stream!\n");
+		goto target_create_fail;
+	}
+
+	val_set.surface_count = 0;
+	streams[0]->src.width = mode->hdisplay;
+	streams[0]->src.height = mode->vdisplay;
+	streams[0]->dst = streams[0]->src;
+
+	if (dc_validate_resources(adev->dm.dc, &val_set, 1))
+		result = MODE_OK;
+
+	dc_target_release(target);
+target_create_fail:
+	dc_stream_release(streams[0]);
+stream_create_fail:
+	/* TODO: error handling*/
+	return result;
+}
+
+
+static const struct drm_connector_helper_funcs
+amdgpu_dm_connector_helper_funcs = {
+	/*
+	* If hotplug a second bigger display in FB Con mode, bigger resolution
+	* modes will be filtered by drm_mode_validate_size(), and those modes
+	* is missing after user start lightdm. So we need to renew modes list.
+	* in get_modes call back, not just return the modes count
+	*/
+	.get_modes = get_modes,
+	.mode_valid = amdgpu_dm_connector_mode_valid,
+	.best_encoder = best_encoder
+};
+
+static void dm_crtc_helper_disable(struct drm_crtc *crtc)
+{
+}
+
+static int dm_crtc_helper_atomic_check(
+	struct drm_crtc *crtc,
+	struct drm_crtc_state *state)
+{
+	return 0;
+}
+
+static bool dm_crtc_helper_mode_fixup(
+	struct drm_crtc *crtc,
+	const struct drm_display_mode *mode,
+	struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = {
+	.disable = dm_crtc_helper_disable,
+	.atomic_check = dm_crtc_helper_atomic_check,
+	.mode_fixup = dm_crtc_helper_mode_fixup
+};
+
+static void dm_encoder_helper_disable(struct drm_encoder *encoder)
+{
+
+}
+
+static int dm_encoder_helper_atomic_check(
+	struct drm_encoder *encoder,
+	struct drm_crtc_state *crtc_state,
+	struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = {
+	.disable = dm_encoder_helper_disable,
+	.atomic_check = dm_encoder_helper_atomic_check
+};
+
+static const struct drm_plane_funcs dm_plane_funcs = {
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state
+};
+
+static void clear_unrelated_fields(struct drm_plane_state *state)
+{
+	state->crtc = NULL;
+	state->fb = NULL;
+	state->state = NULL;
+	state->fence = NULL;
+}
+
+static bool page_flip_needed(
+	const struct drm_plane_state *new_state,
+	const struct drm_plane_state *old_state)
+{
+	struct drm_plane_state old_state_tmp;
+	struct drm_plane_state new_state_tmp;
+
+	struct amdgpu_framebuffer *amdgpu_fb_old;
+	struct amdgpu_framebuffer *amdgpu_fb_new;
+
+	uint64_t old_tiling_flags;
+	uint64_t new_tiling_flags;
+
+	if (!old_state)
+		return false;
+
+	if (!old_state->fb)
+		return false;
+
+	if (!new_state)
+		return false;
+
+	if (!new_state->fb)
+		return false;
+
+	old_state_tmp = *old_state;
+	new_state_tmp = *new_state;
+
+	if (!new_state->crtc->state->event)
+		return false;
+
+	amdgpu_fb_old = to_amdgpu_framebuffer(old_state->fb);
+	amdgpu_fb_new = to_amdgpu_framebuffer(new_state->fb);
+
+	if (!get_fb_info(amdgpu_fb_old, &old_tiling_flags, NULL))
+		return false;
+
+	if (!get_fb_info(amdgpu_fb_new, &new_tiling_flags, NULL))
+		return false;
+
+	if (old_tiling_flags != new_tiling_flags)
+		return false;
+
+	clear_unrelated_fields(&old_state_tmp);
+	clear_unrelated_fields(&new_state_tmp);
+
+	return memcmp(&old_state_tmp, &new_state_tmp, sizeof(old_state_tmp)) == 0;
+}
+
+static int dm_plane_helper_prepare_fb(
+	struct drm_plane *plane,
+	const struct drm_plane_state *new_state)
+{
+	struct drm_framebuffer *fb = new_state->fb;
+	struct amdgpu_framebuffer *afb;
+	struct drm_gem_object *obj;
+	struct amdgpu_bo *rbo;
+	int r;
+
+	if (!fb) {
+		DRM_DEBUG_KMS("No FB bound\n");
+		return 0;
+	}
+
+	afb = to_amdgpu_framebuffer(fb);
+
+	obj = afb->obj;
+	rbo = gem_to_amdgpu_bo(obj);
+	r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r != 0))
+		return r;
+
+	r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL);
+
+	amdgpu_bo_unreserve(rbo);
+
+	if (unlikely(r != 0)) {
+		DRM_ERROR("Failed to pin framebuffer\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static void dm_plane_helper_cleanup_fb(
+	struct drm_plane *plane,
+	const struct drm_plane_state *old_state)
+{
+	struct drm_framebuffer *fb = old_state->fb;
+	struct amdgpu_bo *rbo;
+	struct amdgpu_framebuffer *afb;
+	int r;
+
+	if (!fb)
+		return;
+
+	afb = to_amdgpu_framebuffer(fb);
+	rbo = gem_to_amdgpu_bo(afb->obj);
+	r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r)) {
+		DRM_ERROR("failed to reserve rbo before unpin\n");
+		return;
+	} else {
+		amdgpu_bo_unpin(rbo);
+		amdgpu_bo_unreserve(rbo);
+	}
+}
+
+int dm_create_validation_set_for_target(struct drm_connector *connector,
+		struct drm_display_mode *mode, struct dc_validation_set *val_set)
+{
+	int result = MODE_ERROR;
+	const struct dc_sink *dc_sink =
+			to_amdgpu_connector(connector)->dc_sink;
+	/* TODO: Unhardcode stream count */
+	struct dc_stream *streams[1];
+	struct dc_target *target;
+
+	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+			(mode->flags & DRM_MODE_FLAG_DBLSCAN))
+		return result;
+
+	if (NULL == dc_sink) {
+		DRM_ERROR("dc_sink is NULL!\n");
+		return result;
+	}
+
+	streams[0] = dc_create_stream_for_sink(dc_sink);
+
+	if (NULL == streams[0]) {
+		DRM_ERROR("Failed to create stream for sink!\n");
+		return result;
+	}
+
+	drm_mode_set_crtcinfo(mode, 0);
+	dc_timing_from_drm_display_mode(&streams[0]->timing, mode, connector);
+
+	target = dc_create_target_for_streams(streams, 1);
+	val_set->target = target;
+
+	if (NULL == val_set->target) {
+		DRM_ERROR("Failed to create target with stream!\n");
+		goto fail;
+	}
+
+	streams[0]->src.width = mode->hdisplay;
+	streams[0]->src.height = mode->vdisplay;
+	streams[0]->dst = streams[0]->src;
+
+	return MODE_OK;
+
+fail:
+	dc_stream_release(streams[0]);
+	return result;
+
+}
+
+static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
+	.prepare_fb = dm_plane_helper_prepare_fb,
+	.cleanup_fb = dm_plane_helper_cleanup_fb,
+};
+
+/*
+ * TODO: these are currently initialized to rgb formats only.
+ * For future use cases we should either initialize them dynamically based on
+ * plane capabilities, or initialize this array to all formats, so internal drm
+ * check will succeed, and let DC to implement proper check
+ */
+static uint32_t rgb_formats[] = {
+	DRM_FORMAT_XRGB4444,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_RGBA4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_RGBA8888,
+};
+
+int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
+			struct amdgpu_crtc *acrtc,
+			uint32_t crtc_index)
+{
+	int res = -ENOMEM;
+
+	struct drm_plane *primary_plane =
+		kzalloc(sizeof(*primary_plane), GFP_KERNEL);
+
+	if (!primary_plane)
+		goto fail_plane;
+
+	primary_plane->format_default = true;
+
+	res = drm_universal_plane_init(
+		dm->adev->ddev,
+		primary_plane,
+		0,
+		&dm_plane_funcs,
+		rgb_formats,
+		ARRAY_SIZE(rgb_formats),
+		DRM_PLANE_TYPE_PRIMARY,
+		NULL);
+
+	primary_plane->crtc = &acrtc->base;
+
+	drm_plane_helper_add(primary_plane, &dm_plane_helper_funcs);
+
+	res = drm_crtc_init_with_planes(
+			dm->ddev,
+			&acrtc->base,
+			primary_plane,
+			NULL,
+			&amdgpu_dm_crtc_funcs,
+			NULL);
+
+	if (res)
+		goto fail;
+
+	drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs);
+
+	acrtc->max_cursor_width = 128;
+	acrtc->max_cursor_height = 128;
+
+	acrtc->crtc_id = crtc_index;
+	acrtc->base.enabled = false;
+
+	dm->adev->mode_info.crtcs[crtc_index] = acrtc;
+	drm_mode_crtc_set_gamma_size(&acrtc->base, 256);
+
+	acrtc->pflip_queue =
+		create_singlethread_workqueue("amdgpu-pageflip-queue");
+
+	return 0;
+fail:
+	kfree(primary_plane);
+fail_plane:
+	acrtc->crtc_id = -1;
+	return res;
+}
+
+static int to_drm_connector_type(enum signal_type st)
+{
+	switch (st) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		return DRM_MODE_CONNECTOR_HDMIA;
+	case SIGNAL_TYPE_EDP:
+		return DRM_MODE_CONNECTOR_eDP;
+	case SIGNAL_TYPE_RGB:
+		return DRM_MODE_CONNECTOR_VGA;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		return DRM_MODE_CONNECTOR_DisplayPort;
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+		return DRM_MODE_CONNECTOR_DVID;
+	case SIGNAL_TYPE_VIRTUAL:
+		return DRM_MODE_CONNECTOR_VIRTUAL;
+
+	default:
+		return DRM_MODE_CONNECTOR_Unknown;
+	}
+}
+
+static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
+{
+	const struct drm_connector_helper_funcs *helper =
+		connector->helper_private;
+	struct drm_encoder *encoder;
+	struct amdgpu_encoder *amdgpu_encoder;
+
+	encoder = helper->best_encoder(connector);
+
+	if (encoder == NULL)
+		return;
+
+	amdgpu_encoder = to_amdgpu_encoder(encoder);
+
+	amdgpu_encoder->native_mode.clock = 0;
+
+	if (!list_empty(&connector->probed_modes)) {
+		struct drm_display_mode *preferred_mode = NULL;
+		list_for_each_entry(preferred_mode,
+				&connector->probed_modes,
+				head) {
+		if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) {
+			amdgpu_encoder->native_mode = *preferred_mode;
+		}
+			break;
+		}
+
+	}
+}
+
+static struct drm_display_mode *amdgpu_dm_create_common_mode(
+		struct drm_encoder *encoder, char *name,
+		int hdisplay, int vdisplay)
+{
+	struct drm_device *dev = encoder->dev;
+	struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
+	struct drm_display_mode *mode = NULL;
+	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
+
+	mode = drm_mode_duplicate(dev, native_mode);
+
+	if(mode == NULL)
+		return NULL;
+
+	mode->hdisplay = hdisplay;
+	mode->vdisplay = vdisplay;
+	mode->type &= ~DRM_MODE_TYPE_PREFERRED;
+	strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN);
+
+	return mode;
+
+}
+
+static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
+					struct drm_connector *connector)
+{
+	struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
+	struct drm_display_mode *mode = NULL;
+	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
+	struct amdgpu_connector *amdgpu_connector =
+				to_amdgpu_connector(connector);
+	int i;
+	int n;
+	struct mode_size {
+		char name[DRM_DISPLAY_MODE_LEN];
+		int w;
+		int h;
+	}common_modes[] = {
+		{  "640x480",  640,  480},
+		{  "800x600",  800,  600},
+		{ "1024x768", 1024,  768},
+		{ "1280x720", 1280,  720},
+		{ "1280x800", 1280,  800},
+		{"1280x1024", 1280, 1024},
+		{ "1440x900", 1440,  900},
+		{"1680x1050", 1680, 1050},
+		{"1600x1200", 1600, 1200},
+		{"1920x1080", 1920, 1080},
+		{"1920x1200", 1920, 1200}
+	};
+
+	n = sizeof(common_modes) / sizeof(common_modes[0]);
+
+	for (i = 0; i < n; i++) {
+		struct drm_display_mode *curmode = NULL;
+		bool mode_existed = false;
+
+		if (common_modes[i].w > native_mode->hdisplay ||
+			common_modes[i].h > native_mode->vdisplay ||
+			(common_modes[i].w == native_mode->hdisplay &&
+			common_modes[i].h == native_mode->vdisplay))
+				continue;
+
+		list_for_each_entry(curmode, &connector->probed_modes, head) {
+			if (common_modes[i].w == curmode->hdisplay &&
+				common_modes[i].h == curmode->vdisplay) {
+				mode_existed = true;
+				break;
+			}
+		}
+
+		if (mode_existed)
+			continue;
+
+		mode = amdgpu_dm_create_common_mode(encoder,
+				common_modes[i].name, common_modes[i].w,
+				common_modes[i].h);
+		drm_mode_probed_add(connector, mode);
+		amdgpu_connector->num_modes++;
+	}
+}
+
+static void amdgpu_dm_connector_ddc_get_modes(
+	struct drm_connector *connector,
+	struct edid *edid)
+{
+	struct amdgpu_connector *amdgpu_connector =
+			to_amdgpu_connector(connector);
+
+	if (edid) {
+		/* empty probed_modes */
+		INIT_LIST_HEAD(&connector->probed_modes);
+		amdgpu_connector->num_modes =
+				drm_add_edid_modes(connector, edid);
+
+		drm_edid_to_eld(connector, edid);
+
+		amdgpu_dm_get_native_mode(connector);
+	} else
+		amdgpu_connector->num_modes = 0;
+}
+
+int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
+{
+	const struct drm_connector_helper_funcs *helper =
+			connector->helper_private;
+	struct amdgpu_connector *amdgpu_connector =
+			to_amdgpu_connector(connector);
+	struct drm_encoder *encoder;
+	struct edid *edid = amdgpu_connector->edid;
+
+	encoder = helper->best_encoder(connector);
+
+	amdgpu_dm_connector_ddc_get_modes(connector, edid);
+	amdgpu_dm_connector_add_common_modes(encoder, connector);
+	return amdgpu_connector->num_modes;
+}
+
+void amdgpu_dm_connector_init_helper(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector,
+	int connector_type,
+	const struct dc_link *link,
+	int link_index)
+{
+	struct amdgpu_device *adev = dm->ddev->dev_private;
+
+	aconnector->connector_id = link_index;
+	aconnector->dc_link = link;
+	aconnector->base.interlace_allowed = true;
+	aconnector->base.doublescan_allowed = true;
+	aconnector->base.dpms = DRM_MODE_DPMS_OFF;
+	aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */
+
+	/*configure suport HPD hot plug connector_>polled default value is 0
+	 * which means HPD hot plug not supported*/
+	switch (connector_type) {
+	case DRM_MODE_CONNECTOR_HDMIA:
+		aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	case DRM_MODE_CONNECTOR_DVID:
+		aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	default:
+		break;
+	}
+
+	drm_object_attach_property(&aconnector->base.base,
+				dm->ddev->mode_config.scaling_mode_property,
+				DRM_MODE_SCALE_NONE);
+
+	drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.underscan_property,
+				UNDERSCAN_OFF);
+	drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.underscan_hborder_property,
+				0);
+	drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.underscan_vborder_property,
+				0);
+}
+
+/* Note: this function assumes that dc_link_detect() was called for the
+ * dc_link which will be represented by this aconnector. */
+int amdgpu_dm_connector_init(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector,
+	uint32_t link_index,
+	struct amdgpu_encoder *aencoder)
+{
+	int res, connector_type;
+	struct dc *dc = dm->dc;
+	const struct dc_link *link = dc_get_link_at_index(dc, link_index);
+
+	DRM_DEBUG_KMS("%s()\n", __func__);
+
+	connector_type = to_drm_connector_type(link->connector_signal);
+
+	res = drm_connector_init(
+			dm->ddev,
+			&aconnector->base,
+			&amdgpu_dm_connector_funcs,
+			connector_type);
+
+	if (res) {
+		DRM_ERROR("connector_init failed\n");
+		aconnector->connector_id = -1;
+		return res;
+	}
+
+	drm_connector_helper_add(
+			&aconnector->base,
+			&amdgpu_dm_connector_helper_funcs);
+
+	amdgpu_dm_connector_init_helper(
+		dm,
+		aconnector,
+		connector_type,
+		link,
+		link_index);
+
+	drm_mode_connector_attach_encoder(
+		&aconnector->base, &aencoder->base);
+
+	drm_connector_register(&aconnector->base);
+
+	if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
+		|| connector_type == DRM_MODE_CONNECTOR_eDP)
+		amdgpu_dm_initialize_mst_connector(dm, aconnector);
+
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
+	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+	/* NOTE: this currently will create backlight device even if a panel
+	 * is not connected to the eDP/LVDS connector.
+	 *
+	 * This is less than ideal but we don't have sink information at this
+	 * stage since detection happens after. We can't do detection earlier
+	 * since MST detection needs connectors to be created first.
+	 */
+	if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) {
+		/* Event if registration failed, we should continue with
+		 * DM initialization because not having a backlight control
+		 * is better then a black screen. */
+		amdgpu_dm_register_backlight_device(dm);
+
+		if (dm->backlight_dev)
+			dm->backlight_link = link;
+	}
+#endif
+
+	return 0;
+}
+
+int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev)
+{
+	switch (adev->mode_info.num_crtc) {
+	case 1:
+		return 0x1;
+	case 2:
+		return 0x3;
+	case 3:
+		return 0x7;
+	case 4:
+		return 0xf;
+	case 5:
+		return 0x1f;
+	case 6:
+	default:
+		return 0x3f;
+	}
+}
+
+int amdgpu_dm_encoder_init(
+	struct drm_device *dev,
+	struct amdgpu_encoder *aencoder,
+	uint32_t link_index)
+{
+	struct amdgpu_device *adev = dev->dev_private;
+
+	int res = drm_encoder_init(dev,
+				   &aencoder->base,
+				   &amdgpu_dm_encoder_funcs,
+				   DRM_MODE_ENCODER_TMDS,
+				   NULL);
+
+	aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
+
+	if (!res)
+		aencoder->encoder_id = link_index;
+	else
+		aencoder->encoder_id = -1;
+
+	drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs);
+
+	return res;
+}
+
+enum dm_commit_action {
+	DM_COMMIT_ACTION_NOTHING,
+	DM_COMMIT_ACTION_RESET,
+	DM_COMMIT_ACTION_DPMS_ON,
+	DM_COMMIT_ACTION_DPMS_OFF,
+	DM_COMMIT_ACTION_SET
+};
+
+static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state)
+{
+	/* mode changed means either actually mode changed or enabled changed */
+	/* active changed means dpms changed */
+	if (state->mode_changed) {
+		/* if it is got disabled - call reset mode */
+		if (!state->enable)
+			return DM_COMMIT_ACTION_RESET;
+
+		if (state->active)
+			return DM_COMMIT_ACTION_SET;
+		else
+			return DM_COMMIT_ACTION_RESET;
+	} else {
+		/* ! mode_changed */
+
+		/* if it is remain disable - skip it */
+		if (!state->enable)
+			return DM_COMMIT_ACTION_NOTHING;
+
+		if (state->active_changed) {
+			if (state->active) {
+				return DM_COMMIT_ACTION_DPMS_ON;
+			} else {
+				return DM_COMMIT_ACTION_DPMS_OFF;
+			}
+		} else {
+			/* ! active_changed */
+			return DM_COMMIT_ACTION_NOTHING;
+		}
+	}
+}
+
+static void manage_dm_interrupts(
+	struct amdgpu_device *adev,
+	struct amdgpu_crtc *acrtc,
+	bool enable)
+{
+	/*
+	 * this is not correct translation but will work as soon as VBLANK
+	 * constant is the same as PFLIP
+	 */
+	int irq_type =
+		amdgpu_crtc_idx_to_irq_type(
+			adev,
+			acrtc->crtc_id);
+
+	if (enable) {
+		drm_crtc_vblank_on(&acrtc->base);
+		amdgpu_irq_get(
+			adev,
+			&adev->pageflip_irq,
+			irq_type);
+	} else {
+		unsigned long flags;
+		amdgpu_irq_put(
+			adev,
+			&adev->pageflip_irq,
+			irq_type);
+		drm_crtc_vblank_off(&acrtc->base);
+
+		/*
+		 * should be called here, to guarantee no works left in queue.
+		 * As this function sleeps it was bug to call it inside the
+		 * amdgpu_dm_flip_cleanup function under locked event_lock
+		 */
+		flush_workqueue(acrtc->pflip_queue);
+
+		/*
+		 * TODO: once Vitaly's change to adjust locking in
+		 * page_flip_work_func is submitted to base driver move
+		 * lock and check to amdgpu_dm_flip_cleanup function
+		 */
+
+		spin_lock_irqsave(&adev->ddev->event_lock, flags);
+		if (acrtc->pflip_status != AMDGPU_FLIP_NONE) {
+			/*
+			 * this is the case when on reset, last pending pflip
+			 * interrupt did not not occur. Clean-up
+			 */
+			amdgpu_dm_flip_cleanup(adev, acrtc);
+		}
+		spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+	}
+}
+
+/*
+ * Handle headless hotplug workaround
+ *
+ * In case of headless hotplug, if plugging the same monitor to the same
+ * DDI, DRM consider it as mode unchanged. We should check whether the
+ * sink pointer changed, and set mode_changed properly to
+ * make sure commit is doing everything.
+ */
+static void handle_headless_hotplug(
+		const struct amdgpu_crtc *acrtc,
+		struct drm_crtc_state *state,
+		struct amdgpu_connector **aconnector)
+{
+	struct amdgpu_connector *old_connector =
+			aconnector_from_drm_crtc_id(&acrtc->base);
+
+	/*
+	 * TODO Revisit this. This code is kinda hacky and might break things.
+	 */
+
+	if (!old_connector)
+		return;
+
+	if (!*aconnector)
+		*aconnector = old_connector;
+
+	if (acrtc->target && (*aconnector)->dc_sink) {
+		if ((*aconnector)->dc_sink !=
+				acrtc->target->streams[0]->sink) {
+			state->mode_changed = true;
+		}
+	}
+
+	if (!acrtc->target) {
+		/* In case of headless with DPMS on, when system waked up,
+		 * if no monitor connected, target is null and will not create
+		 * new target, on that condition, we should check
+		 * if any connector is connected, if connected,
+		 * it means a hot plug happened after wake up,
+		 * mode_changed should be set to true to make sure
+		 * commit targets will do everything.
+		 */
+		state->mode_changed =
+			(*aconnector)->base.status ==
+					connector_status_connected;
+	} else {
+		/* In case of headless hotplug, if plug same monitor to same
+		 * DDI, DRM consider it as mode unchanged, we should check
+		 * sink pointer changed, and set mode changed properly to
+		 * make sure commit doing everything.
+		 */
+		/* check if sink has changed from last commit */
+		if ((*aconnector)->dc_sink && (*aconnector)->dc_sink !=
+					acrtc->target->streams[0]->sink)
+			state->mode_changed = true;
+	}
+}
+
+int amdgpu_dm_atomic_commit(
+	struct drm_device *dev,
+	struct drm_atomic_state *state,
+	bool async)
+{
+	struct amdgpu_device *adev = dev->dev_private;
+	struct amdgpu_display_manager *dm = &adev->dm;
+	struct drm_plane *plane;
+	struct drm_plane_state *old_plane_state;
+	uint32_t i, j;
+	int32_t ret;
+	uint32_t commit_targets_count = 0;
+	uint32_t new_crtcs_count = 0;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *old_crtc_state;
+
+	struct dc_target *commit_targets[DAL_MAX_CONTROLLERS];
+	struct amdgpu_crtc *new_crtcs[DAL_MAX_CONTROLLERS];
+
+	/* In this step all new fb would be pinned */
+
+	ret = drm_atomic_helper_prepare_planes(dev, state);
+	if (ret)
+		return ret;
+
+	/*
+	 * This is the point of no return - everything below never fails except
+	 * when the hw goes bonghits. Which means we can commit the new state on
+	 * the software side now.
+	 */
+
+	drm_atomic_helper_swap_state(dev, state);
+
+	/*
+	 * From this point state become old state really. New state is
+	 * initialized to appropriate objects and could be accessed from there
+	 */
+
+	/*
+	 * there is no fences usage yet in state. We can skip the following line
+	 * wait_for_fences(dev, state);
+	 */
+
+	drm_atomic_helper_update_legacy_modeset_state(dev, state);
+
+	/* update changed items */
+	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+		struct amdgpu_crtc *acrtc;
+		struct amdgpu_connector *aconnector = NULL;
+		enum dm_commit_action action;
+		struct drm_crtc_state *new_state = crtc->state;
+		struct drm_connector *connector;
+		struct drm_connector_state *old_con_state;
+
+		acrtc = to_amdgpu_crtc(crtc);
+
+		for_each_connector_in_state(
+			state,
+			connector,
+			old_con_state,
+			j) {
+			if (connector->state->crtc == crtc) {
+				aconnector = to_amdgpu_connector(connector);
+				break;
+			}
+		}
+
+		/* handles headless hotplug case, updating new_state and
+		 * aconnector as needed
+		 */
+		handle_headless_hotplug(acrtc, new_state, &aconnector);
+
+		action = get_dm_commit_action(new_state);
+
+		switch (action) {
+		case DM_COMMIT_ACTION_DPMS_ON:
+		case DM_COMMIT_ACTION_SET: {
+			struct dc_target *new_target =
+				create_target_for_sink(
+					aconnector,
+					&crtc->state->mode);
+
+			DRM_DEBUG_KMS("Atomic commit: SET.\n");
+
+			if (!new_target) {
+				/*
+				 * this could happen because of issues with
+				 * userspace notifications delivery.
+				 * In this case userspace tries to set mode on
+				 * display which is disconnect in fact.
+				 * dc_sink in NULL in this case on aconnector.
+				 * We expect reset mode will come soon.
+				 *
+				 * This can also happen when unplug is done
+				 * during resume sequence ended
+				 */
+				new_state->planes_changed = false;
+				DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n",
+						__func__, acrtc->base.base.id);
+				break;
+			}
+
+			if (acrtc->target) {
+				/*
+				 * we evade vblanks and pflips on crtc that
+				 * should be changed
+				 */
+				manage_dm_interrupts(adev, acrtc, false);
+				/* this is the update mode case */
+				dc_target_release(acrtc->target);
+				acrtc->target = NULL;
+			}
+
+			/*
+			 * this loop saves set mode crtcs
+			 * we needed to enable vblanks once all
+			 * resources acquired in dc after dc_commit_targets
+			 */
+			new_crtcs[new_crtcs_count] = acrtc;
+			new_crtcs_count++;
+
+			acrtc->target = new_target;
+			acrtc->enabled = true;
+
+			break;
+		}
+
+		case DM_COMMIT_ACTION_NOTHING:
+			break;
+
+		case DM_COMMIT_ACTION_DPMS_OFF:
+		case DM_COMMIT_ACTION_RESET:
+			DRM_DEBUG_KMS("Atomic commit: RESET.\n");
+			/* i.e. reset mode */
+			if (acrtc->target) {
+				manage_dm_interrupts(adev, acrtc, false);
+
+				dc_target_release(acrtc->target);
+				acrtc->target = NULL;
+				acrtc->enabled = false;
+			}
+			break;
+		} /* switch() */
+	} /* for_each_crtc_in_state() */
+
+	commit_targets_count = 0;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+		if (acrtc->target) {
+			commit_targets[commit_targets_count] = acrtc->target;
+			++commit_targets_count;
+		}
+	}
+
+	/* DC is optimized not to do anything if 'targets' didn't change. */
+	dc_commit_targets(dm->dc, commit_targets, commit_targets_count);
+
+	/* update planes when needed */
+	for_each_plane_in_state(state, plane, old_plane_state, i) {
+		struct drm_plane_state *plane_state = plane->state;
+		struct drm_crtc *crtc = plane_state->crtc;
+		struct drm_framebuffer *fb = plane_state->fb;
+		struct drm_connector *connector;
+		struct dm_connector_state *dm_state = NULL;
+		enum dm_commit_action action;
+
+		if (!fb || !crtc || !crtc->state->planes_changed ||
+			!crtc->state->active)
+			continue;
+
+		action = get_dm_commit_action(crtc->state);
+
+		/* Surfaces are created under two scenarios:
+		 * 1. This commit is not a page flip.
+		 * 2. This commit is a page flip, and targets are created.
+		 */
+		if (!page_flip_needed(plane_state, old_plane_state) ||
+				action == DM_COMMIT_ACTION_DPMS_ON ||
+				action == DM_COMMIT_ACTION_SET) {
+			list_for_each_entry(connector,
+				&dev->mode_config.connector_list, head)	{
+				if (connector->state->crtc == crtc) {
+					dm_state = to_dm_connector_state(
+						connector->state);
+					break;
+				}
+			}
+
+			/*
+			 * This situation happens in the following case:
+			 * we are about to get set mode for connector who's only
+			 * possible crtc (in encoder crtc mask) is used by
+			 * another connector, that is why it will try to
+			 * re-assing crtcs in order to make configuration
+			 * supported. For our implementation we need to make all
+			 * encoders support all crtcs, then this issue will
+			 * never arise again. But to guard code from this issue
+			 * check is left.
+			 *
+			 * Also it should be needed when used with actual
+			 * drm_atomic_commit ioctl in future
+			 */
+			if (!dm_state)
+				continue;
+
+			dm_dc_surface_commit(
+				dm->dc,
+				crtc,
+				dm_state);
+		}
+	}
+
+	for (i = 0; i < new_crtcs_count; i++) {
+		/*
+		 * loop to enable interrupts on newly arrived crtc
+		 */
+		struct amdgpu_crtc *acrtc = new_crtcs[i];
+
+		manage_dm_interrupts(adev, acrtc, true);
+		dm_crtc_cursor_reset(&acrtc->base);
+
+	}
+
+	/* Page flip if needed */
+	for_each_plane_in_state(state, plane, old_plane_state, i) {
+		struct drm_plane_state *plane_state = plane->state;
+		struct drm_crtc *crtc = plane_state->crtc;
+		struct drm_framebuffer *fb = plane_state->fb;
+
+		if (!fb || !crtc || !crtc->state->planes_changed ||
+			!crtc->state->active)
+			continue;
+
+		if (page_flip_needed(plane_state, old_plane_state))
+			amdgpu_crtc_page_flip(
+				crtc,
+				fb,
+				crtc->state->event,
+				0);
+	}
+
+	drm_atomic_helper_wait_for_vblanks(dev, state);
+
+	/* In this state all old framebuffers would be unpinned */
+
+	drm_atomic_helper_cleanup_planes(dev, state);
+
+	drm_atomic_state_free(state);
+
+	return 0;
+}
+
+static uint32_t add_val_sets_surface(
+	struct dc_validation_set *val_sets,
+	uint32_t set_count,
+	const struct dc_target *target,
+	const struct dc_surface *surface)
+{
+	uint32_t i = 0;
+
+	while (i < set_count) {
+		if (val_sets[i].target == target)
+			break;
+		++i;
+	}
+
+	val_sets[i].surfaces[val_sets[i].surface_count] = surface;
+	val_sets[i].surface_count++;
+
+	return val_sets[i].surface_count;
+}
+
+static uint32_t update_in_val_sets_target(
+	struct dc_validation_set *val_sets,
+	uint32_t set_count,
+	const struct dc_target *old_target,
+	const struct dc_target *new_target)
+{
+	uint32_t i = 0;
+
+	while (i < set_count) {
+		if (val_sets[i].target == old_target)
+			break;
+		++i;
+	}
+
+	val_sets[i].target = new_target;
+
+	if (i == set_count) {
+		/* nothing found. add new one to the end */
+		return set_count + 1;
+	}
+
+	return set_count;
+}
+
+static uint32_t remove_from_val_sets(
+	struct dc_validation_set *val_sets,
+	uint32_t set_count,
+	const struct dc_target *target)
+{
+	uint32_t i = 0;
+
+	while (i < set_count) {
+		if (val_sets[i].target == target)
+			break;
+		++i;
+	}
+
+	if (i == set_count) {
+		/* nothing found */
+		return set_count;
+	}
+
+	memmove(
+		&val_sets[i],
+		&val_sets[i + 1],
+		sizeof(struct dc_validation_set *) * (set_count - i - 1));
+
+	return set_count - 1;
+}
+
+int amdgpu_dm_atomic_check(struct drm_device *dev,
+			struct drm_atomic_state *state)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_plane *plane;
+	struct drm_plane_state *plane_state;
+	int i;
+	int j;
+	int ret;
+	int set_count;
+	int new_target_count;
+	struct dc_validation_set set[MAX_TARGET_NUM] = {{ 0 }};
+	struct dc_target *new_targets[MAX_TARGET_NUM] = { 0 };
+	struct amdgpu_device *adev = dev->dev_private;
+	struct dc *dc = adev->dm.dc;
+	bool need_to_validate = false;
+
+	ret = drm_atomic_helper_check(dev, state);
+
+	if (ret) {
+		DRM_ERROR("Atomic state validation failed with error :%d !\n",
+				ret);
+		return ret;
+	}
+
+	ret = -EINVAL;
+
+	/* copy existing configuration */
+	new_target_count = 0;
+	set_count = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+		if (acrtc->target) {
+			set[set_count].target = acrtc->target;
+			++set_count;
+		}
+	}
+
+	/* update changed items */
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		struct amdgpu_crtc *acrtc = NULL;
+		struct amdgpu_connector *aconnector = NULL;
+		enum dm_commit_action action;
+		struct drm_connector *connector;
+		struct drm_connector_state *con_state;
+
+		acrtc = to_amdgpu_crtc(crtc);
+
+		for_each_connector_in_state(state, connector, con_state, j) {
+			if (con_state->crtc == crtc) {
+				aconnector = to_amdgpu_connector(connector);
+				break;
+			}
+		}
+
+		/*TODO:
+		handle_headless_hotplug(acrtc, crtc_state, &aconnector);*/
+
+		action = get_dm_commit_action(crtc_state);
+
+		switch (action) {
+		case DM_COMMIT_ACTION_DPMS_ON:
+		case DM_COMMIT_ACTION_SET: {
+			struct drm_display_mode mode = crtc_state->mode;
+			struct dc_target *new_target = NULL;
+
+			if (!aconnector) {
+				DRM_ERROR(
+					"%s: Can't find connector for crtc %d\n",
+					__func__,
+					acrtc->crtc_id);
+				goto connector_not_found;
+			}
+
+			new_target =
+				create_target_for_sink(
+					aconnector,
+					&mode);
+
+			/*
+			 * we can have no target on ACTION_SET if a display
+			 * was disconnected during S3, in this case it not and
+			 * error, the OS will be updated after detection, and
+			 * do the right thing on next atomic commit
+			 */
+			if (!new_target) {
+				DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n",
+						__func__, acrtc->base.base.id);
+				break;
+			}
+
+			new_targets[new_target_count] = new_target;
+
+			set_count = update_in_val_sets_target(
+					set,
+					set_count,
+					acrtc->target,
+					new_target);
+			new_target_count++;
+			need_to_validate = true;
+			break;
+		}
+
+		case DM_COMMIT_ACTION_NOTHING:
+			break;
+		case DM_COMMIT_ACTION_DPMS_OFF:
+		case DM_COMMIT_ACTION_RESET:
+			/* i.e. reset mode */
+			if (acrtc->target) {
+				set_count = remove_from_val_sets(
+						set,
+						set_count,
+						acrtc->target);
+			}
+			break;
+		}
+	}
+
+
+	for (i = 0; i < set_count; i++) {
+		for_each_plane_in_state(state, plane, plane_state, j) {
+			struct drm_plane_state *old_plane_state = plane->state;
+			struct drm_framebuffer *fb = plane_state->fb;
+			struct drm_crtc *crtc = plane_state->crtc;
+			struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+			if (!fb || acrtc->target != set[i].target)
+				continue;
+
+			if (!crtc->state->planes_changed)
+				continue;
+
+			if (!page_flip_needed(plane_state, old_plane_state)) {
+				struct dc_surface *surface =
+					dc_create_surface(dc);
+
+				fill_plane_attributes(
+					surface,
+					plane_state);
+
+				add_val_sets_surface(
+					set,
+					set_count,
+					acrtc->target,
+					surface);
+				need_to_validate = true;
+			}
+		}
+
+	}
+
+	if (need_to_validate == false || set_count == 0
+				|| dc_validate_resources(dc, set, set_count))
+		ret = 0;
+
+connector_not_found:
+	for (i = 0; i < set_count; i++) {
+		for (j = 0; j < set[i].surface_count; j++) {
+			dc_surface_release(set[i].surfaces[j]);
+		}
+	}
+	for (i = 0; i < new_target_count; i++)
+		dc_target_release(new_targets[i]);
+
+	if (ret != 0)
+		DRM_ERROR("Atomic check failed.\n");
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
new file mode 100644
index 000000000000..0481075de6e9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012-13 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#ifndef __AMDGPU_DM_TYPES_H__
+#define __AMDGPU_DM_TYPES_H__
+
+#include <drm/drmP.h>
+
+struct amdgpu_framebuffer;
+struct amdgpu_display_manager;
+struct dc_validation_set;
+struct dc_surface;
+
+/*TODO Jodan Hersen use the one in amdgpu_dm*/
+int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
+			struct amdgpu_crtc *amdgpu_crtc,
+			uint32_t link_index);
+int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
+			struct amdgpu_connector *amdgpu_connector,
+			uint32_t link_index,
+			struct amdgpu_encoder *amdgpu_encoder);
+int amdgpu_dm_encoder_init(
+	struct drm_device *dev,
+	struct amdgpu_encoder *aencoder,
+	uint32_t link_index);
+
+void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc);
+void amdgpu_dm_connector_destroy(struct drm_connector *connector);
+void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder);
+
+void dm_add_display_info(
+	struct drm_display_info *disp_info,
+	struct amdgpu_display_manager *dm,
+	uint32_t display_index);
+
+int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
+
+int amdgpu_dm_atomic_commit(
+	struct drm_device *dev,
+	struct drm_atomic_state *state,
+	bool async);
+int amdgpu_dm_atomic_check(struct drm_device *dev,
+				struct drm_atomic_state *state);
+
+int dm_create_validation_set_for_target(
+	struct drm_connector *connector,
+	struct drm_display_mode *mode,
+	struct dc_validation_set *val_set);
+
+void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector);
+struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state(
+	struct drm_connector *connector);
+void amdgpu_dm_connector_atomic_destroy_state(
+	struct drm_connector *connector,
+	struct drm_connector_state *state);
+int amdgpu_dm_connector_atomic_set_property(
+	struct drm_connector *connector,
+	struct drm_connector_state *state,
+	struct drm_property *property,
+	uint64_t val);
+
+int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev);
+
+void amdgpu_dm_connector_init_helper(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector,
+	int connector_type,
+	const struct dc_link *link,
+	int link_index);
+
+int amdgpu_dm_connector_mode_valid(
+	struct drm_connector *connector,
+	struct drm_display_mode *mode);
+
+extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs;
+
+#endif		/* __AMDGPU_DM_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services.h b/drivers/gpu/drm/amd/dal/dc/dm_services.h
index 206c0b7df7c6..47bbb9e6e060 100644
--- a/drivers/gpu/drm/amd/dal/dc/dm_services.h
+++ b/drivers/gpu/drm/amd/dal/dc/dm_services.h
@@ -166,19 +166,7 @@ bool dm_exec_bios_cmd_table(
 	uint32_t index,
 	void *params);
 
-#ifdef BUILD_DAL_TEST
-uint32_t dm_bios_cmd_table_para_revision(
-struct dc_context *ctx,
-	uint32_t index);
 
-bool dm_bios_cmd_table_revision(
-	struct dc_context *ctx,
-	uint32_t index,
-	uint8_t *frev,
-	uint8_t *crev);
-#endif
-
-#ifndef BUILD_DAL_TEST
 static inline uint32_t dm_bios_cmd_table_para_revision(
 	struct dc_context *ctx,
 	uint32_t index)
@@ -195,11 +183,6 @@ static inline uint32_t dm_bios_cmd_table_para_revision(
 
 	return crev;
 }
-#else
-uint32_t dm_bios_cmd_table_para_revision(
-		struct dc_context *ctx,
-		uint32_t index);
-#endif
 
 /**************************************
  * Power Play (PP) interfaces
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v2 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
                     ` (24 preceding siblings ...)
  2016-02-16 22:28   ` [PATCH v2 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
@ 2016-02-16 22:28   ` Harry Wentland
  25 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-16 22:28 UTC (permalink / raw)
  To: dri-devel

Start to use dal by default on Carrizo, Tonga, and Fiji ASICs.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/Kconfig         |   3 +
 drivers/gpu/drm/amd/amdgpu/Makefile        |  17 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h        |  10 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |  69 ++++++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c    |   4 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c     |   5 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c    |  20 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h   |  54 ++++++-
 drivers/gpu/drm/amd/amdgpu/vi.c            | 250 +++++++++++++++++++++++++++++
 9 files changed, 402 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
index b30fcfa4b1f2..3a37e37bef28 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -15,3 +15,6 @@ config DRM_AMDGPU_USERPTR
 	help
 	  This option selects CONFIG_MMU_NOTIFIER if it isn't already
 	  selected to enabled full userptr support.
+
+source "drivers/gpu/drm/amd/dal/Kconfig"
+
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index c7fcdcedaadb..c434ee5c589f 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -3,13 +3,19 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 FULL_AMD_PATH=$(src)/..
+DAL_FOLDER_NAME=dal
+FULL_AMD_DAL_PATH = $(FULL_AMD_PATH)/$(DAL_FOLDER_NAME)
 
 ccflags-y := -Iinclude/drm -I$(FULL_AMD_PATH)/include/asic_reg \
 	-I$(FULL_AMD_PATH)/include \
 	-I$(FULL_AMD_PATH)/amdgpu \
 	-I$(FULL_AMD_PATH)/scheduler \
 	-I$(FULL_AMD_PATH)/powerplay/inc \
-	-I$(FULL_AMD_PATH)/acp/include
+	-I$(FULL_AMD_PATH)/acp/include \
+	-I$(FULL_AMD_DAL_PATH) \
+	-I$(FULL_AMD_DAL_PATH)/include \
+	-I$(FULL_AMD_DAL_PATH)/dc \
+	-I$(FULL_AMD_DAL_PATH)/amdgpu_dm
 
 amdgpu-y := amdgpu_drv.o
 
@@ -118,6 +124,15 @@ amdgpu-y += $(AMD_POWERPLAY_FILES)
 
 endif
 
+ifneq ($(CONFIG_DRM_AMD_DAL),)
+
+RELATIVE_AMD_DAL_PATH = ../$(DAL_FOLDER_NAME)
+include $(FULL_AMD_DAL_PATH)/Makefile
+
+amdgpu-y += $(AMD_DAL_FILES)
+
+endif
+
 obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o
 
 CFLAGS_amdgpu_trace_points.o := -I$(src)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 99e660fec190..d154b3473ae8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -54,6 +54,7 @@
 #include "amdgpu_gds.h"
 #include "amd_powerplay.h"
 #include "amdgpu_acp.h"
+#include "amdgpu_dm.h"
 
 #include "gpu_scheduler.h"
 
@@ -85,6 +86,7 @@ extern int amdgpu_vm_debug;
 extern int amdgpu_sched_jobs;
 extern int amdgpu_sched_hw_submission;
 extern int amdgpu_powerplay;
+extern int amdgpu_dal;
 
 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS	        3000
 #define AMDGPU_MAX_USEC_TIMEOUT			100000	/* 100 ms */
@@ -2017,6 +2019,7 @@ struct amdgpu_device {
 
 	/* display */
 	struct amdgpu_mode_info		mode_info;
+	/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
 	struct work_struct		hotplug_work;
 	struct amdgpu_irq_src		crtc_irq;
 	struct amdgpu_irq_src		pageflip_irq;
@@ -2064,6 +2067,9 @@ struct amdgpu_device {
 	/* GDS */
 	struct amdgpu_gds		gds;
 
+	/* display related functionality */
+	struct amdgpu_display_manager dm;
+
 	const struct amdgpu_ip_block_version *ip_blocks;
 	int				num_ip_blocks;
 	struct amdgpu_ip_block_status	*ip_block_status;
@@ -2100,7 +2106,7 @@ void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v);
 
 u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index);
 void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v);
-
+bool amdgpu_device_has_dal_support(struct amdgpu_device *adev);
 /*
  * Cast helper
  */
@@ -2345,6 +2351,8 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
 
 #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a))
 
+#define amdgpu_has_dal_support(adev) (amdgpu_dal && amdgpu_device_has_dal_support(adev))
+
 /* Common functions */
 int amdgpu_gpu_reset(struct amdgpu_device *adev);
 void amdgpu_pci_config_reset(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index f0fb938457d9..3df6fe35ec63 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1369,6 +1369,32 @@ static int amdgpu_resume(struct amdgpu_device *adev)
 	return 0;
 }
 
+
+/**
+ * amdgpu_device_has_dal_support - check if dal is supported
+ *
+ * @adev: amdgpu_device_pointer
+ *
+ * Returns true for supported, false for not supported
+ */
+bool amdgpu_device_has_dal_support(struct amdgpu_device *adev)
+{
+	switch(adev->asic_type) {
+#if defined(CONFIG_DRM_AMD_DAL) && defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case CHIP_CARRIZO:
+		return true;
+#endif
+#if defined(CONFIG_DRM_AMD_DAL) && defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case CHIP_TONGA:
+	case CHIP_FIJI:
+		return true;
+#endif
+	default:
+		return false;
+	}
+}
+
+
 /**
  * amdgpu_device_init - initialize the driver
  *
@@ -1522,7 +1548,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
 		return r;
 	}
 	/* init i2c buses */
-	amdgpu_atombios_i2c_init(adev);
+	if (!amdgpu_has_dal_support(adev))
+		amdgpu_atombios_i2c_init(adev);
 
 	/* Fence driver */
 	r = amdgpu_fence_driver_init(adev);
@@ -1628,7 +1655,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
 	adev->ip_block_status = NULL;
 	adev->accel_working = false;
 	/* free i2c buses */
-	amdgpu_i2c_fini(adev);
+	if (!amdgpu_has_dal_support(adev))
+		amdgpu_i2c_fini(adev);
 	amdgpu_atombios_fini(adev);
 	kfree(adev->bios);
 	adev->bios = NULL;
@@ -1676,12 +1704,14 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 
 	drm_kms_helper_poll_disable(dev);
 
-	/* turn off display hw */
-	drm_modeset_lock_all(dev);
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+	if (!amdgpu_has_dal_support(adev)) {
+		/* turn off display hw */
+		drm_modeset_lock_all(dev);
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+		}
+		drm_modeset_unlock_all(dev);
 	}
-	drm_modeset_unlock_all(dev);
 
 	/* unpin the front buffers and cursors */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -1773,6 +1803,9 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
 
 	r = amdgpu_resume(adev);
 
+	if (r)
+		DRM_ERROR("amdgpu_resume failed (%d).\n", r);
+
 	amdgpu_fence_driver_resume(adev);
 
 	r = amdgpu_ib_ring_tests(adev);
@@ -1803,17 +1836,25 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
 
 	/* blat the mode back in */
 	if (fbcon) {
-		drm_helper_resume_force_mode(dev);
-		/* turn on display hw */
-		drm_modeset_lock_all(dev);
-		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+		if (!amdgpu_has_dal_support(adev)) {
+			/* pre DCE11 */
+			drm_helper_resume_force_mode(dev);
+
+			/* turn on display hw */
+			drm_modeset_lock_all(dev);
+			list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+				drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+			}
+			drm_modeset_unlock_all(dev);
 		}
-		drm_modeset_unlock_all(dev);
 	}
 
 	drm_kms_helper_poll_enable(dev);
-	drm_helper_hpd_irq_event(dev);
+
+	if (!amdgpu_has_dal_support(adev))
+		 drm_helper_hpd_irq_event(dev);
+	else
+		drm_kms_helper_hotplug_event(dev);
 
 	if (fbcon) {
 		amdgpu_fbdev_set_suspend(adev, 0);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index ce79a8b605a0..6f1dec5d76c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -80,6 +80,7 @@ int amdgpu_exp_hw_support = 0;
 int amdgpu_sched_jobs = 32;
 int amdgpu_sched_hw_submission = 2;
 int amdgpu_powerplay = -1;
+int amdgpu_dal = 1;
 
 MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
 module_param_named(vramlimit, amdgpu_vram_limit, int, 0600);
@@ -158,6 +159,9 @@ MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 =
 module_param_named(powerplay, amdgpu_powerplay, int, 0444);
 #endif
 
+MODULE_PARM_DESC(dal, "DAL display driver (1 = enable (default), 0 = disable)");
+module_param_named(dal, amdgpu_dal, int, 0444);
+
 static struct pci_device_id pciidlist[] = {
 #ifdef CONFIG_DRM_AMDGPU_CIK
 	/* Kaveri */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 919146780a15..e694c9983bbd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -42,11 +42,6 @@
    this contains a helper + a amdgpu fb
    the helper contains a pointer to amdgpu framebuffer baseclass.
 */
-struct amdgpu_fbdev {
-	struct drm_fb_helper helper;
-	struct amdgpu_framebuffer rfb;
-	struct amdgpu_device *adev;
-};
 
 static struct fb_ops amdgpufb_ops = {
 	.owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index f594cfaa97e5..4775930b678d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -36,6 +36,10 @@
 
 #include <linux/pm_runtime.h>
 
+#ifdef CONFIG_DRM_AMD_DAL
+#include "amdgpu_dm_irq.h"
+#endif
+
 #define AMDGPU_WAIT_IDLE_TIMEOUT 200
 
 /*
@@ -215,10 +219,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
 	int r = 0;
 
 	spin_lock_init(&adev->irq.lock);
-	r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
-	if (r) {
-		return r;
-	}
+
 	/* enable msi */
 	adev->irq.msi_enabled = false;
 
@@ -230,7 +231,16 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
 		}
 	}
 
-	INIT_WORK(&adev->hotplug_work, amdgpu_hotplug_work_func);
+	if (!amdgpu_has_dal_support(adev)) {
+		r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
+		if (r)
+			return r;
+
+		/* pre DCE11 */
+		INIT_WORK(&adev->hotplug_work,
+				amdgpu_hotplug_work_func);
+	}
+
 	INIT_WORK(&adev->reset_work, amdgpu_irq_reset_work_func);
 
 	adev->irq.installed = true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index fdc1be8550da..e2fb0c5bab82 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -35,11 +35,13 @@
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_fixed.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_fb_helper.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 
+#include <drm/drm_dp_mst_helper.h>
+
 struct amdgpu_bo;
 struct amdgpu_device;
 struct amdgpu_encoder;
@@ -305,6 +307,18 @@ struct amdgpu_display_funcs {
 				 struct amdgpu_mode_mc_save *save);
 };
 
+struct amdgpu_framebuffer {
+	struct drm_framebuffer base;
+	struct drm_gem_object *obj;
+};
+
+struct amdgpu_fbdev {
+	struct drm_fb_helper helper;
+	struct amdgpu_framebuffer rfb;
+	struct list_head fbdev_list;
+	struct amdgpu_device *adev;
+};
+
 struct amdgpu_mode_info {
 	struct atom_context *atom_context;
 	struct card_info *atom_card_info;
@@ -410,6 +424,9 @@ struct amdgpu_crtc {
 	u32 wm_high;
 	u32 lb_vblank_lead_lines;
 	struct drm_display_mode hw_mode;
+
+	/* After Set Mode target will be non-NULL */
+	struct dc_target *target;
 };
 
 struct amdgpu_encoder_atom_dig {
@@ -499,6 +516,13 @@ enum amdgpu_connector_dither {
 	AMDGPU_FMT_DITHER_ENABLE = 1,
 };
 
+struct amdgpu_dm_dp_aux {
+	struct drm_dp_aux aux;
+	uint32_t link_index;
+};
+
+#define TO_DM_AUX(x) container_of((x), struct amdgpu_dm_dp_aux, aux)
+
 struct amdgpu_connector {
 	struct drm_connector base;
 	uint32_t connector_id;
@@ -510,6 +534,13 @@ struct amdgpu_connector {
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
 	struct edid *edid;
+	/* number of modes generated from EDID at 'dc_sink' */
+	int num_modes;
+	/* The 'old' sink - before an HPD.
+	 * The 'current' sink is in dc_link->sink. */
+	const struct dc_sink *dc_sink;
+	const struct dc_link *dc_link;
+	const struct dc_target *target;
 	void *con_priv;
 	bool dac_load_detect;
 	bool detected_by_load; /* if the connection status was determined by load */
@@ -520,11 +551,26 @@ struct amdgpu_connector {
 	enum amdgpu_connector_audio audio;
 	enum amdgpu_connector_dither dither;
 	unsigned pixelclock_for_modeset;
+
+	struct drm_dp_mst_topology_mgr mst_mgr;
+	struct amdgpu_dm_dp_aux dm_dp_aux;
+	struct drm_dp_mst_port *port;
+	struct amdgpu_connector *mst_port;
+	bool is_mst_connector;
+	struct amdgpu_encoder *mst_encoder;
+	struct semaphore mst_sem;
 };
 
-struct amdgpu_framebuffer {
-	struct drm_framebuffer base;
-	struct drm_gem_object *obj;
+/* TODO: start to use this struct and remove same field from base one */
+struct amdgpu_mst_connector {
+	struct amdgpu_connector base;
+
+	struct drm_dp_mst_topology_mgr mst_mgr;
+	struct amdgpu_dm_dp_aux dm_dp_aux;
+	struct drm_dp_mst_port *port;
+	struct amdgpu_connector *mst_port;
+	bool is_mst_connector;
+	struct amdgpu_encoder *mst_encoder;
 };
 
 #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 125003517544..4b27092d14c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -77,6 +77,7 @@
 #if defined(CONFIG_DRM_AMD_ACP)
 #include "amdgpu_acp.h"
 #endif
+#include "amdgpu_dm.h"
 
 /*
  * Indirect registers accessor
@@ -984,6 +985,225 @@ static const struct amdgpu_ip_block_version cz_ip_blocks[] =
 #endif
 };
 
+/*
+ * This is temporary. After we've gone through full testing with
+ * DAL we want to remove dce_v11
+ */
+#if defined(CONFIG_DRM_AMD_DAL)
+static const struct amdgpu_ip_block_version cz_ip_blocks_dal[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &cz_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 11,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &amdgpu_dm_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+#if defined(CONFIG_DRM_AMD_ACP)
+	{
+		.type = AMD_IP_BLOCK_TYPE_ACP,
+		.major = 2,
+		.minor = 2,
+		.rev = 0,
+		.funcs = &acp_ip_funcs,
+	},
+#endif
+};
+
+static const struct amdgpu_ip_block_version tonga_ip_blocks_dal[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &tonga_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 7,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 10,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &amdgpu_dm_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 5,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v5_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+};
+
+static const struct amdgpu_ip_block_version fiji_ip_blocks_dal[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 5,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &tonga_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 7,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 10,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &amdgpu_dm_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+};
+#endif
+
 int vi_set_ip_blocks(struct amdgpu_device *adev)
 {
 	switch (adev->asic_type) {
@@ -992,17 +1212,47 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		adev->num_ip_blocks = ARRAY_SIZE(topaz_ip_blocks);
 		break;
 	case CHIP_FIJI:
+#if defined(CONFIG_DRM_AMD_DAL)
+		if (amdgpu_dal && amdgpu_device_has_dal_support(adev)) {
+			adev->ip_blocks = fiji_ip_blocks_dal;
+			adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks_dal);
+		} else {
+			adev->ip_blocks = fiji_ip_blocks;
+			adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks);
+		}
+#else
 		adev->ip_blocks = fiji_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks);
+#endif
 		break;
 	case CHIP_TONGA:
+#if defined(CONFIG_DRM_AMD_DAL)
+		if (amdgpu_dal && amdgpu_device_has_dal_support(adev)) {
+			adev->ip_blocks = tonga_ip_blocks_dal;
+			adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks_dal);
+		} else {
+			adev->ip_blocks = tonga_ip_blocks;
+			adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
+		}
+#else
 		adev->ip_blocks = tonga_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
+#endif
 		break;
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
+#if defined(CONFIG_DRM_AMD_DAL)
+		if (amdgpu_dal && amdgpu_device_has_dal_support(adev)) {
+			adev->ip_blocks = cz_ip_blocks_dal;
+			adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks_dal);
+		} else {
+			adev->ip_blocks = cz_ip_blocks;
+			adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks);
+		}
+#else
 		adev->ip_blocks = cz_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks);
+#endif
 		break;
 	default:
 		/* FIXME: not supported yet */
-- 
2.1.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* Re: [PATCH 08/29] drm/amd/dal: I2C Aux Manager
  2016-02-11 20:19   ` Rob Clark
  2016-02-11 20:52     ` Daniel Vetter
@ 2016-02-17  3:23     ` Harry Wentland
  1 sibling, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-17  3:23 UTC (permalink / raw)
  To: Rob Clark; +Cc: Deucher, Alexander, Cheng, Tony, dri-devel

Hi Rob,

that's a good point. We'll see if we can use DRM and existing amdgpu 
code for i2c/aux and rip this one out.

Cheers,
Harry

On 2016-02-11 03:19 PM, Rob Clark wrote:
> On Thu, Feb 11, 2016 at 12:19 PM, Harry Wentland <harry.wentland@amd.com> wrote:
>> Implements low-level communication layer over I2C and Aux lines using
>> GPIO handles.
> so without actually looking too closely at this rather large patch (in
> a rather huge patchset)..  I do wonder, why not i2c_adapter?  Kernel
> already has an implementation of that on top of gpio's..
>
> BR,
> -R
>
>> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
>> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
>> ---
>>   drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |  33 +
>>   drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     | 567 ++++++++++++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     | 119 +++
>>   .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   | 788 +++++++++++++++++
>>   .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |  56 ++
>>   .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |  25 +
>>   .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    | 954 +++++++++++++++++++++
>>   .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |  58 ++
>>   .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    | 172 ++++
>>   .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |  43 +
>>   .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   | 266 ++++++
>>   .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |  39 +
>>   .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    | 112 +++
>>   .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |  33 +
>>   drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         | 129 +++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |  67 ++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     | 121 +++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     | 113 +++
>>   .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  | 286 ++++++
>>   .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |  77 ++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  | 246 ++++++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |  80 ++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  | 614 +++++++++++++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |  81 ++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         | 529 ++++++++++++
>>   drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         | 123 +++
>>   26 files changed, 5731 insertions(+)
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
>>   create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-14 13:32         ` Rob Clark
  2016-02-14 13:51           ` Daniel Vetter
@ 2016-02-17  3:26           ` Harry Wentland
  1 sibling, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-17  3:26 UTC (permalink / raw)
  To: Rob Clark; +Cc: dri-devel, Deucher, Alexander, Cheng, Tony, Lysenko, Mykola

Hi Rob,

thanks for the heads-up for this. We're definitely interested in 
contributing to proposed new frameworks.

I'm not sure we want to tightly couple userspace with hardware, though. 
Your proposal seems to assume that user mode is responsible for knowing 
how many planes any given configuration needs, or iterating through 
failures until a successful solution is found. First this is quite 
sub-optimal and would be hard to get right without duplicating most of 
kernel driver resource management in user mode. Second this doesn't 
solve the problem with fbcon or other solutions when there is no 
user-mode component.

Cheers,
Harry

On 2016-02-14 08:32 AM, Rob Clark wrote:
> On Fri, Feb 12, 2016 at 7:05 PM, Wentland, Harry <Harry.Wentland@amd.com> wrote:
>> The current amdgpu display stack grew somewhat organically and as such is not well suited to handling all of the hardware dependencies involved especially in areas like audio.  The drm abstractions used by the old code map less and less well to new hw pipelines.  Atomic helps, but if we are going to convert, it seemed like a good time to start fresh.
>>
>> Our DC (Display Core in dc.h, etc.) is the framework to allow us to well represent current and future HW architectures. These don't always map one-to-one to DRM interfaces. For one we can't make the assumption that surfaces map one-to-one to pipes.
> So, this sounds a bit vaguely like some things that I have discussed
> from drm/msm.. where you might end up using multiple planes to scan
> out a single surface, or multiplex a single plane between multiple
> surfaces (or combinations thereof)..
>
> I think what we'll end up doing is virtualizing planes so we advertise
> to userspace more planes than actually exist, and at atomic update
> time, dynamically assign pipes to planes, and reject things if
> userspace asks for too many planes..  although this is getting into an
> area where it helps to assume that there is a userspace component
> which is familiar with your hw, which is true for android (and I think
> some day wayland compositors will have to grow similar capability for
> driver specific userspace plugin to make decisions about how to assign
> planes).
>
> Not sure if a similar approach would help you to fit better into the
> kms/atomic framework?
>
> BR,
> -R

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-14 11:22         ` Jerome Glisse
  2016-02-14 13:23           ` Daniel Vetter
@ 2016-02-17  3:28           ` Harry Wentland
  1 sibling, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-17  3:28 UTC (permalink / raw)
  To: Jerome Glisse; +Cc: dri-devel, Deucher, Alexander, Cheng, Tony, Lysenko, Mykola

Hi Jerome,

some of the kernel API is abstracted to allow testing of this driver in 
user space for pre- and post-silicon validation. An alternative that 
we've considered is implementing the kernel functions in user space. 
That's definitely an option.

We're definitely open to push things into drm and help develop common 
functionality, such as MST and others. The DC abstraction is necessary, 
however, to handle current and future hardware requirements agnostically.

Cheers,
Harry

On 2016-02-14 06:22 AM, Jerome Glisse wrote:
> On Sat, Feb 13, 2016 at 12:05:48AM +0000, Wentland, Harry wrote:
>> Hi Dave, Daniel, others,
> [...]
>
>> There's still a bunch of legacy stuff in these patches that's on our list of things to refactor. Some of that is
>> - dc/adapter
>> - dc/asic_capability
>> - dc/audio
>> - dc/bios
>> - dc/gpio
>>
>> We should be able to cut the size of this code to about 1/3 of what it is now.
>>
>> As for the LOC we have about
>> 22k for HW programming
>> 30k legacy stuff
>> 6k  dc/calcs - autogenerated from formulas provided by HW team
>> 15k includes
>> 6k  amdgpu_dm
>> 8k  dc/core
>>
>> About 14k of those are blank lines (we have a habit of leaving lots of blank space) and 16k are comments.
> Cleaning up that is not enough, abstracting kernel API like kmalloc or i2c,
> or similar, is a no go. If the current drm infrastructure does not suit your
> need then you need to work on improving it to suit your need. You can not
> redevelop a whole drm layer inside your code and expect to upstream it.
>
> Linux device driver are about sharing infrastructure and trying to expose
> it through common API to userspace.
>
> So i strongly suggest that you start thinking on how to change the drm API
> to suit your need and to start discussions about those changes. If you need
> them then they will likely be usefull to others down the road.
>
> Cheers,
> Jérôme

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-14 14:01         ` Daniel Vetter
@ 2016-02-17  3:32           ` Harry Wentland
  0 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-17  3:32 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: dri-devel, Deucher, Alexander, Cheng, Tony, Lysenko, Mykola

Hi Daniel,

we've considered making cursor a plane but haven't done so (yet) because 
cursor is sort of a unique concept in our HW and doesn't map well to planes.

Will take the time to look at the other mappings a bit more closely.

Cheers,
Harry

On 2016-02-14 09:01 AM, Daniel Vetter wrote:
> top-level post since I can't reply to the diagram directly. So from
> very cursor reading-around in the code I think you have a few
> mismatches in how you map drm concepts to dal structures:
>
> - cursor is just a drm_plane - step 0 of atomic support is universale
> plane support, and you didn't do that in this patch series. Same holds
> for video overlay support (which seems implemented but not exposed).
>
> - drm_plane should probably match to both surface + target structs,
> since how a plane is composited in the screen rect is a plane state
>
> - stream should probably map to crtc
>
> - for cases where you need 2 streams for 1 crtc or 2 surfaces for 1
> plane internally remap them with some aux pointer. But imo still base
> them on drm core structures (since in most cases you can expose them
> all). You probably need a full remapping table to make this work, but
> the state itself should still all be in extensions of core drm_*_state
> structs
>
> - drm_encoder probably matches to dc_link, but not sure. drm_encoder
> is mostly just a convenience thing really, you can ignore it
>
> - dc_sink seems to be the drm_connector, or well mostly. Here it gets
> really unclear due to the massive amount of private code for
> screen/sink handling that dal has.
>
> Cheers, Daniel
>
>
> On Sat, Feb 13, 2016 at 1:05 AM, Wentland, Harry <Harry.Wentland@amd.com> wrote:
>> Hi Dave, Daniel, others,
>>
>> The goal with DAL is to provide a unified, full featured display stack to service all of our Linux offerings. This driver will have to support our full feature set beyond what's supported by amdgpu, e.g.
>>    - synchronzied timings across different displays
>>    - freesync
>>    - solid support of 6 displays in any configuration (HDMI, DVI, DP, DP MST, etc)
>>    - solid support of 4k@60 timings on APUs
>>    - power features, such as
>>      - clock-accurate bandwidth formulas
>>      - improved interaction with powerplay to maximize power savings
>> - Improved audio and other infoframe related features
>> - Improved stability with powerplay since display hw is involved in the SMC hw interactions and improper programming sequences can lead to GPU hangs, etc.
>>
>> The current amdgpu display stack grew somewhat organically and as such is not well suited to handling all of the hardware dependencies involved especially in areas like audio.  The drm abstractions used by the old code map less and less well to new hw pipelines.  Atomic helps, but if we are going to convert, it seemed like a good time to start fresh.
>>
>> Our DC (Display Core in dc.h, etc.) is the framework to allow us to well represent current and future HW architectures. These don't always map one-to-one to DRM interfaces. For one we can't make the assumption that surfaces map one-to-one to pipes.
>>
>> The DAL internal abstractions were used since they match the abstractions used by our drivers for other OSes, pre and post silicon validation tools and HW team programming models. Keeping it as close to that as possible makes it easier to debug and validate and provides the most likely change of success in complex display configurations.
>>
>> Please see the attached DC.png for an overview of the DAL design.
>>
>> For an atomic sequence you might want to look at
>> - enable/disable displays or change display config -> dc_commit_targets
>>      (in dc/core/dc.c, called from amdgpu_dm_atomic_commit in amdgpu_dm/amdgpu_dm_types.c)
>>
>> - commit planes                                    -> dc_commit_surfaces_to_targets
>>      (in dc/core/dc_target.c, called from dm_dc_surface_commit in amdgpu_dm/amdgpu_dm_types.c)
>>
>> - validate                                         -> dc_validate_resources
>>      (in dc/core/dc.c, called from amdgpu_dm_atomic_check in amdgpu_dm/amdgpu_dm_types.c)
>>
>>
>> There's still a bunch of legacy stuff in these patches that's on our list of things to refactor. Some of that is
>> - dc/adapter
>> - dc/asic_capability
>> - dc/audio
>> - dc/bios
>> - dc/gpio
>>
>> We should be able to cut the size of this code to about 1/3 of what it is now.
>>
>> As for the LOC we have about
>> 22k for HW programming
>> 30k legacy stuff
>> 6k  dc/calcs - autogenerated from formulas provided by HW team
>> 15k includes
>> 6k  amdgpu_dm
>> 8k  dc/core
>>
>> About 14k of those are blank lines (we have a habit of leaving lots of blank space) and 16k are comments.
>>
>> Cheers,
>> Harry
>>
>> ________________________________________
>> From: Daniel Vetter <daniel.vetter@ffwll.ch> on behalf of Daniel Vetter <daniel@ffwll.ch>
>> Sent: Friday, February 12, 2016 12:34 AM
>> To: Dave Airlie
>> Cc: Wentland, Harry; dri-devel
>> Subject: Re: [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
>>
>> On Thu, Feb 11, 2016 at 10:06:14PM +0100, Daniel Vetter wrote:
>>> On Thu, Feb 11, 2016 at 9:52 PM, Dave Airlie <airlied@gmail.com> wrote:
>>>> On 12 February 2016 at 03:19, Harry Wentland <harry.wentland@amd.com> wrote:
>>>>> This set of patches enables the new DAL display driver for amdgpu on Carrizo
>>>>> Tonga, and Fiji ASICs. This driver will allow us going forward to bring
>>>>> display features on the open amdgpu driver (mostly) on par with the Catalyst
>>>>> driver.
>>>>>
>>>>> This driver adds support for
>>>>> - Atomic KMS API
>>>>> - MST
>>>>> - HDMI 2.0
>>>>> - Better powerplay integration
>>>>> - Support of HW bandwidth formula on Carrizo
>>>>> - Better multi-display support and handling of co-functionality
>>>>> - Broader support of display dongles
>>>>> - Timing synchronization between DP and HDMI
>>>>>
>>>>> This patch series is based on Alex Deucher's drm-next-4.6-wip tree.
>>>>>
>>>> So the first minor criticism is this patch doesn't explain WHY.
>>>>
>>>> Why does the Linux kernel need 93k lines of code to run the displays
>>>> when whole drivers don't even come close.
>>>>
>>>> We've spent a lot of time ripping abstraction layers out of drivers (exynos
>>>> being the major one), what benefits does this major change bring to the
>>>> Linux kernel and the AMDGPU driver over and above a leaner, more focused
>>>> work.
>>>>
>>>> If were even to consider merging this it would be at a guess considered
>>>> staging level material which would require a TODO list of major cleanups.
>>>>
>>>> I do realise you've put a lot of work into this, but I think you are going to
>>>> get a lot of review pushback in the next few days and without knowing the
>>>> reasons this path was chosen it is going to be hard to take.
>>> Yeah agreed, we need to figure out the why/how first. Assembling a
>>> de-staging TODO is imo a second step. And the problem with that is
>>> that before we can do a full TODO we need to remove all the os and drm
>>> abstractions. I found delayed_work, timer, memory handling, pixel
>>> formats (in multiple copies), the i2c stuff Rob noticed and there's
>>> more I'm sure. With all that I just can't even see how the main DAL
>>> structures connect and how that would sensibly map to drm concepts.
>>> Which is most likely needed to make DAL properly atomic.
>> More stuff plain duplicated I spotted:
>> - some edid handling (probably because of the duplicated i2c, but probably
>>    also because dal).
>> - has it's own infoframe encoding it seems
>> - home-grown logging. Yes, DRM_DEBUG isn't the most awesome, but dynamic
>>    prinkt is pretty neat from what I understand and we should just move
>>    DRM_DEBUG over to that if you need more flexibility.
>>
>> Cheers, Daniel
>>
>>> So de-staging DAL (if we decided this is the right approach) would be
>>> multi-stage, with removal of the abstractions not needed first, then
>>> taking a 2nd look and figuring out how to untangle the actual
>>> concepts.
>>>
>>> Aside: If all this abstraction is to make dal run in userspace for
>>> testing or whatever - nouveau does this, we (Intel) want to do this
>>> too for unit-testing, so there's definitely room for sharing the
>>> tools. But the right approach imo is to just implement kernel services
>>> (like timers) in userspace.
>>>
>>> Another thing is that some of the features in here (hdmi 2.0, improved
>>> dongle support) really should be in shared helpers. If we have that
>>> hidden behind the dal abstraction it'll be pretty much impossible
>>> (with major work, which is unreasonable to ask of other people trying
>>> to get their own driver in) to extract&share it. And for sink handling
>>> having multiple copies of the same code just doesn't make sense.
>>>
>>> Anyway that's my quick thoughts from 2h of reading this. One wishlist:
>>> Some design overview or diagram how dal structures connect would be
>>> awesome as a reading aid.
>> --
>> Daniel Vetter
>> Software Engineer, Intel Corporation
>> http://blog.ffwll.ch
>
>

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga
  2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                   ` (31 preceding siblings ...)
  2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
@ 2016-02-29 21:56 ` Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 01/26] drm/amd/dal: Add dal headers Harry Wentland
                     ` (5 more replies)
  32 siblings, 6 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-29 21:56 UTC (permalink / raw)
  To: dri-devel

Limitting v3 patches to only the modified patches, so as to reduce spam:
0001-drm-amd-dal-Add-dal-headers.patch
0005-drm-amd-dal-GPIO-General-Purpose-IO.patch
0007-drm-amd-dal-BIOS-Parser.patch
0024-drm-amd-dal-Add-display-core.patch
0025-drm-amd-dal-Adding-amdgpu_dm-for-dal.patch
0026-drm-amdgpu-Use-dal-driver-for-Carrizo-Tonga-and-Fiji.patch

Change History
--------------

v3:
- rebase on Alex's latest drm-next-4.6-wip
- export some functions to share with DAL
- use amdgpu's existing dce functions for some things, such as mc_access
- add stoney to dal check
- add missing hawaii and stoney case statements
- remove page work flip queue and use system queue instead
- minor dm_helpers function name cleanup
- expose I2C through i2c_adapter and route dal i2c calls through this

v2:
This is just a squash of the three small fixes into the main patches to
make for an easier read. No other changes yet.


Description
-----------

This set of patches enables the new DAL display driver for amdgpu on Carrizo
Tonga, and Fiji ASICs. This driver will allow us going forward to bring
display features on the open amdgpu driver (mostly) on par with the Catalyst
driver.

This driver adds support for 
- Atomic KMS API
- MST
- HDMI 2.0
- Better powerplay integration
- Support of HW bandwidth formula on Carrizo
- Better multi-display support and handling of co-functionality
- Broader support of display dongles
- Timing synchronization between DP and HDMI

This patch series is based on Alex Deucher's drm-next-4.6-wip tree.

Harry Wentland (26):
  drm/amd/dal: Add dal headers
  drm/amd/dal: Add DAL Basic Types and Logger
  drm/amd/dal: Fixed point arithmetic
  drm/amd/dal: Asic Capabilities
  drm/amd/dal: GPIO (General Purpose IO)
  drm/amd/dal: Adapter Service
  drm/amd/dal: BIOS Parser
  drm/amd/dal: I2C Aux Manager
  drm/amd/dal: IRQ Service
  drm/amd/dal: GPU
  drm/amd/dal: Audio
  drm/amd/dal: Bandwidth calculations
  drm/amd/dal: Add encoder HW programming
  drm/amd/dal: Add clock source HW programming
  drm/amd/dal: Add timing generator HW programming
  drm/amd/dal: Add surface HW programming
  drm/amd/dal: Add framebuffer compression HW programming
  drm/amd/dal: Add input pixel processing HW programming
  drm/amd/dal: Add output pixel processing HW programming
  drm/amd/dal: Add transform & scaler HW programming
  drm/amd/dal: Add Carrizo HW sequencer and resource
  drm/amd/dal: Add Tonga/Fiji HW sequencer and resource
  drm/amd/dal: Add empty encoder programming for virtual HW
  drm/amd/dal: Add display core
  drm/amd/dal: Adding amdgpu_dm for dal
  drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji

 drivers/gpu/drm/amd/amdgpu/Kconfig                 |    3 +
 drivers/gpu/drm/amd/amdgpu/Makefile                |   17 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h                |    8 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         |   70 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c            |    4 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c             |    5 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c            |   20 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h           |   63 +-
 drivers/gpu/drm/amd/amdgpu/dce_v10_0.c             |   12 +-
 drivers/gpu/drm/amd/amdgpu/dce_v10_0.h             |    7 +
 drivers/gpu/drm/amd/amdgpu/dce_v11_0.c             |   12 +-
 drivers/gpu/drm/amd/amdgpu/dce_v11_0.h             |    7 +
 drivers/gpu/drm/amd/amdgpu/dce_v8_0.c              |   12 +-
 drivers/gpu/drm/amd/amdgpu/dce_v8_0.h              |    7 +
 drivers/gpu/drm/amd/amdgpu/vi.c                    |  250 +
 drivers/gpu/drm/amd/dal/Kconfig                    |   48 +
 drivers/gpu/drm/amd/dal/Makefile                   |   21 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile         |   17 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c      | 1271 +++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h      |  168 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c  |  517 ++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c  |  820 ++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h  |  122 +
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c    |  480 ++
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h    |   36 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c |  457 ++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c    | 2649 +++++++++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h    |  100 +
 drivers/gpu/drm/amd/dal/dal_services.h             |  266 ++
 drivers/gpu/drm/amd/dal/dal_services_types.h       |   62 +
 drivers/gpu/drm/amd/dal/dc/Makefile                |   28 +
 drivers/gpu/drm/amd/dal/dc/adapter/Makefile        |   24 +
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.c   | 2089 ++++++++
 .../gpu/drm/amd/dal/dc/adapter/adapter_service.h   |   71 +
 .../adapter/dce110/hw_ctx_adapter_service_dce110.c |  304 ++
 .../adapter/dce110/hw_ctx_adapter_service_dce110.h |   40 +
 .../diagnostics/hw_ctx_adapter_service_diag.c      |  133 +
 .../diagnostics/hw_ctx_adapter_service_diag.h      |   33 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.c    |  164 +
 .../amd/dal/dc/adapter/hw_ctx_adapter_service.h    |   86 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.c  |  208 +
 .../drm/amd/dal/dc/adapter/wireless_data_source.h  |   80 +
 .../gpu/drm/amd/dal/dc/asic_capability/Makefile    |   35 +
 .../amd/dal/dc/asic_capability/asic_capability.c   |  190 +
 .../dc/asic_capability/carrizo_asic_capability.c   |  147 +
 .../dc/asic_capability/carrizo_asic_capability.h   |   36 +
 .../dal/dc/asic_capability/tonga_asic_capability.c |  146 +
 .../dal/dc/asic_capability/tonga_asic_capability.h |   36 +
 drivers/gpu/drm/amd/dal/dc/audio/Makefile          |   22 +
 drivers/gpu/drm/amd/dal/dc/audio/audio.h           |  195 +
 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c      |  470 ++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c |  453 ++
 .../gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h |   42 +
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c  | 1930 ++++++++
 .../amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h  |   47 +
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c    |  771 +++
 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h    |  285 ++
 drivers/gpu/drm/amd/dal/dc/basics/Makefile         |   10 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.c     |  224 +
 drivers/gpu/drm/amd/dal/dc/basics/conversion.h     |   49 +
 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c     |  692 +++
 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c     |  223 +
 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c |  134 +
 drivers/gpu/drm/amd/dal/dc/basics/logger.c         |  954 ++++
 drivers/gpu/drm/amd/dal/dc/basics/logger.h         |   64 +
 .../gpu/drm/amd/dal/dc/basics/register_logger.c    |  197 +
 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c   |  116 +
 drivers/gpu/drm/amd/dal/dc/basics/vector.c         |  309 ++
 drivers/gpu/drm/amd/dal/dc/bios/Makefile           |   26 +
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c      | 5030 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h      |   84 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c   |  198 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h   |  108 +
 drivers/gpu/drm/amd/dal/dc/bios/command_table.c    | 2730 +++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/command_table.h    |  117 +
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.c |  285 ++
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.h |   90 +
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.c |  484 ++
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.h |   34 +
 .../dc/bios/dce110/command_table_helper_dce110.c   |  366 ++
 .../dc/bios/dce110/command_table_helper_dce110.h   |   34 +
 drivers/gpu/drm/amd/dal/dc/calcs/Makefile          |   10 +
 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c | 3941 +++++++++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c        |  300 ++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c   | 1992 ++++++++
 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h   |   74 +
 drivers/gpu/drm/amd/dal/dc/core/dc.c               |  947 ++++
 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c  |   56 +
 drivers/gpu/drm/amd/dal/dc/core/dc_link.c          | 1645 +++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c      | 1121 +++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c       | 1728 +++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c     |  201 +
 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c      | 1243 +++++
 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c          |  116 +
 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c        |  188 +
 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c       |  123 +
 drivers/gpu/drm/amd/dal/dc/core/dc_target.c        |  548 +++
 drivers/gpu/drm/amd/dal/dc/dc.h                    |  466 ++
 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h         |  277 ++
 drivers/gpu/drm/amd/dal/dc/dc_ddc_types.h          |  129 +
 drivers/gpu/drm/amd/dal/dc/dc_types.h              |  935 ++++
 drivers/gpu/drm/amd/dal/dc/dce100/Makefile         |   23 +
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.c    |  360 ++
 .../drm/amd/dal/dc/dce100/dce100_hw_sequencer.h    |   36 +
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c    | 1135 +++++
 .../gpu/drm/amd/dal/dc/dce100/dce100_resource.h    |   43 +
 drivers/gpu/drm/amd/dal/dc/dce110/Makefile         |   15 +
 .../drm/amd/dal/dc/dce110/dce110_clock_source.c    | 1162 +++++
 .../drm/amd/dal/dc/dce110/dce110_clock_source.h    |   64 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.c  |  886 ++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_compressor.h  |   84 +
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c    | 1658 +++++++
 .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.h    |   36 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c     |   65 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h     |  100 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c  |  256 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c   |  872 ++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.c    | 1927 ++++++++
 .../drm/amd/dal/dc/dce110/dce110_link_encoder.h    |  156 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c   |  965 ++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h   |  117 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c     |  272 ++
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h     |  143 +
 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c |  904 ++++
 .../drm/amd/dal/dc/dce110/dce110_opp_formatter.c   |  610 +++
 .../gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c | 2474 ++++++++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c    | 1238 +++++
 .../gpu/drm/amd/dal/dc/dce110/dce110_resource.h    |   46 +
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.c  | 1123 +++++
 .../drm/amd/dal/dc/dce110/dce110_stream_encoder.h  |  122 +
 .../amd/dal/dc/dce110/dce110_timing_generator.c    | 1864 ++++++++
 .../amd/dal/dc/dce110/dce110_timing_generator.h    |  234 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.c   |   91 +
 .../gpu/drm/amd/dal/dc/dce110/dce110_transform.h   |   87 +
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.c |  851 ++++
 .../amd/dal/dc/dce110/dce110_transform_bit_depth.h |   51 +
 .../drm/amd/dal/dc/dce110/dce110_transform_gamut.c |  296 ++
 .../drm/amd/dal/dc/dce110/dce110_transform_scl.c   |  818 ++++
 .../drm/amd/dal/dc/dce110/dce110_transform_sclv.c  |  531 +++
 drivers/gpu/drm/amd/dal/dc/dm_helpers.h            |  103 +
 drivers/gpu/drm/amd/dal/dc/dm_services.h           |  468 ++
 drivers/gpu/drm/amd/dal/dc/dm_services_types.h     |  167 +
 drivers/gpu/drm/amd/dal/dc/gpio/Makefile           |   32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c |  882 ++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h |   46 +
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c |   81 +
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h |   32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c |  366 ++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h |   47 +
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.c   |  400 ++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.h   |   34 +
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c              |  290 ++
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h              |   38 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c  |   97 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h  |   34 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.c  |   65 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.h  |   32 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c  |  101 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h  |   35 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.c    |   41 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.h    |   34 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h             |   48 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c        |  279 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c     |  386 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h     |   57 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c           |  104 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h           |   60 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c       |   93 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h       |   71 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c          |  407 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h          |  129 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c      |   92 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h      |   47 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c      |   85 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h      |   79 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c           |   87 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h           |   45 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c     |   77 +
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h     |   50 +
 drivers/gpu/drm/amd/dal/dc/gpio/irq.c              |  180 +
 drivers/gpu/drm/amd/dal/dc/gpio/irq.h              |   42 +
 drivers/gpu/drm/amd/dal/dc/gpu/Makefile            |   22 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c    |   92 +
 .../gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h    |   63 +
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c |   90 +
 .../amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h |   33 +
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.c   |  968 ++++
 .../amd/dal/dc/gpu/dce110/display_clock_dce110.h   |   53 +
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c     |  205 +
 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h     |   82 +
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c     |  127 +
 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h     |   63 +
 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile         |   33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c     |  567 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h     |  119 +
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.c   |  788 +++
 .../amd/dal/dc/i2caux/dce110/aux_engine_dce110.h   |   56 +
 .../i2caux/dce110/i2c_generic_hw_engine_dce110.h   |   25 +
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c    |  954 ++++
 .../dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h    |   58 +
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c    |  172 +
 .../dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h    |   43 +
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c   |  266 ++
 .../drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h   |   39 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.c    |  112 +
 .../amd/dal/dc/i2caux/diagnostics/i2caux_diag.h    |   33 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h         |  129 +
 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c    |   67 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c     |  121 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h     |  113 +
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c  |  286 ++
 .../drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h  |   77 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c  |  246 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h  |   80 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c  |  614 +++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h  |   81 +
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c         |  529 ++
 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h         |  123 +
 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h   |  510 ++
 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h          |   64 +
 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h      |  176 +
 drivers/gpu/drm/amd/dal/dc/inc/compressor.h        |  140 +
 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h           |   54 +
 drivers/gpu/drm/amd/dal/dc/inc/core_status.h       |   46 +
 drivers/gpu/drm/amd/dal/dc/inc/core_types.h        |  357 ++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h       |  152 +
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h        |   56 +
 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h       |  118 +
 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h      |  126 +
 drivers/gpu/drm/amd/dal/dc/inc/ipp.h               |  106 +
 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h      |  138 +
 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h         |   68 +
 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h         |   83 +
 drivers/gpu/drm/amd/dal/dc/inc/opp.h               |  308 ++
 drivers/gpu/drm/amd/dal/dc/inc/resource.h          |   80 +
 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h    |   88 +
 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h  |  155 +
 drivers/gpu/drm/amd/dal/dc/inc/transform.h         |  217 +
 drivers/gpu/drm/amd/dal/dc/irq/Makefile            |   21 +
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.c |  389 ++
 .../drm/amd/dal/dc/irq/dce110/irq_service_dce110.h |   34 +
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c       |  177 +
 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h       |   85 +
 drivers/gpu/drm/amd/dal/dc/irq_types.h             |  199 +
 drivers/gpu/drm/amd/dal/dc/virtual/Makefile        |    9 +
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.c  |  133 +
 .../drm/amd/dal/dc/virtual/virtual_link_encoder.h  |   35 +
 .../amd/dal/dc/virtual/virtual_stream_encoder.c    |  124 +
 .../amd/dal/dc/virtual/virtual_stream_encoder.h    |   39 +
 .../amd/dal/include/adapter_service_interface.h    |  632 +++
 .../drm/amd/dal/include/adapter_service_types.h    |   71 +
 .../amd/dal/include/asic_capability_interface.h    |   58 +
 .../drm/amd/dal/include/asic_capability_types.h    |  134 +
 drivers/gpu/drm/amd/dal/include/audio_interface.h  |  184 +
 drivers/gpu/drm/amd/dal/include/audio_types.h      |  277 ++
 .../drm/amd/dal/include/bios_parser_interface.h    |   98 +
 .../gpu/drm/amd/dal/include/bios_parser_types.h    |  327 ++
 drivers/gpu/drm/amd/dal/include/dal_asic_id.h      |  117 +
 .../gpu/drm/amd/dal/include/dal_register_logger.h  |   43 +
 drivers/gpu/drm/amd/dal/include/dal_types.h        |  305 ++
 .../amd/dal/include/dc_clock_generator_interface.h |   77 +
 drivers/gpu/drm/amd/dal/include/dcs_types.h        |  742 +++
 drivers/gpu/drm/amd/dal/include/ddc_interface.h    |   74 +
 .../gpu/drm/amd/dal/include/ddc_service_types.h    |  191 +
 .../drm/amd/dal/include/display_clock_interface.h  |  186 +
 .../drm/amd/dal/include/display_path_interface.h   |  436 ++
 drivers/gpu/drm/amd/dal/include/dmcu_interface.h   |   87 +
 drivers/gpu/drm/amd/dal/include/dmcu_types.h       |  199 +
 drivers/gpu/drm/amd/dal/include/dpcd_defs.h        |  873 ++++
 .../gpu/drm/amd/dal/include/encoder_interface.h    |  278 ++
 drivers/gpu/drm/amd/dal/include/fixed31_32.h       |  389 ++
 drivers/gpu/drm/amd/dal/include/fixed32_32.h       |   82 +
 drivers/gpu/drm/amd/dal/include/gpio_interface.h   |   93 +
 .../drm/amd/dal/include/gpio_service_interface.h   |   81 +
 drivers/gpu/drm/amd/dal/include/gpio_types.h       |  337 ++
 drivers/gpu/drm/amd/dal/include/grph_csc_types.h   |   98 +
 .../drm/amd/dal/include/grph_object_ctrl_defs.h    |  593 +++
 drivers/gpu/drm/amd/dal/include/grph_object_defs.h |  328 ++
 drivers/gpu/drm/amd/dal/include/grph_object_id.h   |  277 ++
 .../drm/amd/dal/include/hw_sequencer_interface.h   |  388 ++
 .../gpu/drm/amd/dal/include/hw_sequencer_types.h   |  304 ++
 drivers/gpu/drm/amd/dal/include/i2caux_interface.h |  104 +
 drivers/gpu/drm/amd/dal/include/irq_interface.h    |   53 +
 .../drm/amd/dal/include/irq_service_interface.h    |   55 +
 .../drm/amd/dal/include/link_service_interface.h   |  202 +
 .../gpu/drm/amd/dal/include/link_service_types.h   |  427 ++
 drivers/gpu/drm/amd/dal/include/logger_interface.h |  153 +
 drivers/gpu/drm/amd/dal/include/logger_types.h     |  356 ++
 drivers/gpu/drm/amd/dal/include/scaler_types.h     |  196 +
 drivers/gpu/drm/amd/dal/include/set_mode_types.h   |  142 +
 drivers/gpu/drm/amd/dal/include/signal_types.h     |   59 +
 drivers/gpu/drm/amd/dal/include/vector.h           |  150 +
 drivers/gpu/drm/amd/dal/include/video_csc_types.h  |  135 +
 .../gpu/drm/amd/dal/include/video_gamma_types.h    |   57 +
 294 files changed, 93968 insertions(+), 48 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/dal/Kconfig
 create mode 100644 drivers/gpu/drm/amd/dal/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/dce110/hw_ctx_adapter_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/diagnostics/hw_ctx_adapter_service_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/hw_ctx_adapter_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/adapter/wireless_data_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/carrizo_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/asic_capability/tonga_asic_capability.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/audio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/dce110/hw_ctx_audio_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/audio/hw_ctx_audio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/conversion.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt31_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/fixpt32_32.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/grph_object_id.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/register_logger.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/signal_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/basics/vector.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bandwidth_calcs.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/bw_fixed.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/calcs/scaler_filter.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_target.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_ddc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_cursor.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_ipp_gamma.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_csc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_formatter.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_opp_regamma.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_bit_depth.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_gamut.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_scl.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_transform_sclv.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_helpers.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dc_clock_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/dc_clock_gating_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/display_clock_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/display_clock.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/divider_range.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/aux_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/aux_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_generic_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_hw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2c_sw_engine_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/dce110/i2caux_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/diagnostics/i2caux_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/engine_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_generic_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_hw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2c_sw_engine.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/i2caux/i2caux.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_status.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/dce110/irq_service_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq/irq_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/virtual/virtual_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_asic_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_register_logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_clock_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_path_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed31_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed32_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/i2caux_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/scaler_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/signal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/vector.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_gamma_types.h

-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 87+ messages in thread

* [PATCH v3 01/26] drm/amd/dal: Add dal headers
  2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
@ 2016-02-29 21:56   ` Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-29 21:56 UTC (permalink / raw)
  To: dri-devel

v3 changes:
- expose I2C through i2c_adapter and route dal i2c calls through this

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dal_services.h             | 266 ++++++
 drivers/gpu/drm/amd/dal/dal_services_types.h       |  62 ++
 drivers/gpu/drm/amd/dal/dc/dc.h                    | 466 ++++++++++
 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h         | 277 ++++++
 drivers/gpu/drm/amd/dal/dc/dc_ddc_types.h          | 129 +++
 drivers/gpu/drm/amd/dal/dc/dc_types.h              | 935 +++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/dm_helpers.h            | 103 +++
 drivers/gpu/drm/amd/dal/dc/dm_services.h           | 485 +++++++++++
 drivers/gpu/drm/amd/dal/dc/dm_services_types.h     | 167 ++++
 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h   | 510 +++++++++++
 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h          |  64 ++
 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h      | 176 ++++
 drivers/gpu/drm/amd/dal/dc/inc/compressor.h        | 140 +++
 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h           |  54 ++
 drivers/gpu/drm/amd/dal/dc/inc/core_status.h       |  46 +
 drivers/gpu/drm/amd/dal/dc/inc/core_types.h        | 357 ++++++++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h       | 152 ++++
 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h        |  56 ++
 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h       | 118 +++
 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h      | 126 +++
 drivers/gpu/drm/amd/dal/dc/inc/ipp.h               | 106 +++
 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h      | 138 +++
 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h         |  68 ++
 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h         |  83 ++
 drivers/gpu/drm/amd/dal/dc/inc/opp.h               | 308 +++++++
 drivers/gpu/drm/amd/dal/dc/inc/resource.h          |  80 ++
 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h    |  88 ++
 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h  | 155 ++++
 drivers/gpu/drm/amd/dal/dc/inc/transform.h         | 217 +++++
 drivers/gpu/drm/amd/dal/dc/irq_types.h             | 199 +++++
 .../amd/dal/include/adapter_service_interface.h    | 632 ++++++++++++++
 .../drm/amd/dal/include/adapter_service_types.h    |  71 ++
 .../amd/dal/include/asic_capability_interface.h    |  58 ++
 .../drm/amd/dal/include/asic_capability_types.h    | 134 +++
 drivers/gpu/drm/amd/dal/include/audio_interface.h  | 184 ++++
 drivers/gpu/drm/amd/dal/include/audio_types.h      | 277 ++++++
 .../drm/amd/dal/include/bios_parser_interface.h    |  98 +++
 .../gpu/drm/amd/dal/include/bios_parser_types.h    | 327 +++++++
 drivers/gpu/drm/amd/dal/include/dal_asic_id.h      | 117 +++
 .../gpu/drm/amd/dal/include/dal_register_logger.h  |  43 +
 drivers/gpu/drm/amd/dal/include/dal_types.h        | 305 +++++++
 .../amd/dal/include/dc_clock_generator_interface.h |  77 ++
 drivers/gpu/drm/amd/dal/include/dcs_types.h        | 742 ++++++++++++++++
 drivers/gpu/drm/amd/dal/include/ddc_interface.h    |  74 ++
 .../gpu/drm/amd/dal/include/ddc_service_types.h    | 191 +++++
 .../drm/amd/dal/include/display_clock_interface.h  | 186 ++++
 .../drm/amd/dal/include/display_path_interface.h   | 436 ++++++++++
 drivers/gpu/drm/amd/dal/include/dmcu_interface.h   |  87 ++
 drivers/gpu/drm/amd/dal/include/dmcu_types.h       | 199 +++++
 drivers/gpu/drm/amd/dal/include/dpcd_defs.h        | 873 +++++++++++++++++++
 .../gpu/drm/amd/dal/include/encoder_interface.h    | 278 ++++++
 drivers/gpu/drm/amd/dal/include/fixed31_32.h       | 389 +++++++++
 drivers/gpu/drm/amd/dal/include/fixed32_32.h       |  82 ++
 drivers/gpu/drm/amd/dal/include/gpio_interface.h   |  93 ++
 .../drm/amd/dal/include/gpio_service_interface.h   |  81 ++
 drivers/gpu/drm/amd/dal/include/gpio_types.h       | 337 ++++++++
 drivers/gpu/drm/amd/dal/include/grph_csc_types.h   |  98 +++
 .../drm/amd/dal/include/grph_object_ctrl_defs.h    | 593 +++++++++++++
 drivers/gpu/drm/amd/dal/include/grph_object_defs.h | 328 ++++++++
 drivers/gpu/drm/amd/dal/include/grph_object_id.h   | 277 ++++++
 .../drm/amd/dal/include/hw_sequencer_interface.h   | 388 +++++++++
 .../gpu/drm/amd/dal/include/hw_sequencer_types.h   | 304 +++++++
 drivers/gpu/drm/amd/dal/include/i2caux_interface.h | 104 +++
 drivers/gpu/drm/amd/dal/include/irq_interface.h    |  53 ++
 .../drm/amd/dal/include/irq_service_interface.h    |  55 ++
 .../drm/amd/dal/include/link_service_interface.h   | 202 +++++
 .../gpu/drm/amd/dal/include/link_service_types.h   | 427 ++++++++++
 drivers/gpu/drm/amd/dal/include/logger_interface.h | 153 ++++
 drivers/gpu/drm/amd/dal/include/logger_types.h     | 356 ++++++++
 drivers/gpu/drm/amd/dal/include/scaler_types.h     | 196 +++++
 drivers/gpu/drm/amd/dal/include/set_mode_types.h   | 142 ++++
 drivers/gpu/drm/amd/dal/include/signal_types.h     |  59 ++
 drivers/gpu/drm/amd/dal/include/vector.h           | 150 ++++
 drivers/gpu/drm/amd/dal/include/video_csc_types.h  | 135 +++
 .../gpu/drm/amd/dal/include/video_gamma_types.h    |  57 ++
 75 files changed, 16579 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dal_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_ddc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_helpers.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/dm_services_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/compressor.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_status.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/core_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/ipp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/opp.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/resource.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/transform.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/irq_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/adapter_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/asic_capability_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/audio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/bios_parser_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_asic_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_register_logger.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dcs_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/ddc_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_clock_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/display_path_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dmcu_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/dpcd_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/encoder_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed31_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/fixed32_32.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/gpio_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_defs.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/grph_object_id.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/i2caux_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/irq_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/link_service_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_interface.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/logger_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/scaler_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/set_mode_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/signal_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/vector.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_csc_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/include/video_gamma_types.h

diff --git a/drivers/gpu/drm/amd/dal/dal_services.h b/drivers/gpu/drm/amd/dal/dal_services.h
new file mode 100644
index 000000000000..398e4e559455
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dal_services.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SERVICES_H__
+#define __DAL_SERVICES_H__
+
+/* DC headers*/
+#include "dc/dc_services.h"
+
+#include "dal_power_interface_types.h"
+
+#include "irq_types.h"
+#include "include/dal_types.h"
+
+/* TODO: investigate if it can be removed. */
+/* Undefine DEPRECATED because it conflicts with printk.h */
+#undef DEPRECATED
+
+/*
+ *
+ * interrupt services to register and unregister handlers
+ *
+ */
+
+/* the timer "interrupt" current implementation supports only
+'one-shot' type, and LOW level (asynchronous) context */
+void dal_register_timer_interrupt(
+	struct dc_context *ctx,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *handler_args);
+
+/*
+ *
+ * kernel memory manipulation
+ *
+ */
+
+/* Reallocate memory. The contents will remain unchanged.*/
+void *dc_service_realloc(struct dc_context *ctx, const void *ptr, uint32_t size);
+
+void dc_service_memmove(void *dst, const void *src, uint32_t size);
+
+void dc_service_memset(void *p, int32_t c, uint32_t count);
+
+int32_t dal_memcmp(const void *p1, const void *p2, uint32_t count);
+
+int32_t dal_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count);
+
+/*
+ *
+ * GPU registers access
+ *
+ */
+static inline uint32_t dal_read_reg(
+	const struct dc_context *ctx,
+	uint32_t address)
+{
+	uint32_t value = cgs_read_register(ctx->cgs_device, address);
+
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s 0x%x 0x%x\n", __func__, address, value);
+	}
+#endif
+	return value;
+}
+
+static inline uint32_t get_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (mask & reg_value) >> shift;
+}
+
+#define get_reg_field_value(reg_value, reg_name, reg_field)\
+	get_reg_field_value_ex(\
+		(reg_value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+static inline uint32_t set_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (reg_value & ~mask) | (mask & (value << shift));
+}
+
+#define set_reg_field_value(reg_value, value, reg_name, reg_field)\
+	(reg_value) = set_reg_field_value_ex(\
+		(reg_value),\
+		(value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+static inline void dal_write_reg(
+	const struct dc_context *ctx,
+	uint32_t address,
+	uint32_t value)
+{
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s 0x%x 0x%x\n", __func__, address, value);
+	}
+#endif
+	cgs_write_register(ctx->cgs_device, address, value);
+}
+
+static inline uint32_t dal_read_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index)
+{
+	return cgs_read_ind_register(ctx->cgs_device,addr_space,index);
+}
+
+static inline void dal_write_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index,
+	uint32_t value)
+{
+	cgs_write_ind_register(ctx->cgs_device,addr_space,index,value);
+}
+
+enum platform_method {
+	PM_GET_AVAILABLE_METHODS = 1 << 0,
+	PM_GET_LID_STATE = 1 << 1,
+	PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2
+};
+
+struct platform_info_params {
+	enum platform_method method;
+	void *data;
+};
+
+struct platform_info_brightness_caps {
+	uint8_t ac_level_percentage;
+	uint8_t dc_level_percentage;
+};
+
+struct platform_info_ext_brightness_caps {
+	struct platform_info_brightness_caps basic_caps;
+	struct data_point {
+		uint8_t luminance;
+		uint8_t	signal_level;
+	} data_points[99];
+
+	uint8_t	data_points_num;
+	uint8_t	min_input_signal;
+	uint8_t	max_input_signal;
+};
+
+bool dal_get_platform_info(
+	struct dc_context *ctx,
+	struct platform_info_params *params);
+
+
+static inline uint32_t dal_bios_cmd_table_para_revision(
+	struct dc_context *ctx,
+	uint32_t index)
+{
+	uint8_t frev;
+	uint8_t crev;
+
+	if (cgs_atom_get_cmd_table_revs(
+			ctx->cgs_device,
+			index,
+			&frev,
+			&crev) != 0)
+		return 0;
+
+	return crev;
+}
+
+/* Calls to notification */
+
+/* Notify display manager for hotplug event */
+void dal_notify_hotplug(
+	struct dc_context *ctx,
+	uint32_t display_index,
+	bool is_connected);
+
+
+void dal_notify_setmode_complete(
+	struct dc_context *ctx,
+	uint32_t h_total,
+	uint32_t v_total,
+	uint32_t h_active,
+	uint32_t v_active,
+	uint32_t pix_clk_in_khz);
+
+/* End of notification calls */
+
+/*
+ *
+ * Delay functions.
+ *
+ *
+ */
+
+/* Following the guidance:
+ * https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
+ *
+ * This is a busy wait for nano seconds and should be used only for
+ * extremely short ranges
+ */
+void dal_delay_in_nanoseconds(uint32_t nanoseconds);
+
+
+/*
+ *
+ * atombios services
+ *
+ */
+
+bool dal_exec_bios_cmd_table(
+	struct dc_context *ctx,
+	uint32_t index,
+	void *params);
+
+/*
+ *
+ * print-out services
+ *
+ */
+#define dal_log_to_buffer(buffer, size, fmt, args)\
+	vsnprintf(buffer, size, fmt, args)
+
+long dal_get_pid(void);
+long dal_get_tgid(void);
+
+/*
+ *
+ * general debug capabilities
+ *
+ */
+
+#endif /* __DAL_SERVICES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dal_services_types.h b/drivers/gpu/drm/amd/dal/dal_services_types.h
new file mode 100644
index 000000000000..89c73c651d09
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dal_services_types.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SERVICES_TYPES_H__
+#define __DAL_SERVICES_TYPES_H__
+
+#define INVALID_DISPLAY_INDEX 0xffffffff
+
+#if defined __KERNEL__
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <drm/drmP.h>
+
+#include "cgs_linux.h"
+
+#if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU)
+#define BIGENDIAN_CPU
+#elif defined(__LITTLE_ENDIAN) && !defined(LITTLEENDIAN_CPU)
+#define LITTLEENDIAN_CPU
+#endif
+
+#undef READ
+#undef WRITE
+#undef FRAME_SIZE
+
+#define dal_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__)
+
+#define dal_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__)
+
+#define dal_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__)
+
+#define dal_vlog(fmt, args) vprintk(fmt, args)
+
+#define dal_min(x, y) min(x, y)
+#define dal_max(x, y) max(x, y)
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/dc.h b/drivers/gpu/drm/amd/dal/dc/dc.h
new file mode 100644
index 000000000000..46f24ec9228a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc.h
@@ -0,0 +1,466 @@
+/*
+ * Copyright 2012-14 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DC_INTERFACE_H_
+#define DC_INTERFACE_H_
+
+#include "dc_types.h"
+#include "dal_types.h"
+#include "audio_types.h"
+#include "logger_types.h"
+
+#define MAX_SINKS_PER_LINK 4
+
+/*******************************************************************************
+ * Display Core Interfaces
+ ******************************************************************************/
+struct dc_init_data {
+	struct dc_context *ctx;
+	struct adapter_service *adapter_srv;
+	uint8_t num_virtual_links;
+};
+
+struct dc_caps {
+    uint32_t max_targets;
+    uint32_t max_links;
+    uint32_t max_audios;
+};
+
+void dc_get_caps(const struct dc *dc, struct dc_caps *caps);
+
+struct dc *dc_create(const struct dal_init_data *init_params);
+void dc_destroy(struct dc **dc);
+
+/*******************************************************************************
+ * Surface Interfaces
+ ******************************************************************************/
+
+struct dc_surface {
+	bool visible;
+	bool flip_immediate;
+	struct dc_plane_address address;
+
+	struct scaling_taps scaling_quality;
+	struct rect src_rect;
+	struct rect dst_rect;
+	struct rect clip_rect;
+
+	union plane_size plane_size;
+	struct dc_tiling_info tiling_info;
+	struct plane_colorimetry colorimetry;
+
+	enum surface_pixel_format format;
+	enum dc_rotation_angle rotation;
+	enum plane_stereo_format stereo_format;
+
+	struct gamma_ramp gamma_correction; /* deprecated */
+	struct dc_gamma_ramp gamma;
+};
+
+/*
+ * This structure is filled in by dc_surface_get_status and contains
+ * the last requested address and the currently active address so the called
+ * can determine if there are any outstanding flips
+ */
+struct dc_surface_status {
+	struct dc_plane_address requested_address;
+	struct dc_plane_address current_address;
+	const struct dc_target *dc_target;
+};
+
+/*
+ * Create a new surface with default parameters;
+ */
+struct dc_surface *dc_create_surface(const struct dc *dc);
+const struct dc_surface_status* dc_surface_get_status(
+						struct dc_surface *dc_surface);
+
+void dc_surface_retain(const struct dc_surface *dc_surface);
+void dc_surface_release(const struct dc_surface *dc_surface);
+
+/*
+ * This structure holds a surface address.  There could be multiple addresses
+ * in cases such as Stereo 3D, Planar YUV, etc.  Other per-flip attributes such
+ * as frame durations and DCC format can also be set.
+ */
+struct dc_flip_addrs {
+	struct dc_plane_address address;
+	bool flip_immediate;
+	/* TODO: DCC format info */
+	/* TODO: add flip duration for FreeSync */
+};
+
+/*
+ * Optimized flip address update function.
+ *
+ * After this call:
+ *   Surface addresses and flip attributes are programmed.
+ *   Surface flip occur at next configured time (h_sync or v_sync flip)
+ */
+void dc_flip_surface_addrs(struct dc* dc,
+		const struct dc_surface *const surfaces[],
+		struct dc_flip_addrs flip_addrs[],
+		uint32_t count);
+
+/*
+ * Set up surface attributes and associate to a target
+ * The surfaces parameter is an absolute set of all surface active for the target.
+ * If no surfaces are provided, the target will be blanked; no memory read.
+ * Any flip related attribute changes must be done through this interface.
+ *
+ * After this call:
+ *   Surfaces attributes are programmed and configured to be composed into target.
+ *   This does not trigger a flip.  No surface address is programmed.
+ */
+bool dc_commit_surfaces_to_target(
+		struct dc *dc,
+		struct dc_surface *dc_surfaces[],
+		uint8_t surface_count,
+		struct dc_target *dc_target);
+
+/*******************************************************************************
+ * Target Interfaces
+ ******************************************************************************/
+#define MAX_STREAM_NUM 1
+
+struct dc_target {
+	uint8_t stream_count;
+	const struct dc_stream *streams[MAX_STREAM_NUM];
+};
+
+/*
+ * Target status is returned from dc_target_get_status in order to get the
+ * the IRQ source, current frame counter and currently attached surfaces.
+ */
+struct dc_target_status {
+	enum dc_irq_source page_flip_src;
+	enum dc_irq_source v_update_src;
+	uint32_t cur_frame_count;
+	const struct dc_surface *surfaces[MAX_SURFACE_NUM];
+	uint8_t surface_count;
+};
+
+struct dc_target *dc_create_target_for_streams(
+		struct dc_stream *dc_streams[],
+		uint8_t stream_count);
+
+/*
+ * Get the current target status.
+ */
+const struct dc_target_status *dc_target_get_status(
+					const struct dc_target* dc_target);
+
+void dc_target_retain(struct dc_target *dc_target);
+void dc_target_release(struct dc_target *dc_target);
+void dc_target_log(
+	const struct dc_target *dc_target,
+	struct dal_logger *dal_logger,
+	enum log_major log_major,
+	enum log_minor log_minor);
+
+uint8_t dc_get_current_target_count(const struct dc *dc);
+struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i);
+
+bool dc_target_is_connected_to_sink(
+		const struct dc_target *dc_target,
+		const struct dc_sink *dc_sink);
+
+uint8_t dc_target_get_link_index(const struct dc_target *dc_target);
+uint8_t dc_target_get_controller_id(const struct dc_target *dc_target);
+
+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target);
+enum dc_irq_source dc_target_get_irq_src(
+	const struct dc_target *dc_target, const enum irq_type irq_type);
+
+void dc_target_enable_memory_requests(struct dc_target *target);
+void dc_target_disable_memory_requests(struct dc_target *target);
+
+/*
+ * Structure to store surface/target associations for validation
+ */
+struct dc_validation_set {
+	const struct dc_target *target;
+	const struct dc_surface *surfaces[4];
+	uint8_t surface_count;
+};
+
+/*
+ * This function takes a set of resources and checks that they are cofunctional.
+ *
+ * After this call:
+ *   No hardware is programmed for call.  Only validation is done.
+ */
+bool dc_validate_resources(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count);
+
+/*
+ * Set up streams and links associated to targets to drive sinks
+ * The targets parameter is an absolute set of all active targets.
+ *
+ * After this call:
+ *   Phy, Encoder, Timing Generator are programmed and enabled.
+ *   New targets are enabled with blank stream; no memory read.
+ */
+bool dc_commit_targets(
+		struct dc *dc,
+		struct dc_target *targets[],
+		uint8_t target_count);
+
+/*******************************************************************************
+ * Stream Interfaces
+ ******************************************************************************/
+struct dc_stream {
+	const struct dc_sink *sink;
+	struct dc_crtc_timing timing;
+
+	struct rect src; /* viewport in target space*/
+	struct rect dst; /* stream addressable area */
+
+	struct audio_info audio_info;
+
+	/* TODO: dithering */
+	/* TODO: transfer function (CSC/regamma/gamut remap) */
+	/* TODO: custom INFO packets */
+	/* TODO: DRR/Freesync parameters */
+	/* TODO: ABM info (DMCU) */
+	/* TODO: PSR info */
+	/* TODO: CEA VIC */
+};
+
+/**
+ * Create a new default stream for the requested sink
+ */
+struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink);
+
+void dc_stream_retain(struct dc_stream *dc_stream);
+void dc_stream_release(struct dc_stream *dc_stream);
+
+void dc_update_stream(const struct dc_stream *dc_stream,
+		struct rect *src, struct rect *dst);
+
+/*******************************************************************************
+ * Link Interfaces
+ ******************************************************************************/
+
+/*
+ * A link contains one or more sinks and their connected status.
+ * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported.
+ */
+struct dc_link {
+	const struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK];
+	unsigned int sink_count;
+	const struct dc_sink *local_sink;
+	unsigned int link_index;
+	enum dc_connection_type type;
+	enum signal_type connector_signal;
+	enum dc_irq_source irq_source_hpd;
+	enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse  */
+};
+
+/*
+ * Return an enumerated dc_link.  dc_link order is constant and determined at
+ * boot time.  They cannot be created or destroyed.
+ * Use dc_get_caps() to get number of links.
+ */
+const struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index);
+
+/* Return id of physical connector represented by a dc_link at link_index.*/
+const struct graphics_object_id dc_get_link_id_at_index(
+		struct dc *dc, uint32_t link_index);
+
+/* Set backlight level of an embedded panel (eDP, LVDS). */
+bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level);
+
+/* Request DC to detect if there is a Panel connected.
+ * boot - If this call is during initial boot.
+ * Return false for any type of detection failure or MST detection
+ * true otherwise. True meaning further action is required (status update
+ * and OS notification).
+ */
+bool dc_link_detect(const struct dc_link *dc_link, bool boot);
+
+/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt).
+ * Return:
+ * true - Downstream port status changed. DM should call DC to do the
+ * detection.
+ * false - no change in Downstream port status. No further action required
+ * from DM. */
+bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link);
+
+bool dc_link_add_remote_sink(const struct dc_link *link, struct dc_sink *sink);
+
+void dc_link_remove_remote_sink(
+	const struct dc_link *link,
+	const struct dc_sink *sink);
+
+/* Used by diagnostics for virtual link at the moment */
+void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink);
+
+/*******************************************************************************
+ * Sink Interfaces - A sink corresponds to a display output device
+ ******************************************************************************/
+
+/*
+ * The sink structure contains EDID and other display device properties
+ */
+struct dc_sink {
+	enum signal_type sink_signal;
+	struct dc_edid dc_edid; /* raw edid */
+	struct dc_edid_caps edid_caps; /* parse display caps */
+};
+
+void dc_sink_retain(const struct dc_sink *sink);
+void dc_sink_release(const struct dc_sink *sink);
+
+const struct audio **dc_get_audios(struct dc *dc);
+
+struct dc_sink_init_data {
+	enum signal_type sink_signal;
+	const struct dc_link *link;
+	uint32_t dongle_max_pix_clk;
+	bool converter_disable_audio;
+};
+
+struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params);
+
+
+/*******************************************************************************
+ * Cursor interfaces - To manages the cursor within a target
+ ******************************************************************************/
+/* TODO: Deprecated once we switch to dc_set_cursor_position */
+bool dc_target_set_cursor_attributes(
+	struct dc_target *dc_target,
+	const struct dc_cursor_attributes *attributes);
+
+bool dc_target_set_cursor_position(
+	struct dc_target *dc_target,
+	const struct dc_cursor_position *position);
+
+/* Newer interfaces  */
+struct dc_cursor {
+	struct dc_plane_address address;
+	struct dc_cursor_attributes attributes;
+};
+
+/*
+ * Create a new cursor with default values for a given target.
+ */
+struct dc_cursor *dc_create_cursor_for_target(
+		const struct dc *dc,
+		struct dc_target *dc_target);
+
+/**
+ * Commit cursor attribute changes such as pixel format and dimensions and
+ * surface address.
+ *
+ * After this call:
+ *   Cursor address and format is programmed to the new values.
+ *   Cursor position is unmodified.
+ */
+bool dc_commit_cursor(
+		const struct dc *dc,
+		struct dc_cursor *cursor);
+
+/*
+ * Optimized cursor position update
+ *
+ * After this call:
+ *   Cursor position will be programmed as well as enable/disable bit.
+ */
+bool dc_set_cursor_position(
+		const struct dc *dc,
+		struct dc_cursor *cursor,
+		struct dc_cursor_position *pos);
+
+
+
+/*******************************************************************************
+ * Interrupt interfaces
+ ******************************************************************************/
+enum dc_irq_source dc_interrupt_to_irq_source(
+		struct dc *dc,
+		uint32_t src_id,
+		uint32_t ext_id);
+void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable);
+void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src);
+const enum dc_irq_source dc_get_hpd_irq_source_at_index(
+		struct dc *dc, uint32_t link_index);
+const struct dc_target *dc_get_target_on_irq_source(
+		const struct dc *dc,
+		enum dc_irq_source src);
+
+
+/*******************************************************************************
+ * Power Interfaces
+ ******************************************************************************/
+
+void dc_set_power_state(
+		struct dc *dc,
+		enum dc_acpi_cm_power_state power_state,
+		enum dc_video_power_state video_power_state);
+void dc_resume(const struct dc *dc);
+
+/*******************************************************************************
+ * DDC Interfaces
+ ******************************************************************************/
+
+const struct ddc_service *dc_get_ddc_at_index(
+		struct dc *dc, uint32_t link_index);
+
+/*
+ * DPCD access interfaces
+ */
+
+bool dc_read_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size);
+
+bool dc_write_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		const uint8_t *data,
+	uint32_t size);
+
+bool dc_submit_i2c(
+		struct dc *dc,
+		uint32_t link_index,
+		struct i2c_command *cmd);
+
+uint8_t dc_get_dig_index(const struct dc_stream *stream);
+
+enum signal_type  dc_get_display_signal(
+		const struct dc_stream *stream);
+
+enum gpio_ddc_line dc_get_ddc_line(
+		const struct dc_stream *stream);
+
+
+#endif /* DC_INTERFACE_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dc_bios_types.h b/drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
new file mode 100644
index 000000000000..53f047788b31
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc_bios_types.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DC_BIOS_TYPES_H
+#define DC_BIOS_TYPES_H
+
+/******************************************************************************
+ * Interface file for VBIOS implementations.
+ *
+ * The default implementation is inside DC.
+ * Display Manager (which instantiates DC) has the option to supply it's own
+ * (external to DC) implementation of VBIOS, which will be called by DC, using
+ * this interface.
+ * (The intended use is Diagnostics, but other uses may appear.)
+ *****************************************************************************/
+
+#include "include/bios_parser_types.h"
+
+
+struct dc_vbios_funcs {
+	uint8_t (*get_connectors_number)(struct dc_bios *bios);
+
+	void (*power_down)(struct dc_bios *bios);
+	void (*power_up)(struct dc_bios *bios);
+
+	uint8_t (*get_encoders_number)(struct dc_bios *bios);
+	uint32_t (*get_oem_ddc_lines_number)(struct dc_bios *bios);
+
+	struct graphics_object_id (*get_encoder_id)(
+		struct dc_bios *bios,
+		uint32_t i);
+	struct graphics_object_id (*get_connector_id)(
+		struct dc_bios *bios,
+		uint8_t connector_index);
+	uint32_t (*get_src_number)(
+		struct dc_bios *bios,
+		struct graphics_object_id id);
+	uint32_t (*get_dst_number)(
+		struct dc_bios *bios,
+		struct graphics_object_id id);
+
+	uint32_t (*get_gpio_record)(
+		struct dc_bios *dcb,
+		struct graphics_object_id id,
+		struct bp_gpio_cntl_info *gpio_record,
+		uint32_t record_size);
+
+	enum bp_result (*get_src_obj)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id, uint32_t index,
+		struct graphics_object_id *src_object_id);
+	enum bp_result (*get_dst_obj)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id, uint32_t index,
+		struct graphics_object_id *dest_object_id);
+	enum bp_result (*get_oem_ddc_info)(
+		struct dc_bios *bios,
+		uint32_t index,
+		struct graphics_object_i2c_info *info);
+
+	enum bp_result (*get_i2c_info)(
+		struct dc_bios *dcb,
+		struct graphics_object_id id,
+		struct graphics_object_i2c_info *info);
+
+	enum bp_result (*get_voltage_ddc_info)(
+		struct dc_bios *bios,
+		uint32_t index,
+		struct graphics_object_i2c_info *info);
+	enum bp_result (*get_thermal_ddc_info)(
+		struct dc_bios *bios,
+		uint32_t i2c_channel_id,
+		struct graphics_object_i2c_info *info);
+	enum bp_result (*get_hpd_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id id,
+		struct graphics_object_hpd_info *info);
+	enum bp_result (*get_device_tag)(
+		struct dc_bios *bios,
+		struct graphics_object_id connector_object_id,
+		uint32_t device_tag_index,
+		struct connector_device_tag_info *info);
+	enum bp_result (*get_firmware_info)(
+		struct dc_bios *bios,
+		struct firmware_info *info);
+	enum bp_result (*get_spread_spectrum_info)(
+		struct dc_bios *bios,
+		enum as_signal_type signal,
+		uint32_t index,
+		struct spread_spectrum_info *ss_info);
+	uint32_t (*get_ss_entry_number)(
+		struct dc_bios *bios,
+		enum as_signal_type signal);
+	enum bp_result (*get_embedded_panel_info)(
+		struct dc_bios *bios,
+		struct embedded_panel_info *info);
+	enum bp_result (*enum_embedded_panel_patch_mode)(
+		struct dc_bios *bios,
+		uint32_t index,
+		struct embedded_panel_patch_mode *mode);
+	enum bp_result (*get_gpio_pin_info)(
+		struct dc_bios *bios,
+		uint32_t gpio_id,
+		struct gpio_pin_info *info);
+	enum bp_result (*get_faked_edid_len)(
+		struct dc_bios *bios,
+		uint32_t *len);
+	enum bp_result (*get_faked_edid_buf)(
+		struct dc_bios *bios,
+		uint8_t *buff,
+		uint32_t len);
+	enum bp_result (*get_encoder_cap_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id,
+		struct bp_encoder_cap_info *info);
+	enum bp_result (*get_din_connector_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id id,
+		struct din_connector_info *info);
+
+	bool (*is_lid_open)(
+		struct dc_bios *bios);
+	bool (*is_lid_status_changed)(
+		struct dc_bios *bios);
+	bool (*is_display_config_changed)(
+		struct dc_bios *bios);
+	bool (*is_accelerated_mode)(
+		struct dc_bios *bios);
+	void (*set_scratch_lcd_scale)(
+		struct dc_bios *bios,
+		enum lcd_scale scale);
+	enum lcd_scale  (*get_scratch_lcd_scale)(
+		struct dc_bios *bios);
+	void (*get_bios_event_info)(
+		struct dc_bios *bios,
+		struct bios_event_info *info);
+	void (*update_requested_backlight_level)(
+		struct dc_bios *bios,
+		uint32_t backlight_8bit);
+	uint32_t (*get_requested_backlight_level)(
+		struct dc_bios *bios);
+	void (*take_backlight_control)(
+		struct dc_bios *bios,
+		bool cntl);
+	bool (*is_active_display)(
+		struct dc_bios *bios,
+		enum signal_type signal,
+		const struct connector_device_tag_info *device_tag);
+	enum controller_id (*get_embedded_display_controller_id)(
+		struct dc_bios *bios);
+	uint32_t (*get_embedded_display_refresh_rate)(
+		struct dc_bios *bios);
+	void (*set_scratch_connected)(
+		struct dc_bios *bios,
+		struct graphics_object_id connector_id,
+		bool connected,
+		const struct connector_device_tag_info *device_tag);
+	void (*prepare_scratch_active_and_requested)(
+		struct dc_bios *bios,
+		enum controller_id controller_id,
+		enum signal_type signal,
+		const struct connector_device_tag_info *device_tag);
+	void (*set_scratch_active_and_requested)(
+		struct dc_bios *bios);
+	void (*set_scratch_critical_state)(
+		struct dc_bios *bios,
+		bool state);
+	void (*set_scratch_acc_mode_change)(
+		struct dc_bios *bios);
+
+	bool (*is_device_id_supported)(
+		struct dc_bios *bios,
+		struct device_id id);
+
+	/* COMMANDS */
+
+	enum bp_result (*encoder_control)(
+		struct dc_bios *bios,
+		struct bp_encoder_control *cntl);
+	enum bp_result (*transmitter_control)(
+		struct dc_bios *bios,
+		struct bp_transmitter_control *cntl);
+	enum bp_result (*crt_control)(
+		struct dc_bios *bios,
+		enum engine_id engine_id,
+		bool enable,
+		uint32_t pixel_clock);
+	enum bp_result (*enable_crtc)(
+		struct dc_bios *bios,
+		enum controller_id id,
+		bool enable);
+	enum bp_result (*adjust_pixel_clock)(
+		struct dc_bios *bios,
+		struct bp_adjust_pixel_clock_parameters *bp_params);
+	enum bp_result (*set_pixel_clock)(
+		struct dc_bios *bios,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*set_dce_clock)(
+		struct dc_bios *bios,
+		struct bp_set_dce_clock_parameters *bp_params);
+	enum bp_result (*enable_spread_spectrum_on_ppll)(
+		struct dc_bios *bios,
+		struct bp_spread_spectrum_parameters *bp_params,
+		bool enable);
+	enum bp_result (*program_crtc_timing)(
+		struct dc_bios *bios,
+		struct bp_hw_crtc_timing_parameters *bp_params);
+	enum bp_result (*blank_crtc)(
+		struct dc_bios *bios,
+		struct bp_blank_crtc_parameters *bp_params,
+		bool blank);
+	enum bp_result (*set_overscan)(
+		struct dc_bios *bios,
+		struct bp_hw_crtc_overscan_parameters *bp_params);
+	enum bp_result (*crtc_source_select)(
+		struct dc_bios *bios,
+		struct bp_crtc_source_select *bp_params);
+	enum bp_result (*program_display_engine_pll)(
+		struct dc_bios *bios,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*get_divider_for_target_display_clock)(
+		struct dc_bios *bios,
+		struct bp_display_clock_parameters *bp_params);
+	enum signal_type (*dac_load_detect)(
+		struct dc_bios *bios,
+		struct graphics_object_id encoder,
+		struct graphics_object_id connector,
+		enum signal_type display_signal);
+	enum bp_result (*enable_memory_requests)(
+		struct dc_bios *bios,
+		enum controller_id controller_id,
+		bool enable);
+	enum bp_result (*external_encoder_control)(
+		struct dc_bios *bios,
+		struct bp_external_encoder_control *cntl);
+	enum bp_result (*enable_disp_power_gating)(
+		struct dc_bios *bios,
+		enum controller_id controller_id,
+		enum bp_pipe_control_action action);
+
+	void (*post_init)(struct dc_bios *bios);
+
+	struct integrated_info *(*create_integrated_info)(
+		struct dc_bios *bios);
+
+	void (*destroy_integrated_info)(
+		struct dc_bios *dcb,
+		struct integrated_info **info);
+};
+
+struct dc_bios {
+	const struct dc_vbios_funcs *funcs;
+};
+
+#endif /* DC_BIOS_TYPES_H */
diff --git a/drivers/gpu/drm/amd/dal/dc/dc_ddc_types.h b/drivers/gpu/drm/amd/dal/dc/dc_ddc_types.h
new file mode 100644
index 000000000000..c74d99c3af45
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc_ddc_types.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef DC_DDC_TYPES_H_
+#define DC_DDC_TYPES_H_
+
+struct i2c_payload {
+	bool write;
+	uint8_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+enum i2c_command_engine {
+	I2C_COMMAND_ENGINE_DEFAULT,
+	I2C_COMMAND_ENGINE_SW,
+	I2C_COMMAND_ENGINE_HW
+};
+
+struct i2c_command {
+	struct i2c_payload *payloads;
+	uint8_t number_of_payloads;
+
+	enum i2c_command_engine engine;
+
+	/* expressed in KHz
+	 * zero means "use default value" */
+	uint32_t speed;
+};
+
+struct gpio_ddc_hw_info {
+	bool hw_supported;
+	uint32_t ddc_channel;
+};
+
+struct ddc {
+	struct gpio *pin_data;
+	struct gpio *pin_clock;
+	struct gpio_ddc_hw_info hw_info;
+	struct dc_context *ctx;
+};
+
+
+union ddc_wa {
+	struct {
+		uint32_t DP_SKIP_POWER_OFF:1;
+		uint32_t DP_AUX_POWER_UP_WA_DELAY:1;
+	} bits;
+	uint32_t raw;
+};
+
+struct ddc_flags {
+	uint8_t EDID_QUERY_DONE_ONCE:1;
+	uint8_t IS_INTERNAL_DISPLAY:1;
+	uint8_t FORCE_READ_REPEATED_START:1;
+	uint8_t EDID_STRESS_READ:1;
+
+};
+
+enum ddc_transaction_type {
+	DDC_TRANSACTION_TYPE_NONE = 0,
+	DDC_TRANSACTION_TYPE_I2C,
+	DDC_TRANSACTION_TYPE_I2C_OVER_AUX,
+	DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER,
+	DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER
+};
+
+enum display_dongle_type {
+	DISPLAY_DONGLE_NONE = 0,
+	/* Active converter types*/
+	DISPLAY_DONGLE_DP_VGA_CONVERTER,
+	DISPLAY_DONGLE_DP_DVI_CONVERTER,
+	DISPLAY_DONGLE_DP_HDMI_CONVERTER,
+	/* DP-HDMI/DVI passive dongles (Type 1 and Type 2)*/
+	DISPLAY_DONGLE_DP_DVI_DONGLE,
+	DISPLAY_DONGLE_DP_HDMI_DONGLE,
+	/* Other types of dongle*/
+	DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE,
+};
+
+struct dp_receiver_id_info {
+	uint32_t dpcd_rev;
+	uint32_t sink_id;
+	int8_t sink_id_str[6];
+	int8_t sink_hw_revision;
+	int8_t sink_fw_revision[2];
+	uint32_t branch_id;
+	int8_t branch_name[6];
+	enum display_dongle_type dongle_type;
+};
+
+struct ddc_service {
+	struct ddc *ddc_pin;
+	struct ddc_flags flags;
+	union ddc_wa wa;
+	enum ddc_transaction_type transaction_type;
+	enum display_dongle_type dongle_type;
+	struct dp_receiver_id_info dp_receiver_id_info;
+	struct adapter_service *as;
+	struct dc_context *ctx;
+	struct core_link *link;
+
+	uint32_t address;
+	uint32_t edid_buf_len;
+	uint8_t edid_buf[MAX_EDID_BUFFER_SIZE];
+};
+
+#endif /* DC_DDC_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dc_types.h b/drivers/gpu/drm/amd/dal/dc/dc_types.h
new file mode 100644
index 000000000000..4a9377146c8f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dc_types.h
@@ -0,0 +1,935 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef DC_TYPES_H_
+#define DC_TYPES_H_
+
+#include "dm_services_types.h"
+#include "fixed32_32.h"
+#include "fixed31_32.h"
+#include "irq_types.h"
+
+/* forward declarations */
+struct dc;
+struct dc_surface;
+struct dc_target;
+struct dc_stream;
+struct dc_link;
+struct dc_sink;
+struct dal;
+
+/********************************
+ * Environment definitions
+ ********************************/
+enum dce_environment {
+	DCE_ENV_PRODUCTION_DRV = 0,
+	/* Emulation on FPGA, in "Maximus" System.
+	 * This environment enforces that *only* DC registers accessed.
+	 * (access to non-DC registers will hang FPGA) */
+	DCE_ENV_FPGA_MAXIMUS,
+	/* Emulation on real HW or on FPGA. Used by Diagnostics, enforces
+	 * requirements of Diagnostics team. */
+	DCE_ENV_DIAG
+};
+
+/* Note: use these macro definitions instead of direct comparison! */
+#define IS_FPGA_MAXIMUS_DC(dce_environment) \
+	(dce_environment == DCE_ENV_FPGA_MAXIMUS)
+
+#define IS_DIAG_DC(dce_environment) \
+	(IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG))
+
+/********************************/
+
+#define MAX_EDID_BUFFER_SIZE 512
+#define MAX_SURFACE_NUM 2
+#define NUM_PIXEL_FORMATS 10
+
+enum surface_color_space {
+	SURFACE_COLOR_SPACE_SRGB = 0x0000,
+	SURFACE_COLOR_SPACE_BT601 = 0x0001,
+	SURFACE_COLOR_SPACE_BT709 = 0x0002,
+	SURFACE_COLOR_SPACE_XVYCC_BT601 = 0x0004,
+	SURFACE_COLOR_SPACE_XVYCC_BT709 = 0x0008,
+	SURFACE_COLOR_SPACE_XRRGB = 0x0010
+};
+
+/*Displayable pixel format in fb*/
+enum surface_pixel_format {
+	SURFACE_PIXEL_FORMAT_GRPH_BEGIN = 0,
+	/*TOBE REMOVED paletta 256 colors*/
+	SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS = SURFACE_PIXEL_FORMAT_GRPH_BEGIN,
+	/*16 bpp*/
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB1555,
+	/*16 bpp*/
+	SURFACE_PIXEL_FORMAT_GRPH_RGB565,
+	/*32 bpp*/
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB8888,
+	/*32 bpp swaped*/
+	SURFACE_PIXEL_FORMAT_GRPH_BGRA8888,
+
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010,
+	/*swaped*/
+	SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010,
+	/*TOBE REMOVED swaped, XR_BIAS has no differance
+	 * for pixel layout than previous and we can
+	 * delete this after discusion*/
+	SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS,
+	/*64 bpp */
+	SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616,
+	/*swaped & float*/
+	SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F,
+	/*grow graphics here if necessary */
+
+	SURFACE_PIXEL_FORMAT_VIDEO_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr = SURFACE_PIXEL_FORMAT_VIDEO_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCr,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbY,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrY,
+	/*grow 422/420 video here if necessary */
+	SURFACE_PIXEL_FORMAT_VIDEO_444_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb1555 = SURFACE_PIXEL_FORMAT_VIDEO_444_BEGIN,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_CrYCb565,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb4444,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA5551,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb8888,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb2101010,
+	SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA1010102
+/*grow 444 video here if necessary */
+};
+/* Pixel format */
+enum pixel_format {
+	/*graph*/
+	PIXEL_FORMAT_UNINITIALIZED,
+	PIXEL_FORMAT_INDEX8,
+	PIXEL_FORMAT_RGB565,
+	PIXEL_FORMAT_ARGB8888,
+	PIXEL_FORMAT_ARGB2101010,
+	PIXEL_FORMAT_ARGB2101010_XRBIAS,
+	PIXEL_FORMAT_FP16,
+	/*video*/
+	PIXEL_FORMAT_420BPP12,
+	PIXEL_FORMAT_422BPP16,
+	PIXEL_FORMAT_444BPP16,
+	PIXEL_FORMAT_444BPP32,
+	/*end of pixel format definition*/
+	PIXEL_FORMAT_INVALID,
+
+	PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8,
+	PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16,
+	PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12,
+	PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_444BPP32,
+	PIXEL_FORMAT_UNKNOWN
+};
+
+
+#include "dc_ddc_types.h"
+
+enum tiling_mode {
+	TILING_MODE_INVALID,
+	TILING_MODE_LINEAR,
+	TILING_MODE_TILED,
+	TILING_MODE_COUNT
+};
+
+enum plane_stereo_format {
+	PLANE_STEREO_FORMAT_NONE = 0,
+	PLANE_STEREO_FORMAT_SIDE_BY_SIDE = 1,
+	PLANE_STEREO_FORMAT_TOP_AND_BOTTOM = 2,
+	PLANE_STEREO_FORMAT_FRAME_ALTERNATE = 3,
+	PLANE_STEREO_FORMAT_ROW_INTERLEAVED = 5,
+	PLANE_STEREO_FORMAT_COLUMN_INTERLEAVED = 6,
+	PLANE_STEREO_FORMAT_CHECKER_BOARD = 7
+};
+
+/* 3D format for view, typically define how L/R eye surface is arranged within
+ * frames
+ */
+enum view_3d_format {
+	VIEW_3D_FORMAT_NONE = 0,
+	VIEW_3D_FORMAT_FRAME_SEQUENTIAL,
+	VIEW_3D_FORMAT_SIDE_BY_SIDE,
+	VIEW_3D_FORMAT_TOP_AND_BOTTOM,
+	VIEW_3D_FORMAT_COUNT,
+	VIEW_3D_FORMAT_FIRST = VIEW_3D_FORMAT_FRAME_SEQUENTIAL
+};
+
+enum dc_pixel_encoding {
+	PIXEL_ENCODING_UNDEFINED,
+	PIXEL_ENCODING_RGB,
+	PIXEL_ENCODING_YCBCR422,
+	PIXEL_ENCODING_YCBCR444,
+	PIXEL_ENCODING_YCBCR420,
+	PIXEL_ENCODING_COUNT
+};
+
+
+/* TODO: Find way to calculate number of bits
+ *  Please increase if pixel_format enum increases
+ * num  from  PIXEL_FORMAT_INDEX8 to PIXEL_FORMAT_444BPP32
+ */
+
+union large_integer {
+	struct {
+		uint32_t low_part;
+		int32_t high_part;
+	};
+
+	struct {
+		uint32_t low_part;
+		int32_t high_part;
+	} u;
+
+	int64_t quad_part;
+};
+
+#define PHYSICAL_ADDRESS_LOC union large_integer
+
+enum dc_edid_connector_type {
+	EDID_CONNECTOR_UNKNOWN = 0,
+	EDID_CONNECTOR_ANALOG = 1,
+	EDID_CONNECTOR_DIGITAL = 10,
+	EDID_CONNECTOR_DVI = 11,
+	EDID_CONNECTOR_HDMIA = 12,
+	EDID_CONNECTOR_MDDI = 14,
+	EDID_CONNECTOR_DISPLAYPORT = 15
+};
+
+enum dc_edid_status {
+	EDID_OK,
+	EDID_BAD_INPUT,
+	EDID_NO_RESPONSE,
+	EDID_BAD_CHECKSUM,
+};
+
+struct plane_colorimetry {
+	enum surface_color_space color_space;
+	bool limited_range;
+};
+
+/* audio capability from EDID*/
+struct dc_cea_audio_mode {
+	uint8_t format_code; /* ucData[0] [6:3]*/
+	uint8_t channel_count; /* ucData[0] [2:0]*/
+	uint8_t sample_rate; /* ucData[1]*/
+	union {
+		uint8_t sample_size; /* for LPCM*/
+		/*  for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/
+		uint8_t max_bit_rate;
+		uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/
+	};
+};
+
+struct dc_edid {
+	uint32_t length;
+	uint8_t raw_edid[MAX_EDID_BUFFER_SIZE];
+};
+
+/* When speaker location data block is not available, DEFAULT_SPEAKER_LOCATION
+ * is used. In this case we assume speaker location are: front left, front
+ * right and front center. */
+#define DEFAULT_SPEAKER_LOCATION 5
+
+#define DC_MAX_AUDIO_DESC_COUNT 16
+
+#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20
+
+struct dc_edid_caps {
+	/* sink identification */
+	uint16_t manufacturer_id;
+	uint16_t product_id;
+	uint32_t serial_number;
+	uint8_t manufacture_week;
+	uint8_t manufacture_year;
+	uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS];
+
+	/* audio caps */
+	uint8_t speaker_flags;
+	uint32_t audio_mode_count;
+	struct dc_cea_audio_mode audio_modes[DC_MAX_AUDIO_DESC_COUNT];
+	uint32_t audio_latency;
+	uint32_t video_latency;
+
+	/*HDMI 2.0 caps*/
+	uint8_t lte_340mcsc_scramble;
+};
+
+struct scaling_taps {
+	uint32_t v_taps;
+	uint32_t h_taps;
+	uint32_t v_taps_c;
+	uint32_t h_taps_c;
+};
+
+struct scaling_ratios {
+	struct fixed31_32 horz;
+	struct fixed31_32 vert;
+	struct fixed31_32 horz_c;
+	struct fixed31_32 vert_c;
+};
+
+struct rect {
+	uint32_t x;
+	uint32_t y;
+	uint32_t width;
+	uint32_t height;
+};
+
+struct view {
+	uint32_t width;
+	uint32_t height;
+};
+
+struct dc_resolution {
+	uint32_t width;
+	uint32_t height;
+};
+
+
+struct dc_mode_flags {
+	/* note: part of refresh rate flag*/
+	uint32_t INTERLACE :1;
+	/* native display timing*/
+	uint32_t NATIVE :1;
+	/* preferred is the recommended mode, one per display */
+	uint32_t PREFERRED :1;
+	/* true if this mode should use reduced blanking timings
+	 *_not_ related to the Reduced Blanking adjustment*/
+	uint32_t REDUCED_BLANKING :1;
+	/* note: part of refreshrate flag*/
+	uint32_t VIDEO_OPTIMIZED_RATE :1;
+	/* should be reported to upper layers as mode_flags*/
+	uint32_t PACKED_PIXEL_FORMAT :1;
+	/*< preferred view*/
+	uint32_t PREFERRED_VIEW :1;
+	/* this timing should be used only in tiled mode*/
+	uint32_t TILED_MODE :1;
+	uint32_t DSE_MODE :1;
+	/* Refresh rate divider when Miracast sink is using a
+	 different rate than the output display device
+	 Must be zero for wired displays and non-zero for
+	 Miracast displays*/
+	uint32_t MIRACAST_REFRESH_DIVIDER;
+};
+
+struct dc_crtc_timing_flags {
+	uint32_t INTERLACE :1;
+	uint32_t HSYNC_POSITIVE_POLARITY :1; /* when set to 1,
+	 it is positive polarity --reversed with dal1 or video bios define*/
+	uint32_t VSYNC_POSITIVE_POLARITY :1; /* when set to 1,
+	 it is positive polarity --reversed with dal1 or video bios define*/
+
+	uint32_t HORZ_COUNT_BY_TWO:1;
+
+	uint32_t EXCLUSIVE_3D :1; /* if this bit set,
+	 timing can be driven in 3D format only
+	 and there is no corresponding 2D timing*/
+	uint32_t RIGHT_EYE_3D_POLARITY :1; /* 1 - means right eye polarity
+	 (right eye = '1', left eye = '0') */
+	uint32_t SUB_SAMPLE_3D :1; /* 1 - means left/right  images subsampled
+	 when mixed into 3D image. 0 - means summation (3D timing is doubled)*/
+	uint32_t USE_IN_3D_VIEW_ONLY :1; /* Do not use this timing in 2D View,
+	 because corresponding 2D timing also present in the list*/
+	uint32_t STEREO_3D_PREFERENCE :1; /* Means this is 2D timing
+	 and we want to match priority of corresponding 3D timing*/
+	uint32_t Y_ONLY :1;
+
+	uint32_t YCBCR420 :1; /* TODO: shouldn't need this flag, should be a separate pixel format */
+	uint32_t DTD_COUNTER :5; /* values 1 to 16 */
+
+	/* HDMI 2.0 - Support scrambling for TMDS character
+	 * rates less than or equal to 340Mcsc */
+	uint32_t LTE_340MCSC_SCRAMBLE:1;
+
+};
+
+enum dc_timing_standard {
+	TIMING_STANDARD_UNDEFINED,
+	TIMING_STANDARD_DMT,
+	TIMING_STANDARD_GTF,
+	TIMING_STANDARD_CVT,
+	TIMING_STANDARD_CVT_RB,
+	TIMING_STANDARD_CEA770,
+	TIMING_STANDARD_CEA861,
+	TIMING_STANDARD_HDMI,
+	TIMING_STANDARD_TV_NTSC,
+	TIMING_STANDARD_TV_NTSC_J,
+	TIMING_STANDARD_TV_PAL,
+	TIMING_STANDARD_TV_PAL_M,
+	TIMING_STANDARD_TV_PAL_CN,
+	TIMING_STANDARD_TV_SECAM,
+	TIMING_STANDARD_EXPLICIT,
+	/*!< For explicit timings from EDID, VBIOS, etc.*/
+	TIMING_STANDARD_USER_OVERRIDE,
+	/*!< For mode timing override by user*/
+	TIMING_STANDARD_MAX
+};
+
+enum dc_aspect_ratio {
+	ASPECT_RATIO_NO_DATA,
+	ASPECT_RATIO_4_3,
+	ASPECT_RATIO_16_9,
+	ASPECT_RATIO_64_27,
+	ASPECT_RATIO_256_135,
+	ASPECT_RATIO_FUTURE
+};
+
+enum dc_color_depth {
+	COLOR_DEPTH_UNDEFINED,
+	COLOR_DEPTH_666,
+	COLOR_DEPTH_888,
+	COLOR_DEPTH_101010,
+	COLOR_DEPTH_121212,
+	COLOR_DEPTH_141414,
+	COLOR_DEPTH_161616,
+	COLOR_DEPTH_COUNT
+};
+
+enum dc_timing_3d_format {
+	TIMING_3D_FORMAT_NONE,
+	TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/
+	TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/
+	TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/
+	/* for active DP-HDMI dongle*/
+	TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/
+	TIMING_3D_FORMAT_HW_FRAME_PACKING,
+	TIMING_3D_FORMAT_SW_FRAME_PACKING,
+	TIMING_3D_FORMAT_ROW_INTERLEAVE,
+	TIMING_3D_FORMAT_COLUMN_INTERLEAVE,
+	TIMING_3D_FORMAT_PIXEL_INTERLEAVE,
+	TIMING_3D_FORMAT_SIDE_BY_SIDE,
+	TIMING_3D_FORMAT_TOP_AND_BOTTOM,
+	TIMING_3D_FORMAT_SBS_SW_PACKED,
+	/* Side-by-side, packed by application/driver into 2D frame*/
+	TIMING_3D_FORMAT_TB_SW_PACKED,
+	/* Top-and-bottom, packed by application/driver into 2D frame*/
+
+	TIMING_3D_FORMAT_MAX,
+};
+
+enum dc_timing_source {
+	TIMING_SOURCE_UNDEFINED,
+
+	/* explicitly specifed by user, most important*/
+	TIMING_SOURCE_USER_FORCED,
+	TIMING_SOURCE_USER_OVERRIDE,
+	TIMING_SOURCE_CUSTOM,
+	TIMING_SOURCE_EXPLICIT,
+
+	/* explicitly specified by the display device, more important*/
+	TIMING_SOURCE_EDID_CEA_SVD_3D,
+	TIMING_SOURCE_EDID_CEA_SVD_PREFERRED,
+	TIMING_SOURCE_EDID_CEA_SVD_420,
+	TIMING_SOURCE_EDID_DETAILED,
+	TIMING_SOURCE_EDID_ESTABLISHED,
+	TIMING_SOURCE_EDID_STANDARD,
+	TIMING_SOURCE_EDID_CEA_SVD,
+	TIMING_SOURCE_EDID_CVT_3BYTE,
+	TIMING_SOURCE_EDID_4BYTE,
+	TIMING_SOURCE_VBIOS,
+	TIMING_SOURCE_CV,
+	TIMING_SOURCE_TV,
+	TIMING_SOURCE_HDMI_VIC,
+
+	/* implicitly specified by display device, still safe but less important*/
+	TIMING_SOURCE_DEFAULT,
+
+	/* only used for custom base modes */
+	TIMING_SOURCE_CUSTOM_BASE,
+
+	/* these timing might not work, least important*/
+	TIMING_SOURCE_RANGELIMIT,
+	TIMING_SOURCE_OS_FORCED,
+	TIMING_SOURCE_IMPLICIT,
+
+	/* only used by default mode list*/
+	TIMING_SOURCE_BASICMODE,
+
+	TIMING_SOURCE_COUNT
+};
+
+enum dc_timing_support_method {
+	TIMING_SUPPORT_METHOD_UNDEFINED,
+	TIMING_SUPPORT_METHOD_EXPLICIT,
+	TIMING_SUPPORT_METHOD_IMPLICIT,
+	TIMING_SUPPORT_METHOD_NATIVE
+};
+
+struct dc_mode_info {
+	uint32_t pixel_width;
+	uint32_t pixel_height;
+	uint32_t field_rate;
+	/* Vertical refresh rate for progressive modes.
+	* Field rate for interlaced modes.*/
+
+	enum dc_timing_standard timing_standard;
+	enum dc_timing_source timing_source;
+	struct dc_mode_flags flags;
+};
+
+/* TODO: assess necessity*/
+/*scanning type*/
+enum scanning_type {
+	SCANNING_TYPE_NODATA = 0,
+	SCANNING_TYPE_OVERSCAN,
+	SCANNING_TYPE_UNDERSCAN,
+	SCANNING_TYPE_FUTURE,
+	SCANNING_TYPE_UNDEFINED
+};
+
+struct dc_crtc_timing {
+	uint32_t h_total;
+	uint32_t h_border_left;
+	uint32_t h_addressable;
+	uint32_t h_border_right;
+	uint32_t h_front_porch;
+	uint32_t h_sync_width;
+
+	uint32_t v_total;
+	uint32_t v_border_top;
+	uint32_t v_addressable;
+	uint32_t v_border_bottom;
+	uint32_t v_front_porch;
+	uint32_t v_sync_width;
+
+	uint32_t pix_clk_khz;
+
+	uint32_t vic;
+	uint32_t hdmi_vic;
+	enum dc_timing_standard timing_standard;
+	enum dc_timing_3d_format timing_3d_format;
+	enum dc_color_depth display_color_depth;
+	enum dc_pixel_encoding pixel_encoding;
+	enum dc_aspect_ratio aspect_ratio;
+	enum scanning_type scan_type;
+
+	struct dc_crtc_timing_flags flags;
+};
+
+struct dc_mode_timing {
+	struct dc_mode_info mode_info;
+	struct dc_crtc_timing crtc_timing;
+};
+
+/* Rotation angle */
+enum dc_rotation_angle {
+	ROTATION_ANGLE_0 = 0,
+	ROTATION_ANGLE_90,
+	ROTATION_ANGLE_180,
+	ROTATION_ANGLE_270,
+	ROTATION_ANGLE_COUNT
+};
+
+struct dc_cursor_position {
+	uint32_t x;
+	uint32_t y;
+
+	uint32_t x_origin;
+	uint32_t y_origin;
+
+	/*
+	 * This parameter indicates whether HW cursor should be enabled
+	 */
+	bool enable;
+
+	/*
+	 * This parameter indicates whether cursor hot spot should be
+	 * programmed
+	 */
+	bool hot_spot_enable;
+};
+
+/* This enum is for programming CURSOR_MODE register field. */
+/* What this register should be programmed to depends on */
+/* OS requested cursor shape flags */
+/* and what we stored in the cursor surface. */
+enum dc_cursor_color_format {
+	CURSOR_MODE_MONO,
+	CURSOR_MODE_COLOR_1BIT_AND,
+	CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA,
+	CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA
+};
+
+union dc_cursor_attribute_flags {
+	struct {
+		uint32_t ENABLE_MAGNIFICATION:1;
+		uint32_t INVERSE_TRANSPARENT_CLAMPING:1;
+		uint32_t HORIZONTAL_MIRROR:1;
+		uint32_t VERTICAL_MIRROR:1;
+		uint32_t RESERVED:28;
+	} bits;
+	uint32_t value;
+};
+
+/* This is all the parameters required by DAL in order to */
+/* update the cursor attributes, */
+/* including the new cursor image surface address, size, */
+/* hotspot location, color format, etc. */
+struct dc_cursor_attributes {
+	PHYSICAL_ADDRESS_LOC address;
+
+	/* Width and height should correspond to cursor surface width x heigh */
+	uint32_t width;
+	uint32_t height;
+	uint32_t x_hot;
+	uint32_t y_hot;
+
+	enum dc_cursor_color_format color_format;
+
+	/* In case we support HW Cursor rotation in the future */
+	enum dc_rotation_angle rotation_angle;
+
+	union dc_cursor_attribute_flags attribute_flags;
+
+};
+
+
+enum dc_plane_addr_type {
+	PLN_ADDR_TYPE_GRAPHICS = 0,
+	PLN_ADDR_TYPE_GRPH_STEREO,
+	PLN_ADDR_TYPE_VIDEO_PROGRESSIVE,
+};
+
+struct dc_plane_address {
+	enum dc_plane_addr_type type;
+	union {
+		struct{
+			PHYSICAL_ADDRESS_LOC addr;
+		} grph;
+
+		/*stereo*/
+		struct {
+			PHYSICAL_ADDRESS_LOC left_addr;
+			PHYSICAL_ADDRESS_LOC right_addr;
+		} grph_stereo;
+
+		/*video  progressive*/
+		struct {
+			PHYSICAL_ADDRESS_LOC chroma_addr;
+			PHYSICAL_ADDRESS_LOC luma_addr;
+		} video_progressive;
+	};
+};
+
+enum dc_power_state {
+	DC_POWER_STATE_ON = 1,
+	DC_POWER_STATE_STANDBY,
+	DC_POWER_STATE_SUSPEND,
+	DC_POWER_STATE_OFF
+};
+
+/* DC PowerStates */
+enum dc_video_power_state {
+	DC_VIDEO_POWER_UNSPECIFIED = 0,
+	DC_VIDEO_POWER_ON = 1,
+	DC_VIDEO_POWER_STANDBY,
+	DC_VIDEO_POWER_SUSPEND,
+	DC_VIDEO_POWER_OFF,
+	DC_VIDEO_POWER_HIBERNATE,
+	DC_VIDEO_POWER_SHUTDOWN,
+	DC_VIDEO_POWER_ULPS,	/* BACO or Ultra-Light-Power-State */
+	DC_VIDEO_POWER_AFTER_RESET,
+	DC_VIDEO_POWER_MAXIMUM
+};
+
+enum dc_acpi_cm_power_state {
+	DC_ACPI_CM_POWER_STATE_D0 = 1,
+	DC_ACPI_CM_POWER_STATE_D1 = 2,
+	DC_ACPI_CM_POWER_STATE_D2 = 4,
+	DC_ACPI_CM_POWER_STATE_D3 = 8
+};
+
+struct view_port_alignment {
+	uint8_t x_width_size_alignment;
+	uint8_t y_height_size_alignment;
+	uint8_t x_start_alignment;
+	uint8_t y_start_alignment;
+};
+
+enum dc_connection_type {
+	dc_connection_none,
+	dc_connection_single,
+	dc_connection_mst_branch,
+	dc_connection_active_dongle
+};
+
+/*
+ * Gamma ramp representation in DC
+ *
+ * A gamma ramp is just a curve defined within the range of [min, max] with
+ * arbitrary precision.
+ *
+ * DM is responsible for providing DC with an interface to obtain any y value
+ * within that range with a selected precision.
+ *
+ * bit32 ------------------------------------------------- bit 0
+ *       [  padding  ][ exponent bits ][  fraction bits  ]
+ *
+ * DC specifies the input x value and precision to the callback function
+ * get_gamma_value as well as providing the context and DM returns the y
+ * value.
+ *
+ * If fraction_bits + exponent_bits exceed width of 32 bits, get_gamma_value
+ * returns 0.  If x is outside the bounds of [min, max], get_gamma_value
+ * returns 0.
+ *
+ */
+/* TODO: Deprecated */
+enum {
+	RGB_256X3X16 = 256,
+	DX_GAMMA_RAMP_MAX = 1025
+};
+
+enum gamma_ramp_type {
+	GAMMA_RAMP_UNINITIALIZED = 0,
+	GAMMA_RAMP_DEFAULT,
+	GAMMA_RAMP_RBG256X3X16,
+	GAMMA_RAMP_DXGI_1,
+};
+
+struct dxgi_rgb {
+	struct fixed32_32 red;
+	struct fixed32_32 green;
+	struct fixed32_32 blue;
+};
+
+struct gamma_ramp_dxgi_1 {
+	struct dxgi_rgb scale;
+	struct dxgi_rgb offset;
+	struct dxgi_rgb gamma_curve[DX_GAMMA_RAMP_MAX];
+};
+
+struct gamma_ramp_rgb256x3x16 {
+	uint16_t red[RGB_256X3X16];
+	uint16_t green[RGB_256X3X16];
+	uint16_t blue[RGB_256X3X16];
+};
+
+struct gamma_ramp {
+	enum gamma_ramp_type type;
+	union {
+		struct gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16;
+		struct gamma_ramp_dxgi_1 gamma_ramp_dxgi1;
+	};
+	uint32_t size;
+};
+
+
+struct dc_gamma_ramp {
+	uint32_t (*get_gamma_value) (
+			void *context,
+			uint8_t exponent_bits,
+			uint8_t fraction_bits,
+			uint32_t x);
+	void *context;
+	uint32_t min;
+	uint32_t max;
+};
+
+struct dc_csc_adjustments {
+	struct fixed31_32 contrast;
+	struct fixed31_32 saturation;
+	struct fixed31_32 brightness;
+	struct fixed31_32 hue;
+};
+
+
+enum {
+	MAX_LANES = 2,
+	MAX_COFUNC_PATH = 6,
+	LAYER_INDEX_PRIMARY = -1,
+};
+
+/* Scaling format */
+enum scaling_transformation {
+	SCALING_TRANSFORMATION_UNINITIALIZED,
+	SCALING_TRANSFORMATION_IDENTITY = 0x0001,
+	SCALING_TRANSFORMATION_CENTER_TIMING = 0x0002,
+	SCALING_TRANSFORMATION_FULL_SCREEN_SCALE = 0x0004,
+	SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE = 0x0008,
+	SCALING_TRANSFORMATION_DAL_DECIDE = 0x0010,
+	SCALING_TRANSFORMATION_INVALID = 0x80000000,
+
+	/* Flag the first and last */
+	SCALING_TRANSFORMATION_BEGING = SCALING_TRANSFORMATION_IDENTITY,
+	SCALING_TRANSFORMATION_END =
+		SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE
+};
+
+struct view_stereo_3d_support {
+	enum view_3d_format format;
+	struct {
+		uint32_t CLONE_MODE:1;
+		uint32_t SCALING:1;
+		uint32_t SINGLE_FRAME_SW_PACKED:1;
+	} features;
+};
+
+struct view_position {
+	uint32_t x;
+	uint32_t y;
+};
+
+struct render_mode {
+	struct view view;
+	enum pixel_format pixel_format;
+};
+
+struct pixel_format_support {
+	bool INDEX8 :1;
+	bool RGB565 :1;
+	bool ARGB8888 :1;
+	bool ARGB2101010 :1;
+	bool ARGB2101010_XRBIAS :1;
+	bool FP16 :1;
+};
+
+struct stereo_3d_view {
+	enum view_3d_format view_3d_format;
+	union {
+		uint32_t raw;
+		struct /*stereo_3d_view_flags*/
+		{
+			bool SINGLE_FRAME_SW_PACKED :1;
+			bool EXCLUSIVE_3D :1;
+		} bits;
+	} flags;
+};
+
+/* TODO: These values come from hardware spec. We need to readdress this
+ * if they ever change.
+ */
+enum array_mode_values {
+	DC_ARRAY_UNDEFINED = 0,
+	DC_ARRAY_1D_TILED_THIN1 = 0x2,
+	DC_ARRAY_2D_TILED_THIN1 = 0x4,
+};
+
+
+enum tile_mode_values {
+	DC_ADDR_SURF_MICRO_TILING_DISPLAY = 0x0,
+	DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1,
+};
+
+enum tile_split_values {
+	DC_DISPLAY_MICRO_TILING = 0x0,
+	DC_THIN_MICRO_TILING = 0x1,
+	DC_DEPTH_MICRO_TILING = 0x2,
+	DC_ROTATED_MICRO_TILING = 0x3,
+};
+
+struct dc_tiling_info {
+
+	/* Specifies the number of memory banks for tiling
+	 *	purposes.
+	 * Only applies to 2D and 3D tiling modes.
+	 *	POSSIBLE VALUES: 2,4,8,16
+	 */
+	unsigned int num_banks;
+	/* Specifies the number of tiles in the x direction
+	 *	to be incorporated into the same bank.
+	 * Only applies to 2D and 3D tiling modes.
+	 *	POSSIBLE VALUES: 1,2,4,8
+	 */
+	unsigned int bank_width;
+	/* Specifies the number of tiles in the y direction to
+	 *	be incorporated into the same bank.
+	 * Only applies to 2D and 3D tiling modes.
+	 *	POSSIBLE VALUES: 1,2,4,8
+	 */
+	unsigned int bank_height;
+	/* Specifies the macro tile aspect ratio. Only applies
+	 * to 2D and 3D tiling modes.
+	 */
+	unsigned int tile_aspect;
+	/* Specifies the number of bytes that will be stored
+	 *	contiguously for each tile.
+	 * If the tile data requires more storage than this
+	 *	amount, it is split into multiple slices.
+	 * This field must not be larger than
+	 *	GB_ADDR_CONFIG.DRAM_ROW_SIZE.
+	 * Only applies to 2D and 3D tiling modes.
+	 * For color render targets, TILE_SPLIT >= 256B.
+	 */
+	enum tile_split_values tile_split;
+	/* Specifies the addressing within a tile.
+	 *	0x0 - DISPLAY_MICRO_TILING
+	 *	0x1 - THIN_MICRO_TILING
+	 *	0x2 - DEPTH_MICRO_TILING
+	 *	0x3 - ROTATED_MICRO_TILING
+	 */
+	enum tile_mode_values tile_mode;
+	/* Specifies the number of pipes and how they are
+	 *	interleaved in the surface.
+	 * Refer to memory addressing document for complete
+	 *	details and constraints.
+	 */
+	unsigned int pipe_config;
+	/* Specifies the tiling mode of the surface.
+	 * THIN tiles use an 8x8x1 tile size.
+	 * THICK tiles use an 8x8x4 tile size.
+	 * 2D tiling modes rotate banks for successive Z slices
+	 * 3D tiling modes rotate pipes and banks for Z slices
+	 * Refer to memory addressing document for complete
+	 *	details and constraints.
+	 */
+	enum array_mode_values array_mode;
+};
+
+union plane_size {
+	/* Grph or Video will be selected
+	 * based on format above:
+	 * Use Video structure if
+	 * format >= DalPixelFormat_VideoBegin
+	 * else use Grph structure
+	 */
+	struct {
+		struct rect surface_size;
+		/* Graphic surface pitch in pixels.
+		 * In LINEAR_GENERAL mode, pitch
+		 * is 32 pixel aligned.
+		 */
+		uint32_t surface_pitch;
+	} grph;
+
+	struct {
+		struct rect luma_size;
+		/* Graphic surface pitch in pixels.
+		 * In LINEAR_GENERAL mode, pitch is
+		 * 32 pixel aligned.
+		 */
+		uint32_t luma_pitch;
+
+		struct rect chroma_size;
+		/* Graphic surface pitch in pixels.
+		 * In LINEAR_GENERAL mode, pitch is
+		 * 32 pixel aligned.
+		 */
+		uint32_t chroma_pitch;
+	} video;
+};
+
+#endif /* DC_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_helpers.h b/drivers/gpu/drm/amd/dal/dc/dm_helpers.h
new file mode 100644
index 000000000000..350dd111f6c9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dm_helpers.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/**
+ * This file defines helper functions provided by the Display Manager to
+ * Display Core.
+ */
+#ifndef __DM_HELPERS__
+#define __DM_HELPERS__
+
+#include "dc_types.h"
+#include "dc.h"
+
+struct dp_mst_stream_allocation_table;
+
+enum dc_edid_status dm_helpers_parse_edid_caps(
+	struct dc_context *ctx,
+	const struct dc_edid *edid,
+	struct dc_edid_caps *edid_caps);
+
+/*
+ * Writes payload allocation table in immediate downstream device.
+ */
+bool dm_helpers_dp_mst_write_payload_allocation_table(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		struct dp_mst_stream_allocation_table *proposed_table,
+		bool enable);
+
+/*
+ * Polls for ACT (allocation change trigger) handled and
+ */
+bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+		struct dc_context *ctx,
+		const struct dc_stream *stream);
+/*
+ * Sends ALLOCATE_PAYLOAD message.
+ */
+bool dm_helpers_dp_mst_send_payload_allocation(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		bool enable);
+
+void dm_helpers_dp_mst_handle_mst_hpd_rx_irq(
+		void *param);
+
+bool dm_helpers_dp_mst_start_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		bool boot);
+
+void dm_helpers_dp_mst_stop_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link);
+
+/**
+ * OS specific aux read callback.
+ */
+bool dm_helpers_dp_read_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size);
+
+/**
+ * OS specific aux write callback.
+ */
+bool dm_helpers_dp_write_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t size);
+
+bool dm_helpers_submit_i2c(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		struct i2c_command *cmd);
+
+#endif /* __DM_HELPERS__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services.h b/drivers/gpu/drm/amd/dal/dc/dm_services.h
new file mode 100644
index 000000000000..206c0b7df7c6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dm_services.h
@@ -0,0 +1,485 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/**
+ * This file defines external dependencies of Display Core.
+ */
+
+#ifndef __DM_SERVICES_H__
+
+#define __DM_SERVICES_H__
+
+/* TODO: remove when DC is complete. */
+#include "dm_services_types.h"
+#include "logger_interface.h"
+#include "include/dal_types.h"
+#include "irq_types.h"
+#include "link_service_types.h"
+
+#undef DEPRECATED
+
+/* if the pointer is not NULL, the allocated memory is zeroed */
+void *dm_alloc(struct dc_context *ctx, uint32_t size);
+
+/* reallocate memory. The contents will remain unchanged.*/
+void *dm_realloc(struct dc_context *ctx, const void *ptr, uint32_t size);
+
+void dm_free(struct dc_context *ctx, void *p);
+
+void dm_memset(void *p, int32_t c, uint32_t count);
+
+void dm_memmove(void *dst, const void *src, uint32_t size);
+
+int32_t dm_memcmp(const void *p1, const void *p2, uint32_t count);
+
+int32_t dm_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count);
+
+irq_handler_idx dm_register_interrupt(
+	struct dc_context *ctx,
+	struct dc_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *handler_args);
+
+void dm_unregister_interrupt(
+	struct dc_context *ctx,
+	enum dc_irq_source irq_source,
+	irq_handler_idx handler_idx);
+
+/*
+ *
+ * GPU registers access
+ *
+ */
+
+#define dm_read_reg(ctx, address)	\
+		dm_read_reg_func(ctx, address, __func__)
+
+static inline uint32_t dm_read_reg_func(
+	const struct dc_context *ctx,
+	uint32_t address,
+	const char *func_name)
+{
+	uint32_t value = cgs_read_register(ctx->cgs_device, address);
+
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s DC_READ_REG: 0x%x 0x%x\n", func_name, address, value);
+	}
+#endif
+	return value;
+}
+
+#define dm_write_reg(ctx, address, value)	\
+	dm_write_reg_func(ctx, address, value, __func__)
+
+static inline void dm_write_reg_func(
+	const struct dc_context *ctx,
+	uint32_t address,
+	uint32_t value,
+	const char *func_name)
+{
+#if defined(__DAL_REGISTER_LOGGER__)
+	if (true == dal_reg_logger_should_dump_register()) {
+		dal_reg_logger_rw_count_increment();
+		DRM_INFO("%s DC_WRITE_REG: 0x%x 0x%x\n", func_name, address, value);
+	}
+#endif
+	cgs_write_register(ctx->cgs_device, address, value);
+}
+
+static inline uint32_t dm_read_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index)
+{
+	return cgs_read_ind_register(ctx->cgs_device, addr_space, index);
+}
+
+static inline void dm_write_index_reg(
+	const struct dc_context *ctx,
+	enum cgs_ind_reg addr_space,
+	uint32_t index,
+	uint32_t value)
+{
+	cgs_write_ind_register(ctx->cgs_device, addr_space, index, value);
+}
+
+static inline uint32_t get_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (mask & reg_value) >> shift;
+}
+
+#define get_reg_field_value(reg_value, reg_name, reg_field)\
+	get_reg_field_value_ex(\
+		(reg_value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+static inline uint32_t set_reg_field_value_ex(
+	uint32_t reg_value,
+	uint32_t value,
+	uint32_t mask,
+	uint8_t shift)
+{
+	return (reg_value & ~mask) | (mask & (value << shift));
+}
+
+#define set_reg_field_value(reg_value, value, reg_name, reg_field)\
+	(reg_value) = set_reg_field_value_ex(\
+		(reg_value),\
+		(value),\
+		reg_name ## __ ## reg_field ## _MASK,\
+		reg_name ## __ ## reg_field ## __SHIFT)
+
+/*
+ * atombios services
+ */
+
+bool dm_exec_bios_cmd_table(
+	struct dc_context *ctx,
+	uint32_t index,
+	void *params);
+
+#ifdef BUILD_DAL_TEST
+uint32_t dm_bios_cmd_table_para_revision(
+struct dc_context *ctx,
+	uint32_t index);
+
+bool dm_bios_cmd_table_revision(
+	struct dc_context *ctx,
+	uint32_t index,
+	uint8_t *frev,
+	uint8_t *crev);
+#endif
+
+#ifndef BUILD_DAL_TEST
+static inline uint32_t dm_bios_cmd_table_para_revision(
+	struct dc_context *ctx,
+	uint32_t index)
+{
+	uint8_t frev;
+	uint8_t crev;
+
+	if (cgs_atom_get_cmd_table_revs(
+			ctx->cgs_device,
+			index,
+			&frev,
+			&crev) != 0)
+		return 0;
+
+	return crev;
+}
+#else
+uint32_t dm_bios_cmd_table_para_revision(
+		struct dc_context *ctx,
+		uint32_t index);
+#endif
+
+/**************************************
+ * Power Play (PP) interfaces
+ **************************************/
+
+enum dal_to_power_clocks_state {
+	PP_CLOCKS_STATE_INVALID,
+	PP_CLOCKS_STATE_ULTRA_LOW,
+	PP_CLOCKS_STATE_LOW,
+	PP_CLOCKS_STATE_NOMINAL,
+	PP_CLOCKS_STATE_PERFORMANCE
+};
+
+/* clocks in khz */
+struct dal_to_power_info {
+	enum dal_to_power_clocks_state required_clock;
+	uint32_t min_sclk;
+	uint32_t min_mclk;
+	uint32_t min_deep_sleep_sclk;
+};
+
+/* clocks in khz */
+struct power_to_dal_info {
+	uint32_t min_sclk;
+	uint32_t max_sclk;
+	uint32_t min_mclk;
+	uint32_t max_mclk;
+};
+
+/* clocks in khz */
+struct dal_system_clock_range {
+	uint32_t min_sclk;
+	uint32_t max_sclk;
+
+	uint32_t min_mclk;
+	uint32_t max_mclk;
+
+	uint32_t min_dclk;
+	uint32_t max_dclk;
+
+	/* Wireless Display */
+	uint32_t min_eclk;
+	uint32_t max_eclk;
+};
+
+/* clocks in khz */
+struct dal_to_power_dclk {
+	uint32_t optimal; /* input: best optimizes for stutter efficiency */
+	uint32_t minimal; /* input: the lowest clk that DAL can support */
+	uint32_t established; /* output: the actually set one */
+};
+
+/* DAL calls this function to notify PP about clocks it needs for the Mode Set.
+ * This is done *before* it changes DCE clock.
+ *
+ * If required clock is higher than current, then PP will increase the voltage.
+ *
+ * If required clock is lower than current, then PP will defer reduction of
+ * voltage until the call to dc_service_pp_post_dce_clock_change().
+ *
+ * \input - Contains clocks needed for Mode Set.
+ *
+ * \output - Contains clocks adjusted by PP which DAL should use for Mode Set.
+ *		Valid only if function returns zero.
+ *
+ * \returns	true - call is successful
+ *		false - call failed
+ */
+bool dm_pp_pre_dce_clock_change(
+	struct dc_context *ctx,
+	struct dal_to_power_info *input,
+	struct power_to_dal_info *output);
+
+struct dc_pp_single_disp_config {
+	enum signal_type signal;
+	uint8_t transmitter;
+	uint8_t ddi_channel_mapping;
+	uint8_t pipe_idx;
+	uint32_t src_height;
+	uint32_t src_width;
+	uint32_t v_refresh;
+	uint32_t sym_clock; /* HDMI only */
+	struct link_settings link_settings; /* DP only */
+};
+
+struct dc_pp_display_configuration {
+	bool nb_pstate_switch_disable;/* controls NB PState switch */
+	bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */
+	bool cpu_pstate_disable;
+	uint32_t cpu_pstate_separation_time;
+
+	uint32_t min_memory_clock_khz;
+	uint32_t min_engine_clock_khz;
+	uint32_t min_engine_clock_deep_sleep_khz;
+
+	uint32_t avail_mclk_switch_time_us;
+	uint32_t avail_mclk_switch_time_in_disp_active_us;
+
+	uint32_t disp_clk_khz;
+
+	bool all_displays_in_sync;
+
+	uint8_t display_count;
+	struct dc_pp_single_disp_config disp_configs[3];
+
+	/*Controller Index of primary display - used in MCLK SMC switching hang
+	 * SW Workaround*/
+	uint8_t crtc_index;
+	/*htotal*1000/pixelclk - used in MCLK SMC switching hang SW Workaround*/
+	uint32_t line_time_in_us;
+};
+
+enum dc_pp_clocks_state {
+	DC_PP_CLOCKS_STATE_INVALID = 0,
+	DC_PP_CLOCKS_STATE_ULTRA_LOW,
+	DC_PP_CLOCKS_STATE_LOW,
+	DC_PP_CLOCKS_STATE_NOMINAL,
+	DC_PP_CLOCKS_STATE_PERFORMANCE,
+
+	/* Starting from DCE11, Max 8 levels of DPM state supported. */
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_INVALID = DC_PP_CLOCKS_STATE_INVALID,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_0 = DC_PP_CLOCKS_STATE_ULTRA_LOW,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_1 = DC_PP_CLOCKS_STATE_LOW,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_2 = DC_PP_CLOCKS_STATE_NOMINAL,
+	/* to be backward compatible */
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_3 = DC_PP_CLOCKS_STATE_PERFORMANCE,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_4 = DC_PP_CLOCKS_DPM_STATE_LEVEL_3 + 1,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_5 = DC_PP_CLOCKS_DPM_STATE_LEVEL_4 + 1,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_6 = DC_PP_CLOCKS_DPM_STATE_LEVEL_5 + 1,
+	DC_PP_CLOCKS_DPM_STATE_LEVEL_7 = DC_PP_CLOCKS_DPM_STATE_LEVEL_6 + 1,
+};
+
+struct dc_pp_static_clock_info {
+	uint32_t max_sclk_khz;
+	uint32_t max_mclk_khz;
+
+	 /* max possible display block clocks state */
+	enum dc_pp_clocks_state max_clocks_state;
+};
+
+/* The returned clocks range are 'static' system clocks which will be used for
+ * mode validation purposes.
+ *
+ * \returns	true - call is successful
+ *		false - call failed
+ */
+bool dc_service_get_system_clocks_range(
+	const struct dc_context *ctx,
+	struct dal_system_clock_range *sys_clks);
+
+enum dc_pp_clock_type {
+	DC_PP_CLOCK_TYPE_DISPLAY_CLK = 1,
+	DC_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */
+	DC_PP_CLOCK_TYPE_MEMORY_CLK
+};
+
+#define DC_DECODE_PP_CLOCK_TYPE(clk_type) \
+	(clk_type) == DC_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \
+	(clk_type) == DC_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \
+	(clk_type) == DC_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid"
+
+#define DC_PP_MAX_CLOCK_LEVELS 8
+
+struct dc_pp_clock_levels {
+	uint32_t num_levels;
+	uint32_t clocks_in_khz[DC_PP_MAX_CLOCK_LEVELS];
+};
+
+/* Gets valid clocks levels from pplib
+ *
+ * input: clk_type - display clk / sclk / mem clk
+ *
+ * output: array of valid clock levels for given type in ascending order,
+ * with invalid levels filtered out
+ *
+ */
+bool dm_pp_get_clock_levels_by_type(
+	const struct dc_context *ctx,
+	enum dc_pp_clock_type clk_type,
+	struct dc_pp_clock_levels *clk_level_info);
+
+
+bool dm_pp_apply_safe_state(
+		const struct dc_context *ctx);
+
+/* DAL calls this function to notify PP about completion of Mode Set.
+ * For PP it means that current DCE clocks are those which were returned
+ * by dc_service_pp_pre_dce_clock_change(), in the 'output' parameter.
+ *
+ * If the clocks are higher than before, then PP does nothing.
+ *
+ * If the clocks are lower than before, then PP reduces the voltage.
+ *
+ * \returns	true - call is successful
+ *		false - call failed
+ */
+bool dm_pp_apply_display_requirements(
+	const struct dc_context *ctx,
+	const struct dc_pp_display_configuration *pp_display_cfg);
+
+
+/****** end of PP interfaces ******/
+
+void dm_sleep_in_milliseconds(struct dc_context *ctx, uint32_t milliseconds);
+
+void dm_delay_in_microseconds(struct dc_context *ctx, uint32_t microseconds);
+
+enum platform_method {
+	PM_GET_AVAILABLE_METHODS = 1 << 0,
+	PM_GET_LID_STATE = 1 << 1,
+	PM_GET_EXTENDED_BRIGHNESS_CAPS = 1 << 2
+};
+
+struct platform_info_params {
+	enum platform_method method;
+	void *data;
+};
+
+struct platform_info_brightness_caps {
+	uint8_t ac_level_percentage;
+	uint8_t dc_level_percentage;
+};
+
+struct platform_info_ext_brightness_caps {
+	struct platform_info_brightness_caps basic_caps;
+	struct data_point {
+		uint8_t luminance;
+		uint8_t	signal_level;
+	} data_points[99];
+
+	uint8_t	data_points_num;
+	uint8_t	min_input_signal;
+	uint8_t	max_input_signal;
+};
+
+bool dm_get_platform_info(
+	struct dc_context *ctx,
+	struct platform_info_params *params);
+
+/*
+ *
+ * print-out services
+ *
+ */
+#define dm_log_to_buffer(buffer, size, fmt, args)\
+	vsnprintf(buffer, size, fmt, args)
+
+long dm_get_pid(void);
+long dm_get_tgid(void);
+
+/*
+ *
+ * general debug capabilities
+ *
+ */
+#if defined(CONFIG_DEBUG_KERNEL) || defined(CONFIG_DEBUG_DRIVER)
+
+#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB)
+#define ASSERT_CRITICAL(expr) do {	\
+	if (WARN_ON(!(expr))) { \
+		kgdb_breakpoint(); \
+	} \
+} while (0)
+#else
+#define ASSERT_CRITICAL(expr) do {	\
+	if (WARN_ON(!(expr))) { \
+		; \
+	} \
+} while (0)
+#endif
+
+#if defined(CONFIG_DEBUG_KERNEL_DAL)
+#define ASSERT(expr) ASSERT_CRITICAL(expr)
+
+#else
+#define ASSERT(expr) WARN_ON(!(expr))
+#endif
+
+#define BREAK_TO_DEBUGGER() ASSERT(0)
+
+#endif /* CONFIG_DEBUG_KERNEL || CONFIG_DEBUG_DRIVER */
+
+#endif /* __DM_SERVICES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services_types.h b/drivers/gpu/drm/amd/dal/dc/dm_services_types.h
new file mode 100644
index 000000000000..bc458aa41a5d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/dm_services_types.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DM_SERVICES_TYPES_H__
+#define __DM_SERVICES_TYPES_H__
+
+#define INVALID_DISPLAY_INDEX 0xffffffff
+
+#if defined __KERNEL__
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <drm/drmP.h>
+
+#include "cgs_linux.h"
+
+#if defined(__BIG_ENDIAN) && !defined(BIGENDIAN_CPU)
+#define BIGENDIAN_CPU
+#elif defined(__LITTLE_ENDIAN) && !defined(LITTLEENDIAN_CPU)
+#define LITTLEENDIAN_CPU
+#endif
+
+#undef READ
+#undef WRITE
+#undef FRAME_SIZE
+
+#define dm_output_to_console(fmt, ...) DRM_INFO(fmt, ##__VA_ARGS__)
+
+#define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__)
+
+#define dm_debug(fmt, ...) DRM_DEBUG_KMS(fmt, ##__VA_ARGS__)
+
+#define dm_vlog(fmt, args) vprintk(fmt, args)
+
+#define dm_min(x, y) min(x, y)
+#define dm_max(x, y) max(x, y)
+
+#elif defined BUILD_DAL_TEST
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdio.h>
+
+#include <stdarg.h>
+
+#include "cgs_linux.h"
+
+#define LONG_MAX	((long)(~0UL>>1))
+#define LONG_MIN	(-LONG_MAX - 1)
+#define LLONG_MAX	((long long)(~0ULL>>1))
+#define LLONG_MIN	(-LLONG_MAX - 1)
+#define UINT_MAX	(~0U)
+
+typedef _Bool bool;
+enum { false, true };
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define LITTLEENDIAN_CPU 1
+
+#include <test_context.h>
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#define container_of(ptr, type, member) \
+	((type *)((char *)(ptr) - offsetof(type, member)))
+
+#define dal_test_not_implemented() \
+	printf("[DAL_TEST_NOT_IMPL]:%s\n", __func__)
+
+#define dm_output_to_console(fmt, ...) do { \
+	printf("[DAL_LOG]" fmt, ##__VA_ARGS__); } \
+	while (false)
+
+#define dm_error(fmt, ...) printf("[DAL_ERROR]" fmt, ##__VA_ARGS__)
+
+#define dm_output_to_console(fmt, ...) do { \
+			printf("[DAL_LOG]" fmt, ##__VA_ARGS__); } \
+				while (false)
+
+
+#define dm_debug(fmt, ...) printf("[DAL_DBG]" fmt, ##__VA_ARGS__)
+
+#define dm_vlog(fmt, args) vprintf(fmt, args)
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+#define dm_min(x, y) ({\
+	typeof(x) _min1 = (x);\
+	typeof(y) _min2 = (y);\
+	(void) (&_min1 == &_min2);\
+	_min1 < _min2 ? _min1 : _min2; })
+
+#define dm_max(x, y) ({\
+	typeof(x) _max1 = (x);\
+	typeof(y) _max2 = (y);\
+	(void) (&_max1 == &_max2);\
+	_max1 > _max2 ? _max1 : _max2; })
+
+/* division functions */
+
+static inline int64_t div64_s64(int64_t x, int64_t y)
+{
+	return x / y;
+}
+
+static inline uint64_t div64_u64(uint64_t x, uint64_t y)
+{
+	return x / y;
+}
+
+static inline uint64_t div_u64(uint64_t x, uint32_t y)
+{
+	return x / y;
+}
+
+static inline uint64_t div64_u64_rem(uint64_t x, uint64_t y, uint64_t *rem)
+{
+	if (rem)
+		*rem = x % y;
+	return x / y;
+}
+
+static inline uint64_t div_u64_rem(uint64_t x, uint32_t y, uint32_t *rem)
+{
+	if (rem)
+		*rem = x % y;
+	return x / y;
+}
+
+#define cpu_to_le16(do_nothing) do_nothing
+
+#define le16_to_cpu(do_nothing) do_nothing
+
+#define cpu_to_le32(do_nothing) do_nothing
+
+#define le32_to_cpu(do_nothing) do_nothing
+
+#endif
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
new file mode 100644
index 000000000000..0d228ed0455c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/bandwidth_calcs.h
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/**
+ * Bandwidth and Watermark calculations interface.
+ * (Refer to "DCE11_mode_support.xlsm" from Perforce.)
+ */
+#ifndef __BANDWIDTH_CALCS_H__
+#define __BANDWIDTH_CALCS_H__
+
+#include "bw_fixed.h"
+/*******************************************************************************
+ * There are three types of input into Calculations:
+ * 1. per-DCE static values - these are "hardcoded" properties of the DCEIP
+ * 2. board-level values - these are generally coming from VBIOS parser
+ * 3. mode/configuration values - depending Mode, Scaling number of Displays etc.
+ ******************************************************************************/
+enum bw_defines {
+	/*Common*/
+	bw_def_no = 0,
+	bw_def_none = 0,
+	bw_def_yes = 1,
+	bw_def_ok = 1,
+	bw_def_high = 2,
+	bw_def_mid = 1,
+	bw_def_low = 0,
+
+	/*Internal*/
+	bw_defs_start = 255,
+	bw_def_underlay422,
+	bw_def_underlay420_luma,
+	bw_def_underlay420_chroma,
+	bw_def_underlay444,
+	bw_def_graphics,
+	bw_def_display_write_back420_luma,
+	bw_def_display_write_back420_chroma,
+	bw_def_portrait,
+	bw_def_hsr_mtn_4,
+	bw_def_hsr_mtn_h_taps,
+	bw_def_ceiling__h_taps_div_4___meq_hsr,
+	bw_def_invalid_linear_or_stereo_mode,
+	bw_def_invalid_rotation_or_bpp_or_stereo,
+	bw_def_vsr_mtn_v_taps,
+	bw_def_vsr_mtn_4,
+	bw_def_auto,
+	bw_def_manual,
+	bw_def_exceeded_allowed_maximum_sclk,
+	bw_def_exceeded_allowed_page_close_open,
+	bw_def_exceeded_allowed_outstanding_pte_req_queue_size,
+	bw_def_exceeded_allowed_maximum_bw,
+	bw_def_high_no_nbp_state_change,
+	bw_def_landscape,
+
+	/*Panning and bezel*/
+	bw_def_any_lines,
+
+	/*Underlay mode*/
+	bw_def_underlay_only,
+	bw_def_blended,
+	bw_def_blend,
+
+	/*Stereo mode*/
+	bw_def_mono,
+	bw_def_side_by_side,
+	bw_def_top_bottom,
+
+	/*Underlay surface type*/
+	bw_def_420,
+	bw_def_422,
+	bw_def_444,
+
+	/*Tiling mode*/
+	bw_def_linear,
+	bw_def_tiled,
+
+	bw_def_notok = -1,
+	bw_def_na = -1
+};
+
+struct bw_calcs_dceip {
+	struct bw_fixed dmif_request_buffer_size;
+	struct bw_fixed de_tiling_buffer;
+	bool dcfclk_request_generation;
+	uint32_t lines_interleaved_into_lb;
+	uint32_t chunk_width;
+	uint32_t number_of_graphics_pipes;
+	uint32_t number_of_underlay_pipes;
+	bool display_write_back_supported;
+	bool argb_compression_support;
+	struct bw_fixed underlay_vscaler_efficiency6_bit_per_component;
+	struct bw_fixed underlay_vscaler_efficiency8_bit_per_component;
+	struct bw_fixed underlay_vscaler_efficiency10_bit_per_component;
+	struct bw_fixed underlay_vscaler_efficiency12_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency6_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency8_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency10_bit_per_component;
+	struct bw_fixed graphics_vscaler_efficiency12_bit_per_component;
+	struct bw_fixed alpha_vscaler_efficiency;
+	uint32_t max_dmif_buffer_allocated;
+	uint32_t graphics_dmif_size;
+	uint32_t underlay_luma_dmif_size;
+	uint32_t underlay_chroma_dmif_size;
+	bool pre_downscaler_enabled;
+	bool underlay_downscale_prefetch_enabled;
+	struct bw_fixed lb_write_pixels_per_dispclk;
+	struct bw_fixed lb_size_per_component444;
+	bool graphics_lb_nodownscaling_multi_line_prefetching;
+	struct bw_fixed stutter_and_dram_clock_state_change_gated_before_cursor;
+	struct bw_fixed underlay420_luma_lb_size_per_component;
+	struct bw_fixed underlay420_chroma_lb_size_per_component;
+	struct bw_fixed underlay422_lb_size_per_component;
+	struct bw_fixed cursor_chunk_width;
+	struct bw_fixed cursor_dcp_buffer_lines;
+	struct bw_fixed cursor_memory_interface_buffer_pixels;
+	struct bw_fixed underlay_maximum_width_efficient_for_tiling;
+	struct bw_fixed underlay_maximum_height_efficient_for_tiling;
+	struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display;
+	struct bw_fixed peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation;
+	struct bw_fixed minimum_outstanding_pte_request_limit;
+	struct bw_fixed maximum_total_outstanding_pte_requests_allowed_by_saw;
+	bool limit_excessive_outstanding_dmif_requests;
+	struct bw_fixed linear_mode_line_request_alternation_slice;
+	uint32_t scatter_gather_lines_of_pte_prefetching_in_linear_mode;
+	uint32_t display_write_back420_luma_mcifwr_buffer_size;
+	uint32_t display_write_back420_chroma_mcifwr_buffer_size;
+	struct bw_fixed request_efficiency;
+	struct bw_fixed dispclk_per_request;
+	struct bw_fixed dispclk_ramping_factor;
+	struct bw_fixed display_pipe_throughput_factor;
+	uint32_t scatter_gather_pte_request_rows_in_tiling_mode;
+	struct bw_fixed mcifwr_all_surfaces_burst_time; /* 0 todo: this is a bug*/
+};
+
+struct bw_calcs_vbios {
+	uint32_t dram_channel_width_in_bits;
+	uint32_t number_of_dram_channels;
+	uint32_t number_of_dram_banks;
+	struct bw_fixed high_yclk; /*MHz*/
+	struct bw_fixed mid_yclk; /*MHz*/
+	struct bw_fixed low_yclk; /*MHz*/
+	struct bw_fixed low_sclk; /*MHz*/
+	struct bw_fixed mid_sclk; /*MHz*/
+	struct bw_fixed high_sclk; /*MHz*/
+	struct bw_fixed low_voltage_max_dispclk; /*MHz*/
+	struct bw_fixed mid_voltage_max_dispclk; /*MHz*/
+	struct bw_fixed high_voltage_max_dispclk; /*MHz*/
+	struct bw_fixed data_return_bus_width;
+	struct bw_fixed trc;
+	struct bw_fixed dmifmc_urgent_latency;
+	struct bw_fixed stutter_self_refresh_exit_latency;
+	struct bw_fixed nbp_state_change_latency;
+	struct bw_fixed mcifwrmc_urgent_latency;
+	bool scatter_gather_enable;
+	struct bw_fixed down_spread_percentage;
+	uint32_t cursor_width;
+	uint32_t average_compression_rate;
+	uint32_t number_of_request_slots_gmc_reserves_for_dmif_per_channel;
+	struct bw_fixed blackout_duration;
+	struct bw_fixed maximum_blackout_recovery_time;
+};
+
+struct bw_calcs_mode_data_internal {
+	/* data for all displays */
+	uint32_t number_of_displays;
+	uint32_t graphics_rotation_angle;
+	uint32_t underlay_rotation_angle;
+	enum bw_defines display_synchronization_enabled;
+	enum bw_defines underlay_surface_type;
+	enum bw_defines panning_and_bezel_adjustment;
+	enum bw_defines graphics_tiling_mode;
+	bool graphics_interlace_mode;
+	uint32_t graphics_bytes_per_pixel;
+	uint32_t graphics_htaps;
+	uint32_t graphics_vtaps;
+	uint32_t graphics_lb_bpc;
+	uint32_t underlay_lb_bpc;
+	enum bw_defines underlay_tiling_mode;
+	uint32_t underlay_htaps;
+	uint32_t underlay_vtaps;
+	uint32_t underlay_src_width;
+	uint32_t underlay_src_height;
+	uint32_t underlay_pitch_in_pixels;
+	enum bw_defines underlay_stereo_mode;
+	bool d0_fbc_enable;
+	bool d0_lpt_enable;
+	uint32_t d0_htotal;
+	struct bw_fixed d0_pixel_rate;
+	uint32_t d0_graphics_src_width;
+	uint32_t d0_graphics_src_height;
+	struct bw_fixed d0_graphics_scale_ratio;
+	enum bw_defines d0_graphics_stereo_mode;
+	enum bw_defines d0_underlay_mode;
+	struct bw_fixed d0_underlay_scale_ratio;
+	uint32_t d1_htotal;
+	struct bw_fixed d1_pixel_rate;
+	uint32_t d1_graphics_src_width;
+	uint32_t d1_graphics_src_height;
+	struct bw_fixed d1_graphics_scale_ratio;
+	enum bw_defines d1_graphics_stereo_mode;
+	bool d1_display_write_back_dwb_enable;
+	enum bw_defines d1_underlay_mode;
+	struct bw_fixed d1_underlay_scale_ratio;
+	uint32_t d2_htotal;
+	struct bw_fixed d2_pixel_rate;
+	uint32_t d2_graphics_src_width;
+	uint32_t d2_graphics_src_height;
+	struct bw_fixed d2_graphics_scale_ratio;
+	enum bw_defines d2_graphics_stereo_mode;
+};
+
+
+struct bw_calcs_input_single_display {
+	uint32_t graphics_rotation_angle;
+	uint32_t underlay_rotation_angle;
+	enum bw_defines underlay_surface_type;
+	enum bw_defines panning_and_bezel_adjustment;
+	uint32_t graphics_bytes_per_pixel;
+	bool graphics_interlace_mode;
+	enum bw_defines graphics_tiling_mode;
+	uint32_t graphics_h_taps;
+	uint32_t graphics_v_taps;
+	uint32_t graphics_lb_bpc;
+	uint32_t underlay_lb_bpc;
+	enum bw_defines underlay_tiling_mode;
+	uint32_t underlay_h_taps;
+	uint32_t underlay_v_taps;
+	uint32_t underlay_src_width;
+	uint32_t underlay_src_height;
+	uint32_t underlay_pitch_in_pixels;
+	enum bw_defines underlay_stereo_mode;
+	bool fbc_enable;
+	bool lpt_enable;
+	uint32_t h_total;
+	struct bw_fixed pixel_rate;
+	uint32_t graphics_src_width;
+	uint32_t graphics_src_height;
+	struct bw_fixed graphics_scale_ratio;
+	enum bw_defines graphics_stereo_mode;
+	enum bw_defines underlay_mode;
+};
+
+#define BW_CALCS_MAX_NUM_DISPLAYS 3
+
+struct bw_calcs_mode_data {
+	/* data for all displays */
+	uint8_t number_of_displays;
+	bool display_synchronization_enabled;
+
+	struct bw_calcs_input_single_display
+				displays_data[BW_CALCS_MAX_NUM_DISPLAYS];
+};
+
+/*******************************************************************************
+ * Output data structure(s).
+ ******************************************************************************/
+#define maximum_number_of_surfaces 12
+/*Units : MHz, us */
+struct bw_calcs_results {
+	bool cpup_state_change_enable;
+	bool cpuc_state_change_enable;
+	bool nbp_state_change_enable;
+	bool stutter_mode_enable;
+	uint32_t y_clk_level;
+	uint32_t sclk_level;
+	uint32_t number_of_underlay_surfaces;
+	struct bw_fixed src_width_after_surface_type;
+	struct bw_fixed src_height_after_surface_type;
+	struct bw_fixed hsr_after_surface_type;
+	struct bw_fixed vsr_after_surface_type;
+	struct bw_fixed src_width_after_rotation;
+	struct bw_fixed src_height_after_rotation;
+	struct bw_fixed hsr_after_rotation;
+	struct bw_fixed vsr_after_rotation;
+	struct bw_fixed source_height_pixels;
+	struct bw_fixed hsr_after_stereo;
+	struct bw_fixed vsr_after_stereo;
+	struct bw_fixed source_width_in_lb;
+	struct bw_fixed lb_line_pitch;
+	struct bw_fixed underlay_maximum_source_efficient_for_tiling;
+	struct bw_fixed num_lines_at_frame_start;
+	struct bw_fixed min_dmif_size_in_time;
+	struct bw_fixed min_mcifwr_size_in_time;
+	struct bw_fixed total_requests_for_dmif_size;
+	struct bw_fixed peak_pte_request_to_eviction_ratio_limiting;
+	struct bw_fixed useful_pte_per_pte_request;
+	struct bw_fixed scatter_gather_pte_request_rows;
+	struct bw_fixed scatter_gather_row_height;
+	struct bw_fixed scatter_gather_pte_requests_in_vblank;
+	struct bw_fixed inefficient_linear_pitch_in_bytes;
+	struct bw_fixed inefficient_underlay_pitch_in_pixels;
+	struct bw_fixed minimum_underlay_pitch_padding_recommended_for_efficiency;
+	struct bw_fixed cursor_total_data;
+	struct bw_fixed cursor_total_request_groups;
+	struct bw_fixed scatter_gather_total_pte_requests;
+	struct bw_fixed scatter_gather_total_pte_request_groups;
+	struct bw_fixed tile_width_in_pixels;
+	struct bw_fixed dmif_total_number_of_data_request_page_close_open;
+	struct bw_fixed mcifwr_total_number_of_data_request_page_close_open;
+	struct bw_fixed bytes_per_page_close_open;
+	struct bw_fixed mcifwr_total_page_close_open_time;
+	struct bw_fixed total_requests_for_adjusted_dmif_size;
+	struct bw_fixed total_dmifmc_urgent_trips;
+	struct bw_fixed total_dmifmc_urgent_latency;
+	struct bw_fixed total_display_reads_required_data;
+	struct bw_fixed total_display_reads_required_dram_access_data;
+	struct bw_fixed total_display_writes_required_data;
+	struct bw_fixed total_display_writes_required_dram_access_data;
+	struct bw_fixed display_reads_required_data;
+	struct bw_fixed display_reads_required_dram_access_data;
+	struct bw_fixed dmif_total_page_close_open_time;
+	struct bw_fixed min_cursor_memory_interface_buffer_size_in_time;
+	struct bw_fixed min_read_buffer_size_in_time;
+	struct bw_fixed display_reads_time_for_data_transfer;
+	struct bw_fixed display_writes_time_for_data_transfer;
+	struct bw_fixed dmif_required_dram_bandwidth;
+	struct bw_fixed mcifwr_required_dram_bandwidth;
+	struct bw_fixed required_dmifmc_urgent_latency_for_page_close_open;
+	struct bw_fixed required_mcifmcwr_urgent_latency;
+	struct bw_fixed required_dram_bandwidth_gbyte_per_second;
+	struct bw_fixed dram_bandwidth;
+	struct bw_fixed dmif_required_sclk;
+	struct bw_fixed mcifwr_required_sclk;
+	struct bw_fixed required_sclk;
+	struct bw_fixed downspread_factor;
+	struct bw_fixed v_scaler_efficiency;
+	struct bw_fixed scaler_limits_factor;
+	struct bw_fixed display_pipe_pixel_throughput;
+	struct bw_fixed total_dispclk_required_with_ramping;
+	struct bw_fixed total_dispclk_required_without_ramping;
+	struct bw_fixed total_read_request_bandwidth;
+	struct bw_fixed total_write_request_bandwidth;
+	struct bw_fixed dispclk_required_for_total_read_request_bandwidth;
+	struct bw_fixed total_dispclk_required_with_ramping_with_request_bandwidth;
+	struct bw_fixed total_dispclk_required_without_ramping_with_request_bandwidth;
+	struct bw_fixed dispclk;
+	struct bw_fixed blackout_recovery_time;
+	struct bw_fixed min_pixels_per_data_fifo_entry;
+	struct bw_fixed sclk_deep_sleep;
+	struct bw_fixed chunk_request_time;
+	struct bw_fixed cursor_request_time;
+	struct bw_fixed line_source_pixels_transfer_time;
+	struct bw_fixed dmifdram_access_efficiency;
+	struct bw_fixed mcifwrdram_access_efficiency;
+	struct bw_fixed total_average_bandwidth_no_compression;
+	struct bw_fixed total_average_bandwidth;
+	struct bw_fixed total_stutter_cycle_duration;
+	struct bw_fixed stutter_burst_time;
+	struct bw_fixed time_in_self_refresh;
+	struct bw_fixed stutter_efficiency;
+	struct bw_fixed worst_number_of_trips_to_memory;
+	struct bw_fixed immediate_flip_time;
+	struct bw_fixed latency_for_non_dmif_clients;
+	struct bw_fixed latency_for_non_mcifwr_clients;
+	struct bw_fixed dmifmc_urgent_latency_supported_in_high_sclk_and_yclk;
+	struct bw_fixed nbp_state_dram_speed_change_margin;
+	struct bw_fixed display_reads_time_for_data_transfer_and_urgent_latency;
+	bool displays_match_flag[maximum_number_of_surfaces];
+	bool use_alpha[maximum_number_of_surfaces];
+	bool orthogonal_rotation[maximum_number_of_surfaces];
+	bool enable[maximum_number_of_surfaces];
+	bool access_one_channel_only[maximum_number_of_surfaces];
+	bool scatter_gather_enable_for_pipe[maximum_number_of_surfaces];
+	bool interlace_mode[maximum_number_of_surfaces];
+	bool display_pstate_change_enable[maximum_number_of_surfaces];
+	struct bw_fixed dmif_buffer_transfer_time[maximum_number_of_surfaces];
+	struct bw_fixed displays_with_same_mode[maximum_number_of_surfaces];
+	uint32_t bytes_per_pixel[maximum_number_of_surfaces];
+	struct bw_fixed h_total[maximum_number_of_surfaces];
+	struct bw_fixed pixel_rate[maximum_number_of_surfaces];
+	struct bw_fixed src_width[maximum_number_of_surfaces];
+	struct bw_fixed pitch_in_pixels[maximum_number_of_surfaces];
+	struct bw_fixed pitch_in_pixels_after_surface_type[maximum_number_of_surfaces];
+	struct bw_fixed src_height[maximum_number_of_surfaces];
+	struct bw_fixed scale_ratio[maximum_number_of_surfaces];
+	struct bw_fixed h_taps[maximum_number_of_surfaces];
+	struct bw_fixed v_taps[maximum_number_of_surfaces];
+	struct bw_fixed rotation_angle[maximum_number_of_surfaces];
+	uint32_t lb_bpc[maximum_number_of_surfaces];
+	struct bw_fixed compression_rate[maximum_number_of_surfaces];
+	struct bw_fixed hsr[maximum_number_of_surfaces];
+	struct bw_fixed vsr[maximum_number_of_surfaces];
+	struct bw_fixed source_width_rounded_up_to_chunks[maximum_number_of_surfaces];
+	struct bw_fixed source_width_pixels[maximum_number_of_surfaces];
+	struct bw_fixed source_height_rounded_up_to_chunks[maximum_number_of_surfaces];
+	struct bw_fixed display_bandwidth[maximum_number_of_surfaces];
+	struct bw_fixed request_bandwidth[maximum_number_of_surfaces];
+	struct bw_fixed bytes_per_request[maximum_number_of_surfaces];
+	struct bw_fixed useful_bytes_per_request[maximum_number_of_surfaces];
+	struct bw_fixed lines_interleaved_in_mem_access[maximum_number_of_surfaces];
+	struct bw_fixed latency_hiding_lines[maximum_number_of_surfaces];
+	struct bw_fixed lb_partitions[maximum_number_of_surfaces];
+	struct bw_fixed lb_partitions_max[maximum_number_of_surfaces];
+	struct bw_fixed dispclk_required_with_ramping[maximum_number_of_surfaces];
+	struct bw_fixed dispclk_required_without_ramping[maximum_number_of_surfaces];
+	struct bw_fixed data_buffer_size[maximum_number_of_surfaces];
+	struct bw_fixed outstanding_chunk_request_limit[maximum_number_of_surfaces];
+	struct bw_fixed urgent_watermark[maximum_number_of_surfaces];
+	struct bw_fixed stutter_exit_watermark[maximum_number_of_surfaces];
+	struct bw_fixed nbp_state_change_watermark[maximum_number_of_surfaces];
+	struct bw_fixed v_filter_init[maximum_number_of_surfaces];
+	struct bw_fixed stutter_cycle_duration[maximum_number_of_surfaces];
+	struct bw_fixed average_bandwidth[maximum_number_of_surfaces];
+	struct bw_fixed average_bandwidth_no_compression[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_pte_request_limit[maximum_number_of_surfaces];
+	struct bw_fixed lb_size_per_component[maximum_number_of_surfaces];
+	struct bw_fixed memory_chunk_size_in_bytes[maximum_number_of_surfaces];
+	struct bw_fixed pipe_chunk_size_in_bytes[maximum_number_of_surfaces];
+	struct bw_fixed number_of_trips_to_memory_for_getting_apte_row[maximum_number_of_surfaces];
+	struct bw_fixed adjusted_data_buffer_size[maximum_number_of_surfaces];
+	struct bw_fixed adjusted_data_buffer_size_in_memory[maximum_number_of_surfaces];
+	struct bw_fixed pixels_per_data_fifo_entry[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_pte_requests_in_row[maximum_number_of_surfaces];
+	struct bw_fixed pte_request_per_chunk[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_page_width[maximum_number_of_surfaces];
+	struct bw_fixed scatter_gather_page_height[maximum_number_of_surfaces];
+	struct bw_fixed lb_lines_in_per_line_out_in_beginning_of_frame[maximum_number_of_surfaces];
+	struct bw_fixed lb_lines_in_per_line_out_in_middle_of_frame[maximum_number_of_surfaces];
+	struct bw_fixed cursor_width_pixels[maximum_number_of_surfaces];
+	bool line_buffer_prefetch[maximum_number_of_surfaces];
+	struct bw_fixed minimum_latency_hiding[maximum_number_of_surfaces];
+	struct bw_fixed maximum_latency_hiding[maximum_number_of_surfaces];
+	struct bw_fixed minimum_latency_hiding_with_cursor[maximum_number_of_surfaces];
+	struct bw_fixed maximum_latency_hiding_with_cursor[maximum_number_of_surfaces];
+	struct bw_fixed src_pixels_for_first_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed src_pixels_for_last_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed src_data_for_first_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed src_data_for_last_output_pixel[maximum_number_of_surfaces];
+	struct bw_fixed active_time[maximum_number_of_surfaces];
+	struct bw_fixed horizontal_blank_and_chunk_granularity_factor[maximum_number_of_surfaces];
+	struct bw_fixed cursor_latency_hiding[maximum_number_of_surfaces];
+	struct bw_fixed dmif_burst_time[3][3];
+	struct bw_fixed mcifwr_burst_time[3][3];
+	struct bw_fixed line_source_transfer_time[maximum_number_of_surfaces][3][3];
+	struct bw_fixed dram_speed_change_line_source_transfer_time[maximum_number_of_surfaces][3][3];
+	struct bw_fixed min_dram_speed_change_margin[3][3];
+	struct bw_fixed dram_speed_change_margin[3][3];
+	struct bw_fixed dispclk_required_for_dram_speed_change[3][3];
+	struct bw_fixed blackout_duration_margin[3][3];
+	struct bw_fixed dispclk_required_for_blackout_duration[3][3];
+	struct bw_fixed dispclk_required_for_blackout_recovery[3][3];
+	struct bw_fixed dmif_required_sclk_for_urgent_latency[6];
+};
+
+struct bw_watermarks {
+	uint32_t a_mark;
+	uint32_t b_mark;
+};
+
+struct bw_calcs_output {
+	bool cpuc_state_change_enable;
+	bool cpup_state_change_enable;
+	bool stutter_mode_enable;
+	bool nbp_state_change_enable;
+	bool all_displays_in_sync;
+	struct bw_watermarks urgent_wm_ns[4];
+	struct bw_watermarks stutter_exit_wm_ns[4];
+	struct bw_watermarks nbp_state_change_wm_ns[4];
+	uint32_t required_sclk;
+	uint32_t required_sclk_deep_sleep;
+	uint32_t required_yclk;
+	uint32_t dispclk_khz;
+	int32_t required_blackout_duration_us;
+};
+
+
+/**
+ * Initialize structures with data which will NOT change at runtime.
+ */
+void bw_calcs_init(
+	struct bw_calcs_dceip *bw_dceip,
+	struct bw_calcs_vbios *bw_vbios);
+
+/**
+ * Return:
+ *	true -	Display(s) configuration supported.
+ *		In this case 'calcs_output' contains data for HW programming
+ *	false - Display(s) configuration not supported (not enough bandwidth).
+ */
+bool bw_calcs(
+	struct dc_context *ctx,
+	const struct bw_calcs_dceip *dceip,
+	const struct bw_calcs_vbios *vbios,
+	const struct bw_calcs_mode_data *mode_data,
+	struct bw_calcs_output *calcs_output);
+
+
+#endif /* __BANDWIDTH_CALCS_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h b/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
new file mode 100644
index 000000000000..ff271cc0aea1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/bw_fixed.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef BW_FIXED_H_
+#define BW_FIXED_H_
+
+struct bw_fixed {
+	int64_t value;
+};
+
+struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3);
+
+struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3);
+
+struct bw_fixed bw_int_to_fixed(int64_t value);
+
+int32_t bw_fixed_to_int(struct bw_fixed value);
+
+struct bw_fixed bw_frc_to_fixed(int64_t num, int64_t denum);
+
+struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw);
+
+struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2);
+
+struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2);
+struct bw_fixed bw_floor2(const struct bw_fixed arg, const struct bw_fixed significance);
+struct bw_fixed bw_ceil2(const struct bw_fixed arg, const struct bw_fixed significance);
+
+bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2);
+bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2);
+
+
+#endif //BW_FIXED_H_
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h b/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
new file mode 100644
index 000000000000..0120ee23e6be
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_CLOCK_SOURCE_H__
+#define __DC_CLOCK_SOURCE_H__
+
+#include "dc_types.h"
+#include "include/grph_object_id.h"
+#include "include/bios_parser_types.h"
+
+struct clock_source;
+
+struct spread_spectrum_data {
+	uint32_t percentage;		/*> In unit of 0.01% or 0.001%*/
+	uint32_t percentage_divider;	/*> 100 or 1000	*/
+	uint32_t freq_range_khz;
+	uint32_t modulation_freq_hz;
+
+	struct spread_spectrum_flags flags;
+};
+
+struct delta_sigma_data {
+	uint32_t feedback_amount;
+	uint32_t nfrac_amount;
+	uint32_t ds_frac_size;
+	uint32_t ds_frac_amount;
+};
+
+/**
+ *  Pixel Clock Parameters structure
+ *  These parameters are required as input
+ *  when calculating Pixel Clock Dividers for requested Pixel Clock
+ */
+struct pixel_clk_flags {
+	uint32_t ENABLE_SS:1;
+	uint32_t DISPLAY_BLANKED:1;
+	uint32_t PROGRAM_PIXEL_CLOCK:1;
+	uint32_t PROGRAM_ID_CLOCK:1;
+};
+
+/**
+ *  Display Port HW De spread of Reference Clock related Parameters structure
+ *  Store it once at boot for later usage
+  */
+struct csdp_ref_clk_ds_params {
+	bool hw_dso_n_dp_ref_clk;
+/* Flag for HW De Spread enabled (if enabled SS on DP Reference Clock)*/
+	uint32_t avg_dp_ref_clk_khz;
+/* Average DP Reference clock (in KHz)*/
+	uint32_t ss_percentage_on_dp_ref_clk;
+/* DP Reference clock SS percentage
+ * (not to be mixed with DP IDCLK SS from PLL Settings)*/
+	uint32_t ss_percentage_divider;
+/* DP Reference clock SS percentage divider */
+};
+
+struct pixel_clk_params {
+	uint32_t requested_pix_clk; /* in KHz */
+/*> Requested Pixel Clock
+ * (based on Video Timing standard used for requested mode)*/
+	uint32_t requested_sym_clk; /* in KHz */
+/*> Requested Sym Clock (relevant only for display port)*/
+	uint32_t dp_ref_clk; /* in KHz */
+/*> DP reference clock - calculated only for DP signal for specific cases*/
+	struct graphics_object_id encoder_object_id;
+/*> Encoder object Id - needed by VBIOS Exec table*/
+	enum signal_type signal_type;
+/*> signalType -> Encoder Mode - needed by VBIOS Exec table*/
+	enum controller_id controller_id;
+/*> ControllerId - which controller using this PLL*/
+	enum dc_color_depth color_depth;
+	struct csdp_ref_clk_ds_params de_spread_params;
+/*> de-spread info, relevant only for on-the-fly tune-up pixel rate*/
+
+	struct pixel_clk_flags flags;
+};
+
+/**
+ *  Pixel Clock Dividers structure with desired Pixel Clock
+ *  (adjusted after VBIOS exec table),
+ *  with actually calculated Clock and reference Crystal frequency
+ */
+struct pll_settings {
+	uint32_t actual_pix_clk;
+	uint32_t adjusted_pix_clk;
+	uint32_t calculated_pix_clk;
+	uint32_t vco_freq;
+	uint32_t reference_freq;
+	uint32_t reference_divider;
+	uint32_t feedback_divider;
+	uint32_t fract_feedback_divider;
+	uint32_t pix_clk_post_divider;
+	uint32_t ss_percentage;
+	bool use_external_clk;
+};
+
+struct calc_pll_clock_source_init_data {
+	struct dc_bios *bp;
+	uint32_t min_pix_clk_pll_post_divider;
+	uint32_t max_pix_clk_pll_post_divider;
+	uint32_t min_pll_ref_divider;
+	uint32_t max_pll_ref_divider;
+	uint32_t min_override_input_pxl_clk_pll_freq_khz;
+/* if not 0, override the firmware info */
+
+	uint32_t max_override_input_pxl_clk_pll_freq_khz;
+/* if not 0, override the firmware info */
+
+	uint32_t num_fract_fb_divider_decimal_point;
+/* number of decimal point for fractional feedback divider value */
+
+	uint32_t num_fract_fb_divider_decimal_point_precision;
+/* number of decimal point to round off for fractional feedback divider value*/
+	struct dc_context *ctx;
+
+};
+
+struct calc_pll_clock_source {
+	uint32_t ref_freq_khz;
+	uint32_t min_pix_clock_pll_post_divider;
+	uint32_t max_pix_clock_pll_post_divider;
+	uint32_t min_pll_ref_divider;
+	uint32_t max_pll_ref_divider;
+
+	uint32_t max_vco_khz;
+	uint32_t min_vco_khz;
+	uint32_t min_pll_input_freq_khz;
+	uint32_t max_pll_input_freq_khz;
+
+	uint32_t fract_fb_divider_decimal_points_num;
+	uint32_t fract_fb_divider_factor;
+	uint32_t fract_fb_divider_precision;
+	uint32_t fract_fb_divider_precision_factor;
+	struct dc_context *ctx;
+};
+
+struct clock_source_funcs {
+	bool (*cs_power_down)(
+			struct clock_source *);
+	bool (*program_pix_clk)(struct clock_source *,
+			struct pixel_clk_params *, struct pll_settings *);
+	uint32_t (*get_pix_clk_dividers)(
+			struct clock_source *,
+			struct pixel_clk_params *,
+			struct pll_settings *);
+};
+
+struct clock_source {
+	struct clock_source_funcs *funcs;
+	struct dc_context *ctx;
+	enum clock_source_id id;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/compressor.h b/drivers/gpu/drm/amd/dal/dc/inc/compressor.h
new file mode 100644
index 000000000000..4992ffde7c9a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/compressor.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMPRESSOR_H__
+#define __DAL_COMPRESSOR_H__
+
+#include "include/grph_object_id.h"
+
+enum fbc_compress_ratio {
+	FBC_COMPRESS_RATIO_INVALID = 0,
+	FBC_COMPRESS_RATIO_1TO1 = 1,
+	FBC_COMPRESS_RATIO_2TO1 = 2,
+	FBC_COMPRESS_RATIO_4TO1 = 4,
+	FBC_COMPRESS_RATIO_8TO1 = 8,
+};
+
+union fbc_physical_address {
+	struct {
+		uint32_t low_part;
+		int32_t high_part;
+	} addr;
+};
+
+struct compr_addr_and_pitch_params {
+	uint32_t inst;
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+};
+
+struct fbc_lpt_config {
+	uint32_t mem_channels_num;
+	uint32_t banks_num;
+	uint32_t chan_interleave_size;
+	uint32_t row_size;
+};
+
+struct fbc_input_info {
+	bool dynamic_fbc_buffer_alloc;
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+	uint32_t active_targets_num;
+	struct fbc_lpt_config lpt_config;
+};
+
+struct fbc_requested_compressed_size {
+	uint32_t preferred_size;
+	uint32_t preferred_size_alignment;
+	uint32_t min_size;
+	uint32_t min_size_alignment;
+	union {
+		struct {
+			/*Above preferred_size must be allocated in FB pool */
+			uint32_t PREFERRED_MUST_BE_FRAME_BUFFER_POOL:1;
+			/*Above min_size must be allocated in FB pool */
+			uint32_t MIN_MUST_BE_FRAME_BUFFER_POOL:1;
+		} flags;
+		uint32_t bits;
+	};
+};
+
+struct fbc_compressed_surface_info {
+	union fbc_physical_address compressed_surface_address;
+	uint32_t allocated_size;
+	union {
+		struct {
+			uint32_t FB_POOL:1; /*Allocated in FB Pool */
+			uint32_t DYNAMIC_ALLOC:1; /*Dynamic allocation */
+		} allocation_flags;
+		uint32_t bits;
+	};
+};
+
+enum fbc_hw_max_resolution_supported {
+	FBC_MAX_X = 3840,
+	FBC_MAX_Y = 2400
+};
+
+struct fbc_max_resolution_supported {
+	uint32_t source_view_width;
+	uint32_t source_view_height;
+};
+
+struct compressor {
+	struct dc_context *ctx;
+	uint32_t attached_inst;
+	bool is_enabled;
+
+	union {
+		uint32_t raw;
+		struct {
+			uint32_t FBC_SUPPORT:1;
+			uint32_t FB_POOL:1;
+			uint32_t DYNAMIC_ALLOC:1;
+			uint32_t LPT_SUPPORT:1;
+			uint32_t LPT_MC_CONFIG:1;
+			uint32_t DUMMY_BACKEND:1;
+			uint32_t CLK_GATING_DISABLED:1;
+
+		} bits;
+	} options;
+
+	union fbc_physical_address compr_surface_address;
+
+	uint32_t embedded_panel_h_size;
+	uint32_t embedded_panel_v_size;
+	uint32_t memory_bus_width;
+	uint32_t banks_num;
+	uint32_t raw_size;
+	uint32_t channel_interleave_size;
+	uint32_t dram_channels_num;
+
+	uint32_t allocated_size;
+	uint32_t preferred_requested_size;
+	uint32_t lpt_channels_num;
+	enum fbc_compress_ratio min_compress_ratio;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h b/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
new file mode 100644
index 000000000000..3e66ad7ea72d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_dc.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __CORE_DC_H__
+#define __CORE_DC_H__
+
+#include "core_types.h"
+#include "hw_sequencer.h"
+
+struct dc {
+	struct dc_context *ctx;
+
+	uint8_t link_count;
+	struct core_link *links[MAX_PIPES * 2];
+
+	/* TODO: determine max number of targets*/
+	struct validate_context current_context;
+	struct resource_pool res_pool;
+
+	/*Power State*/
+	enum dc_video_power_state previous_power_state;
+	enum dc_video_power_state current_power_state;
+
+	/* Inputs into BW and WM calculations. */
+	struct bw_calcs_dceip bw_dceip;
+	struct bw_calcs_vbios bw_vbios;
+
+	/* HW functions */
+	struct hw_sequencer_funcs hwss;
+};
+
+#endif /* __CORE_DC_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_status.h b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h
new file mode 100644
index 000000000000..9682cf866886
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_status.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _CORE_STATUS_H_
+#define _CORE_STATUS_H_
+
+enum dc_status {
+	DC_OK = 1,
+
+	DC_NO_CONTROLLER_RESOURCE,
+	DC_NO_STREAM_ENG_RESOURCE,
+	DC_NO_STREAM_AUDIO_RESOURCE,
+	DC_NO_CLOCK_SOURCE_RESOURCE,
+	DC_FAIL_CONTROLLER_VALIDATE,
+	DC_FAIL_ENC_VALIDATE,
+	DC_FAIL_ATTACH_SURFACES,
+	DC_NO_DP_LINK_BANDWIDTH,
+	DC_EXCEED_DONGLE_MAX_CLK,
+	DC_FAIL_BANDWIDTH_VALIDATE, /* BW and Watermark validation */
+
+	DC_ERROR_UNEXPECTED = -1
+};
+
+#endif /* _CORE_STATUS_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
new file mode 100644
index 000000000000..7d63ebb8e789
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _CORE_TYPES_H_
+#define _CORE_TYPES_H_
+
+#include "dc.h"
+#include "bandwidth_calcs.h"
+#include "ddc_service_types.h"
+
+struct core_stream;
+/********* core_target *************/
+
+#define CONST_DC_TARGET_TO_CORE(dc_target) \
+	container_of(dc_target, const struct core_target, public)
+#define DC_TARGET_TO_CORE(dc_target) \
+	container_of(dc_target, struct core_target, public)
+
+#define MAX_PIPES 6
+#define MAX_STREAMS 6
+#define MAX_CLOCK_SOURCES 7
+
+struct core_target {
+	struct dc_target public;
+	struct dc_target_status status;
+
+	struct dc_context *ctx;
+};
+
+/********* core_surface **********/
+#define DC_SURFACE_TO_CORE(dc_surface) \
+	container_of(dc_surface, struct core_surface, public)
+
+struct core_surface {
+	struct dc_surface public;
+	struct dc_surface_status status;
+	struct dc_context *ctx;
+};
+
+void enable_surface_flip_reporting(struct dc_surface *dc_surface,
+		uint32_t controller_id);
+
+/********* core_stream ************/
+#include "grph_object_id.h"
+#include "link_encoder.h"
+#include "stream_encoder.h"
+#include "clock_source.h"
+#include "audio_interface.h"
+#include "scaler_types.h"
+#include "hw_sequencer_types.h"
+#include "opp.h"
+
+#define DC_STREAM_TO_CORE(dc_stream) container_of( \
+	dc_stream, struct core_stream, public)
+
+#define PIXEL_CLOCK	27030
+
+struct core_stream {
+	struct dc_stream public;
+
+	/* field internal to DC */
+	const struct core_sink *sink;
+
+	struct clock_source *clock_source;
+
+	struct mem_input *mi;
+	struct input_pixel_processor *ipp;
+	struct transform *xfm;
+	struct output_pixel_processor *opp;
+	struct timing_generator *tg;
+	struct stream_encoder *stream_enc;
+	struct display_clock *dis_clk;
+
+	struct overscan_info overscan;
+	struct scaling_ratios ratios;
+	struct rect viewport;
+	struct scaling_taps taps;
+	enum pixel_format format;
+
+	uint8_t controller_idx;
+
+	struct audio *audio;
+
+	enum signal_type signal;
+
+	/* TODO: move these members into appropriate places (work in progress)*/
+	/* timing validation (HDMI only) */
+	uint32_t max_tmds_clk_from_edid_in_mhz;
+	/* maximum supported deep color depth for HDMI */
+	enum dc_color_depth max_hdmi_deep_color;
+	/* maximum supported pixel clock for HDMI */
+	uint32_t max_hdmi_pixel_clock;
+	/* end of TODO */
+
+	/*TODO: AUTO merge if possible*/
+	struct pixel_clk_params pix_clk_params;
+	struct pll_settings pll_settings;
+
+	/*fmt*/
+	/*TODO: AUTO new codepath in apply_context to hw to
+	 * generate these bw unrelated/no fail params*/
+	struct bit_depth_reduction_params bit_depth_params;/* used by DCP and FMT */
+	struct clamping_and_pixel_encoding_params clamping;
+	struct hw_info_frame info_frame;
+	struct encoder_info_frame encoder_info_frame;
+
+	struct audio_output audio_output;
+	struct dc_context *ctx;
+};
+
+
+/************ core_sink *****************/
+
+#define DC_SINK_TO_CORE(dc_sink) \
+	container_of(dc_sink, struct core_sink, public)
+
+struct core_sink {
+	/** The public, read-only (for DM) area of sink. **/
+	struct dc_sink public;
+	/** End-of-public area. **/
+
+	/** The 'protected' area - read/write access, for use only inside DC **/
+	/* not used for now */
+	struct core_link *link;
+	struct dc_context *ctx;
+	uint32_t dongle_max_pix_clk;
+	bool converter_disable_audio;
+};
+
+/************ link *****************/
+#define DC_LINK_TO_CORE(dc_link) container_of(dc_link, struct core_link, public)
+
+struct link_init_data {
+	const struct dc *dc;
+	struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */
+	uint32_t connector_index; /* this will be mapped to the HPD pins */
+	uint32_t link_index; /* this is mapped to DAL display_index
+				TODO: remove it when DC is complete. */
+	struct adapter_service *adapter_srv;
+};
+
+struct link_caps {
+	/* support for Spread Spectrum(SS) */
+	bool ss_supported;
+	/* DP link settings (laneCount, linkRate, Spread) */
+	uint32_t lane_count;
+	uint32_t rate;
+	uint32_t spread;
+	enum dpcd_revision dpcd_revision;
+};
+
+struct dpcd_caps {
+	union dpcd_rev dpcd_rev;
+	union max_lane_count max_ln_count;
+
+	/* dongle type (DP converter, CV smart dongle) */
+	enum display_dongle_type dongle_type;
+	/* Dongle's downstream count. */
+	union sink_count sink_count;
+	/* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER,
+	indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/
+	bool is_dp_hdmi_s3d_converter;
+
+	bool allow_invalid_MSA_timing_param;
+	bool panel_mode_edp;
+	uint32_t sink_dev_id;
+	uint32_t branch_dev_id;
+	int8_t branch_dev_name[6];
+};
+
+union dp_wa {
+	struct {
+		/* keep DP receiver powered up on DisplayOutput */
+		uint32_t KEEP_RECEIVER_POWERED:1;
+
+		/* TODO: may add other member in.*/
+	} bits;
+	uint32_t raw;
+};
+
+/* DP MST stream allocation (payload bandwidth number) */
+struct link_mst_stream_allocation {
+	/* DIG front */
+	const struct stream_encoder *stream_enc;
+	/* associate DRM payload table with DC stream encoder */
+	uint8_t vcp_id;
+	/* number of slots required for the DP stream in transport packet */
+	uint8_t slot_count;
+};
+
+/* DP MST stream allocation table */
+struct link_mst_stream_allocation_table {
+	/* number of DP video streams */
+	int stream_count;
+	/* array of stream allocations */
+	struct link_mst_stream_allocation
+	stream_allocations[MAX_CONTROLLER_NUM];
+};
+
+struct core_link {
+	struct dc_link public;
+	const struct dc *dc;
+
+	struct dc_context *ctx; /* TODO: AUTO remove 'dal' when DC is complete*/
+
+	struct adapter_service *adapter_srv;
+	struct link_encoder *link_enc;
+	struct ddc_service *ddc;
+	struct graphics_object_id link_id;
+	union ddi_channel_mapping ddi_channel_mapping;
+	struct connector_device_tag_info device_tag;
+	/* caps is the same as reported_link_cap. link_traing use
+	 * reported_link_cap. Will clean up.  TODO */
+	struct link_settings reported_link_cap;
+	struct link_settings verified_link_cap;
+	struct link_settings max_link_setting;
+	struct link_settings cur_link_settings;
+	struct lane_settings ln_setting;
+	struct dpcd_caps dpcd_caps;
+	unsigned int dpcd_sink_count;
+
+	enum edp_revision edp_revision;
+
+	/* MST record stream using this link */
+	struct link_flags {
+		bool dp_keep_receiver_powered;
+	} wa_flags;
+	struct link_mst_stream_allocation_table mst_stream_alloc_table;
+};
+
+#define DC_LINK_TO_LINK(dc_link) container_of(dc_link, struct core_link, public)
+
+struct core_link *link_create(const struct link_init_data *init_params);
+void link_destroy(struct core_link **link);
+
+enum dc_status dc_link_validate_mode_timing(
+		const struct core_sink *sink,
+		struct core_link *link,
+		const struct dc_crtc_timing *timing);
+
+void core_link_resume(struct core_link *link);
+
+void core_link_enable_stream(
+		struct core_link *link,
+		struct core_stream *stream);
+
+void core_link_disable_stream(
+		struct core_link *link,
+		struct core_stream *stream);
+
+/********** DAL Core*********************/
+#include "display_clock_interface.h"
+
+struct resource_pool;
+struct validate_context;
+
+struct resource_funcs {
+	void (*destruct)(struct resource_pool *pool);
+	struct link_encoder *(*link_enc_create)(
+			const struct encoder_init_data *init);
+	void (*link_enc_destroy)(struct link_encoder **enc);
+	enum dc_status (*validate_with_context)(
+					const struct dc *dc,
+					const struct dc_validation_set set[],
+					uint8_t set_count,
+					struct validate_context *context);
+
+	enum dc_status (*validate_bandwidth)(
+					const struct dc *dc,
+					struct validate_context *context);
+};
+
+struct resource_pool {
+	struct scaler_filter * scaler_filter;
+
+	struct mem_input *mis[MAX_PIPES];
+	struct input_pixel_processor *ipps[MAX_PIPES];
+	struct transform *transforms[MAX_PIPES];
+	struct output_pixel_processor *opps[MAX_PIPES];
+	struct timing_generator *timing_generators[MAX_STREAMS];
+	struct stream_encoder *stream_enc[MAX_PIPES * 2];
+
+	uint8_t controller_count;
+	uint8_t stream_enc_count;
+
+	union supported_stream_engines stream_engines;
+
+	struct clock_source *clock_sources[MAX_CLOCK_SOURCES];
+	uint8_t clk_src_count;
+
+	struct audio *audios[MAX_STREAMS];
+	uint8_t audio_count;
+
+	struct display_clock *display_clock;
+	struct adapter_service *adapter_srv;
+	struct irq_service *irqs;
+
+	struct resource_funcs *funcs;
+};
+
+struct controller_ctx {
+	struct core_surface *surface;
+	struct core_stream *stream;
+	struct flags {
+		bool unchanged;
+		bool timing_changed;
+	} flags;
+};
+
+struct resource_context {
+	struct resource_pool pool;
+	struct controller_ctx controller_ctx[MAX_PIPES];
+	union supported_stream_engines used_stream_engines;
+	bool is_stream_enc_acquired[MAX_PIPES * 2];
+	bool is_audio_acquired[MAX_STREAMS];
+	uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES];
+ };
+
+struct target_flags {
+	bool unchanged;
+};
+struct validate_context {
+	struct core_target *targets[MAX_PIPES];
+	struct target_flags target_flags[MAX_PIPES];
+	uint8_t target_count;
+
+	struct resource_context res_ctx;
+
+	struct bw_calcs_mode_data bw_mode_data;
+	/* The output from BW and WM calculations. */
+	struct bw_calcs_output bw_results;
+};
+
+
+#endif /* _CORE_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
new file mode 100644
index 000000000000..088afce646c6
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_ddc.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DDC_SERVICE_H__
+#define __DAL_DDC_SERVICE_H__
+
+#include "include/ddc_service_types.h"
+#include "include/i2caux_interface.h"
+
+#define EDID_SEGMENT_SIZE 256
+
+struct ddc_service;
+struct adapter_service;
+struct graphics_object_id;
+enum ddc_result;
+struct av_sync_data;
+struct dp_receiver_id_info;
+
+struct i2c_payloads;
+struct aux_payloads;
+
+struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count);
+struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p);
+uint32_t  dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p);
+void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p);
+
+struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count);
+struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p);
+uint32_t dal_ddc_aux_payloads_get_count(struct aux_payloads *p);
+void dal_ddc_aux_payloads_destroy(struct aux_payloads **p);
+
+void dal_ddc_i2c_payloads_add(
+		struct i2c_payloads *payloads,
+		uint32_t address,
+		uint32_t len,
+		uint8_t *data,
+		bool write);
+
+void dal_ddc_aux_payloads_add(
+		struct aux_payloads *payloads,
+		uint32_t address,
+		uint32_t len,
+		uint8_t *data,
+		bool write);
+
+struct ddc_service_init_data {
+	struct adapter_service *as;
+	struct graphics_object_id id;
+	struct dc_context *ctx;
+	struct core_link *link;
+};
+
+struct ddc_service *dal_ddc_service_create(
+		struct ddc_service_init_data *ddc_init_data);
+
+void dal_ddc_service_destroy(struct ddc_service **ddc);
+
+enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc);
+
+void dal_ddc_service_set_transaction_type(
+		struct ddc_service *ddc,
+		enum ddc_transaction_type type);
+
+bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc);
+
+uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc);
+
+uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc);
+
+void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf);
+
+void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
+		struct ddc_service *ddc,
+		struct display_sink_capability *sink_cap);
+
+bool dal_ddc_service_query_ddc_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		uint8_t *write_buf,
+		uint32_t write_size,
+		uint8_t *read_buf,
+		uint32_t read_size);
+
+bool dal_ddc_service_get_dp_receiver_id_info(
+		struct ddc_service *ddc,
+		struct dp_receiver_id_info *info);
+
+enum ddc_result dal_ddc_service_read_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t len);
+
+enum ddc_result dal_ddc_service_write_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t len);
+
+void dal_ddc_service_write_scdc_data(
+		struct ddc_service *ddc_service,
+		uint32_t pix_clk,
+		bool lte_340_scramble);
+
+void dal_ddc_service_read_scdc_data(
+		struct ddc_service *ddc_service);
+
+void ddc_service_set_dongle_type(struct ddc_service *ddc,
+		enum display_dongle_type dongle_type);
+
+void dal_ddc_service_set_ddc_pin(
+		struct ddc_service *ddc_service,
+		struct ddc *ddc);
+
+struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service);
+void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service);
+
+enum ddc_result dal_ddc_service_read_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t len);
+enum ddc_result dal_ddc_service_write_dpcd_data(
+		struct ddc_service *ddc,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t len);
+
+#endif /* __DAL_DDC_SERVICE_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
new file mode 100644
index 000000000000..682c0b432bdb
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/dc_link_dp.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_LINK_DP_H__
+#define __DC_LINK_DP_H__
+
+struct core_link;
+struct core_stream;
+struct link_settings;
+
+bool dp_hbr_verify_link_cap(
+	struct core_link *link,
+	struct link_settings *known_limit_link_setting);
+
+bool dp_validate_mode_timing(
+	struct core_link *link,
+	const struct dc_crtc_timing *timing);
+
+void decide_link_settings(
+	struct core_stream *stream,
+	struct link_settings *link_setting);
+
+bool perform_link_training(
+	struct core_link *link,
+	const struct link_settings *link_setting,
+	bool skip_video_pattern);
+
+bool is_mst_supported(struct core_link *link);
+
+void detect_dp_sink_caps(struct core_link *link);
+
+bool is_dp_active_dongle(const struct core_link *link);
+
+#endif /* __DC_LINK_DP_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h b/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
new file mode 100644
index 000000000000..17cb10f117e1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/gamma_types.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef GAMMA_TYPES_H_
+
+#define GAMMA_TYPES_H_
+
+#include "dc_types.h"
+#include "dm_services_types.h"
+
+/* TODO: Used in IPP and OPP */
+struct dev_c_lut {
+	uint8_t red;
+	uint8_t green;
+	uint8_t blue;
+};
+
+struct dev_c_lut16 {
+	uint16_t red;
+	uint16_t green;
+	uint16_t blue;
+};
+
+struct regamma_ramp {
+	uint16_t gamma[RGB_256X3X16 * 3];
+};
+
+/* used by Graphics and Overlay gamma */
+struct gamma_coeff {
+	int32_t gamma[3];
+	int32_t a0[3]; /* index 0 for red, 1 for green, 2 for blue */
+	int32_t a1[3];
+	int32_t a2[3];
+	int32_t a3[3];
+};
+
+struct regamma_lut {
+	union {
+		struct {
+			uint32_t GRAPHICS_DEGAMMA_SRGB :1;
+			uint32_t OVERLAY_DEGAMMA_SRGB :1;
+			uint32_t GAMMA_RAMP_ARRAY :1;
+			uint32_t APPLY_DEGAMMA :1;
+			uint32_t RESERVED :28;
+		} bits;
+		uint32_t value;
+	} features;
+
+	union {
+		struct regamma_ramp regamma_ramp;
+		struct gamma_coeff gamma_coeff;
+	};
+};
+
+union gamma_flag {
+	struct {
+		uint32_t config_is_changed :1;
+		uint32_t both_pipe_req :1;
+		uint32_t regamma_update :1;
+		uint32_t gamma_update :1;
+		uint32_t reserved :28;
+	} bits;
+	uint32_t u_all;
+};
+
+enum graphics_regamma_adjust {
+	GRAPHICS_REGAMMA_ADJUST_BYPASS = 0, GRAPHICS_REGAMMA_ADJUST_HW, /* without adjustments */
+	GRAPHICS_REGAMMA_ADJUST_SW /* use adjustments */
+};
+
+enum graphics_gamma_lut {
+	GRAPHICS_GAMMA_LUT_LEGACY = 0, /* use only legacy LUT */
+	GRAPHICS_GAMMA_LUT_REGAMMA, /* use only regamma LUT */
+	GRAPHICS_GAMMA_LUT_LEGACY_AND_REGAMMA /* use legacy & regamma LUT's */
+};
+
+enum graphics_degamma_adjust {
+	GRAPHICS_DEGAMMA_ADJUST_BYPASS = 0, GRAPHICS_DEGAMMA_ADJUST_HW, /*without adjustments */
+	GRAPHICS_DEGAMMA_ADJUST_SW /* use adjustments */
+};
+
+struct gamma_parameters {
+	union gamma_flag flag;
+	enum pixel_format surface_pixel_format; /*OS surface pixel format*/
+	struct regamma_lut regamma;
+
+	enum graphics_regamma_adjust regamma_adjust_type;
+	enum graphics_degamma_adjust degamma_adjust_type;
+
+	enum graphics_gamma_lut selected_gamma_lut;
+
+	bool disable_adjustments;
+
+	/* here we grow with parameters if necessary */
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
new file mode 100644
index 000000000000..8460dd729e91
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/hw_sequencer.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HW_SEQUENCER_H__
+#define __DC_HW_SEQUENCER_H__
+#include "core_types.h"
+
+struct gamma_parameters;
+
+enum pipe_gating_control {
+	PIPE_GATING_CONTROL_DISABLE = 0,
+	PIPE_GATING_CONTROL_ENABLE,
+	PIPE_GATING_CONTROL_INIT
+};
+
+
+struct hw_sequencer_funcs {
+
+	enum dc_status (*apply_ctx_to_hw)(
+			const struct dc *dc, struct validate_context *context);
+
+	void (*reset_hw_ctx)(
+				struct dc *dc,
+				struct validate_context *context,
+				uint8_t target_count);
+
+	bool (*set_plane_config)(
+				const struct dc *dc,
+				struct core_surface *surface,
+				struct core_target *target);
+
+	bool (*update_plane_address)(
+				const struct dc *dc,
+				const struct core_surface *surface,
+				struct core_target *target);
+
+	bool (*set_gamma_ramp)(
+				struct input_pixel_processor *ipp,
+				struct output_pixel_processor *opp,
+				const struct gamma_ramp *ramp,
+				const struct gamma_parameters *params);
+
+	void (*power_down)(struct dc *dc);
+
+	void (*enable_accelerated_mode)(struct dc *dc);
+
+	void (*enable_timing_synchronization)(
+					struct dc_context *dc_ctx,
+					uint32_t timing_generator_num,
+					struct timing_generator *tgs[]);
+
+	/* backlight control */
+	void (*encoder_set_lcd_backlight_level)(
+		struct link_encoder *enc, uint32_t level);
+
+
+	void (*crtc_switch_to_clk_src)(struct clock_source *, uint8_t);
+
+	/* power management */
+	void (*clock_gating_power_up)(struct dc_context *ctx, bool enable);
+
+	void (*enable_display_pipe_clock_gating)(
+					struct dc_context *ctx,
+					bool clock_gating);
+
+	bool (*enable_display_power_gating)(
+					struct dc_context *ctx,
+					uint8_t controller_id,
+					struct dc_bios *dcb,
+					enum pipe_gating_control power_gating);
+
+	void (*program_bw)(struct dc *dc, struct validate_context *context);
+
+	void (*enable_stream)(struct core_stream *stream);
+
+	void (*disable_stream)(struct core_stream *stream);
+
+	void (*enable_fe_clock)(
+		struct dc_context *ctx, uint8_t controller_id, bool enable);
+
+	bool (*pipe_control_lock)(
+				struct dc_context *ctx,
+				uint8_t controller_idx,
+				uint32_t control_mask,
+				bool lock);
+
+	void (*set_blender_mode)(
+				struct dc_context *ctx,
+				uint8_t controller_id,
+				uint32_t mode);
+
+	void (*set_displaymarks)(
+				const struct dc *dc,
+				struct validate_context *context);
+
+	void (*set_display_clock)(struct validate_context *context);
+};
+
+bool dc_construct_hw_sequencer(
+				struct adapter_service *adapter_serv,
+				struct dc *dc);
+
+
+#endif /* __DC_HW_SEQUENCER_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/ipp.h b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h
new file mode 100644
index 000000000000..8e7cc31dfb9c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/ipp.h
@@ -0,0 +1,106 @@
+
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IPP_H__
+#define __DAL_IPP_H__
+
+#include "include/grph_object_id.h"
+#include "include/grph_csc_types.h"
+#include "include/video_csc_types.h"
+#include "include/hw_sequencer_types.h"
+
+struct dev_c_lut;
+
+#define MAXTRIX_COEFFICIENTS_NUMBER 12
+#define MAXTRIX_COEFFICIENTS_WRAP_NUMBER (MAXTRIX_COEFFICIENTS_NUMBER + 4)
+#define MAX_OVL_MATRIX_COUNT 12
+
+/* IPP RELATED */
+struct input_pixel_processor {
+	struct  dc_context *ctx;
+	uint32_t inst;
+	struct ipp_funcs *funcs;
+};
+
+enum wide_gamut_degamma_mode {
+	/*  00  - BITS1:0 Bypass */
+	WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_BYPASS,
+	/*  0x1 - PWL gamma ROM A */
+	WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_PWL_ROM_A,
+	/*  0x2 - PWL gamma ROM B */
+	WIDE_GAMUT_DEGAMMA_MODE_GRAPHICS_PWL_ROM_B,
+	/*  00  - BITS5:4 Bypass */
+	WIDE_GAMUT_DEGAMMA_MODE_OVL_BYPASS,
+	/*  0x1 - PWL gamma ROM A */
+	WIDE_GAMUT_DEGAMMA_MODE_OVL_PWL_ROM_A,
+	/*  0x2 - PWL gamma ROM B */
+	WIDE_GAMUT_DEGAMMA_MODE_OVL_PWL_ROM_B,
+};
+
+struct dcp_video_matrix {
+	enum ovl_color_space color_space;
+	int32_t value[MAXTRIX_COEFFICIENTS_NUMBER];
+};
+
+struct ipp_funcs {
+
+	/* CURSOR RELATED */
+	bool (*ipp_cursor_set_position)(
+		struct input_pixel_processor *ipp,
+		const struct dc_cursor_position *position);
+
+	bool (*ipp_cursor_set_attributes)(
+		struct input_pixel_processor *ipp,
+		const struct dc_cursor_attributes *attributes);
+
+	/* DEGAMMA RELATED */
+	bool (*ipp_set_degamma)(
+		struct input_pixel_processor *ipp,
+		const struct gamma_parameters *params,
+		bool force_bypass);
+
+	void (*ipp_program_prescale)(
+		struct input_pixel_processor *ipp,
+		enum pixel_format pixel_format);
+
+	void (*ipp_set_legacy_input_gamma_mode)(
+			struct input_pixel_processor *ipp,
+			bool is_legacy);
+
+	bool (*ipp_set_legacy_input_gamma_ramp)(
+		struct input_pixel_processor *ipp,
+		const struct gamma_ramp *gamma_ramp,
+		const struct gamma_parameters *params);
+
+	bool (*ipp_set_palette)(
+		struct input_pixel_processor *ipp,
+		const struct dev_c_lut *palette,
+		uint32_t start,
+		uint32_t length,
+		enum pixel_format surface_pixel_format);
+};
+
+#endif /* __DAL_IPP_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
new file mode 100644
index 000000000000..d60c59463fc2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/link_encoder.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef LINK_ENCODER_H_
+#define LINK_ENCODER_H_
+
+#include "grph_object_defs.h"
+#include "signal_types.h"
+#include "dc_types.h"
+
+struct dc_context;
+struct adapter_service;
+struct encoder_set_dp_phy_pattern_param;
+struct link_mst_stream_allocation_table;
+struct link_settings;
+struct link_training_settings;
+struct core_stream;
+
+struct encoder_init_data {
+	struct adapter_service *adapter_service;
+	enum channel_id channel;
+	struct graphics_object_id connector;
+	enum hpd_source_id hpd_source;
+	/* TODO: in DAL2, here was pointer to EventManagerInterface */
+	struct graphics_object_id encoder;
+	struct dc_context *ctx;
+	enum transmitter transmitter;
+};
+
+struct encoder_feature_support {
+	union {
+		struct {
+			/* 1 - external encoder; 0 - internal encoder */
+			uint32_t EXTERNAL_ENCODER:1;
+			uint32_t ANALOG_ENCODER:1;
+			uint32_t STEREO_SYNC:1;
+			/* check the DDC data pin
+			 * when performing DP Sink detection */
+			uint32_t DP_SINK_DETECT_POLL_DATA_PIN:1;
+			/* CPLIB authentication
+			 * for external DP chip supported */
+			uint32_t CPLIB_DP_AUTHENTICATION:1;
+			uint32_t IS_HBR2_CAPABLE:1;
+			uint32_t IS_HBR2_VALIDATED:1;
+			uint32_t IS_TPS3_CAPABLE:1;
+			uint32_t IS_AUDIO_CAPABLE:1;
+			uint32_t IS_VCE_SUPPORTED:1;
+			uint32_t IS_CONVERTER:1;
+			uint32_t IS_Y_ONLY_CAPABLE:1;
+			uint32_t IS_YCBCR_CAPABLE:1;
+		} bits;
+		uint32_t raw;
+	} flags;
+	/* maximum supported deep color depth */
+	enum dc_color_depth max_deep_color;
+	/* maximum supported clock */
+	uint32_t max_pixel_clock;
+};
+
+struct link_enc_status {
+	int dummy; /*TODO*/
+};
+struct link_encoder {
+	struct link_encoder_funcs *funcs;
+	struct adapter_service *adapter_service;
+	int32_t aux_channel_offset;
+	struct dc_context *ctx;
+	struct graphics_object_id id;
+	struct graphics_object_id connector;
+	uint32_t input_signals;
+	uint32_t output_signals;
+	enum engine_id preferred_engine;
+	struct encoder_feature_support features;
+	enum transmitter transmitter;
+	enum hpd_source_id hpd_source;
+};
+
+struct link_encoder_funcs {
+	bool (*validate_output_with_stream)(struct link_encoder *enc,
+		struct core_stream *stream);
+	void (*hw_init)(struct link_encoder *enc);
+	void (*setup)(struct link_encoder *enc,
+		enum signal_type signal);
+	void (*enable_tmds_output)(struct link_encoder *enc,
+		enum clock_source_id clock_source,
+		enum dc_color_depth color_depth,
+		bool hdmi,
+		bool dual_link,
+		uint32_t pixel_clock);
+	void (*enable_dp_output)(struct link_encoder *enc,
+		const struct link_settings *link_settings,
+		enum clock_source_id clock_source);
+	void (*enable_dp_mst_output)(struct link_encoder *enc,
+		const struct link_settings *link_settings,
+		enum clock_source_id clock_source);
+	void (*disable_output)(struct link_encoder *link_enc,
+		enum signal_type signal);
+	void (*dp_set_lane_settings)(struct link_encoder *enc,
+		const struct link_training_settings *link_settings);
+	void (*dp_set_phy_pattern)(struct link_encoder *enc,
+		const struct encoder_set_dp_phy_pattern_param *para);
+	void (*update_mst_stream_allocation_table)(
+		struct link_encoder *enc,
+		const struct link_mst_stream_allocation_table *table);
+	void (*set_lcd_backlight_level) (struct link_encoder *enc,
+		uint32_t level);
+	void (*backlight_control) (struct link_encoder *enc,
+		bool enable);
+	void (*power_control) (struct link_encoder *enc,
+		bool power_up);
+	void (*connect_dig_be_to_fe)(struct link_encoder *enc,
+		enum engine_id engine,
+		bool connect);
+};
+
+#endif /* LINK_ENCODER_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
new file mode 100644
index 000000000000..d9a48c037c3e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/link_hwss.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_LINK_HWSS_H__
+#define __DC_LINK_HWSS_H__
+
+#include "inc/core_status.h"
+
+enum dc_status core_link_read_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t size);
+
+enum dc_status core_link_write_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t size);
+
+void dp_enable_link_phy(
+	struct core_link *link,
+	enum signal_type signal,
+	const struct link_settings *link_settings);
+
+void dp_receiver_power_ctrl(struct core_link *link, bool on);
+
+void dp_disable_link_phy(struct core_link *link, enum signal_type signal);
+
+void dp_disable_link_phy_mst(struct core_link *link, struct core_stream *stream);
+
+bool dp_set_hw_training_pattern(
+	struct core_link *link,
+	enum hw_dp_training_pattern pattern);
+
+void dp_set_hw_lane_settings(
+	struct core_link *link,
+	const struct link_training_settings *link_settings);
+
+void dp_set_hw_test_pattern(
+	struct core_link *link,
+	enum dp_test_pattern test_pattern);
+
+enum dp_panel_mode dp_get_panel_mode(struct core_link *link);
+
+#endif /* __DC_LINK_HWSS_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h b/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
new file mode 100644
index 000000000000..7d6335d3bcf4
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/mem_input.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_MEM_INPUT_H__
+#define __DAL_MEM_INPUT_H__
+
+#include "include/grph_object_id.h"
+#include "dc.h"
+
+struct mem_input {
+	struct mem_input_funcs *funcs;
+	struct dc_context *ctx;
+	uint32_t inst;
+};
+
+struct mem_input_funcs {
+	void (*mem_input_program_safe_display_marks)(struct mem_input *mi);
+	void (*mem_input_program_display_marks)(
+		struct mem_input *mem_input,
+		struct bw_watermarks nbp,
+		struct bw_watermarks stutter,
+		struct bw_watermarks urgent,
+		uint32_t h_total,
+		uint32_t pixel_clk_in_khz,
+		uint32_t pstate_blackout_duration_ns);
+	void (*mem_input_allocate_dmif_buffer)(
+			struct mem_input *mem_input,
+			struct dc_crtc_timing *timing,
+			uint32_t paths_num);
+	void (*mem_input_deallocate_dmif_buffer)(
+		struct mem_input *mem_input, uint32_t paths_num);
+	bool (*mem_input_program_surface_flip_and_addr)(
+		struct mem_input *mem_input,
+		const struct dc_plane_address *address,
+		bool flip_immediate);
+	bool (*mem_input_program_surface_config)(
+		struct mem_input *mem_input,
+		enum surface_pixel_format format,
+		struct dc_tiling_info *tiling_info,
+		union plane_size *plane_size,
+		enum dc_rotation_angle rotation);
+};
+
+enum stutter_mode_type {
+	STUTTER_MODE_LEGACY = 0X00000001,
+	STUTTER_MODE_ENHANCED = 0X00000002,
+	STUTTER_MODE_FID_NBP_STATE = 0X00000004,
+	STUTTER_MODE_WATERMARK_NBP_STATE = 0X00000008,
+	STUTTER_MODE_SINGLE_DISPLAY_MODEL = 0X00000010,
+	STUTTER_MODE_MIXED_DISPLAY_MODEL = 0X00000020,
+	STUTTER_MODE_DUAL_DMIF_BUFFER = 0X00000040,
+	STUTTER_MODE_NO_DMIF_BUFFER_ALLOCATION = 0X00000080,
+	STUTTER_MODE_NO_ADVANCED_REQUEST = 0X00000100,
+	STUTTER_MODE_NO_LB_RESET = 0X00000200,
+	STUTTER_MODE_DISABLED = 0X00000400,
+	STUTTER_MODE_AGGRESSIVE_MARKS = 0X00000800,
+	STUTTER_MODE_URGENCY = 0X00001000,
+	STUTTER_MODE_QUAD_DMIF_BUFFER = 0X00002000,
+	STUTTER_MODE_NOT_USED = 0X00008000
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/opp.h b/drivers/gpu/drm/amd/dal/dc/inc/opp.h
new file mode 100644
index 000000000000..b097983246df
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/opp.h
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_OPP_H__
+#define __DAL_OPP_H__
+
+#include "dc_types.h"
+#include "grph_object_id.h"
+#include "grph_csc_types.h"
+#include "dm_services_types.h"
+
+struct fixed31_32;
+struct gamma_parameters;
+
+/* TODO: Need cleanup */
+
+enum clamping_range {
+	CLAMPING_FULL_RANGE = 0,	   /* No Clamping */
+	CLAMPING_LIMITED_RANGE_8BPC,   /* 8  bpc: Clamping 1  to FE */
+	CLAMPING_LIMITED_RANGE_10BPC, /* 10 bpc: Clamping 4  to 3FB */
+	CLAMPING_LIMITED_RANGE_12BPC, /* 12 bpc: Clamping 10 to FEF */
+	/* Use programmable clampping value on FMT_CLAMP_COMPONENT_R/G/B. */
+	CLAMPING_LIMITED_RANGE_PROGRAMMABLE
+};
+
+struct clamping_and_pixel_encoding_params {
+	enum dc_pixel_encoding pixel_encoding; /* Pixel Encoding */
+	enum clamping_range clamping_level; /* Clamping identifier */
+	enum dc_color_depth c_depth; /* Deep color use. */
+};
+
+struct bit_depth_reduction_params {
+	struct {
+		/* truncate/round */
+		/* trunc/round enabled*/
+		uint32_t TRUNCATE_ENABLED:1;
+		/* 2 bits: 0=6 bpc, 1=8 bpc, 2 = 10bpc*/
+		uint32_t TRUNCATE_DEPTH:2;
+		/* truncate or round*/
+		uint32_t TRUNCATE_MODE:1;
+
+		/* spatial dither */
+		/* Spatial Bit Depth Reduction enabled*/
+		uint32_t SPATIAL_DITHER_ENABLED:1;
+		/* 2 bits: 0=6 bpc, 1 = 8 bpc, 2 = 10bpc*/
+		uint32_t SPATIAL_DITHER_DEPTH:2;
+		/* 0-3 to select patterns*/
+		uint32_t SPATIAL_DITHER_MODE:2;
+		/* Enable RGB random dithering*/
+		uint32_t RGB_RANDOM:1;
+		/* Enable Frame random dithering*/
+		uint32_t FRAME_RANDOM:1;
+		/* Enable HighPass random dithering*/
+		uint32_t HIGHPASS_RANDOM:1;
+
+		/* temporal dither*/
+		 /* frame modulation enabled*/
+		uint32_t FRAME_MODULATION_ENABLED:1;
+		/* same as for trunc/spatial*/
+		uint32_t FRAME_MODULATION_DEPTH:2;
+		/* 2/4 gray levels*/
+		uint32_t TEMPORAL_LEVEL:1;
+		uint32_t FRC25:2;
+		uint32_t FRC50:2;
+		uint32_t FRC75:2;
+	} flags;
+
+	uint32_t r_seed_value;
+	uint32_t b_seed_value;
+	uint32_t g_seed_value;
+};
+
+
+
+enum wide_gamut_regamma_mode {
+	/*  0x0  - BITS2:0 Bypass */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_BYPASS,
+	/*  0x1  - Fixed curve sRGB 2.4 */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_SRGB24,
+	/*  0x2  - Fixed curve xvYCC 2.22 */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_XYYCC22,
+	/*  0x3  - Programmable control A */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_A,
+	/*  0x4  - Programmable control B */
+	WIDE_GAMUT_REGAMMA_MODE_GRAPHICS_MATRIX_B,
+	/*  0x0  - BITS6:4 Bypass */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_BYPASS,
+	/*  0x1  - Fixed curve sRGB 2.4 */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_SRGB24,
+	/*  0x2  - Fixed curve xvYCC 2.22 */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_XYYCC22,
+	/*  0x3  - Programmable control A */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_A,
+	/*  0x4  - Programmable control B */
+	WIDE_GAMUT_REGAMMA_MODE_OVL_MATRIX_B
+};
+
+struct pwl_result_data {
+	struct fixed31_32 red;
+	struct fixed31_32 green;
+	struct fixed31_32 blue;
+
+	struct fixed31_32 delta_red;
+	struct fixed31_32 delta_green;
+	struct fixed31_32 delta_blue;
+
+	uint32_t red_reg;
+	uint32_t green_reg;
+	uint32_t blue_reg;
+
+	uint32_t delta_red_reg;
+	uint32_t delta_green_reg;
+	uint32_t delta_blue_reg;
+};
+
+struct gamma_pixel {
+	struct fixed31_32 r;
+	struct fixed31_32 g;
+	struct fixed31_32 b;
+};
+
+struct gamma_curve {
+	uint32_t offset;
+	uint32_t segments_num;
+};
+
+struct curve_points {
+	struct fixed31_32 x;
+	struct fixed31_32 y;
+	struct fixed31_32 offset;
+	struct fixed31_32 slope;
+
+	uint32_t custom_float_x;
+	uint32_t custom_float_y;
+	uint32_t custom_float_offset;
+	uint32_t custom_float_slope;
+};
+
+enum channel_name {
+	CHANNEL_NAME_RED,
+	CHANNEL_NAME_GREEN,
+	CHANNEL_NAME_BLUE
+};
+
+struct custom_float_format {
+	uint32_t mantissa_bits;
+	uint32_t exponenta_bits;
+	bool sign;
+};
+
+struct custom_float_value {
+	uint32_t mantissa;
+	uint32_t exponenta;
+	uint32_t value;
+	bool negative;
+};
+
+struct hw_x_point {
+	uint32_t custom_float_x;
+	uint32_t custom_float_x_adjusted;
+	struct fixed31_32 x;
+	struct fixed31_32 adjusted_x;
+	struct fixed31_32 regamma_y_red;
+	struct fixed31_32 regamma_y_green;
+	struct fixed31_32 regamma_y_blue;
+
+};
+
+struct pwl_float_data_ex {
+	struct fixed31_32 r;
+	struct fixed31_32 g;
+	struct fixed31_32 b;
+	struct fixed31_32 delta_r;
+	struct fixed31_32 delta_g;
+	struct fixed31_32 delta_b;
+};
+
+enum hw_point_position {
+	/* hw point sits between left and right sw points */
+	HW_POINT_POSITION_MIDDLE,
+	/* hw point lays left from left (smaller) sw point */
+	HW_POINT_POSITION_LEFT,
+	/* hw point lays stays from right (bigger) sw point */
+	HW_POINT_POSITION_RIGHT
+};
+
+struct gamma_point {
+	int32_t left_index;
+	int32_t right_index;
+	enum hw_point_position pos;
+	struct fixed31_32 coeff;
+};
+
+struct pixel_gamma_point {
+	struct gamma_point r;
+	struct gamma_point g;
+	struct gamma_point b;
+};
+
+struct gamma_coefficients {
+	struct fixed31_32 a0[3];
+	struct fixed31_32 a1[3];
+	struct fixed31_32 a2[3];
+	struct fixed31_32 a3[3];
+	struct fixed31_32 user_gamma[3];
+	struct fixed31_32 user_contrast;
+	struct fixed31_32 user_brightness;
+};
+
+struct csc_adjustments {
+	struct fixed31_32 contrast;
+	struct fixed31_32 saturation;
+	struct fixed31_32 brightness;
+	struct fixed31_32 hue;
+};
+
+struct pwl_float_data {
+	struct fixed31_32 r;
+	struct fixed31_32 g;
+	struct fixed31_32 b;
+};
+
+
+/* TODO: Use when we redefine the OPP interface */
+enum opp_regamma {
+	OPP_REGAMMA_BYPASS = 0,
+	OPP_REGAMMA_SRGB,
+	OPP_REGAMMA_3_6,
+	OPP_REGAMMA_PQ,
+	OPP_REGAMMA_PQ_INTERIM,
+};
+
+struct output_pixel_processor {
+	struct dc_context *ctx;
+	uint32_t inst;
+	struct opp_funcs *funcs;
+};
+
+enum fmt_stereo_action {
+	FMT_STEREO_ACTION_ENABLE = 0,
+	FMT_STEREO_ACTION_DISABLE,
+	FMT_STEREO_ACTION_UPDATE_POLARITY
+};
+
+struct opp_funcs {
+	void (*opp_power_on_regamma_lut)(
+		struct output_pixel_processor *opp,
+		bool power_on);
+
+	bool (*opp_set_regamma)(
+		struct output_pixel_processor *opp,
+		const struct gamma_ramp *ramp,
+		const struct gamma_parameters *params,
+		bool force_bypass);
+
+	bool (*opp_map_legacy_and_regamma_hw_to_x_user)(
+		struct output_pixel_processor *opp,
+		const struct gamma_ramp *gamma_ramp,
+		const struct gamma_parameters *params);
+
+	void (*opp_set_csc_adjustment)(
+		struct output_pixel_processor *opp,
+		const struct grph_csc_adjustment *adjust);
+
+	void (*opp_set_csc_default)(
+		struct output_pixel_processor *opp,
+		const struct default_adjustment *default_adjust);
+
+	/* FORMATTER RELATED */
+	void (*opp_program_bit_depth_reduction)(
+		struct output_pixel_processor *opp,
+		const struct bit_depth_reduction_params *params);
+
+	void (*opp_program_clamping_and_pixel_encoding)(
+		struct output_pixel_processor *opp,
+		const struct clamping_and_pixel_encoding_params *params);
+
+
+	void (*opp_set_dyn_expansion)(
+		struct output_pixel_processor *opp,
+		enum color_space color_sp,
+		enum dc_color_depth color_dpth,
+		enum signal_type signal);
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/resource.h b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
new file mode 100644
index 000000000000..bda92e3c4f66
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/resource.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ */
+
+#ifndef DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_
+#define DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_
+
+#include "core_types.h"
+#include "core_status.h"
+#include "core_dc.h"
+
+/* TODO unhardcode, 4 for CZ*/
+#define MEMORY_TYPE_MULTIPLIER 4
+
+bool dc_construct_resource_pool(struct adapter_service *adapter_serv,
+				struct dc *dc,
+				uint8_t num_virtual_links);
+
+void build_scaling_params(
+	const struct dc_surface *surface,
+	struct core_stream *stream);
+
+void build_scaling_params_for_context(
+	const struct dc *dc,
+	struct validate_context *context);
+
+void unreference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source);
+
+void reference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source);
+
+bool is_same_timing(
+	const struct dc_crtc_timing *timing1,
+	const struct dc_crtc_timing *timing2);
+
+struct clock_source *find_used_clk_src_for_sharing(
+		struct validate_context *context,
+		struct core_stream *stream);
+
+bool logical_attach_surfaces_to_target(
+		struct dc_surface *surfaces[],
+		uint8_t surface_count,
+		struct dc_target *dc_target);
+
+void pplib_apply_safe_state(const struct dc *dc);
+
+void pplib_apply_display_requirements(
+	const struct dc *dc,
+	const struct validate_context *context);
+
+void build_info_frame(struct core_stream *stream);
+
+enum dc_status map_resources(
+	const struct dc *dc,
+	struct validate_context *context);
+
+#endif /* DRIVERS_GPU_DRM_AMD_DAL_DEV_DC_INC_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h b/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
new file mode 100644
index 000000000000..6bb1d007de21
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/stream_encoder.h
@@ -0,0 +1,88 @@
+/*
+ * stream_encoder.h
+ *
+ */
+
+#ifndef STREAM_ENCODER_H_
+#define STREAM_ENCODER_H_
+
+#include "include/hw_sequencer_types.h"
+
+struct dc_bios;
+struct dc_context;
+struct dc_crtc_timing;
+
+
+struct encoder_info_packet {
+	bool valid;
+	uint8_t hb0;
+	uint8_t hb1;
+	uint8_t hb2;
+	uint8_t hb3;
+	uint8_t sb[28];
+};
+
+struct encoder_info_frame {
+	/* auxiliary video information */
+	struct encoder_info_packet avi;
+	struct encoder_info_packet gamut;
+	struct encoder_info_packet vendor;
+	/* source product description */
+	struct encoder_info_packet spd;
+	/* video stream configuration */
+	struct encoder_info_packet vsc;
+};
+
+struct encoder_unblank_param {
+	struct hw_crtc_timing crtc_timing;
+	struct link_settings link_settings;
+};
+
+struct encoder_set_dp_phy_pattern_param {
+	enum dp_test_pattern dp_phy_pattern;
+	const uint8_t *custom_pattern;
+	uint32_t custom_pattern_size;
+	enum dp_panel_mode dp_panel_mode;
+};
+
+
+struct stream_encoder {
+	struct stream_encoder_funcs *funcs;
+	struct dc_context *ctx;
+	struct dc_bios *bp;
+	enum engine_id id;
+};
+
+struct stream_encoder_funcs {
+	void (*dp_set_stream_attribute)(
+		struct stream_encoder *enc,
+		struct dc_crtc_timing *crtc_timing);
+	void (*hdmi_set_stream_attribute)(
+		struct stream_encoder *enc,
+		struct dc_crtc_timing *crtc_timing,
+		bool enable_audio);
+	void (*dvi_set_stream_attribute)(
+		struct stream_encoder *enc,
+		struct dc_crtc_timing *crtc_timing,
+		bool is_dual_link);
+	void (*set_mst_bandwidth)(
+		struct stream_encoder *enc,
+		struct fixed31_32 avg_time_slots_per_mtp);
+	void (*update_hdmi_info_packets)(
+		struct stream_encoder *enc,
+		const struct encoder_info_frame *info_frame);
+	void (*stop_hdmi_info_packets)(
+		struct stream_encoder *enc);
+	void (*update_dp_info_packets)(
+		struct stream_encoder *enc,
+		const struct encoder_info_frame *info_frame);
+	void (*stop_dp_info_packets)(
+		struct stream_encoder *enc);
+	void (*dp_blank)(
+		struct stream_encoder *enc);
+	void (*dp_unblank)(
+		struct stream_encoder *enc,
+		const struct encoder_unblank_param *param);
+};
+
+#endif /* STREAM_ENCODER_H_ */
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h b/drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
new file mode 100644
index 000000000000..e9ca16938572
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/timing_generator.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TIMING_GENERATOR_TYPES_H__
+#define __DAL_TIMING_GENERATOR_TYPES_H__
+
+#include "include/grph_csc_types.h"
+
+struct dc_bios;
+
+/**
+ *  These parameters are required as input when doing blanking/Unblanking
+*/
+struct crtc_black_color {
+	uint32_t black_color_r_cr;
+	uint32_t black_color_g_y;
+	uint32_t black_color_b_cb;
+};
+
+/* Contains CRTC vertical/horizontal pixel counters */
+struct crtc_position {
+	uint32_t vertical_count;
+	uint32_t horizontal_count;
+	uint32_t nominal_vcount;
+};
+
+
+enum dcp_gsl_purpose {
+	DCP_GSL_PURPOSE_SURFACE_FLIP = 0,
+	DCP_GSL_PURPOSE_STEREO3D_PHASE,
+	DCP_GSL_PURPOSE_UNDEFINED
+};
+
+struct dcp_gsl_params {
+	enum sync_source gsl_group;
+	enum dcp_gsl_purpose gsl_purpose;
+	bool timing_server;
+	bool overlay_present;
+	bool gsl_paused;
+};
+
+#define LEFT_EYE_3D_PRIMARY_SURFACE 1
+#define RIGHT_EYE_3D_PRIMARY_SURFACE 0
+
+enum test_pattern_dyn_range {
+	TEST_PATTERN_DYN_RANGE_VESA = 0,
+	TEST_PATTERN_DYN_RANGE_CEA
+};
+
+enum test_pattern_mode {
+	TEST_PATTERN_MODE_COLORSQUARES_RGB = 0,
+	TEST_PATTERN_MODE_COLORSQUARES_YCBCR601,
+	TEST_PATTERN_MODE_COLORSQUARES_YCBCR709,
+	TEST_PATTERN_MODE_VERTICALBARS,
+	TEST_PATTERN_MODE_HORIZONTALBARS,
+	TEST_PATTERN_MODE_SINGLERAMP_RGB,
+	TEST_PATTERN_MODE_DUALRAMP_RGB
+};
+
+enum test_pattern_color_format {
+	TEST_PATTERN_COLOR_FORMAT_BPC_6 = 0,
+	TEST_PATTERN_COLOR_FORMAT_BPC_8,
+	TEST_PATTERN_COLOR_FORMAT_BPC_10,
+	TEST_PATTERN_COLOR_FORMAT_BPC_12
+};
+
+enum controller_dp_test_pattern {
+	CONTROLLER_DP_TEST_PATTERN_D102 = 0,
+	CONTROLLER_DP_TEST_PATTERN_SYMBOLERROR,
+	CONTROLLER_DP_TEST_PATTERN_PRBS7,
+	CONTROLLER_DP_TEST_PATTERN_COLORSQUARES,
+	CONTROLLER_DP_TEST_PATTERN_VERTICALBARS,
+	CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS,
+	CONTROLLER_DP_TEST_PATTERN_COLORRAMP,
+	CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+	CONTROLLER_DP_TEST_PATTERN_RESERVED_8,
+	CONTROLLER_DP_TEST_PATTERN_RESERVED_9,
+	CONTROLLER_DP_TEST_PATTERN_RESERVED_A,
+	CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA
+};
+
+enum crtc_state {
+	CRTC_STATE_VBLANK = 0,
+	CRTC_STATE_VACTIVE
+};
+
+struct timing_generator {
+	struct timing_generator_funcs *funcs;
+	struct dc_bios *bp;
+	struct dc_context *ctx;
+};
+
+
+struct dc_crtc_timing;
+
+struct timing_generator_funcs {
+	bool (*validate_timing)(struct timing_generator *tg,
+							const struct dc_crtc_timing *timing);
+	void (*program_timing)(struct timing_generator *tg,
+							const struct dc_crtc_timing *timing,
+							bool use_vbios);
+	bool (*enable_crtc)(struct timing_generator *tg);
+	bool (*disable_crtc)(struct timing_generator *tg);
+	bool (*is_counter_moving)(struct timing_generator *tg);
+	void (*get_position)(struct timing_generator *tg,
+								int32_t *h_position,
+								int32_t *v_position);
+	uint32_t (*get_frame_count)(struct timing_generator *tg);
+	void (*set_early_control)(struct timing_generator *tg,
+							   uint32_t early_cntl);
+	void (*wait_for_state)(struct timing_generator *tg,
+							enum crtc_state state);
+	bool (*set_blank)(struct timing_generator *tg,
+					   bool enable_blanking);
+	void (*set_overscan_blank_color) (struct timing_generator *tg, enum color_space black_color);
+	void (*set_blank_color)(struct timing_generator *tg, enum color_space black_color);
+	void (*set_colors)(struct timing_generator *tg,
+						const struct crtc_black_color *blank_color,
+						const struct crtc_black_color *overscan_color);
+
+	void (*disable_vga)(struct timing_generator *tg);
+	bool (*did_triggered_reset_occur)(struct timing_generator *tg);
+	void (*setup_global_swap_lock)(struct timing_generator *tg,
+							const struct dcp_gsl_params *gsl_params);
+	void (*enable_reset_trigger)(struct timing_generator *tg,
+						const struct trigger_params *trigger_params);
+	void (*disable_reset_trigger)(struct timing_generator *tg);
+	void (*tear_down_global_swap_lock)(struct timing_generator *tg);
+	void (*enable_advanced_request)(struct timing_generator *tg,
+					bool enable, const struct dc_crtc_timing *timing);
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/inc/transform.h b/drivers/gpu/drm/amd/dal/dc/inc/transform.h
new file mode 100644
index 000000000000..22803575ed72
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/inc/transform.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TRANSFORM_H__
+#define __DAL_TRANSFORM_H__
+
+#include "include/scaler_types.h"
+#include "include/grph_csc_types.h"
+#include "calcs/scaler_filter.h"
+#include "grph_object_id.h"
+
+struct bit_depth_reduction_params;
+
+enum scaling_type {
+	SCALING_TYPE_NO_SCALING = 0,
+	SCALING_TYPE_UPSCALING,
+	SCALING_TYPE_DOWNSCALING
+};
+
+struct transform {
+	struct transform_funcs *funcs;
+	struct dc_context *ctx;
+	uint32_t inst;
+	struct scaler_filter *filter;
+};
+
+
+struct scaler_taps_and_ratio {
+	uint32_t h_tap;
+	uint32_t v_tap;
+	uint32_t lo_ratio;
+	uint32_t hi_ratio;
+};
+
+struct scaler_taps {
+	uint32_t h_tap;
+	uint32_t v_tap;
+};
+
+struct sclv_ratios_inits {
+	uint32_t chroma_enable;
+	uint32_t h_int_scale_ratio_luma;
+	uint32_t h_int_scale_ratio_chroma;
+	uint32_t v_int_scale_ratio_luma;
+	uint32_t v_int_scale_ratio_chroma;
+	struct init_int_and_frac h_init_luma;
+	struct init_int_and_frac h_init_chroma;
+	struct init_int_and_frac v_init_luma;
+	struct init_int_and_frac v_init_chroma;
+	struct init_int_and_frac h_init_lumabottom;
+	struct init_int_and_frac h_init_chromabottom;
+	struct init_int_and_frac v_init_lumabottom;
+	struct init_int_and_frac v_init_chromabottom;
+};
+
+enum lb_pixel_depth {
+	/* do not change the values because it is used as bit vector */
+	LB_PIXEL_DEPTH_18BPP = 1,
+	LB_PIXEL_DEPTH_24BPP = 2,
+	LB_PIXEL_DEPTH_30BPP = 4,
+	LB_PIXEL_DEPTH_36BPP = 8
+};
+
+
+struct raw_gamma_ramp_rgb {
+       uint32_t red;
+       uint32_t green;
+       uint32_t blue;
+};
+
+enum raw_gamma_ramp_type {
+       GAMMA_RAMP_TYPE_UNINITIALIZED,
+       GAMMA_RAMP_TYPE_DEFAULT,
+       GAMMA_RAMP_TYPE_RGB256,
+       GAMMA_RAMP_TYPE_FIXED_POINT
+};
+
+#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256
+struct raw_gamma_ramp {
+       enum raw_gamma_ramp_type type;
+       struct raw_gamma_ramp_rgb rgb_256[NUM_OF_RAW_GAMMA_RAMP_RGB_256];
+       uint32_t size;
+};
+
+
+/* Colorimetry */
+enum colorimetry {
+       COLORIMETRY_NO_DATA = 0,
+       COLORIMETRY_ITU601 = 1,
+       COLORIMETRY_ITU709 = 2,
+       COLORIMETRY_EXTENDED = 3
+};
+
+/* ColorimetryEx */
+enum colorimetry_ex {
+       COLORIMETRY_EX_XVYCC601 = 0,
+       COLORIMETRY_EX_XVYCC709 = 1,
+       COLORIMETRY_EX_SYCC601 = 2,
+       COLORIMETRY_EX_ADOBEYCC601 = 3,
+       COLORIMETRY_EX_ADOBERGB = 4,
+       COLORIMETRY_EX_RESERVED5 = 5,
+       COLORIMETRY_EX_RESERVED6 = 6,
+       COLORIMETRY_EX_RESERVED7 = 7
+};
+
+enum ds_color_space {
+       DS_COLOR_SPACE_UNKNOWN = 0,
+       DS_COLOR_SPACE_SRGB_FULLRANGE = 1,
+       DS_COLOR_SPACE_SRGB_LIMITEDRANGE,
+       DS_COLOR_SPACE_YPBPR601,
+       DS_COLOR_SPACE_YPBPR709,
+       DS_COLOR_SPACE_YCBCR601,
+       DS_COLOR_SPACE_YCBCR709,
+       DS_COLOR_SPACE_NMVPU_SUPERAA,
+       DS_COLOR_SPACE_YCBCR601_YONLY,
+       DS_COLOR_SPACE_YCBCR709_YONLY/*same as YCbCr, but Y in Full range*/
+};
+
+
+enum active_format_info {
+       ACTIVE_FORMAT_NO_DATA = 0,
+       ACTIVE_FORMAT_VALID = 1
+};
+
+/* Active format aspect ratio */
+enum active_format_aspect_ratio {
+       ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE = 8,
+       ACTIVE_FORMAT_ASPECT_RATIO_4_3 = 9,
+       ACTIVE_FORMAT_ASPECT_RATIO_16_9 = 0XA,
+       ACTIVE_FORMAT_ASPECT_RATIO_14_9 = 0XB
+};
+
+enum bar_info {
+       BAR_INFO_NOT_VALID = 0,
+       BAR_INFO_VERTICAL_VALID = 1,
+       BAR_INFO_HORIZONTAL_VALID = 2,
+       BAR_INFO_BOTH_VALID = 3
+};
+
+enum picture_scaling {
+       PICTURE_SCALING_UNIFORM = 0,
+       PICTURE_SCALING_HORIZONTAL = 1,
+       PICTURE_SCALING_VERTICAL = 2,
+       PICTURE_SCALING_BOTH = 3
+};
+
+/* RGB quantization range */
+enum rgb_quantization_range {
+       RGB_QUANTIZATION_DEFAULT_RANGE = 0,
+       RGB_QUANTIZATION_LIMITED_RANGE = 1,
+       RGB_QUANTIZATION_FULL_RANGE = 2,
+       RGB_QUANTIZATION_RESERVED = 3
+};
+
+/* YYC quantization range */
+enum yyc_quantization_range {
+       YYC_QUANTIZATION_LIMITED_RANGE = 0,
+       YYC_QUANTIZATION_FULL_RANGE = 1,
+       YYC_QUANTIZATION_RESERVED2 = 2,
+       YYC_QUANTIZATION_RESERVED3 = 3
+};
+
+struct transform_funcs {
+	bool (*transform_power_up)(struct transform *xfm);
+
+	bool (*transform_set_scaler)(
+		struct transform *xfm,
+		const struct scaler_data *data);
+
+	void (*transform_set_scaler_bypass)(struct transform *xfm);
+
+	bool (*transform_update_viewport)(
+		struct transform *xfm,
+		const struct rect *view_port,
+		bool is_fbc_attached);
+
+	void (*transform_set_scaler_filter)(
+		struct transform *xfm,
+		struct scaler_filter *filter);
+
+	void (*transform_set_gamut_remap)(
+		struct transform *xfm,
+		const struct grph_csc_adjustment *adjust);
+
+	bool (*transform_set_pixel_storage_depth)(
+		struct transform *xfm,
+		enum lb_pixel_depth depth,
+		const struct bit_depth_reduction_params *bit_depth_params);
+
+	bool (*transform_get_current_pixel_storage_depth)(
+		struct transform *xfm,
+		enum lb_pixel_depth *depth);
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/irq_types.h b/drivers/gpu/drm/amd/dal/dc/irq_types.h
new file mode 100644
index 000000000000..35a099166613
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/irq_types.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_TYPES_H__
+#define __DAL_IRQ_TYPES_H__
+
+struct dc_context;
+
+typedef void (*interrupt_handler)(void *);
+
+typedef void *irq_handler_idx;
+#define DAL_INVALID_IRQ_HANDLER_IDX NULL
+
+
+/* The order of the IRQ sources is important and MUST match the one's
+of base driver */
+enum dc_irq_source {
+	/* Use as mask to specify invalid irq source */
+	DC_IRQ_SOURCE_INVALID = 0,
+
+	DC_IRQ_SOURCE_HPD1,
+	DC_IRQ_SOURCE_HPD2,
+	DC_IRQ_SOURCE_HPD3,
+	DC_IRQ_SOURCE_HPD4,
+	DC_IRQ_SOURCE_HPD5,
+	DC_IRQ_SOURCE_HPD6,
+
+	DC_IRQ_SOURCE_HPD1RX,
+	DC_IRQ_SOURCE_HPD2RX,
+	DC_IRQ_SOURCE_HPD3RX,
+	DC_IRQ_SOURCE_HPD4RX,
+	DC_IRQ_SOURCE_HPD5RX,
+	DC_IRQ_SOURCE_HPD6RX,
+
+	DC_IRQ_SOURCE_I2C_DDC1,
+	DC_IRQ_SOURCE_I2C_DDC2,
+	DC_IRQ_SOURCE_I2C_DDC3,
+	DC_IRQ_SOURCE_I2C_DDC4,
+	DC_IRQ_SOURCE_I2C_DDC5,
+	DC_IRQ_SOURCE_I2C_DDC6,
+
+	DC_IRQ_SOURCE_AZALIA0,
+	DC_IRQ_SOURCE_AZALIA1,
+	DC_IRQ_SOURCE_AZALIA2,
+	DC_IRQ_SOURCE_AZALIA3,
+	DC_IRQ_SOURCE_AZALIA4,
+	DC_IRQ_SOURCE_AZALIA5,
+
+	DC_IRQ_SOURCE_DPSINK1,
+	DC_IRQ_SOURCE_DPSINK2,
+	DC_IRQ_SOURCE_DPSINK3,
+	DC_IRQ_SOURCE_DPSINK4,
+	DC_IRQ_SOURCE_DPSINK5,
+	DC_IRQ_SOURCE_DPSINK6,
+
+	DC_IRQ_SOURCE_CRTC1VSYNC,
+	DC_IRQ_SOURCE_CRTC2VSYNC,
+	DC_IRQ_SOURCE_CRTC3VSYNC,
+	DC_IRQ_SOURCE_CRTC4VSYNC,
+	DC_IRQ_SOURCE_CRTC5VSYNC,
+	DC_IRQ_SOURCE_CRTC6VSYNC,
+	DC_IRQ_SOURCE_TIMER,
+
+	DC_IRQ_SOURCE_PFLIP_FIRST,
+	DC_IRQ_SOURCE_PFLIP1 = DC_IRQ_SOURCE_PFLIP_FIRST,
+	DC_IRQ_SOURCE_PFLIP2,
+	DC_IRQ_SOURCE_PFLIP3,
+	DC_IRQ_SOURCE_PFLIP4,
+	DC_IRQ_SOURCE_PFLIP5,
+	DC_IRQ_SOURCE_PFLIP6,
+	DC_IRQ_SOURCE_PFLIP_UNDERLAY0,
+	DC_IRQ_SOURCE_PFLIP_LAST = DC_IRQ_SOURCE_PFLIP_UNDERLAY0,
+
+	DC_IRQ_SOURCE_GPIOPAD0,
+	DC_IRQ_SOURCE_GPIOPAD1,
+	DC_IRQ_SOURCE_GPIOPAD2,
+	DC_IRQ_SOURCE_GPIOPAD3,
+	DC_IRQ_SOURCE_GPIOPAD4,
+	DC_IRQ_SOURCE_GPIOPAD5,
+	DC_IRQ_SOURCE_GPIOPAD6,
+	DC_IRQ_SOURCE_GPIOPAD7,
+	DC_IRQ_SOURCE_GPIOPAD8,
+	DC_IRQ_SOURCE_GPIOPAD9,
+	DC_IRQ_SOURCE_GPIOPAD10,
+	DC_IRQ_SOURCE_GPIOPAD11,
+	DC_IRQ_SOURCE_GPIOPAD12,
+	DC_IRQ_SOURCE_GPIOPAD13,
+	DC_IRQ_SOURCE_GPIOPAD14,
+	DC_IRQ_SOURCE_GPIOPAD15,
+	DC_IRQ_SOURCE_GPIOPAD16,
+	DC_IRQ_SOURCE_GPIOPAD17,
+	DC_IRQ_SOURCE_GPIOPAD18,
+	DC_IRQ_SOURCE_GPIOPAD19,
+	DC_IRQ_SOURCE_GPIOPAD20,
+	DC_IRQ_SOURCE_GPIOPAD21,
+	DC_IRQ_SOURCE_GPIOPAD22,
+	DC_IRQ_SOURCE_GPIOPAD23,
+	DC_IRQ_SOURCE_GPIOPAD24,
+	DC_IRQ_SOURCE_GPIOPAD25,
+	DC_IRQ_SOURCE_GPIOPAD26,
+	DC_IRQ_SOURCE_GPIOPAD27,
+	DC_IRQ_SOURCE_GPIOPAD28,
+	DC_IRQ_SOURCE_GPIOPAD29,
+	DC_IRQ_SOURCE_GPIOPAD30,
+
+	DC_IRQ_SOURCE_DC1UNDERFLOW,
+	DC_IRQ_SOURCE_DC2UNDERFLOW,
+	DC_IRQ_SOURCE_DC3UNDERFLOW,
+	DC_IRQ_SOURCE_DC4UNDERFLOW,
+	DC_IRQ_SOURCE_DC5UNDERFLOW,
+	DC_IRQ_SOURCE_DC6UNDERFLOW,
+
+	DC_IRQ_SOURCE_DMCU_SCP,
+	DC_IRQ_SOURCE_VBIOS_SW,
+
+	DC_IRQ_SOURCE_VUPDATE1,
+	DC_IRQ_SOURCE_VUPDATE2,
+	DC_IRQ_SOURCE_VUPDATE3,
+	DC_IRQ_SOURCE_VUPDATE4,
+	DC_IRQ_SOURCE_VUPDATE5,
+	DC_IRQ_SOURCE_VUPDATE6,
+
+	DAL_IRQ_SOURCES_NUMBER
+};
+
+enum irq_type
+{
+	IRQ_TYPE_PFLIP = DC_IRQ_SOURCE_PFLIP1,
+	IRQ_TYPE_VUPDATE = DC_IRQ_SOURCE_VUPDATE1,
+};
+
+#define DAL_VALID_IRQ_SRC_NUM(src) \
+	((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID)
+
+/* Number of Page Flip IRQ Sources. */
+#define DAL_PFLIP_IRQ_SRC_NUM \
+	(DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1)
+
+/* the number of contexts may be expanded in the future based on needs */
+enum dc_interrupt_context {
+	INTERRUPT_LOW_IRQ_CONTEXT = 0,
+	INTERRUPT_HIGH_IRQ_CONTEXT,
+	INTERRUPT_CONTEXT_NUMBER
+};
+
+enum dc_interrupt_porlarity {
+	INTERRUPT_POLARITY_DEFAULT = 0,
+	INTERRUPT_POLARITY_LOW = INTERRUPT_POLARITY_DEFAULT,
+	INTERRUPT_POLARITY_HIGH,
+	INTERRUPT_POLARITY_BOTH
+};
+
+#define DC_DECODE_INTERRUPT_POLARITY(int_polarity) \
+	(int_polarity == INTERRUPT_POLARITY_LOW) ? "Low" : \
+	(int_polarity == INTERRUPT_POLARITY_HIGH) ? "High" : \
+	(int_polarity == INTERRUPT_POLARITY_BOTH) ? "Both" : "Invalid"
+
+struct dc_timer_interrupt_params {
+	uint32_t micro_sec_interval;
+	enum dc_interrupt_context int_context;
+};
+
+struct dc_interrupt_params {
+	/* The polarity *change* which will trigger an interrupt.
+	 * If 'requested_polarity == INTERRUPT_POLARITY_BOTH', then
+	 * 'current_polarity' must be initialised. */
+	enum dc_interrupt_porlarity requested_polarity;
+	/* If 'requested_polarity == INTERRUPT_POLARITY_BOTH',
+	 * 'current_polarity' should contain the current state, which means
+	 * the interrupt will be triggered when state changes from what is,
+	 * in 'current_polarity'. */
+	enum dc_interrupt_porlarity current_polarity;
+	enum dc_irq_source irq_source;
+	enum dc_interrupt_context int_context;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h b/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
new file mode 100644
index 000000000000..8ebbe650c124
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/adapter_service_interface.h
@@ -0,0 +1,632 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ADAPTER_SERVICE_INTERFACE_H__
+#define __DAL_ADAPTER_SERVICE_INTERFACE_H__
+
+#include "grph_object_ctrl_defs.h"
+#include "gpio_interface.h"
+#include "ddc_interface.h"
+#include "irq_interface.h"
+#include "bios_parser_interface.h"
+#include "adapter_service_types.h"
+#include "dal_types.h"
+#include "asic_capability_types.h"
+
+/* forward declaration */
+struct i2caux;
+struct adapter_service;
+
+
+/*
+ * enum adapter_feature_id
+ *
+ * Definition of all adapter features
+ *
+ * The enumeration defines the IDs of all the adapter features. The enum
+ * organizes all the features into several feature sets. The range of feature
+ * set N is from ((N-1)*32+1) to (N*32). Because there may be three value-type
+ * feature, boolean-type, unsigned char-type and unsinged int-type, the number
+ * of features should be 32, 4 and 1 in the feature set accordingly.
+ *
+ * In a boolean-type feature set N, the enumeration value of the feature should
+ * be ((N-1)*32+1), ((N-1)*32+2), ..., (N*32).
+ *
+ * In an unsigned char-type feature set N, the enumeration value of the
+ * feature should be ((N-1)*32+1), ((N-1)*32+8), ((N-1)*32+16) and (N*32).
+ *
+ * In an unsigned int-type feature set N, the enumeration value of the feature
+ * should be ((N-1)*32+1)
+ */
+enum adapter_feature_id {
+	FEATURE_UNKNOWN = 0,
+
+	/* Boolean set, up to 32 entries */
+	FEATURE_ENABLE_HW_EDID_POLLING = 1,
+	FEATURE_SET_01_START = FEATURE_ENABLE_HW_EDID_POLLING,
+	FEATURE_DP_SINK_DETECT_POLL_DATA_PIN,
+	FEATURE_UNDERFLOW_INTERRUPT,
+	FEATURE_ALLOW_WATERMARK_ADJUSTMENT,
+	FEATURE_LIGHT_SLEEP,
+	FEATURE_DCP_DITHER_FRAME_RANDOM_ENABLE,
+	FEATURE_DCP_DITHER_RGB_RANDOM_ENABLE,
+	FEATURE_DCP_DITHER_HIGH_PASS_RANDOM_ENABLE,
+	FEATURE_DETECT_REQUIRE_HPD_HIGH,
+	FEATURE_LINE_BUFFER_ENHANCED_PIXEL_DEPTH, /* 10th */
+	FEATURE_MAXIMIZE_URGENCY_WATERMARKS,
+	FEATURE_MAXIMIZE_STUTTER_MARKS,
+	FEATURE_MAXIMIZE_NBP_MARKS,
+	FEATURE_RESTORE_USAGE_I2C_SW_ENGINE,
+	FEATURE_USE_MAX_DISPLAY_CLK,
+	FEATURE_ALLOW_EDP_RESOURCE_SHARING,
+	FEATURE_SUPPORT_DP_YUV,
+	FEATURE_SUPPORT_DP_Y_ONLY,
+	FEATURE_DISABLE_DP_GTC_SYNC,
+	FEATURE_NO_HPD_LOW_POLLING_VCC_OFF, /* 20th */
+	FEATURE_ENABLE_DFS_BYPASS,
+	FEATURE_LB_HIGH_RESOLUTION,
+	FEATURE_DP_DISPLAY_FORCE_SS_ENABLE,
+	FEATURE_REPORT_CE_MODE_ONLY,
+	FEATURE_ALLOW_OPTIMIZED_MODE_AS_DEFAULT,
+	FEATURE_DDC_READ_FORCE_REPEATED_START,
+	FEATURE_FORCE_TIMING_RESYNC,
+	FEATURE_TMDS_DISABLE_DITHERING,
+	FEATURE_HDMI_DISABLE_DITHERING,
+	FEATURE_DP_DISABLE_DITHERING, /* 30th */
+	FEATURE_EMBEDDED_DISABLE_DITHERING,
+	FEATURE_DISABLE_AZ_CLOCK_GATING, /* 32th. This set is full */
+	FEATURE_SET_01_END = FEATURE_SET_01_START + 31,
+
+	/* Boolean set, up to 32 entries */
+	FEATURE_WIRELESS_ENABLE = FEATURE_SET_01_END + 1,
+	FEATURE_SET_02_START = FEATURE_WIRELESS_ENABLE,
+	FEATURE_WIRELESS_FULL_TIMING_ADJUSTMENT,
+	FEATURE_WIRELESS_LIMIT_720P,
+	FEATURE_WIRELESS_ENABLE_COMPRESSED_AUDIO,
+	FEATURE_WIRELESS_INCLUDE_UNVERIFIED_TIMINGS,
+	FEATURE_MODIFY_TIMINGS_FOR_WIRELESS,
+	FEATURE_ALLOW_SELF_REFRESH,
+	FEATURE_ALLOW_DYNAMIC_PIXEL_ENCODING_CHANGE,
+	FEATURE_ALLOW_HSYNC_VSYNC_ADJUSTMENT,
+	FEATURE_FORCE_PSR, /* 10th */
+	FEATURE_PREFER_3D_TIMING,
+	FEATURE_VARI_BRIGHT_ENABLE,
+	FEATURE_PSR_ENABLE,
+	FEATURE_EDID_STRESS_READ,
+	FEATURE_DP_FRAME_PACK_STEREO3D,
+	FEATURE_ALLOW_HDMI_WITHOUT_AUDIO,
+	FEATURE_RESTORE_USAGE_I2C_SW_ENGING,
+	FEATURE_ABM_2_0,
+	FEATURE_SUPPORT_MIRABILIS,
+	FEATURE_LOAD_DMCU_FIRMWARE, /* 20th */
+	FEATURE_ENABLE_GPU_SCALING,
+	FEATURE_DONGLE_SINK_COUNT_CHECK,
+	FEATURE_INSTANT_UP_SCALE_DOWN_SCALE,
+	FEATURE_TILED_DISPLAY,
+	FEATURE_CHANGE_I2C_SPEED_CONTROL,
+	FEATURE_REPORT_SINGLE_SELECTED_TIMING,
+	FEATURE_ALLOW_HDMI_HIGH_CLK_DP_DONGLE,
+	FEATURE_SUPPORT_EXTERNAL_PANEL_DRR,
+	FEATURE_SUPPORT_SMOOTH_BRIGHTNESS,
+	FEATURE_ALLOW_DIRECT_MEMORY_ACCESS_TRIG, /* 30th */
+	FEATURE_POWER_GATING_LB_PORTION, /* 31nd. One more left. */
+	FEATURE_SET_02_END = FEATURE_SET_02_START + 31,
+
+	/* UInt set, 1 entry: DCP Bit Depth Reduction Mode */
+	FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE = FEATURE_SET_02_END + 1,
+	FEATURE_SET_03_START = FEATURE_DCP_BIT_DEPTH_REDUCTION_MODE,
+	FEATURE_SET_03_END = FEATURE_SET_03_START + 31,
+
+	/* UInt set, 1 entry: DCP Dither Mode */
+	FEATURE_DCP_DITHER_MODE = FEATURE_SET_03_END + 1,
+	FEATURE_SET_04_START = FEATURE_DCP_DITHER_MODE,
+	FEATURE_SET_04_END = FEATURE_SET_04_START + 31,
+
+	/* UInt set, 1 entry: DCP Programming WA(workaround) */
+	FEATURE_DCP_PROGRAMMING_WA = FEATURE_SET_04_END + 1,
+	FEATURE_SET_06_START = FEATURE_DCP_PROGRAMMING_WA,
+	FEATURE_SET_06_END = FEATURE_SET_06_START + 31,
+
+	/* UInt set, 1 entry: Maximum co-functional non-DP displays */
+	FEATURE_MAX_COFUNC_NON_DP_DISPLAYS = FEATURE_SET_06_END + 1,
+	FEATURE_SET_07_START = FEATURE_MAX_COFUNC_NON_DP_DISPLAYS,
+	FEATURE_SET_07_END = FEATURE_SET_07_START + 31,
+
+	/* UInt set, 1 entry: Number of supported HDMI connection */
+	FEATURE_SUPPORTED_HDMI_CONNECTION_NUM = FEATURE_SET_07_END + 1,
+	FEATURE_SET_08_START = FEATURE_SUPPORTED_HDMI_CONNECTION_NUM,
+	FEATURE_SET_08_END = FEATURE_SET_08_START + 31,
+
+	/* UInt set, 1 entry: Maximum number of controllers */
+	FEATURE_MAX_CONTROLLER_NUM = FEATURE_SET_08_END + 1,
+	FEATURE_SET_09_START = FEATURE_MAX_CONTROLLER_NUM,
+	FEATURE_SET_09_END = FEATURE_SET_09_START + 31,
+
+	/* UInt set, 1 entry: Type of DRR support */
+	FEATURE_DRR_SUPPORT = FEATURE_SET_09_END + 1,
+	FEATURE_SET_10_START = FEATURE_DRR_SUPPORT,
+	FEATURE_SET_10_END = FEATURE_SET_10_START + 31,
+
+	/* UInt set, 1 entry: Stutter mode support */
+	FEATURE_STUTTER_MODE = FEATURE_SET_10_END + 1,
+	FEATURE_SET_11_START = FEATURE_STUTTER_MODE,
+	FEATURE_SET_11_END = FEATURE_SET_11_START + 31,
+
+	/* UInt set, 1 entry: Measure PSR setup time */
+	FEATURE_PSR_SETUP_TIME_TEST = FEATURE_SET_11_END + 1,
+	FEATURE_SET_12_START = FEATURE_PSR_SETUP_TIME_TEST,
+	FEATURE_SET_12_END = FEATURE_SET_12_START + 31,
+
+	/* Boolean set, up to 32 entries */
+	FEATURE_POWER_GATING_PIPE_IN_TILE = FEATURE_SET_12_END + 1,
+	FEATURE_SET_13_START = FEATURE_POWER_GATING_PIPE_IN_TILE,
+	FEATURE_USE_PPLIB,
+	FEATURE_DISABLE_LPT_SUPPORT,
+	FEATURE_DUMMY_FBC_BACKEND,
+	FEATURE_DISABLE_FBC_COMP_CLK_GATE,
+	FEATURE_DPMS_AUDIO_ENDPOINT_CONTROL,
+	FEATURE_PIXEL_PERFECT_OUTPUT,
+	FEATURE_8BPP_SUPPORTED,
+	FEATURE_SET_13_END = FEATURE_SET_13_START + 31,
+
+	/* UInt set, 1 entry: Display preferred view
+	 * 0: no preferred view
+	 * 1: native and preferred timing of embedded display will have high
+	 *    priority, so other displays will support it always
+	 */
+	FEATURE_DISPLAY_PREFERRED_VIEW = FEATURE_SET_13_END + 1,
+	FEATURE_SET_15_START = FEATURE_DISPLAY_PREFERRED_VIEW,
+	FEATURE_SET_15_END = FEATURE_SET_15_START + 31,
+
+	/* UInt set, 1 entry: DAL optimization */
+	FEATURE_OPTIMIZATION = FEATURE_SET_15_END + 1,
+	FEATURE_SET_16_START = FEATURE_OPTIMIZATION,
+	FEATURE_SET_16_END = FEATURE_SET_16_START + 31,
+
+	/* UInt set, 1 entry: Performance measurement */
+	FEATURE_PERF_MEASURE = FEATURE_SET_16_END + 1,
+	FEATURE_SET_17_START = FEATURE_PERF_MEASURE,
+	FEATURE_SET_17_END = FEATURE_SET_17_START + 31,
+
+	/* UInt set, 1 entry: Minimum backlight value [0-255] */
+	FEATURE_MIN_BACKLIGHT_LEVEL = FEATURE_SET_17_END + 1,
+	FEATURE_SET_18_START = FEATURE_MIN_BACKLIGHT_LEVEL,
+	FEATURE_SET_18_END = FEATURE_SET_18_START + 31,
+
+	/* UInt set, 1 entry: Maximum backlight value [0-255] */
+	FEATURE_MAX_BACKLIGHT_LEVEL = FEATURE_SET_18_END + 1,
+	FEATURE_SET_19_START = FEATURE_MAX_BACKLIGHT_LEVEL,
+	FEATURE_SET_19_END = FEATURE_SET_19_START + 31,
+
+	/* UInt set, 1 entry: AMB setting
+	 *
+	 * Each byte will control the ABM configuration to use for a specific
+	 * ABM level.
+	 *
+	 * HW team provided 12 different ABM min/max reduction pairs to choose
+	 * between for each ABM level.
+	 *
+	 * ABM level Byte Setting
+	 *       1    0   Default = 0 (setting 3), can be override to 1-12
+	 *       2    1   Default = 0 (setting 7), can be override to 1-12
+	 *       3    2   Default = 0 (setting 8), can be override to 1-12
+	 *       4    3   Default = 0 (setting 10), can be override to 1-12
+	 *
+	 * For example,
+	 * FEATURE_PREFERRED_ABM_CONFIG_SET = 0x0C060500, this represents:
+	 * ABM level 1 use default setting (setting 3)
+	 * ABM level 2 uses setting 5
+	 * ABM level 3 uses setting 6
+	 * ABM level 4 uses setting 12
+	 * Internal use only!
+	 */
+	FEATURE_PREFERRED_ABM_CONFIG_SET = FEATURE_SET_19_END + 1,
+	FEATURE_SET_20_START = FEATURE_PREFERRED_ABM_CONFIG_SET,
+	FEATURE_SET_20_END = FEATURE_SET_20_START + 31,
+
+	/* UInt set, 1 entry: Change SW I2C speed */
+	FEATURE_CHANGE_SW_I2C_SPEED = FEATURE_SET_20_END + 1,
+	FEATURE_SET_21_START = FEATURE_CHANGE_SW_I2C_SPEED,
+	FEATURE_SET_21_END = FEATURE_SET_21_START + 31,
+
+	/* UInt set, 1 entry: Change HW I2C speed */
+	FEATURE_CHANGE_HW_I2C_SPEED = FEATURE_SET_21_END + 1,
+	FEATURE_SET_22_START = FEATURE_CHANGE_HW_I2C_SPEED,
+	FEATURE_SET_22_END = FEATURE_SET_22_START + 31,
+
+	/* UInt set, 1 entry:
+	 * When PSR issue occurs, it is sometimes hard to debug since the
+	 * failure occurs immediately at boot. Use this setting to skip or
+	 * postpone PSR functionality and re-enable through DSAT. */
+	FEATURE_DEFAULT_PSR_LEVEL = FEATURE_SET_22_END + 1,
+	FEATURE_SET_23_START = FEATURE_DEFAULT_PSR_LEVEL,
+	FEATURE_SET_23_END = FEATURE_SET_23_START + 31,
+
+	/* UInt set, 1 entry: Allowed pixel clock range for LVDS */
+	FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE = FEATURE_SET_23_END + 1,
+	FEATURE_SET_24_START = FEATURE_LVDS_SAFE_PIXEL_CLOCK_RANGE,
+	FEATURE_SET_24_END = FEATURE_SET_24_START + 31,
+
+	/* UInt set, 1 entry: Max number of clock sources */
+	FEATURE_MAX_CLOCK_SOURCE_NUM = FEATURE_SET_24_END + 1,
+	FEATURE_SET_25_START = FEATURE_MAX_CLOCK_SOURCE_NUM,
+	FEATURE_SET_25_END = FEATURE_SET_25_START + 31,
+
+	/* UInt set, 1 entry: Select the ABM configuration to use.
+	 *
+	 * This feature set is used to allow packaging option to be defined
+	 * to allow OEM to select between the default ABM configuration or
+	 * alternative predefined configurations that may be more aggressive.
+	 *
+	 * Note that this regkey is meant for external use to select the
+	 * configuration OEM wants. Whereas the other PREFERRED_ABM_CONFIG_SET
+	 * key is only used for internal use and allows full reconfiguration.
+	 */
+	FEATURE_ABM_CONFIG = FEATURE_SET_25_END + 1,
+	FEATURE_SET_26_START = FEATURE_ABM_CONFIG,
+	FEATURE_SET_26_END = FEATURE_SET_26_START + 31,
+
+	/* UInt set, 1 entry: Select the default speed in which smooth
+	 * brightness feature should converge towards target backlight level.
+	 *
+	 * For example, a setting of 500 means it takes 500ms to transition
+	 * from current backlight level to the new requested backlight level.
+	 */
+	FEATURE_SMOOTH_BRTN_ADJ_TIME_IN_MS = FEATURE_SET_26_END + 1,
+	FEATURE_SET_27_START = FEATURE_SMOOTH_BRTN_ADJ_TIME_IN_MS,
+	FEATURE_SET_27_END = FEATURE_SET_27_START + 31,
+
+	/* Set 28: UInt set, 1 entry: Allow runtime parameter to force specific
+	 * Static Screen Event triggers for test purposes. */
+	FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS = FEATURE_SET_27_END + 1,
+	FEATURE_SET_28_START = FEATURE_FORCE_STATIC_SCREEN_EVENT_TRIGGERS,
+	FEATURE_SET_28_END = FEATURE_SET_28_START + 31,
+
+	FEATURE_MAXIMUM
+};
+
+/* Adapter Service type of DRR support*/
+enum as_drr_support {
+	AS_DRR_SUPPORT_DISABLED = 0x0,
+	AS_DRR_SUPPORT_ENABLED = 0x1,
+	AS_DRR_SUPPORT_MIN_FORCED_FPS = 0xA
+};
+
+/* Adapter service initialize data structure*/
+struct as_init_data {
+	struct hw_asic_id hw_init_data;
+	struct bp_init_data bp_init_data;
+	struct dc_context *ctx;
+	struct bdf_info bdf_info;
+	const struct dal_override_parameters *display_param;
+	struct dc_bios *vbios_override;
+	enum dce_environment dce_environment;
+};
+
+/* Create adapter service */
+struct adapter_service *dal_adapter_service_create(
+	struct as_init_data *init_data);
+
+/* Destroy adapter service and objects it contains */
+void dal_adapter_service_destroy(
+	struct adapter_service **as);
+
+/* Get the DCE version of current ASIC */
+enum dce_version dal_adapter_service_get_dce_version(
+	const struct adapter_service *as);
+
+enum dce_environment dal_adapter_service_get_dce_environment(
+	const struct adapter_service *as);
+
+/* Get firmware information from BIOS */
+bool dal_adapter_service_get_firmware_info(
+	struct adapter_service *as,
+	struct firmware_info *info);
+
+
+/* functions to get a total number of objects of specific type */
+uint8_t dal_adapter_service_get_connectors_num(
+	struct adapter_service *as);
+
+/* Get number of controllers */
+uint8_t dal_adapter_service_get_controllers_num(
+	struct adapter_service *as);
+
+/* Get number of clock sources */
+uint8_t dal_adapter_service_get_clock_sources_num(
+	struct adapter_service *as);
+
+/* Get number of controllers */
+uint8_t dal_adapter_service_get_func_controllers_num(
+	struct adapter_service *as);
+
+/* Get number of stream engines */
+uint8_t dal_adapter_service_get_stream_engines_num(
+	struct adapter_service *as);
+
+/* functions to get object id based on object index */
+struct graphics_object_id dal_adapter_service_get_connector_obj_id(
+	struct adapter_service *as,
+	uint8_t connector_index);
+
+/* Get number of spread spectrum entries from BIOS */
+uint32_t dal_adapter_service_get_ss_info_num(
+	struct adapter_service *as,
+	enum as_signal_type signal);
+
+/* Get spread spectrum info from BIOS */
+bool dal_adapter_service_get_ss_info(
+	struct adapter_service *as,
+	enum as_signal_type signal,
+	uint32_t idx,
+	struct spread_spectrum_info *info);
+
+/* Check if DFS bypass is enabled */
+bool dal_adapter_service_is_dfs_bypass_enabled(struct adapter_service *as);
+
+/* Get memory controller latency */
+uint32_t dal_adapter_service_get_mc_latency(
+	struct adapter_service *as);
+
+/* Get the video RAM bit width set on the ASIC */
+uint32_t dal_adapter_service_get_asic_vram_bit_width(
+	struct adapter_service *as);
+
+/* Get the bug flags set on this ASIC */
+struct asic_bugs dal_adapter_service_get_asic_bugs(
+	struct adapter_service *as);
+
+/* Get efficiency of DRAM */
+uint32_t dal_adapter_service_get_dram_bandwidth_efficiency(
+	struct adapter_service *as);
+
+/* Get multiplier for the memory type */
+uint32_t dal_adapter_service_get_memory_type_multiplier(
+	struct adapter_service *as);
+
+/* Get parameters for bandwidth tuning */
+bool dal_adapter_service_get_bandwidth_tuning_params(
+	struct adapter_service *as,
+	union bandwidth_tuning_params *params);
+
+/* Get integrated information on BIOS */
+bool dal_adapter_service_get_integrated_info(
+	struct adapter_service *as,
+	struct integrated_info *info);
+
+/* Return if a given feature is supported by the ASIC */
+bool dal_adapter_service_is_feature_supported(
+	enum adapter_feature_id feature_id);
+
+/* Get the cached value of a given feature */
+bool dal_adapter_service_get_feature_value(
+	const enum adapter_feature_id feature_id,
+	void *data,
+	uint32_t size);
+
+/* Get a copy of ASIC feature flags */
+struct asic_feature_flags dal_adapter_service_get_feature_flags(
+	struct adapter_service *as);
+
+/* Obtain DDC */
+struct ddc *dal_adapter_service_obtain_ddc(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+/* Release DDC */
+void dal_adapter_service_release_ddc(
+	struct adapter_service *as,
+	struct ddc *ddc);
+
+/* Obtain HPD interrupt request */
+struct irq *dal_adapter_service_obtain_hpd_irq(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+/* Release interrupt request */
+void dal_adapter_service_release_irq(
+	struct adapter_service *as,
+	struct irq *irq);
+
+/* Obtain GPIO */
+struct gpio *dal_adapter_service_obtain_gpio(
+	struct adapter_service *as,
+	enum gpio_id id,
+	uint32_t en);
+
+/* Obtain GPIO for stereo3D*/
+struct gpio *dal_adapter_service_obtain_stereo_gpio(struct adapter_service *as);
+
+/* Release GPIO */
+void dal_adapter_service_release_gpio(
+		struct adapter_service *as,
+		struct gpio *gpio);
+
+/* Get SW I2C speed */
+uint32_t dal_adapter_service_get_sw_i2c_speed(struct adapter_service *as);
+
+/* Get HW I2C speed */
+uint32_t dal_adapter_service_get_hw_i2c_speed(struct adapter_service *as);
+
+/* Get line buffer size */
+uint32_t dal_adapter_service_get_line_buffer_size(struct adapter_service *as);
+
+/* Get information on audio support */
+union audio_support dal_adapter_service_get_audio_support(
+		struct adapter_service *as);
+
+/* Get I2C information from BIOS */
+bool dal_adapter_service_get_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	struct graphics_object_i2c_info *i2c_info);
+
+/* Get bios parser handler */
+struct dc_bios *dal_adapter_service_get_bios_parser(
+	struct adapter_service *as);
+
+/* Get i2c aux handler */
+struct i2caux *dal_adapter_service_get_i2caux(
+	struct adapter_service *as);
+
+struct dal_asic_runtime_flags dal_adapter_service_get_asic_runtime_flags(
+	struct adapter_service *as);
+
+bool dal_adapter_service_initialize_hw_data(
+	struct adapter_service *as);
+
+struct graphics_object_id dal_adapter_service_enum_fake_path_resource(
+	struct adapter_service *as,
+	uint32_t index);
+
+struct graphics_object_id dal_adapter_service_enum_stereo_sync_object(
+	struct adapter_service *as,
+	uint32_t index);
+
+struct graphics_object_id dal_adapter_service_enum_sync_output_object(
+	struct adapter_service *as,
+	uint32_t index);
+
+struct graphics_object_id dal_adapter_service_enum_audio_object(
+	struct adapter_service *as,
+	uint32_t index);
+
+void dal_adapter_service_update_audio_connectivity(
+	struct adapter_service *as,
+	uint32_t number_of_audio_capable_display_path);
+
+bool dal_adapter_service_has_embedded_display_connector(
+	struct adapter_service *as);
+
+bool dal_adapter_service_get_embedded_panel_info(
+	struct adapter_service *as,
+	struct embedded_panel_info *info);
+
+bool dal_adapter_service_enum_embedded_panel_patch_mode(
+	struct adapter_service *as,
+	uint32_t index,
+	struct embedded_panel_patch_mode *mode);
+
+bool dal_adapter_service_get_faked_edid_len(
+	struct adapter_service *as,
+	uint32_t *len);
+
+bool dal_adapter_service_get_faked_edid_buf(
+	struct adapter_service *as,
+	uint8_t *buf,
+	uint32_t len);
+
+uint32_t dal_adapter_service_get_max_cofunc_non_dp_displays(void);
+
+uint32_t dal_adapter_service_get_single_selected_timing_signals(void);
+
+bool dal_adapter_service_get_device_tag(
+	struct adapter_service *as,
+	struct graphics_object_id connector_object_id,
+	uint32_t device_tag_index,
+	struct connector_device_tag_info *info);
+
+bool dal_adapter_service_is_device_id_supported(
+	struct adapter_service *as,
+	struct device_id id);
+
+bool dal_adapter_service_is_meet_underscan_req(struct adapter_service *as);
+
+bool dal_adapter_service_underscan_for_hdmi_only(struct adapter_service *as);
+
+uint32_t dal_adapter_service_get_src_num(
+	struct adapter_service *as,
+	struct graphics_object_id id);
+
+struct graphics_object_id dal_adapter_service_get_src_obj(
+	struct adapter_service *as,
+	struct graphics_object_id id,
+	uint32_t index);
+
+/* Is this Fusion ASIC */
+bool dal_adapter_service_is_fusion(struct adapter_service *as);
+
+/* Is this ASIC support dynamic DFSbypass switch */
+bool dal_adapter_service_is_dfsbyass_dynamic(struct adapter_service *as);
+
+/* Reports whether driver settings allow requested optimization */
+bool dal_adapter_service_should_optimize(
+		struct adapter_service *as, enum optimization_feature feature);
+
+/* Determine if driver is in accelerated mode */
+bool dal_adapter_service_is_in_accelerated_mode(struct adapter_service *as);
+
+struct ddc *dal_adapter_service_obtain_ddc_from_i2c_info(
+	struct adapter_service *as,
+	struct graphics_object_i2c_info *info);
+
+struct bdf_info dal_adapter_service_get_adapter_info(
+	struct adapter_service *as);
+
+
+/* Determine if this ASIC needs to wait on PLL lock bit */
+bool dal_adapter_service_should_psr_skip_wait_for_pll_lock(
+	struct adapter_service *as);
+
+#define SIZEOF_BACKLIGHT_LUT 101
+#define ABSOLUTE_BACKLIGHT_MAX 255
+#define DEFAULT_MIN_BACKLIGHT 12
+#define DEFAULT_MAX_BACKLIGHT 255
+#define BACKLIGHT_CURVE_COEFFB 100
+#define BACKLIGHT_CURVE_COEFFA_FACTOR 10000
+#define BACKLIGHT_CURVE_COEFFB_FACTOR 100
+
+struct panel_backlight_levels {
+	uint32_t ac_level_percentage;
+	uint32_t dc_level_percentage;
+};
+
+bool dal_adapter_service_is_lid_open(struct adapter_service *as);
+
+bool dal_adapter_service_get_panel_backlight_default_levels(
+	struct adapter_service *as,
+	struct panel_backlight_levels *levels);
+
+bool dal_adapter_service_get_panel_backlight_boundaries(
+	struct adapter_service *as,
+	struct panel_backlight_boundaries *boundaries);
+
+uint32_t dal_adapter_service_get_view_port_pixel_granularity(
+	struct adapter_service *as);
+
+uint32_t dal_adapter_service_get_num_of_path_per_dp_mst_connector(
+		struct adapter_service *as);
+
+uint32_t dal_adapter_service_get_num_of_underlays(
+		struct adapter_service *as);
+
+bool dal_adapter_service_get_encoder_cap_info(
+		struct adapter_service *as,
+		struct graphics_object_id id,
+		struct graphics_object_encoder_cap_info *info);
+
+bool dal_adapter_service_is_mc_tuning_req(struct adapter_service *as);
+
+#endif /* __DAL_ADAPTER_SERVICE_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/adapter_service_types.h b/drivers/gpu/drm/amd/dal/include/adapter_service_types.h
new file mode 100644
index 000000000000..4cb4b4b6eeed
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/adapter_service_types.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ADAPTER_SERVICE_TYPES_H__
+#define __DAL_ADAPTER_SERVICE_TYPES_H__
+
+/* TODO: include signal_types.h and remove this enum */
+enum as_signal_type {
+	AS_SIGNAL_TYPE_NONE = 0L, /* no signal */
+	AS_SIGNAL_TYPE_DVI,
+	AS_SIGNAL_TYPE_HDMI,
+	AS_SIGNAL_TYPE_LVDS,
+	AS_SIGNAL_TYPE_DISPLAY_PORT,
+	AS_SIGNAL_TYPE_GPU_PLL,
+	AS_SIGNAL_TYPE_UNKNOWN
+};
+
+/*
+ * Struct used for algorithm of Bandwidth tuning parameters
+ * the sequence of the fields is binded with runtime parameter.
+ */
+union bandwidth_tuning_params {
+	struct bandwidth_tuning_params_struct {
+		uint32_t read_delay_stutter_off_usec;
+		uint32_t ignore_hblank_time;/*bool*/
+		uint32_t extra_reordering_latency_usec;
+		uint32_t extra_mc_latency_usec;
+		uint32_t data_return_bandwidth_eff;/*in %*/
+		uint32_t dmif_request_bandwidth_eff;/*in %*/
+		uint32_t sclock_latency_multiplier;/*in unit of 0.01*/
+		uint32_t mclock_latency_multiplier;/*in unit of 0.01*/
+		uint32_t fix_latency_multiplier;/*in unit of 0.01*/
+		 /*in unit represent in watermark*/
+		uint32_t use_urgency_watermark_offset;
+	} tuning_info;
+	uint32_t arr_info[sizeof(struct bandwidth_tuning_params_struct)
+		/ sizeof(uint32_t)];
+};
+
+union audio_support {
+	struct {
+		uint32_t DP_AUDIO:1;
+		uint32_t HDMI_AUDIO_ON_DONGLE:1;
+		uint32_t HDMI_AUDIO_NATIVE:1;
+	} bits;
+	uint32_t raw;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h b/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
new file mode 100644
index 000000000000..bdeaaf9066a2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/asic_capability_interface.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of enc software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and enc permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ASIC_CAPABILITY_INTERFACE_H__
+#define __DAL_ASIC_CAPABILITY_INTERFACE_H__
+
+/* Include */
+#include "include/asic_capability_types.h"
+
+/* Forward declaration */
+struct hw_asic_id;
+
+
+/* ASIC capability */
+struct asic_capability {
+	struct dc_context *ctx;
+	struct asic_caps caps;
+	struct asic_stereo_3d_caps stereo_3d_caps;
+	struct asic_bugs bugs;
+	struct dal_asic_runtime_flags runtime_flags;
+	uint32_t data[ASIC_DATA_MAX_NUMBER];
+};
+
+
+/**
+ * Interfaces
+ */
+
+/* Create and initialize ASIC capability */
+struct asic_capability *dal_asic_capability_create(struct hw_asic_id *init,
+		struct dc_context *ctx);
+
+/* Destroy ASIC capability and free memory space */
+void dal_asic_capability_destroy(struct asic_capability **cap);
+
+#endif /* __DAL_ASIC_CAPABILITY_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/asic_capability_types.h b/drivers/gpu/drm/amd/dal/include/asic_capability_types.h
new file mode 100644
index 000000000000..1cb977618bdf
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/asic_capability_types.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_ASIC_CAPABILITY_TYPES_H__
+#define __DAL_ASIC_CAPABILITY_TYPES_H__
+
+/*
+ * ASIC Capabilities
+ */
+struct asic_caps {
+	bool CONSUMER_SINGLE_SELECTED_TIMING:1;
+	bool UNDERSCAN_ADJUST:1;
+	bool DELTA_SIGMA_SUPPORT:1;
+	bool PANEL_SELF_REFRESH_SUPPORTED:1;
+	bool IS_FUSION:1;
+	bool DP_MST_SUPPORTED:1;
+	bool UNDERSCAN_FOR_HDMI_ONLY:1;
+	bool DVI_CLOCK_SHARE_CAPABILITY:1;
+	bool SUPPORT_CEA861E_FINAL:1;
+	bool MIRABILIS_SUPPORTED:1;
+	bool MIRABILIS_ENABLED_BY_DEFAULT:1;
+	bool DEVICE_TAG_REMAP_SUPPORTED:1;
+	bool HEADLESS_NO_OPM_SUPPORTED:1;
+	bool WIRELESS_LIMIT_TO_720P:1;
+	bool WIRELESS_FULL_TIMING_ADJUSTMENT:1;
+	bool WIRELESS_TIMING_ADJUSTMENT:1;
+	bool WIRELESS_COMPRESSED_AUDIO:1;
+	bool VCE_SUPPORTED:1;
+	bool HPD_CHECK_FOR_EDID:1;
+	bool NO_VCC_OFF_HPD_POLLING:1;
+	bool NEED_MC_TUNING:1;
+	bool SKIP_PSR_WAIT_FOR_PLL_LOCK_BIT:1;
+	bool DFSBYPASS_DYNAMIC_SUPPORT:1;
+	bool SUPPORT_8BPP:1;
+};
+
+
+/*
+ * ASIC Stereo 3D Caps
+ */
+struct asic_stereo_3d_caps {
+	bool SUPPORTED:1;
+	bool DISPLAY_BASED_ON_WS:1;
+	bool HDMI_FRAME_PACK:1;
+	bool INTERLACE_FRAME_PACK:1;
+	bool DISPLAYPORT_FRAME_PACK:1;
+	bool DISPLAYPORT_FRAME_ALT:1;
+	bool INTERLEAVE:1;
+};
+
+
+/*
+ * ASIC Bugs
+ */
+struct asic_bugs {
+	bool MST_SYMBOL_MISALIGNMENT:1;
+	bool PSR_2X_LANE_GANGING:1;
+	bool LB_WA_IS_SUPPORTED:1;
+	bool ROM_REGISTER_ACCESS:1;
+	bool PSR_WA_OVERSCAN_CRC_ERROR:1;
+};
+
+
+/*
+ * ASIC Data
+ */
+enum asic_data {
+	ASIC_DATA_FIRST = 0,
+	ASIC_DATA_CONTROLLERS_NUM = ASIC_DATA_FIRST,
+	ASIC_DATA_FUNCTIONAL_CONTROLLERS_NUM,
+	ASIC_DATA_DCE_VERSION,
+	ASIC_DATA_DCE_VERSION_MINOR,
+	ASIC_DATA_VRAM_TYPE,
+	ASIC_DATA_VRAM_BITWIDTH,
+	ASIC_DATA_FEATURE_FLAGS,
+	ASIC_DATA_LINEBUFFER_NUM,
+	ASIC_DATA_LINEBUFFER_SIZE,
+	ASIC_DATA_DRAM_BANDWIDTH_EFFICIENCY,
+	ASIC_DATA_MC_LATENCY,
+	ASIC_DATA_MC_LATENCY_SLOW,
+	ASIC_DATA_CLOCKSOURCES_NUM,
+	ASIC_DATA_MEMORYTYPE_MULTIPLIER,
+	ASIC_DATA_STUTTERMODE,
+	ASIC_DATA_PATH_NUM_PER_DPMST_CONNECTOR,
+	ASIC_DATA_MAX_COFUNC_NONDP_DISPLAYS,
+	ASIC_DATA_REVISION_ID,
+	ASIC_DATA_MAX_UNDERSCAN_PERCENTAGE,
+	ASIC_DATA_VIEWPORT_PIXEL_GRANULARITY,
+	ASIC_DATA_DIGFE_NUM,
+	ASIC_DATA_SUPPORTED_HDMI_CONNECTION_NUM,
+	ASIC_DATA_MIN_DISPCLK_FOR_UNDERSCAN,
+	ASIC_DATA_NUM_OF_VIDEO_PLANES,
+	ASIC_DATA_DEFAULT_I2C_SPEED_IN_KHZ,
+	ASIC_DATA_MAX_NUMBER /* end of enum */
+};
+
+
+/*
+ * ASIC Feature Flags
+ */
+struct asic_feature_flags {
+	union {
+		uint32_t raw;
+		struct {
+			uint32_t LEGACY_CLIENT:1;
+			uint32_t PACKED_PIXEL_FORMAT:1;
+			uint32_t WORKSTATION_STEREO:1;
+			uint32_t WORKSTATION:1;
+		} bits;
+	};
+};
+
+#endif /* __DAL_ASIC_CAPABILITY_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/audio_interface.h b/drivers/gpu/drm/amd/dal/include/audio_interface.h
new file mode 100644
index 000000000000..bf2176279f0e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/audio_interface.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AUDIO_INTERFACE_H__
+#define __DAL_AUDIO_INTERFACE_H__
+
+#include "audio_types.h"
+#include "adapter_service_interface.h"
+#include "signal_types.h"
+#include "link_service_types.h"
+
+/* forward declaration */
+struct audio;
+struct dal_adapter_service;
+
+/*****  audio initialization data  *****/
+/*
+ * by audio, it means audio endpoint id. ASIC may have many endpoints.
+ * upper sw layer will create one audio object instance for each endpoints.
+ * ASIC support internal audio only. So enum number is used to differ
+ * each endpoint
+ */
+struct audio_init_data {
+	struct adapter_service *as;
+	struct graphics_object_id audio_stream_id;
+	struct dc_context *ctx;
+};
+
+enum audio_result {
+	AUDIO_RESULT_OK,
+	AUDIO_RESULT_ERROR,
+};
+
+/****** audio object create, destroy ******/
+struct audio *dal_audio_create(
+	const struct audio_init_data *init_data);
+
+void dal_audio_destroy(
+	struct audio **audio);
+
+/****** graphics object interface ******/
+const struct graphics_object_id dal_audio_get_graphics_object_id(
+	const struct audio *audio);
+
+/* Enumerate Graphics Object supported Input/Output Signal Types */
+uint32_t dal_audio_enumerate_input_signals(
+	struct audio *audio);
+
+uint32_t dal_audio_enumerate_output_signals(
+	struct audio *audio);
+
+/*  Check if signal supported by GraphicsObject  */
+bool dal_audio_is_input_signal_supported(
+	struct audio *audio,
+	enum signal_type signal);
+
+bool dal_audio_is_output_signal_supported(
+	struct audio *audio,
+	enum signal_type signal);
+
+
+/***** programming interface *****/
+
+/* perform power up sequence (boot up, resume, recovery) */
+enum audio_result dal_audio_power_up(
+	struct audio *audio);
+
+/* perform power down (shut down, stand by) */
+enum audio_result dal_audio_power_down(
+	struct audio *audio);
+
+/* setup audio */
+enum audio_result dal_audio_setup(
+	struct audio *audio,
+	struct audio_output *output,
+	struct audio_info *info);
+
+/* enable audio */
+enum audio_result dal_audio_enable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+/* disable audio */
+enum audio_result dal_audio_disable_output(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+/* enable azalia audio endpoint */
+enum audio_result dal_audio_enable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id);
+
+/* disable azalia audio endpoint */
+enum audio_result dal_audio_disable_azalia_audio_jack_presence(
+	struct audio *audio,
+	enum engine_id engine_id);
+
+/* unmute audio */
+enum audio_result dal_audio_unmute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+/* mute audio */
+enum audio_result dal_audio_mute(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal);
+
+
+/***** information interface *****/
+
+struct audio_feature_support dal_audio_get_supported_features(
+	struct audio *audio);
+
+/* get audio bandwidth information */
+void dal_audio_check_audio_bandwidth(
+	struct audio *audio,
+	const struct audio_crtc_info *info,
+	uint32_t channel_count,
+	enum signal_type signal,
+	union audio_sample_rates *sample_rates);
+
+/* Enable multi channel split */
+void dal_audio_enable_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	enum signal_type signal,
+	const struct audio_channel_associate_info *audio_mapping,
+	bool enable);
+
+/* get current multi channel split. */
+enum audio_result dal_audio_get_channel_splitting_mapping(
+	struct audio *audio,
+	enum engine_id engine_id,
+	struct audio_channel_associate_info *audio_mapping);
+
+/* set payload value for the unsolicited response */
+void dal_audio_set_unsolicited_response_payload(
+	struct audio *audio,
+	enum audio_payload payload);
+
+/*Assign GTC group and enable GTC value embedding*/
+void dal_audio_enable_gtc_embedding_with_group(
+	struct audio *audio,
+	uint32_t group_num,
+	uint32_t audio_latency);
+
+/* Disable GTC value embedding */
+void dal_audio_disable_gtc_embedding(
+	struct audio *audio);
+
+/* Update audio wall clock source */
+void dal_audio_setup_audio_wall_dto(
+	struct audio *audio,
+	enum signal_type signal,
+	const struct audio_crtc_info *crtc_info,
+	const struct audio_pll_info *pll_info);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/audio_types.h b/drivers/gpu/drm/amd/dal/include/audio_types.h
new file mode 100644
index 000000000000..54f5546a574c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/audio_types.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AUDIO_TYPES_H__
+#define __AUDIO_TYPES_H__
+
+#include "grph_object_defs.h"
+#include "signal_types.h"
+
+#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20
+#define MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 18
+#define MULTI_CHANNEL_SPLIT_NO_ASSO_INFO 0xFFFFFFFF
+
+
+struct audio_pll_hw_settings {
+	uint32_t feed_back_divider;
+	uint32_t step_size_integer;
+	uint32_t step_size_fraction;
+	uint32_t step_range;
+};
+
+struct audio_clock_info {
+	/* pixel clock frequency*/
+	uint32_t pixel_clock_in_10khz;
+	/* N - 32KHz audio */
+	uint32_t n_32khz;
+	/* CTS - 32KHz audio*/
+	uint32_t cts_32khz;
+	uint32_t n_44khz;
+	uint32_t cts_44khz;
+	uint32_t n_48khz;
+	uint32_t cts_48khz;
+};
+
+struct azalia_clock_info {
+	uint32_t pixel_clock_in_10khz;
+	uint32_t audio_dto_phase;
+	uint32_t audio_dto_module;
+	uint32_t audio_dto_wall_clock_ratio;
+};
+
+enum audio_dto_source {
+	DTO_SOURCE_UNKNOWN = 0,
+	DTO_SOURCE_ID0,
+	DTO_SOURCE_ID1,
+	DTO_SOURCE_ID2,
+	DTO_SOURCE_ID3,
+	DTO_SOURCE_ID4,
+	DTO_SOURCE_ID5
+};
+
+union audio_sample_rates {
+	struct sample_rates {
+		uint8_t RATE_32:1;
+		uint8_t RATE_44_1:1;
+		uint8_t RATE_48:1;
+		uint8_t RATE_88_2:1;
+		uint8_t RATE_96:1;
+		uint8_t RATE_176_4:1;
+		uint8_t RATE_192:1;
+	} rate;
+
+	uint8_t all;
+};
+
+enum audio_format_code {
+	AUDIO_FORMAT_CODE_FIRST = 1,
+	AUDIO_FORMAT_CODE_LINEARPCM = AUDIO_FORMAT_CODE_FIRST,
+
+	AUDIO_FORMAT_CODE_AC3,
+	/*Layers 1 & 2 */
+	AUDIO_FORMAT_CODE_MPEG1,
+	/*MPEG1 Layer 3 */
+	AUDIO_FORMAT_CODE_MP3,
+	/*multichannel */
+	AUDIO_FORMAT_CODE_MPEG2,
+	AUDIO_FORMAT_CODE_AAC,
+	AUDIO_FORMAT_CODE_DTS,
+	AUDIO_FORMAT_CODE_ATRAC,
+	AUDIO_FORMAT_CODE_1BITAUDIO,
+	AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS,
+	AUDIO_FORMAT_CODE_DTS_HD,
+	AUDIO_FORMAT_CODE_MAT_MLP,
+	AUDIO_FORMAT_CODE_DST,
+	AUDIO_FORMAT_CODE_WMAPRO,
+	AUDIO_FORMAT_CODE_LAST,
+	AUDIO_FORMAT_CODE_COUNT =
+		AUDIO_FORMAT_CODE_LAST - AUDIO_FORMAT_CODE_FIRST
+};
+
+struct audio_mode {
+	 /* ucData[0] [6:3] */
+	enum audio_format_code format_code;
+	/* ucData[0] [2:0] */
+	uint8_t channel_count;
+	/* ucData[1] */
+	union audio_sample_rates sample_rates;
+	union {
+		/* for LPCM */
+		uint8_t sample_size;
+		/* for Audio Formats 2-8 (Max bit rate divided by 8 kHz) */
+		uint8_t max_bit_rate;
+		/* for Audio Formats 9-15 */
+		uint8_t vendor_specific;
+	};
+};
+
+struct audio_speaker_flags {
+    uint32_t FL_FR:1;
+    uint32_t LFE:1;
+    uint32_t FC:1;
+    uint32_t RL_RR:1;
+    uint32_t RC:1;
+    uint32_t FLC_FRC:1;
+    uint32_t RLC_RRC:1;
+    uint32_t SUPPORT_AI:1;
+};
+
+struct audio_speaker_info {
+    uint32_t ALLSPEAKERS:7;
+    uint32_t SUPPORT_AI:1;
+};
+
+struct audio_info_flags {
+
+	union {
+
+		struct audio_speaker_flags speaker_flags;
+		struct audio_speaker_info   info;
+
+		uint8_t all;
+	};
+};
+
+
+/*struct audio_info_flags {
+	struct audio_speaker_flags {
+		uint32_t FL_FR:1;
+		uint32_t LFE:1;
+		uint32_t FC:1;
+		uint32_t RL_RR:1;
+		uint32_t RC:1;
+		uint32_t FLC_FRC:1;
+		uint32_t RLC_RRC:1;
+		uint32_t SUPPORT_AI:1;
+	};
+
+	struct audio_speaker_info {
+		uint32_t ALLSPEAKERS:7;
+		uint32_t SUPPORT_AI:1;
+	};
+
+	union {
+		struct audio_speaker_flags speaker_flags;
+		struct audio_speaker_info info;
+	};
+};
+*/
+
+union audio_cea_channels {
+	uint8_t all;
+	struct audio_cea_channels_bits {
+		uint32_t FL:1;
+		uint32_t FR:1;
+		uint32_t LFE:1;
+		uint32_t FC:1;
+		uint32_t RL_RC:1;
+		uint32_t RR:1;
+		uint32_t RC_RLC_FLC:1;
+		uint32_t RRC_FRC:1;
+	} channels;
+};
+
+struct audio_info {
+	struct audio_info_flags flags;
+	uint32_t video_latency;
+	uint32_t audio_latency;
+	uint32_t display_index;
+	uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS];
+	uint32_t manufacture_id;
+	uint32_t product_id;
+	/* PortID used for ContainerID when defined */
+	uint32_t port_id[2];
+	uint32_t mode_count;
+	/* this field must be last in this struct */
+	struct audio_mode modes[DC_MAX_AUDIO_DESC_COUNT];
+};
+
+struct audio_crtc_info {
+	uint32_t h_total;
+	uint32_t h_active;
+	uint32_t v_active;
+	uint32_t pixel_repetition;
+	uint32_t requested_pixel_clock; /* in KHz */
+	uint32_t calculated_pixel_clock; /* in KHz */
+	uint32_t refresh_rate;
+	enum dc_color_depth color_depth;
+	bool interlaced;
+};
+
+/* PLL information required for AZALIA DTO calculation */
+
+struct audio_pll_info {
+	uint32_t dp_dto_source_clock_in_khz;
+	uint32_t feed_back_divider;
+	enum audio_dto_source dto_source;
+	bool ss_enabled;
+	uint32_t ss_percentage;
+	uint32_t ss_percentage_divider;
+};
+
+struct audio_channel_associate_info {
+	union {
+		struct {
+			uint32_t ALL_CHANNEL_FL:4;
+			uint32_t ALL_CHANNEL_FR:4;
+			uint32_t ALL_CHANNEL_FC:4;
+			uint32_t ALL_CHANNEL_Sub:4;
+			uint32_t ALL_CHANNEL_SL:4;
+			uint32_t ALL_CHANNEL_SR:4;
+			uint32_t ALL_CHANNEL_BL:4;
+			uint32_t ALL_CHANNEL_BR:4;
+		} bits;
+		uint32_t u32all;
+	};
+};
+
+struct audio_output {
+	/* Front DIG id. */
+	enum engine_id engine_id;
+	/* encoder output signal */
+	enum signal_type signal;
+	/* video timing */
+	struct audio_crtc_info crtc_info;
+	/* PLL for audio */
+	struct audio_pll_info pll_info;
+};
+
+struct audio_feature_support {
+	/* supported engines*/
+	uint32_t ENGINE_DIGA:1;
+	uint32_t ENGINE_DIGB:1;
+	uint32_t ENGINE_DIGC:1;
+	uint32_t ENGINE_DIGD:1;
+	uint32_t ENGINE_DIGE:1;
+	uint32_t ENGINE_DIGF:1;
+	uint32_t ENGINE_DIGG:1;
+	uint32_t MULTISTREAM_AUDIO:1;
+};
+
+enum audio_payload {
+	CHANNEL_SPLIT_MAPPINGCHANG = 0x9,
+};
+
+#endif /* __AUDIO_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h b/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
new file mode 100644
index 000000000000..e4291b9ff320
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/bios_parser_interface.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_INTERFACE_H__
+#define __DAL_BIOS_PARSER_INTERFACE_H__
+
+#include "dc_bios_types.h"
+
+struct adapter_service;
+struct bios_parser;
+
+struct bp_init_data {
+	struct dc_context *ctx;
+	uint8_t *bios;
+};
+
+struct dc_bios *dal_bios_parser_create(
+	struct bp_init_data *init,
+	struct adapter_service *as);
+
+void dal_bios_parser_destroy(
+	struct dc_bios **dcb);
+
+/*****************************************************************************/
+/* Interfaces of BIOS Parser Helper */
+bool dal_bios_parser_is_lid_open(
+	struct bios_parser *bp);
+bool dal_bios_parser_is_lid_status_changed(
+	struct bios_parser *bp);
+bool dal_bios_parser_is_display_config_changed(
+	struct bios_parser *bp);
+bool dal_bios_parser_is_accelerated_mode(
+	struct bios_parser *bp);
+void dal_bios_parser_set_scratch_lcd_scale(
+	struct bios_parser *bp,
+	enum lcd_scale scale);
+enum lcd_scale  dal_bios_parser_get_scratch_lcd_scale(
+	struct bios_parser *bp);
+void dal_bios_parser_get_bios_event_info(
+	struct bios_parser *bp,
+	struct bios_event_info *info);
+void dal_bios_parser_update_requested_backlight_level(
+	struct bios_parser *bp,
+	uint32_t backlight_8bit);
+uint32_t dal_bios_parser_get_requested_backlight_level(
+	struct bios_parser *bp);
+void dal_bios_parser_take_backlight_control(
+	struct bios_parser *bp,
+	bool cntl);
+bool dal_bios_parser_is_active_display(
+	struct bios_parser *bp,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag);
+enum controller_id dal_bios_parser_get_embedded_display_controller_id(
+	struct bios_parser *bp);
+uint32_t dal_bios_parser_get_embedded_display_refresh_rate(
+	struct bios_parser *bp);
+void dal_bios_parser_set_scratch_connected(
+	struct bios_parser *bp,
+	struct graphics_object_id connector_id,
+	bool connected,
+	const struct connector_device_tag_info *device_tag);
+void dal_bios_parser_prepare_scratch_active_and_requested(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag);
+void dal_bios_parser_set_scratch_active_and_requested(
+	struct bios_parser *bp);
+void dal_bios_parser_set_scratch_critical_state(
+	struct bios_parser *bp,
+	bool state);
+void dal_bios_parser_set_scratch_acc_mode_change(
+	struct bios_parser *bp);
+
+#endif /* __DAL_BIOS_PARSER_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/bios_parser_types.h b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h
new file mode 100644
index 000000000000..550ac874985b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_TYPES_H__
+
+#define __DAL_BIOS_PARSER_TYPES_H__
+
+#include "dm_services.h"
+#include "include/signal_types.h"
+#include "include/grph_object_ctrl_defs.h"
+#include "include/gpio_types.h"
+#include "include/adapter_service_types.h" /* for as_signal_type */
+#include "include/link_service_types.h"
+
+enum bp_result {
+	BP_RESULT_OK = 0, /* There was no error */
+	BP_RESULT_BADINPUT, /*Bad input parameter */
+	BP_RESULT_BADBIOSTABLE, /* Bad BIOS table */
+	BP_RESULT_UNSUPPORTED, /* BIOS Table is not supported */
+	BP_RESULT_NORECORD, /* Record can't be found */
+	BP_RESULT_FAILURE
+};
+
+enum bp_encoder_control_action {
+	/* direct VBIOS translation! Just to simplify the translation */
+	ENCODER_CONTROL_DISABLE = 0,
+	ENCODER_CONTROL_ENABLE,
+	ENCODER_CONTROL_SETUP,
+	ENCODER_CONTROL_INIT
+};
+
+enum bp_transmitter_control_action {
+	/* direct VBIOS translation! Just to simplify the translation */
+	TRANSMITTER_CONTROL_DISABLE = 0,
+	TRANSMITTER_CONTROL_ENABLE,
+	TRANSMITTER_CONTROL_BACKLIGHT_OFF,
+	TRANSMITTER_CONTROL_BACKLIGHT_ON,
+	TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS,
+	TRANSMITTER_CONTROL_LCD_SETF_TEST_START,
+	TRANSMITTER_CONTROL_LCD_SELF_TEST_STOP,
+	TRANSMITTER_CONTROL_INIT,
+	TRANSMITTER_CONTROL_DEACTIVATE,
+	TRANSMITTER_CONTROL_ACTIAVATE,
+	TRANSMITTER_CONTROL_SETUP,
+	TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS,
+	/* ATOM_TRANSMITTER_ACTION_POWER_ON. This action is for eDP only
+	 * (power up the panel)
+	 */
+	TRANSMITTER_CONTROL_POWER_ON,
+	/* ATOM_TRANSMITTER_ACTION_POWER_OFF. This action is for eDP only
+	 * (power down the panel)
+	 */
+	TRANSMITTER_CONTROL_POWER_OFF
+};
+
+enum bp_external_encoder_control_action {
+	EXTERNAL_ENCODER_CONTROL_DISABLE = 0,
+	EXTERNAL_ENCODER_CONTROL_ENABLE = 1,
+	EXTERNAL_ENCODER_CONTROL_INIT = 0x7,
+	EXTERNAL_ENCODER_CONTROL_SETUP = 0xf,
+	EXTERNAL_ENCODER_CONTROL_UNBLANK = 0x10,
+	EXTERNAL_ENCODER_CONTROL_BLANK = 0x11,
+	EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT = 0x12
+};
+
+enum bp_pipe_control_action {
+	ASIC_PIPE_DISABLE = 0,
+	ASIC_PIPE_ENABLE,
+	ASIC_PIPE_INIT
+};
+
+struct bp_encoder_control {
+	enum bp_encoder_control_action action;
+	enum engine_id engine_id;
+	enum transmitter transmitter;
+	enum signal_type signal;
+	enum lane_count lanes_number;
+	enum dc_color_depth color_depth;
+	bool enable_dp_audio;
+	uint32_t pixel_clock; /* khz */
+};
+
+struct bp_external_encoder_control {
+	enum bp_external_encoder_control_action action;
+	enum engine_id engine_id;
+	enum link_rate link_rate;
+	enum lane_count lanes_number;
+	enum signal_type signal;
+	enum dc_color_depth color_depth;
+	bool coherent;
+	struct graphics_object_id encoder_id;
+	struct graphics_object_id connector_obj_id;
+	uint32_t pixel_clock; /* in KHz */
+};
+
+struct bp_crtc_source_select {
+	enum engine_id engine_id;
+	enum controller_id controller_id;
+	/* from GPU Tx aka asic_signal */
+	enum signal_type signal;
+	/* sink_signal may differ from asicSignal if Translator encoder */
+	enum signal_type sink_signal;
+	enum display_output_bit_depth display_output_bit_depth;
+	bool enable_dp_audio;
+};
+
+struct bp_transmitter_control {
+	enum bp_transmitter_control_action action;
+	enum engine_id engine_id;
+	enum transmitter transmitter; /* PhyId */
+	enum lane_count lanes_number;
+	enum clock_source_id pll_id; /* needed for DCE 4.0 */
+	enum signal_type signal;
+	enum dc_color_depth color_depth; /* not used for DCE6.0 */
+	enum hpd_source_id hpd_sel; /* ucHPDSel, used for DCe6.0 */
+	struct graphics_object_id connector_obj_id;
+	/* symClock; in 10kHz, pixel clock, in HDMI deep color mode, it should
+	 * be pixel clock * deep_color_ratio (in KHz)
+	 */
+	uint32_t pixel_clock;
+	uint32_t lane_select;
+	uint32_t lane_settings;
+	bool coherent;
+	bool multi_path;
+	bool single_pll_mode;
+};
+
+struct bp_blank_crtc_parameters {
+	enum controller_id controller_id;
+	uint32_t black_color_rcr;
+	uint32_t black_color_gy;
+	uint32_t black_color_bcb;
+};
+
+struct bp_hw_crtc_timing_parameters {
+	enum controller_id controller_id;
+	/* horizontal part */
+	uint32_t h_total;
+	uint32_t h_addressable;
+	uint32_t h_overscan_left;
+	uint32_t h_overscan_right;
+	uint32_t h_sync_start;
+	uint32_t h_sync_width;
+
+	/* vertical part */
+	uint32_t v_total;
+	uint32_t v_addressable;
+	uint32_t v_overscan_top;
+	uint32_t v_overscan_bottom;
+	uint32_t v_sync_start;
+	uint32_t v_sync_width;
+
+	struct timing_flags {
+		uint32_t INTERLACE:1;
+		uint32_t PIXEL_REPETITION:4;
+		uint32_t HSYNC_POSITIVE_POLARITY:1;
+		uint32_t VSYNC_POSITIVE_POLARITY:1;
+		uint32_t HORZ_COUNT_BY_TWO:1;
+	} flags;
+};
+
+struct bp_hw_crtc_overscan_parameters {
+	enum controller_id controller_id;
+	uint32_t h_overscan_left;
+	uint32_t h_overscan_right;
+	uint32_t v_overscan_top;
+	uint32_t v_overscan_bottom;
+};
+
+struct bp_adjust_pixel_clock_parameters {
+	/* Input: Signal Type - to be converted to Encoder mode */
+	enum signal_type signal_type;
+	/* Input: Encoder object id */
+	struct graphics_object_id encoder_object_id;
+	/* Input: Pixel Clock (requested Pixel clock based on Video timing
+	 * standard used) in KHz
+	 */
+	uint32_t pixel_clock;
+	/* Output: Adjusted Pixel Clock (after VBIOS exec table) in KHz */
+	uint32_t adjusted_pixel_clock;
+	/* Output: If non-zero, this refDiv value should be used to calculate
+	 * other ppll params */
+	uint32_t reference_divider;
+	/* Output: If non-zero, this postDiv value should be used to calculate
+	 * other ppll params */
+	uint32_t pixel_clock_post_divider;
+	/* Input: Enable spread spectrum */
+	bool ss_enable;
+};
+
+struct bp_pixel_clock_parameters {
+	enum controller_id controller_id; /* (Which CRTC uses this PLL) */
+	enum clock_source_id pll_id; /* Clock Source Id */
+	/* signal_type -> Encoder Mode - needed by VBIOS Exec table */
+	enum signal_type signal_type;
+	/* Adjusted Pixel Clock (after VBIOS exec table)
+	 * that becomes Target Pixel Clock (KHz) */
+	uint32_t target_pixel_clock;
+	/* Calculated Reference divider of Display PLL */
+	uint32_t reference_divider;
+	/* Calculated Feedback divider of Display PLL */
+	uint32_t feedback_divider;
+	/* Calculated Fractional Feedback divider of Display PLL */
+	uint32_t fractional_feedback_divider;
+	/* Calculated Pixel Clock Post divider of Display PLL */
+	uint32_t pixel_clock_post_divider;
+	struct graphics_object_id encoder_object_id; /* Encoder object id */
+	/* VBIOS returns a fixed display clock when DFS-bypass feature
+	 * is enabled (KHz) */
+	uint32_t dfs_bypass_display_clock;
+	/* color depth to support HDMI deep color */
+	enum transmitter_color_depth color_depth;
+
+	struct program_pixel_clock_flags {
+		uint32_t FORCE_PROGRAMMING_OF_PLL:1;
+		/* Use Engine Clock as source for Display Clock when
+		 * programming PLL */
+		uint32_t USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK:1;
+		/* Use external reference clock (refDivSrc for PLL) */
+		uint32_t SET_EXTERNAL_REF_DIV_SRC:1;
+		/* Force program PHY PLL only */
+		uint32_t PROGRAM_PHY_PLL_ONLY:1;
+		/* Support for YUV420 */
+		uint32_t SUPPORT_YUV_420:1;
+		/* Use XTALIN reference clock source */
+		uint32_t SET_XTALIN_REF_SRC:1;
+		/* Use GENLK reference clock source */
+		uint32_t SET_GENLOCK_REF_DIV_SRC:1;
+	} flags;
+};
+
+struct bp_display_clock_parameters {
+	uint32_t target_display_clock; /* KHz */
+	/* Actual Display Clock set due to clock divider granularity KHz */
+	uint32_t actual_display_clock;
+	/* Actual Post Divider ID used to generate the actual clock */
+	uint32_t actual_post_divider_id;
+};
+
+enum bp_dce_clock_type {
+	DCECLOCK_TYPE_DISPLAY_CLOCK = 0,
+	DCECLOCK_TYPE_DPREFCLK      = 1
+};
+
+/* DCE Clock Parameters structure for SetDceClock Exec command table */
+struct bp_set_dce_clock_parameters {
+	enum clock_source_id pll_id; /* Clock Source Id */
+	/* Display clock or DPREFCLK value */
+	uint32_t target_clock_frequency;
+	/* Clock to set: =0: DISPCLK  =1: DPREFCLK  =2: PIXCLK */
+	enum bp_dce_clock_type clock_type;
+
+	struct set_dce_clock_flags {
+		uint32_t USE_GENERICA_AS_SOURCE_FOR_DPREFCLK:1;
+		/* Use XTALIN reference clock source */
+		uint32_t USE_XTALIN_AS_SOURCE_FOR_DPREFCLK:1;
+		/* Use PCIE reference clock source */
+		uint32_t USE_PCIE_AS_SOURCE_FOR_DPREFCLK:1;
+		/* Use GENLK reference clock source */
+		uint32_t USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK:1;
+	} flags;
+};
+
+struct spread_spectrum_flags {
+	/* 1 = Center Spread; 0 = down spread */
+	uint32_t CENTER_SPREAD:1;
+	/* 1 = external; 0 = internal */
+	uint32_t EXTERNAL_SS:1;
+	/* 1 = delta-sigma type parameter; 0 = ver1 */
+	uint32_t DS_TYPE:1;
+};
+
+struct bp_spread_spectrum_parameters {
+	enum clock_source_id pll_id;
+	uint32_t percentage;
+	uint32_t ds_frac_amount;
+
+	union {
+		struct {
+			uint32_t step;
+			uint32_t delay;
+			uint32_t range; /* In Hz unit */
+		} ver1;
+		struct {
+			uint32_t feedback_amount;
+			uint32_t nfrac_amount;
+			uint32_t ds_frac_size;
+		} ds;
+	};
+
+	struct spread_spectrum_flags flags;
+};
+
+struct bp_encoder_cap_info {
+	uint32_t DP_HBR2_CAP:1;
+	uint32_t DP_HBR2_EN:1;
+	uint32_t RESERVED:30;
+};
+
+struct bp_gpio_cntl_info {
+	uint32_t id;
+	enum gpio_pin_output_state state;
+};
+
+#endif /*__DAL_BIOS_PARSER_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_asic_id.h b/drivers/gpu/drm/amd/dal/include/dal_asic_id.h
new file mode 100644
index 000000000000..78f88b129a35
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_asic_id.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ASIC_ID_H__
+#define __DAL_ASIC_ID_H__
+
+/*
+ * ASIC internal revision ID
+ */
+
+/* DCE80 (based on ci_id.h in Perforce) */
+
+#define	CI_BONAIRE_M_A0 0x14
+#define	CI_BONAIRE_M_A1	0x15
+#define	CI_HAWAII_P_A0	0x28
+
+#define CI_UNKNOWN	0xFF
+
+#define ASIC_REV_IS_BONAIRE_M(rev) \
+	((rev >= CI_BONAIRE_M_A0) && (rev < CI_HAWAII_P_A0))
+
+#define ASIC_REV_IS_HAWAII_P(rev) \
+	(rev >= CI_HAWAII_P_A0)
+
+/* KV1 with Spectre GFX core, 8-8-1-2 (CU-Pix-Primitive-RB) */
+#define KV_SPECTRE_A0 0x01
+
+/* KV2 with Spooky GFX core, including downgraded from Spectre core,
+ * 3-4-1-1 (CU-Pix-Primitive-RB) */
+#define KV_SPOOKY_A0 0x41
+
+/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define KB_KALINDI_A0 0x81
+
+/* KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define KB_KALINDI_A1 0x82
+
+/* BV with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define BV_KALINDI_A2 0x85
+
+/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define ML_GODAVARI_A0 0xA1
+
+/* ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) */
+#define ML_GODAVARI_A1 0xA2
+
+#define KV_UNKNOWN 0xFF
+
+#define ASIC_REV_IS_KALINDI(rev) \
+	((rev >= KB_KALINDI_A0) && (rev < KV_UNKNOWN))
+
+#define ASIC_REV_IS_BHAVANI(rev) \
+	((rev >= BV_KALINDI_A2) && (rev < ML_GODAVARI_A0))
+
+#define ASIC_REV_IS_GODAVARI(rev) \
+	((rev >= ML_GODAVARI_A0) && (rev < KV_UNKNOWN))
+
+/* VI Family */
+/* DCE10 */
+#define VI_TONGA_P_A0 20
+#define VI_TONGA_P_A1 21
+#define VI_FIJI_P_A0 60
+
+#define ASIC_REV_IS_TONGA_P(eChipRev) ((eChipRev >= VI_TONGA_P_A0) && \
+		(eChipRev < 40))
+#define ASIC_REV_IS_FIJI_P(eChipRev) ((eChipRev >= VI_FIJI_P_A0) && \
+		(eChipRev < 80))
+
+/* DCE11 */
+#define CZ_CARRIZO_A0 0x01
+
+#define STONEY_A0 0x61
+#define CZ_UNKNOWN 0xFF
+
+#define ASIC_REV_IS_STONEY(rev) \
+	((rev >= STONEY_A0) && (rev < CZ_UNKNOWN))
+
+/*
+ * ASIC chip ID
+ */
+/* DCE80 */
+#define DEVICE_ID_KALINDI_9834 0x9834
+#define DEVICE_ID_TEMASH_9839 0x9839
+#define DEVICE_ID_TEMASH_983D 0x983D
+
+
+/* Asic Family IDs for different asic family. */
+#define FAMILY_CI 120 /* Sea Islands: Hawaii (P), Bonaire (M) */
+#define FAMILY_KV 125 /* Fusion => Kaveri: Spectre, Spooky; Kabini: Kalindi */
+#define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */
+#define FAMILY_CZ 135 /* Carrizo */
+
+#define	FAMILY_UNKNOWN 0xFF
+
+#endif /* __DAL_ASIC_ID_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_register_logger.h b/drivers/gpu/drm/amd/dal/include/dal_register_logger.h
new file mode 100644
index 000000000000..176d811327af
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_register_logger.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_REGISTER_LOGGER__
+#define __DAL_REGISTER_LOGGER__
+
+/****************
+ * API functions
+ ***************/
+
+/* dal_reg_logger_push - begin Register Logging */
+void dal_reg_logger_push(const char *caller_func);
+/* dal_reg_logger_pop - stop Register Logging */
+void dal_reg_logger_pop(void);
+
+
+/* for internal use of the Logger only */
+void dal_reg_logger_rw_count_increment(void);
+bool dal_reg_logger_should_dump_register(void);
+
+#endif /* __DAL_REGISTER_LOGGER__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dal_types.h b/drivers/gpu/drm/amd/dal/include/dal_types.h
new file mode 100644
index 000000000000..373977685b70
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dal_types.h
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_TYPES_H__
+#define __DAL_TYPES_H__
+
+#include "signal_types.h"
+#include "dc_types.h"
+
+struct dal_logger;
+struct dc_bios;
+
+enum dce_version {
+	DCE_VERSION_UNKNOWN = (-1),
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	DCE_VERSION_10_0,
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	DCE_VERSION_11_0,
+#endif
+	DCE_VERSION_MAX
+};
+
+/*
+ * ASIC Runtime Flags
+ */
+struct dal_asic_runtime_flags {
+	union {
+		uint32_t raw;
+		struct {
+			uint32_t EMULATE_REPLUG_ON_CAP_CHANGE:1;
+			uint32_t SUPPORT_XRBIAS:1;
+			uint32_t SKIP_POWER_DOWN_ON_RESUME:1;
+			uint32_t FULL_DETECT_ON_RESUME:1;
+			uint32_t GSL_FRAMELOCK:1;
+			uint32_t NO_LOW_BPP_MODES:1;
+			uint32_t BLOCK_ON_INITIAL_DETECTION:1;
+			uint32_t OPTIMIZED_DISPLAY_PROGRAMMING_ON_BOOT:1;
+			uint32_t DRIVER_CONTROLLED_BRIGHTNESS:1;
+			uint32_t MODIFIABLE_FRAME_DURATION:1;
+			uint32_t MIRACAST_SUPPORTED:1;
+			uint32_t CONNECTED_STANDBY_SUPPORTED:1;
+			uint32_t GNB_WAKEUP_SUPPORTED:1;
+		} bits;
+	} flags;
+};
+
+struct hw_asic_id {
+	uint32_t chip_id;
+	uint32_t chip_family;
+	uint32_t pci_revision_id;
+	uint32_t hw_internal_rev;
+	uint32_t vram_type;
+	uint32_t vram_width;
+	uint32_t feature_flags;
+	struct dal_asic_runtime_flags runtime_flags;
+	uint32_t fake_paths_num;
+	void *atombios_base_address;
+};
+
+/* this is pci information. BDF stands for BUS,DEVICE,FUNCTION*/
+
+struct bdf_info {
+	uint16_t BUS_NUMBER:8;
+	uint16_t DEVICE_NUMBER:5;
+	uint16_t FUNCTION_NUMBER:3;
+};
+
+#define DAL_PARAM_INVALID_INT 0x80000000
+
+/* shift values for bool override parameter mask
+ * bmask is for this struct,if we touch this feature
+ * bval indicates every bit fields for this struct too,1 is enable this feature
+ * amdgpu.disp_bval=1594, amdgpu.disp_bmask=1594 ,
+ * finally will show log like this:
+ * Overridden FEATURE_LIGHT_SLEEP is enabled now
+ * Overridden FEATURE_USE_MAX_DISPLAY_CLK is enabled now
+ * Overridden FEATURE_ENABLE_DFS_BYPASS is enabled now
+ * Overridden FEATURE_POWER_GATING_PIPE_IN_TILE is enabled now
+ * Overridden FEATURE_USE_PPLIB is enabled now
+ * Overridden FEATURE_DISABLE_LPT_SUPPORT is enabled now
+ * Overridden FEATURE_DUMMY_FBC_BACKEND is enabled now */
+enum bool_param_shift {
+	DAL_PARAM_MAXIMIZE_STUTTER_MARKS = 0,
+	DAL_PARAM_LIGHT_SLEEP,
+	DAL_PARAM_MAXIMIZE_URGENCY_WATERMARKS,
+	DAL_PARAM_USE_MAX_DISPLAY_CLK,
+	DAL_PARAM_ENABLE_DFS_BYPASS,
+	DAL_PARAM_POWER_GATING_PIPE_IN_TILE,
+	DAL_PARAM_POWER_GATING_LB_PORTION,
+	DAL_PARAM_PSR_ENABLE,
+	DAL_PARAM_VARI_BRIGHT_ENABLE,
+	DAL_PARAM_USE_PPLIB,
+	DAL_PARAM_DISABLE_LPT_SUPPORT,
+	DAL_PARAM_DUMMY_FBC_BACKEND,
+	DAL_PARAM_ENABLE_GPU_SCALING,
+	DAL_BOOL_PARAM_MAX
+};
+
+/* array index for integer override parameters*/
+enum int_param_array_index {
+	DAL_PARAM_MAX_COFUNC_NON_DP_DISPLAYS = 0,
+	DAL_PARAM_DRR_SUPPORT,
+	DAL_INT_PARAM_MAX
+};
+
+struct dal_override_parameters {
+	uint32_t bool_param_enable_mask;
+	uint32_t bool_param_values;
+	uint32_t int_param_values[DAL_INT_PARAM_MAX];
+};
+
+
+struct dal_init_data {
+	struct hw_asic_id asic_id;
+	struct view_port_alignment vp_alignment;
+	struct bdf_info bdf_info;
+	struct dal_override_parameters display_param;
+	void *driver; /* ctx */
+	void *cgs_device;
+	uint8_t num_virtual_links;
+	/* If 'vbios_override' not NULL, it will be called instead
+	 * of the real VBIOS. Intended use is Diagnostics on FPGA. */
+	struct dc_bios *vbios_override;
+	enum dce_environment dce_environment;
+};
+
+struct dal_dc_init_data {
+	struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */
+	struct adapter_service *adapter_srv;
+};
+
+struct dal_dev_c_lut {
+	uint8_t red;
+	uint8_t green;
+	uint8_t blue;
+	uint8_t reserved;
+};
+
+struct dal_dev_gamma_lut {
+	uint16_t red;
+	uint16_t green;
+	uint16_t blue;
+};
+
+struct dc_context {
+	struct dc *dc;
+
+	void *driver_context; /* e.g. amdgpu_device */
+
+	struct dal_logger *logger;
+	void *cgs_device;
+
+	enum dce_environment dce_environment;
+};
+
+/* Wireless display structs */
+
+union dal_remote_display_cea_mode_bitmap {
+	struct {
+		uint32_t CEA_640X480_60P:1;/*0*/
+		uint32_t CEA_720X480_60P:1;/*1*/
+		uint32_t CEA_720X480_60I:1;/*2*/
+		uint32_t CEA_720X576_50P:1;/*3*/
+		uint32_t CEA_720X576_50I:1;/*4*/
+		uint32_t CEA_1280X720_30P:1;/*5*/
+		uint32_t CEA_1280X720_60P:1;/*6*/
+		uint32_t CEA_1920X1080_30P:1;/*7*/
+		uint32_t CEA_1920X1080_60P:1;/*8*/
+		uint32_t CEA_1920X1080_60I:1;/*9*/
+		uint32_t CEA_1280X720_25P:1;/*10*/
+		uint32_t CEA_1280X728_50P:1;/*11*/
+		uint32_t CEA_1920X1080_25P:1;/*12*/
+		uint32_t CEA_1920X1080_50P:1;/*13*/
+		uint32_t CEA_1920X1080_50I:1;/*14*/
+		uint32_t CEA_1280X1024_24P:1;/*15*/
+		uint32_t CEA_1920X1080_24P:1;/*16*/
+		uint32_t RESERVED:15;/*[17-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_vesa_mode_bitmap {
+	struct {
+		uint32_t VESA_800X600_30P:1;/*0*/
+		uint32_t VESA_800X600_60P:1;/*1*/
+		uint32_t VESA_1024X768_30P:1;/*2*/
+		uint32_t VESA_1024X768_60P:1;/*3*/
+		uint32_t VESA_1152X864_30P:1;/*4*/
+		uint32_t VESA_1152X864_60P:1;/*5*/
+		uint32_t VESA_1280X768_30P:1;/*6*/
+		uint32_t VESA_1280X768_60P:1;/*7*/
+		uint32_t VESA_1280X800_30P:1;/*8*/
+		uint32_t VESA_1280X800_60P:1;/*9*/
+		uint32_t VESA_1360X768_30P:1;/*10*/
+		uint32_t VESA_1360X768_60P:1;/*11*/
+		uint32_t VESA_1366X768_30P:1;/*12*/
+		uint32_t VESA_1366X768_60P:1;/*13*/
+		uint32_t VESA_1280X1024_30P:1;/*14*/
+		uint32_t VESA_1280X1024_60P:1;/*15*/
+		uint32_t VESA_1400X1050_30P:1;/*16*/
+		uint32_t VESA_1400X1050_60P:1;/*17*/
+		uint32_t VESA_1440X900_30P:1;/*18*/
+		uint32_t VESA_1440X900_60P:1;/*19*/
+		uint32_t VESA_1600X900_30P:1;/*20*/
+		uint32_t VESA_1600X900_60P:1;/*21*/
+		uint32_t VESA_1600X1200_30P:1;/*22*/
+		uint32_t VESA_1600X1200_60P:1;/*23*/
+		uint32_t VESA_1680X1024_30P:1;/*24*/
+		uint32_t VESA_1680X1024_60P:1;/*25*/
+		uint32_t VESA_1680X1050_30P:1;/*26*/
+		uint32_t VESA_1680X1050_60P:1;/*27*/
+		uint32_t VESA_1920X1200_30P:1;/*28*/
+		uint32_t VESA_1920X1200_60P:1;/*29*/
+		uint32_t RESERVED:2;/*[30-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_hh_mode_bitmap {
+	struct {
+		uint32_t HH_800X480_30P:1;/*0*/
+		uint32_t HH_800X480_60P:1;/*1*/
+		uint32_t HH_854X480_30P:1;/*2*/
+		uint32_t HH_854X480_60P:1;/*3*/
+		uint32_t HH_864X480_30P:1;/*4*/
+		uint32_t HH_864X480_60P:1;/*5*/
+		uint32_t HH_640X360_30P:1;/*6*/
+		uint32_t HH_640X360_60P:1;/*7*/
+		uint32_t HH_960X540_30P:1;/*8*/
+		uint32_t HH_960X540_60P:1;/*9*/
+		uint32_t HH_848X480_30P:1;/*10*/
+		uint32_t HH_848X480_60P:1;/*11*/
+		uint32_t RESERVED:20;/*[12-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_stereo_3d_mode_bitmap {
+	struct {
+		uint32_t STEREO_1920X1080_24P_TOP_AND_BOTTOM:1;/*0*/
+		uint32_t STEREO_1280X720_60P_TOP_AND_BOTTOM:1;/*1*/
+		uint32_t STEREO_1280X720_50P_TOP_AND_BOTTOM:1;/*2*/
+		uint32_t STEREO_1920X1080_24X2P_FRAME_ALTERNATE:1;/*3*/
+		uint32_t STEREO_1280X720_60X2P_FRAME_ALTERNATE:1;/*4*/
+		uint32_t STEREO_1280X720_30X2P_FRAME_ALTERNATE:1;/*5*/
+		uint32_t STEREO_1280X720_50X2P_FRAME_ALTERNATE:1;/*6*/
+		uint32_t STEREO_1280X720_25X2P_FRAME_ALTERNATE:1;/*7*/
+		uint32_t STEREO_1920X1080_24P_FRAME_PACKING:1;/* 8*/
+		uint32_t STEREO_1280X720_60P_FRAME_PACKING:1;/* 9*/
+		uint32_t STEREO_1280X720_30P_FRAME_PACKING:1;/*10*/
+		uint32_t STEREO_1280X720_50P_FRAME_PACKING:1;/*11*/
+		uint32_t STEREO_1280X720_25P_FRAME_PACKING:1;/*12*/
+		uint32_t RESERVED:19; /*[13-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+union dal_remote_display_audio_bitmap {
+	struct {
+		uint32_t LPCM_44100HZ_16BITS_2_CHANNELS:1;/*0*/
+		uint32_t LPCM_48000HZ_16BITS_2_CHANNELS:1;/*1*/
+		uint32_t AAC_48000HZ_16BITS_2_CHANNELS:1;/*2*/
+		uint32_t AAC_48000HZ_16BITS_4_CHANNELS:1;/*3*/
+		uint32_t AAC_48000HZ_16BITS_6_CHANNELS:1;/*4*/
+		uint32_t AAC_48000HZ_16BITS_8_CHANNELS:1;/*5*/
+		uint32_t AC3_48000HZ_16BITS_2_CHANNELS:1;/*6*/
+		uint32_t AC3_48000HZ_16BITS_4_CHANNELS:1;/*7*/
+		uint32_t AC3_48000HZ_16BITS_6_CHANNELS:1;/*8*/
+		uint32_t RESERVED:23;/*[9-31]*/
+	} flags;
+	uint32_t raw;
+};
+
+struct dal_remote_display_receiver_capability {
+	union dal_remote_display_cea_mode_bitmap cea_mode;
+	union dal_remote_display_vesa_mode_bitmap vesa_mode;
+	union dal_remote_display_hh_mode_bitmap hh_mode;
+	union dal_remote_display_stereo_3d_mode_bitmap stereo_3d_mode;
+	union dal_remote_display_audio_bitmap audio;
+};
+
+#endif /* __DAL_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h b/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
new file mode 100644
index 000000000000..b7fb9ff16a97
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dc_clock_generator_interface.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_CLOCK_GENERATOR_INTERFACE_H__
+#define __DC_CLOCK_GENERATOR_INTERFACE_H__
+
+#include "grph_object_ctrl_defs.h"
+#include "set_mode_types.h"
+
+/* Parameter for programming the DCCP_DISP_SLOW_SELECT*/
+struct dccg_mapping_params {
+	uint32_t controllers_num;
+	enum controller_id *controllers;
+};
+
+/* Parameters related to HW DeSpread of DP Reference Clock*/
+struct dccg_dp_ref_clk_ds_params {
+	struct {
+		/* Flag for Enabled SS on DP Reference Clock*/
+		bool SS_ENABLED:1;
+		/* Flag for HW De Spread enabled
+		 * (if enabled SS on DP Reference Clock)*/
+		bool DS_ENABLED:1;
+		/* Flag for HW De Spread Calculations enabled for DS_DTO_INCR
+		 * and DS_DTO_MODULO (if 0 SW programs DS_DTO_INCR and
+		 * DS_DTO_MODULO)*/
+		bool DS_CALCULATIONS:1;
+	} flags;
+	/*DP Reference clock SS percentage
+	 * (if enabled downspread on DP Reference Clock)*/
+	uint32_t ss_percentage;
+	/*DP Reference clock SS percentage Divider (1000 or 100)*/
+	uint32_t ss_percentage_divider;
+};
+
+struct dc_clock_generator;
+
+void dal_dc_clock_generator_destroy(struct dc_clock_generator **dc);
+void dal_dc_clock_generator_set_display_pipe_mapping(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_mapping_params *params);
+bool dal_dc_clock_generator_get_dp_ref_clk_ds_params(
+	struct dc_clock_generator *dc_clk_gen,
+	struct dccg_dp_ref_clk_ds_params *params);
+bool dal_dc_clock_generator_enable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen,
+	uint32_t dprefclk);
+void dal_dc_clock_generator_disable_gtc_counter(
+	struct dc_clock_generator *dc_clk_gen);
+void dal_dc_clock_generator_set_gtc_group_offset(
+	struct dc_clock_generator *dc_clk_gen,
+	enum gtc_group group_num,
+	uint32_t offset);
+
+#endif /* __DC_CLOCK_GENERATOR_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dcs_types.h b/drivers/gpu/drm/amd/dal/include/dcs_types.h
new file mode 100644
index 000000000000..8c650571ff69
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dcs_types.h
@@ -0,0 +1,742 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DCS_TYPES_H__
+#define __DAL_DCS_TYPES_H__
+
+#include "signal_types.h"
+
+#include "dc_types.h"
+
+#define NUM_OF_BYTE_EDID_COLOR_CHARACTERISTICS 10
+#define MAX_NUMBER_OF_HDMI_VSDB_3D_EXTENDED_SUPPORT 21
+#define MAX_NUMBER_OF_HDMI_VSDB_VICS 7
+
+struct drr_config {
+	/* minimum frame per second for dynamic
+	 * refresh rate feature; 0 if drr support not found*/
+	uint32_t min_fps_in_microhz;
+	bool force_lock_on_event;
+	bool lock_to_master_vsync;
+
+	struct {
+		uint8_t FORCED_BY_REGKEY_OR_ESCAPE:1;
+		uint8_t FORCED_BY_VBIOS:1;
+		uint8_t SUPPORTED_BY_EDID:1;
+	} support_method;
+};
+
+struct timing_limits {
+	uint32_t min_pixel_clock_in_khz;
+	uint32_t max_pixel_clock_in_khz;
+};
+
+struct vendor_product_id_info {
+	uint32_t manufacturer_id;
+	uint32_t product_id;
+	uint32_t serial_id;
+	uint32_t manufacture_week;
+	uint32_t manufacture_year;
+};
+
+struct display_range_limits {
+	uint32_t min_v_rate_hz;
+	uint32_t max_v_rate_hz;
+	uint32_t min_h_rate_khz;
+	uint32_t max_h_rateIn_khz;
+	uint32_t max_pix_clk_khz;
+	bool use_override;
+};
+
+struct monitor_user_select_limits {
+	bool use_ati_override;
+	uint32_t max_h_res;
+	uint32_t max_v_res;
+	uint32_t max_refresh_rate;
+};
+
+enum edid_screen_aspect_ratio {
+	EDID_SCREEN_AR_UNKNOWN = 0,
+	EDID_SCREEN_AR_PROJECTOR,
+	EDID_SCREEN_AR_16X9,
+	EDID_SCREEN_AR_16X10,
+	EDID_SCREEN_AR_4X3,
+	EDID_SCREEN_AR_5X4,
+	EDID_SCREEN_AR_9X16,
+	EDID_SCREEN_AR_10X16,
+	EDID_SCREEN_AR_3X4,
+	EDID_SCREEN_AR_4X5
+};
+
+struct edid_screen_info {
+	enum edid_screen_aspect_ratio aspect_ratio;
+	uint32_t width;
+	uint32_t height;
+};
+
+struct display_characteristics {
+	uint8_t gamma;
+	uint8_t color_characteristics[NUM_OF_BYTE_EDID_COLOR_CHARACTERISTICS];
+};
+
+union cv_smart_dongle_modes {
+	uint8_t all;
+	struct cv_smart_dongle_switches {
+		uint8_t MODE_1080I:1;
+		uint8_t MODE_720P:1;
+		uint8_t MODE_540P:1;
+		uint8_t MODE_480P:1;
+		uint8_t MODE_480I:1;
+		uint8_t MODE_16_9:1;
+	} switches;
+};
+
+struct cea_audio_mode {
+	uint8_t format_code; /* ucData[0] [6:3]*/
+	uint8_t channel_count; /* ucData[0] [2:0]*/
+	uint8_t sample_rate; /* ucData[1]*/
+	union {
+		uint8_t sample_size; /* for LPCM*/
+		/*  for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/
+		uint8_t max_bit_rate;
+		uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/
+	};
+};
+
+union cea_speaker_allocation_data_block {
+	struct {
+		uint32_t FL_FR:1;
+		uint32_t LFE:1;
+		uint32_t FC:1;
+		uint32_t RL_RR:1;
+		uint32_t RC:1;
+		uint32_t FLC_FRC:1;
+		uint32_t RLC_RRC:1;
+	} bits;
+	uint32_t raw;
+};
+
+struct cea_colorimetry_data_block {
+	struct {
+		uint32_t XV_YCC601:1;
+		uint32_t XV_YCC709:1;
+		uint32_t S_YCC601:1;
+		uint32_t ADOBE_YCC601:1;
+		uint32_t ADOBE_RGB:1;
+
+	} flag;
+	struct {
+		uint32_t MD0:1;
+		uint32_t MD1:1;
+		uint32_t MD2:1;
+		uint32_t MD3:1;
+	} metadata_flag;
+};
+
+union cea_video_capability_data_block {
+	struct {
+		uint8_t S_CE0:1;
+		uint8_t S_CE1:1;
+		uint8_t S_IT0:1;
+		uint8_t S_IT1:1;
+		uint8_t S_PT0:1;
+		uint8_t S_PT1:1;
+		uint8_t QS:1;
+		uint8_t QY:1;
+	} bits;
+	uint8_t raw;
+};
+
+enum stereo_3d_multi_presence {
+	STEREO_3D_MULTI_NOT_PRESENT = 0,
+	STEREO_3D_MULTI_ALL_FORMATS,
+	STEREO_3D_MULTI_MASKED_FORMATS,
+	STEREO_3D_MULTI_RESERVED
+};
+
+enum cea_hdmi_vic {
+	CEA_HDMI_VIC_RESERVED = 0,
+	CEA_HDMI_VIC_4KX2K_30,
+	CEA_HDMI_VIC_4KX2K_25,
+	CEA_HDMI_VIC_4KX2K_24,
+	CEA_HDMI_VIC_4KX2K_24_SMPTE
+};
+
+struct cea_hdmi_vsdb_extended_caps {
+	uint32_t reserved;
+	uint32_t image_size;
+	enum stereo_3d_multi_presence stereo_3d_multi_present;
+	bool stereo_3d_present;
+	uint32_t hdmi_3d_len;
+	uint32_t hdmi_vic_len;
+};
+
+struct cea_vendor_specific_data_block {
+
+	uint32_t ieee_id;
+
+	struct commonent_phy {
+		uint32_t PHY_ADDR_A:4;
+		uint32_t PHY_ADDR_B:4;
+		uint32_t PHY_ADDR_C:4;
+		uint32_t PHY_ADDR_D:4;
+	} commonent_phy_addr;
+
+	struct byte6 {
+		uint32_t SUPPORTS_AI:1;
+		uint32_t DC_48BIT:1;
+		uint32_t DC_36BIT:1;
+		uint32_t DC_30BIT:1;
+		uint32_t DC_Y444:1;
+		uint32_t DVI_DUAL:1;
+		uint32_t RESERVED:2;
+	} byte6;/* link capabilities*/
+	bool byte6_valid;
+
+	uint32_t max_tmds_clk_mhz;
+
+	struct byte8 {
+		uint32_t LATENCY_FIELDS_PRESENT:1;
+		uint32_t ILATENCY_FIELDS_PRESENT:1;
+		uint32_t HDMI_VIDEO_PRESENT:1;
+		uint32_t RESERVED:1;
+		uint32_t CNC3_GAME:1;
+		uint32_t CNC2_CINEMA:1;
+		uint32_t CNC1_PHOTO:1;
+		uint32_t CNC0_GRAPHICS:1;
+	} byte8;
+	/*bit 6-7: latency flags to indicate valid latency fields*/
+	/*bit 5: support of additional video format capabilities*/
+	/* bit 0-3: flags indicating which content type is supported*/
+	uint32_t video_latency;
+	uint32_t audio_latency;
+	uint32_t i_video_latency;
+	uint32_t i_audio_latency;
+
+	struct cea_hdmi_vsdb_extended_caps hdmi_vsdb_extended_caps;
+
+	enum stereo_3d_multi_presence stereo_3d_multi_present;
+
+	struct {
+		bool FRAME_PACKING:1;
+		bool SIDE_BY_SIDE_HALF:1;
+		bool TOP_AND_BOTTOM:1;
+	} stereo_3d_all_support;
+	uint16_t stereo_3d_mask;
+
+	enum cea_hdmi_vic hdmi_vic[MAX_NUMBER_OF_HDMI_VSDB_VICS];
+	struct stereo_3d_extended_support {
+		struct {
+			bool FRAME_PACKING:1;
+			bool SIDE_BY_SIDE_HALF:1;
+			bool TOP_AND_BOTTOM:1;
+		} format;
+		uint32_t vic_index;
+		uint32_t value;
+		uint32_t size;
+	} stereo_3d_extended_support[MAX_NUMBER_OF_HDMI_VSDB_3D_EXTENDED_SUPPORT];
+};
+
+struct cea861_support {
+
+	uint32_t revision;
+	union {
+		struct {
+			uint32_t NATIVE_COUNT:4;
+			uint32_t BASE_AUDIO:1;
+			uint32_t YCRCB444:1;
+			uint32_t YCRCB422:1;
+			uint32_t UNDER_SCAN:1;
+		} features;
+		uint8_t raw_features;
+	};
+};
+
+struct dcs_customized_mode {
+	struct {
+		uint32_t READ_ONLY:1;
+		uint32_t ADD_BY_DRIVER:1;
+		uint32_t INTERLACED:1;
+		uint32_t BASE_MODE:1;
+	} flags;
+	struct dc_mode_info base_mode_info;
+	struct dc_mode_info customized_mode_info;
+};
+
+struct dcs_override_mode_timing {
+	/* possible timing standards, bit vector of TimingStandard*/
+	uint32_t possible_timing_standards;
+	/* indicate driver default timing is used , no override*/
+	bool use_driver_default_timing;
+	struct dc_mode_timing mode_timing;
+};
+
+struct dcs_override_mode_timing_list {
+	uint32_t max_num_overrides;
+	uint32_t num_overrides;
+	struct dcs_override_mode_timing mode_timings[1];
+};
+
+/* "interface type" is different from Signal Type because
+ * an "interface type" can be driven by more than one Signal Type.
+ * For example, INTERFACE_TYPE_DVI can be driven by
+ * Single or Dual link DVI signal. */
+enum dcs_interface_type {
+	INTERFACE_TYPE_VGA = 0,
+	INTERFACE_TYPE_DVI,
+	INTERFACE_TYPE_CV,
+	INTERFACE_TYPE_TV,
+	INTERFACE_TYPE_LVDS,
+	INTERFACE_TYPE_DP,
+	INTERFACE_TYPE_WIRELESS,
+	INTERFACE_TYPE_CF,
+	INTERFACE_TYPE_EDP
+};
+
+
+union panel_misc_info {
+	struct {
+		uint32_t H_CUT_OFF:1;
+		uint32_t H_SYNC_POLARITY:1;/*0=Active High, 1=Active Low*/
+		uint32_t V_SYNC_POLARITY:1; /*0=Active High, 1=Active Low*/
+		uint32_t V_CUT_OFF:1;
+		uint32_t H_REPLICATION_BY_2:1;
+		uint32_t V_REPLICATION_BY_2:1;
+		uint32_t COMPOSITE_SYNC:1;
+		uint32_t INTERLACE:1;
+		uint32_t DOUBLE_CLOCK:1;
+		uint32_t RGB888:1;
+		uint32_t GREY_LEVEL:2;
+		uint32_t SPATIAL:1;
+		uint32_t TEMPORAL:1;
+		uint32_t API_ENABLED:1;
+	} bits;
+	uint32_t raw;
+};
+
+union hdtv_mode_support {
+	struct {
+		uint32_t HDTV_SUPPORT_480I:1;
+		uint32_t HDTV_SUPPORT_480P:1;
+		uint32_t HDTV_SUPPORT_576I25:1;
+		uint32_t HDTV_SUPPORT_576P50:1;
+		uint32_t HDTV_SUPPORT_720P:1;
+		uint32_t HDTV_SUPPORT_720P50:1;
+		uint32_t HDTV_SUPPORT_1080I:1;
+		uint32_t HDTV_SUPPORT_1080I25:1;
+		uint32_t HDTV_SUPPORT_1080P:1;
+		uint32_t HDTV_SUPPORT_1080P50:1;
+		uint32_t HDTV_SUPPORT_1080P24:1;
+		uint32_t HDTV_SUPPORT_1080P25:1;
+		uint32_t HDTV_SUPPORT_1080P30:1;
+		uint32_t HDTV_SUPPORT_16X9:1;
+	} bits;
+	uint32_t raw;
+};
+
+enum edid_retrieve_status {
+	EDID_RETRIEVE_SUCCESS = 0,
+	EDID_RETRIEVE_FAIL,
+	EDID_RETRIEVE_SAME_EDID,
+	EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS
+};
+
+#define DCS_DECODE_EDID_RETRIEVE_STATUS(status) \
+	(status == EDID_RETRIEVE_SUCCESS) ? "EDID_RETRIEVE_SUCCESS" : \
+	(status == EDID_RETRIEVE_FAIL) ? "EDID_RETRIEVE_FAIL" : \
+	(status == EDID_RETRIEVE_SAME_EDID) ? "EDID_RETRIEVE_SAME_EDID" : \
+	(status == EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS) ? \
+		"EDID_RETRIEVE_FAIL_WITH_PREVIOUS_SUCCESS" : "Unknown"
+
+
+#ifndef TV_SIGNALFORMAT_DEFINED
+#define TV_SIGNALFORMAT_DEFINED
+enum tv_signal_format {
+	TV_SIGNAL_FORMAT_UNKNOWN,
+	TV_SIGNAL_FORMAT_NTSC,
+	TV_SIGNAL_FORMAT_NTSC_J,
+	TV_SIGNAL_FORMAT_PAL,
+	TV_SIGNAL_FORMAT_PAL_M,
+	TV_SIGNAL_FORMAT_PAL_CN,
+	TV_SIGNAL_FORMAT_SECAM
+};
+#endif
+
+enum tv_signal_format_result {
+	TV_SIGNAL_FORMAT_RESULT_OK,
+	TV_SIGNAL_FORMAT_SET_MODE_REQ,
+	TV_SIGNAL_FORMAT_REBOOT_REQ,
+	TV_SIGNAL_FORMAT_ERROR
+};
+
+enum pixel_encoding_mask {
+	PIXEL_ENCODING_MASK_YCBCR444 = 0x01,
+	PIXEL_ENCODING_MASK_YCBCR422 = 0x02,
+	PIXEL_ENCODING_MASK_RGB = 0x04,
+};
+
+struct display_pixel_encoding_support {
+	uint32_t mask;
+};
+
+enum color_depth_index {
+	COLOR_DEPTH_INDEX_UNKNOWN,
+	COLOR_DEPTH_INDEX_666 = 0x01,
+	COLOR_DEPTH_INDEX_888 = 0x02,
+	COLOR_DEPTH_INDEX_101010 = 0x04,
+	COLOR_DEPTH_INDEX_121212 = 0x08,
+	COLOR_DEPTH_INDEX_141414 = 0x10,
+	COLOR_DEPTH_INDEX_161616 = 0x20,
+	COLOR_DEPTH_INDEX_LAST = 0x40,
+};
+
+struct display_color_depth_support {
+	uint32_t mask;
+	bool deep_color_native_res_only;
+};
+
+struct display_color_and_pixel_support {
+	struct display_color_depth_support color_depth_support;
+	struct display_pixel_encoding_support pixel_encoding_support;
+	bool deep_color_y444_support;
+};
+
+enum dcs_packed_pixel_format {
+	DCS_PACKED_PIXEL_FORMAT_NOT_PACKED = 0,
+	DCS_PACKED_PIXEL_FORMAT_SPLIT_G70_B54_R70_B10 = 1,
+	DCS_PACKED_PIXEL_FORMAT_R70_G76 = 2,
+	DCS_PACKED_PIXEL_FORMAT_SPLIT_B70_G10_R70_G76 = 3,
+	DCS_PACKED_PIXEL_FORMAT_G70_B54_R70_B10 = 4,
+	DCS_PACKED_PIXEL_FORMAT_G70_B54 = 5,
+	DCS_PACKED_PIXEL_FORMAT_B70_R30_G70_R74 = 6,
+	DCS_PACKED_PIXEL_FORMAT_B70_G70_R70 = 7,
+	DCS_PACKED_PIXEL_FORMAT_B70_R32_G70_R76 = 8,
+};
+
+enum monitor_manufacturer_id {
+	MONITOR_MANUFACTURER_ID_0 = 0x0000,
+	MONITOR_MANUFACTURER_ID_1 = 0x3834,
+	MONITOR_MANUFACTURER_ID_2 = 0x4d24,
+	MONITOR_MANUFACTURER_ID_3 = 0x293E,
+	MONITOR_MANUFACTURER_ID_4 = 0x635a,
+	MONITOR_MANUFACTURER_ID_5 = 0x1006,
+	MONITOR_MANUFACTURER_ID_6 = 0xc32a,
+	MONITOR_MANUFACTURER_ID_7 = 0x4d24,
+	MONITOR_MANUFACTURER_ID_8 = 0x110e,
+	MONITOR_MANUFACTURER_ID_9 = 0xaf0d,
+	MONITOR_MANUFACTURER_ID_10 = 0x6D1E,
+	MONITOR_MANUFACTURER_ID_11 = 0xA338,
+	MONITOR_MANUFACTURER_ID_12 = 0xC315,
+	MONITOR_MANUFACTURER_ID_13 = 0xD94D,
+	MONITOR_MANUFACTURER_ID_14 = 0x104D,
+	MONITOR_MANUFACTURER_ID_15 = 0x855C,
+	MONITOR_MANUFACTURER_ID_16 = 0x4251,
+	MONITOR_MANUFACTURER_ID_17 = 0xA934,
+	MONITOR_MANUFACTURER_ID_18 = 0x0C41,
+	/* TODO: Update when EDID is available */
+	MONITOR_MANUFACTURER_ID_19 = 0xDEAD,
+	MONITOR_MANUFACTURER_ID_20 = 0x6904,
+	MONITOR_MANUFACTURER_ID_21 = 0xAC10,
+	MONITOR_MANUFACTURER_ID_22 = 0x2D4C,
+	MONITOR_MANUFACTURER_ID_23 = 0x144E,
+	MONITOR_MANUFACTURER_ID_24 = 0x6c50,
+	MONITOR_MANUFACTURER_ID_26 = 0x0c41,
+	MONITOR_MANUFACTURER_ID_27 = 0x143E,
+	MONITOR_MANUFACTURER_ID_25 = 0xffff,
+	MONITOR_MANUFACTURER_ID_28 = 0x3421,
+	MONITOR_MANUFACTURER_ID_29 = 0x2D19,
+	MONITOR_MANUFACTURER_ID_30 = 0x8B52,
+	MONITOR_MANUFACTURER_ID_31 = 0x7204,
+	MONITOR_MANUFACTURER_ID_32 = 0xF022,
+	MONITOR_MANUFACTURER_ID_33 = 0x0E11,
+	MONITOR_MANUFACTURER_ID_34 = 0xD241,
+	MONITOR_MANUFACTURER_ID_35 = 0xAE30,
+	MONITOR_MANUFACTURER_ID_36 = 0xF91E,
+	MONITOR_MANUFACTURER_ID_37 = 0xAB4C,
+};
+
+enum monitor_product_id {
+	MONITOR_PRODUCT_ID_0 = 0x0000,
+	MONITOR_PRODUCT_ID_1 = 0x0BCC,
+	MONITOR_PRODUCT_ID_2 = 0x251F,
+	MONITOR_PRODUCT_ID_3 = 0x5241,
+	MONITOR_PRODUCT_ID_4 = 0x6919,
+	MONITOR_PRODUCT_ID_5 = 0xee18,
+	MONITOR_PRODUCT_ID_6 = 0xf008,
+	MONITOR_PRODUCT_ID_7 = 0x2f0c,
+	MONITOR_PRODUCT_ID_7_2 = 0x3411,
+	MONITOR_PRODUCT_ID_9 = 0x4208,
+	MONITOR_PRODUCT_ID_10 = 0xE51D,
+	MONITOR_PRODUCT_ID_11 = 0x7E22,
+	MONITOR_PRODUCT_ID_12 = 0x0E23,
+	MONITOR_PRODUCT_ID_13 = 0x9d08,
+	MONITOR_PRODUCT_ID_14 = 0x9236,
+	MONITOR_PRODUCT_ID_15 = 0x9227,
+	MONITOR_PRODUCT_ID_16 = 0x0220,
+	MONITOR_PRODUCT_ID_17 = 0x4920,
+	MONITOR_PRODUCT_ID_18 = 0x251f,
+	MONITOR_PRODUCT_ID_19 = 0x1395,
+	MONITOR_PRODUCT_ID_20 = 0xc04e,
+	MONITOR_PRODUCT_ID_21 = 0x5787,
+	MONITOR_PRODUCT_ID_22 = 0x5A71,
+	MONITOR_PRODUCT_ID_23 = 0x6622,
+	MONITOR_PRODUCT_ID_24 = 0x20C1,
+	MONITOR_PRODUCT_ID_25 = 0x2110,
+	MONITOR_PRODUCT_ID_26 = 0x2006,
+	MONITOR_PRODUCT_ID_27 = 0x1827,
+	MONITOR_PRODUCT_ID_28 = 0x0EA0,
+	MONITOR_PRODUCT_ID_29 = 0x03D0,
+	MONITOR_PRODUCT_ID_30 = 0x01D2,
+	MONITOR_PRODUCT_ID_31 = 0x2801,
+	MONITOR_PRODUCT_ID_32 = 0x0FB3,
+	MONITOR_PRODUCT_ID_33 = 0x0FB1,
+	MONITOR_PRODUCT_ID_34 = 0xA045,
+	MONITOR_PRODUCT_ID_35 = 0x0001,
+	MONITOR_PRODUCT_ID_36 = 0xA296,
+	MONITOR_PRODUCT_ID_38 = 0x21DC,
+	MONITOR_PRODUCT_ID_37 = 0x21EA,
+	MONITOR_PRODUCT_ID_39 = 0x4093,
+	MONITOR_PRODUCT_ID_40 = 0x4094,
+	MONITOR_PRODUCT_ID_41 = 0x4094,
+	MONITOR_PRODUCT_ID_42 = 0x32A2,
+	MONITOR_PRODUCT_ID_43 = 0xE009,
+	MONITOR_PRODUCT_ID_44 = 0xA010,
+	MONITOR_PRODUCT_ID_45 = 0x405C,
+	MONITOR_PRODUCT_ID_46 = 0xF017,
+	MONITOR_PRODUCT_ID_47 = 0xD026,
+	MONITOR_PRODUCT_ID_48 = 0x4036,
+	MONITOR_PRODUCT_ID_49 = 0x4065,
+	MONITOR_PRODUCT_ID_50 = 0xA02A,
+	MONITOR_PRODUCT_ID_51 = 0xA02C,
+	MONITOR_PRODUCT_ID_46_HDMI = 0xF016,
+	MONITOR_PRODUCT_ID_53 = 0xF048,
+	MONITOR_PRODUCT_ID_54 = 0xA0A2,
+	MONITOR_PRODUCT_ID_55 = 0x4083,
+	MONITOR_PRODUCT_ID_56 = 0x0E74,
+	MONITOR_PRODUCT_ID_57 = 0x2771,
+	MONITOR_PRODUCT_ID_58 = 0x0814,
+	MONITOR_PRODUCT_ID_59 = 0xffff,
+	MONITOR_PRODUCT_ID_60 = 0x3339,
+	MONITOR_PRODUCT_ID_61 = 0x01F5,
+	MONITOR_PRODUCT_ID_62 = 0x02A5,
+	MONITOR_PRODUCT_ID_63 = 0x06AC,
+	MONITOR_PRODUCT_ID_64 = 0x04D5,
+	MONITOR_PRODUCT_ID_65 = 0x079D,
+	MONITOR_PRODUCT_ID_66 = 0x079F,
+	MONITOR_PRODUCT_ID_67 = 0x0797,
+	MONITOR_PRODUCT_ID_68 = 0x0B80,
+	MONITOR_PRODUCT_ID_69 = 0x7D06,
+	MONITOR_PRODUCT_ID_70 = 0x0131,
+	MONITOR_PRODUCT_ID_71 = 0x8545,
+	MONITOR_PRODUCT_ID_72 = 0x0002,
+	MONITOR_PRODUCT_ID_73 = 0x0125,
+	MONITOR_PRODUCT_ID_74 = 0x00D0,
+	MONITOR_PRODUCT_ID_75 = 0x26F7,
+	MONITOR_PRODUCT_ID_76 = 0x26F9,
+	MONITOR_PRODUCT_ID_77 = 0x2807,
+	MONITOR_PRODUCT_ID_78 = 0x26F3,
+	MONITOR_PRODUCT_ID_79 = 0x2676,
+	MONITOR_PRODUCT_ID_80 = 0x0A72,
+	MONITOR_PRODUCT_ID_81 = 0x2693,
+	MONITOR_PRODUCT_ID_82 = 0x2615,
+	MONITOR_PRODUCT_ID_83 = 0x2613,
+	MONITOR_PRODUCT_ID_84 = 0x262D,
+	MONITOR_PRODUCT_ID_85 = 0x264B,
+	MONITOR_PRODUCT_ID_86 = 0x2869,
+	MONITOR_PRODUCT_ID_87 = 0x286C,
+	MONITOR_PRODUCT_ID_88 = 0x288F,
+	MONITOR_PRODUCT_ID_89 = 0x2954,
+	MONITOR_PRODUCT_ID_90 = 0x6522,
+	MONITOR_PRODUCT_ID_91 = 0x0FAE,
+	MONITOR_PRODUCT_ID_92 = 0x0A0C,
+	MONITOR_PRODUCT_ID_93 = 0x00BF,
+	MONITOR_PRODUCT_ID_94 = 0x0,
+};
+
+enum monitor_patch_type {
+	MONITOR_PATCH_TYPE_NONE,
+	MONITOR_PATCH_TYPE_ERROR_CHECKSUM,
+	MONITOR_PATCH_TYPE_HDTV_WITH_PURE_DFP_EDID,
+	MONITOR_PATCH_TYPE_DO_NOT_USE_DETAILED_TIMING,
+	MONITOR_PATCH_TYPE_DO_NOT_USE_RANGE_LIMITATION,
+	MONITOR_PATCH_TYPE_EDID_EXTENTION_ERROR_CHECK_SUM,
+	MONITOR_PATCH_TYPE_TURN_OFF_DISPLAY_BEFORE_MODE_CHANGE,
+	MONITOR_PATCH_TYPE_RESTRICT_VESA_MODE_TIMING,
+	MONITOR_PATCH_TYPE_DO_NOT_USE_EDID_MAX_PIX_CLK,
+	MONITOR_PATCH_TYPE_VENDOR_0,
+	MONITOR_PATCH_TYPE_RANDOM_CRT,
+	MONITOR_PATCH_TYPE_VENDOR_1,
+	MONITOR_PATCH_TYPE_LIMIT_PANEL_SUPPORT_RGB_ONLY,
+	MONITOR_PATCH_TYPE_PACKED_PIXEL_FORMAT,
+	MONITOR_PATCH_TYPE_LARGE_PANEL,
+	MONITOR_PATCH_TYPE_STEREO_SUPPORT,
+	/* 0 (default) - mean patch will not be applied, however it can be
+	 * explicitly set to 1
+	 */
+	MONITOR_PATCH_TYPE_DUAL_EDID_PANEL,
+	MONITOR_PATCH_TYPE_IGNORE_19X12_STD_TIMING,
+	MONITOR_PATCH_TYPE_MULTIPLE_PACKED_TYPE,
+	MONITOR_PATCH_TYPE_RESET_TX_ON_DISPLAY_POWER_ON,
+	MONITOR_PATCH_TYPE_VENDOR_2,
+	MONITOR_PATCH_TYPE_RESTRICT_PROT_DUAL_LINK_DVI,
+	MONITOR_PATCH_TYPE_FORCE_LINK_RATE,
+	MONITOR_PATCH_TYPE_DELAY_AFTER_DP_RECEIVER_POWER_UP,
+	MONITOR_PATCH_TYPE_KEEP_DP_RECEIVER_POWERED,
+	MONITOR_PATCH_TYPE_DELAY_BEFORE_READ_EDID,
+	MONITOR_PATCH_TYPE_DELAY_AFTER_PIXEL_FORMAT_CHANGE,
+	MONITOR_PATCH_TYPE_INCREASE_DEFER_WRITE_RETRY_I2C_OVER_AUX,
+	MONITOR_PATCH_TYPE_NO_DEFAULT_TIMINGS,
+	MONITOR_PATCH_TYPE_ADD_CEA861_DETAILED_TIMING_VIC16,
+	MONITOR_PATCH_TYPE_ADD_CEA861_DETAILED_TIMING_VIC31,
+	MONITOR_PATCH_TYPE_DELAY_BEFORE_UNMUTE,
+	MONITOR_PATCH_TYPE_RETRY_LINK_TRAINING_ON_FAILURE,
+	MONITOR_PATCH_TYPE_ALLOW_AUX_WHEN_HPD_LOW,
+	MONITOR_PATCH_TYPE_TILED_DISPLAY,
+	MONITOR_PATCH_TYPE_DISABLE_PSR_ENTRY_ABORT,
+	MONITOR_PATCH_TYPE_EDID_EXTENTION_ERROR_CHECKSUM,
+	MONITOR_PATCH_TYPE_ALLOW_ONLY_CE_MODE,
+	MONITOR_PATCH_TYPE_VID_STREAM_DIFFER_TO_SYNC,
+	MONITOR_PATCH_TYPE_EXTRA_DELAY_ON_DISCONNECT,
+	MONITOR_PATCH_TYPE_DELAY_AFTER_DISABLE_BACKLIGHT_DFS_BYPASS,
+	MONITOR_PATCH_TYPE_SINGLE_MODE_PACKED_PIXEL
+};
+
+/* Single entry in the monitor table */
+struct monitor_patch_info {
+	enum monitor_manufacturer_id manufacturer_id;
+	enum monitor_product_id product_id;
+	enum monitor_patch_type type;
+	uint32_t param;
+};
+
+union dcs_monitor_patch_flags {
+        struct {
+                bool ERROR_CHECKSUM:1;
+                bool HDTV_WITH_PURE_DFP_EDID:1;
+                bool DO_NOT_USE_DETAILED_TIMING:1;
+                bool DO_NOT_USE_RANGE_LIMITATION:1;
+                bool EDID_EXTENTION_ERROR_CHECKSUM:1;
+                bool TURN_OFF_DISPLAY_BEFORE_MODE_CHANGE:1;
+                bool RESTRICT_VESA_MODE_TIMING:1;
+                bool DO_NOT_USE_EDID_MAX_PIX_CLK:1;
+                bool VENDOR_0:1;
+                bool RANDOM_CRT:1;/* 10 bits used including this one-*/
+                bool VENDOR_1:1;
+                bool LIMIT_PANEL_SUPPORT_RGB_ONLY:1;
+                bool PACKED_PIXEL_FORMAT:1;
+                bool LARGE_PANEL:1;
+                bool STEREO_SUPPORT:1;
+                bool DUAL_EDID_PANEL:1;
+                bool IGNORE_19X12_STD_TIMING:1;
+                bool MULTIPLE_PACKED_TYPE:1;
+                bool RESET_TX_ON_DISPLAY_POWER_ON:1;
+                bool ALLOW_ONLY_CE_MODE:1;/* 20 bits used including this one*/
+                bool RESTRICT_PROT_DUAL_LINK_DVI:1;
+                bool FORCE_LINK_RATE:1;
+                bool DELAY_AFTER_DP_RECEIVER_POWER_UP:1;
+                bool KEEP_DP_RECEIVER_POWERED:1;
+                bool DELAY_BEFORE_READ_EDID:1;
+                bool DELAY_AFTER_PIXEL_FORMAT_CHANGE:1;
+                bool INCREASE_DEFER_WRITE_RETRY_I2C_OVER_AUX:1;
+                bool NO_DEFAULT_TIMINGS:1;
+                bool ADD_CEA861_DETAILED_TIMING_VIC16:1;
+                bool ADD_CEA861_DETAILED_TIMING_VIC31:1; /* 30 bits*/
+                bool DELAY_BEFORE_UNMUTE:1;
+                bool RETRY_LINK_TRAINING_ON_FAILURE:1;
+                bool ALLOW_AUX_WHEN_HPD_LOW:1;
+                bool TILED_DISPLAY:1;
+                bool DISABLE_PSR_ENTRY_ABORT:1;
+                bool INTERMITTENT_EDID_ERROR:1;/* 36 bits total*/
+                bool VID_STREAM_DIFFER_TO_SYNC:1;/* 37 bits total*/
+                bool EXTRA_DELAY_ON_DISCONNECT:1;/* 38 bits total*/
+                bool DELAY_AFTER_DISABLE_BACKLIGHT_DFS_BYPASS:1;/* 39 bits total*/
+        } flags;
+        uint64_t raw;
+};
+
+struct dcs_edid_supported_max_bw {
+	uint32_t pix_clock_khz;
+	uint32_t bits_per_pixel;
+};
+
+struct dcs_stereo_3d_features {
+	struct {
+/* 3D Format supported by monitor (implies supported by driver)*/
+		uint32_t SUPPORTED:1;
+/* 3D Format supported on all timings
+(no need to check every timing for 3D support)*/
+		uint32_t ALL_TIMINGS:1;
+/* 3D Format supported in clone mode*/
+		uint32_t CLONE_MODE:1;
+/* Scaling allowed when driving 3D Format*/
+		uint32_t SCALING:1;
+/* Left and right images packed by SW within single frame*/
+		uint32_t SINGLE_FRAME_SW_PACKED:1;
+	} flags;
+};
+
+struct dcs_container_id {
+	/*128bit GUID in binary form*/
+	uint8_t guid[16];
+	/* 8 byte port ID -> ELD.PortID*/
+	uint32_t port_id[2];
+	/* 2 byte manufacturer name -> ELD.ManufacturerName*/
+	uint16_t manufacturer_name;
+	/* 2 byte product code -> ELD.ProductCode*/
+	uint16_t product_code;
+};
+
+struct dcs_display_tile {
+/*unique Id of Tiled Display. 0 - means display is not part in Tiled Display*/
+	uint64_t id;
+	uint32_t rows;/* size of Tiled Display in tiles*/
+	uint32_t cols;/* size of Tiled Display in tiles*/
+	uint32_t width;/* size of current Tile in pixels*/
+	uint32_t height;/* size of current Tile in pixels*/
+	uint32_t row;/* location of current Tile*/
+	uint32_t col;/* location of current Tile*/
+	struct {
+		/*in pixels*/
+		uint32_t left;
+		uint32_t right;
+		uint32_t top;
+		uint32_t bottom;
+	} bezel;/* bezel information of current tile*/
+
+	struct {
+		uint32_t SEPARATE_ENCLOSURE:1;
+		uint32_t BEZEL_INFO_PRESENT:1;
+		uint32_t CAN_SCALE:1;
+	} flags;
+
+	struct {
+		uint32_t manufacturer_id;
+		uint32_t product_id;
+		uint32_t serial_id;
+	} topology_id;
+};
+
+#endif /* __DAL_DCS_TYPES_H__ */
+
diff --git a/drivers/gpu/drm/amd/dal/include/ddc_interface.h b/drivers/gpu/drm/amd/dal/include/ddc_interface.h
new file mode 100644
index 000000000000..22fd31f6de7f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/ddc_interface.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DDC_INTERFACE_H__
+#define __DAL_DDC_INTERFACE_H__
+
+#include "gpio_types.h"
+
+struct ddc;
+
+enum gpio_result dal_ddc_open(
+	struct ddc *ddc,
+	enum gpio_mode mode,
+	enum gpio_ddc_config_type config_type);
+
+enum gpio_result dal_ddc_get_clock(
+	const struct ddc *ddc,
+	uint32_t *value);
+
+enum gpio_result dal_ddc_set_clock(
+	const struct ddc *ddc,
+	uint32_t value);
+
+enum gpio_result dal_ddc_get_data(
+	const struct ddc *ddc,
+	uint32_t *value);
+
+enum gpio_result dal_ddc_set_data(
+	const struct ddc *ddc,
+	uint32_t value);
+
+enum gpio_result dal_ddc_change_mode(
+	struct ddc *ddc,
+	enum gpio_mode mode);
+
+bool dal_ddc_is_hw_supported(
+	const struct ddc *ddc);
+
+enum gpio_ddc_line dal_ddc_get_line(
+	const struct ddc *ddc);
+
+bool dal_ddc_check_line_aborted(
+	const struct ddc *ddc);
+
+enum gpio_result dal_ddc_set_config(
+	struct ddc *ddc,
+	enum gpio_ddc_config_type config_type);
+
+void dal_ddc_close(
+	struct ddc *ddc);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/ddc_service_types.h b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h
new file mode 100644
index 000000000000..63dbbc5e86f8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#ifndef __DAL_DDC_SERVICE_TYPES_H__
+#define __DAL_DDC_SERVICE_TYPES_H__
+
+#define DP_BRANCH_DEVICE_ID_1 0x0010FA
+#define DP_BRANCH_DEVICE_ID_2 0x0022B9
+#define DP_SINK_DEVICE_ID_1 0x4CE000
+#define DP_BRANCH_DEVICE_ID_3 0x00001A
+#define DP_BRANCH_DEVICE_ID_4 0x0080e1
+#define DP_BRANCH_DEVICE_ID_5 0x006037
+#define DP_SINK_DEVICE_ID_2 0x001CF8
+
+
+enum ddc_result {
+	DDC_RESULT_UNKNOWN = 0,
+	DDC_RESULT_SUCESSFULL,
+	DDC_RESULT_FAILED_CHANNEL_BUSY,
+	DDC_RESULT_FAILED_TIMEOUT,
+	DDC_RESULT_FAILED_PROTOCOL_ERROR,
+	DDC_RESULT_FAILED_NACK,
+	DDC_RESULT_FAILED_INCOMPLETE,
+	DDC_RESULT_FAILED_OPERATION,
+	DDC_RESULT_FAILED_INVALID_OPERATION,
+	DDC_RESULT_FAILED_BUFFER_OVERFLOW
+};
+
+enum ddc_service_type {
+	DDC_SERVICE_TYPE_CONNECTOR,
+	DDC_SERVICE_TYPE_DISPLAY_PORT_MST,
+};
+
+
+enum dcs_dpcd_revision {
+	DCS_DPCD_REV_10 = 0x10,
+	DCS_DPCD_REV_11 = 0x11,
+	DCS_DPCD_REV_12 = 0x12
+};
+
+/**
+ * display sink capability
+ */
+struct display_sink_capability {
+	/* dongle type (DP converter, CV smart dongle) */
+	enum display_dongle_type dongle_type;
+
+	/**********************************************************
+	 capabilities going INTO SINK DEVICE (stream capabilities)
+	 **********************************************************/
+	/* Dongle's downstream count. */
+	uint32_t downstrm_sink_count;
+	/* Is dongle's downstream count info field (downstrm_sink_count)
+	 * valid. */
+	bool downstrm_sink_count_valid;
+
+	/* Maximum additional audio delay in microsecond (us) */
+	uint32_t additional_audio_delay;
+	/* Audio latency value in microsecond (us) */
+	uint32_t audio_latency;
+	/* Interlace video latency value in microsecond (us) */
+	uint32_t video_latency_interlace;
+	/* Progressive video latency value in microsecond (us) */
+	uint32_t video_latency_progressive;
+	/* Dongle caps: Maximum pixel clock supported over dongle for HDMI */
+	uint32_t max_hdmi_pixel_clock;
+	/* Dongle caps: Maximum deep color supported over dongle for HDMI */
+	enum dc_color_depth max_hdmi_deep_color;
+
+	/************************************************************
+	 capabilities going OUT OF SOURCE DEVICE (link capabilities)
+	 ************************************************************/
+	/* support for Spread Spectrum(SS) */
+	bool ss_supported;
+	/* DP link settings (laneCount, linkRate, Spread) */
+	uint32_t dp_link_lane_count;
+	uint32_t dp_link_rate;
+	uint32_t dp_link_spead;
+
+	enum dcs_dpcd_revision dpcd_revision;
+	/* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER,
+	indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/
+	bool is_dp_hdmi_s3d_converter;
+	/* to check if we have queried the display capability
+	 * for eDP panel already. */
+	bool is_edp_sink_cap_valid;
+
+	enum ddc_transaction_type transaction_type;
+	enum signal_type signal;
+};
+
+
+struct av_sync_data {
+	uint8_t av_granularity;/* DPCD 00023h */
+	uint8_t aud_dec_lat1;/* DPCD 00024h */
+	uint8_t aud_dec_lat2;/* DPCD 00025h */
+	uint8_t aud_pp_lat1;/* DPCD 00026h */
+	uint8_t aud_pp_lat2;/* DPCD 00027h */
+	uint8_t vid_inter_lat;/* DPCD 00028h */
+	uint8_t vid_prog_lat;/* DPCD 00029h */
+	uint8_t aud_del_ins1;/* DPCD 0002Bh */
+	uint8_t aud_del_ins2;/* DPCD 0002Ch */
+	uint8_t aud_del_ins3;/* DPCD 0002Dh */
+};
+
+/** EDID retrieval related constants, also used by MstMgr **/
+
+#define DDC_EDID_SEGMENT_SIZE 256
+#define DDC_EDID_BLOCK_SIZE 128
+#define DDC_EDID_BLOCKS_PER_SEGMENT \
+	(DDC_EDID_SEGMENT_SIZE / DDC_EDID_BLOCK_SIZE)
+
+#define DDC_EDID_EXT_COUNT_OFFSET 0x7E
+
+#define DDC_EDID_ADDRESS_START 0x50
+#define DDC_EDID_ADDRESS_END 0x52
+#define DDC_EDID_SEGMENT_ADDRESS 0x30
+
+/* signatures for Edid 1x */
+#define DDC_EDID1X_VENDORID_SIGNATURE_OFFSET 8
+#define DDC_EDID1X_VENDORID_SIGNATURE_LEN 4
+#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_OFFSET 126
+#define DDC_EDID1X_EXT_CNT_AND_CHECKSUM_LEN 2
+#define DDC_EDID1X_CHECKSUM_OFFSET 127
+/* signatures for Edid 20*/
+#define DDC_EDID_20_SIGNATURE_OFFSET 0
+#define DDC_EDID_20_SIGNATURE 0x20
+
+#define DDC_EDID20_VENDORID_SIGNATURE_OFFSET 1
+#define DDC_EDID20_VENDORID_SIGNATURE_LEN 4
+#define DDC_EDID20_CHECKSUM_OFFSET 255
+#define DDC_EDID20_CHECKSUM_LEN 1
+
+/*DP to VGA converter*/
+static const uint8_t DP_VGA_CONVERTER_ID_1[] = "mVGAa";
+/*DP to Dual link DVI converter*/
+static const uint8_t DP_DVI_CONVERTER_ID_1[] = "m2DVIa";
+/*Travis*/
+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
+/*Nutmeg*/
+static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
+/*DP to VGA converter*/
+static const uint8_t DP_VGA_CONVERTER_ID_4[] = "DpVga";
+/*DP to Dual link DVI converter*/
+static const uint8_t DP_DVI_CONVERTER_ID_4[] = "m2DVIa";
+/*DP to Dual link DVI converter 2*/
+static const uint8_t DP_DVI_CONVERTER_ID_42[] = "v2DVIa";
+
+static const uint8_t DP_SINK_DEV_STRING_ID2_REV0[] = "\0\0\0\0\0\0";
+
+/* Identifies second generation PSR TCON from Parade: Device ID string:
+ * yy-xx-**-**-**-**
+ */
+/* xx - Hw ID high byte */
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_HIGH_BYTE =
+	0x06;
+
+/* yy - HW ID low byte, the same silicon has several package/feature flavors */
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE1 =
+	0x61;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE2 =
+	0x62;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE3 =
+	0x63;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE4 =
+	0x72;
+static const uint32_t DP_SINK_DEV_STRING_ID2_REV1_HW_ID_LOW_BYTE5 =
+	0x73;
+
+#endif /* __DAL_DDC_SERVICE_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/display_clock_interface.h b/drivers/gpu/drm/amd/dal/include/display_clock_interface.h
new file mode 100644
index 000000000000..211847cefe80
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/display_clock_interface.h
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DISPLAY_CLOCK_INTERFACE_H__
+#define __DISPLAY_CLOCK_INTERFACE_H__
+
+#include "hw_sequencer_types.h"
+#include "grph_object_defs.h"
+#include "signal_types.h"
+#include "scaler_types.h"
+
+/* Timing related information*/
+struct dc_timing_params {
+	uint32_t INTERLACED:1;
+	uint32_t HCOUNT_BY_TWO:1;
+	uint32_t PIXEL_REPETITION:4; /*< values 1 to 10 supported*/
+	uint32_t PREFETCH:1;
+
+	uint32_t h_total;
+	uint32_t h_addressable;
+	uint32_t h_sync_width;
+};
+
+/* Scaling related information*/
+struct dc_scaling_params {
+	uint32_t h_overscan_right;
+	uint32_t h_overscan_left;
+	uint32_t h_taps;
+	uint32_t v_taps;
+};
+
+/*Display Request Mode (1 and 2 valid when scaler is OFF)*/
+enum display_request_mode {
+	REQUEST_ONLY_AT_EVERY_READ_POINTER_INCREMENT = 0,
+	REQUEST_WAITING_FOR_THE_FIRST_READ_POINTER_ONLY,
+	REQUEST_WITHOUT_WAITING_FOR_READ_POINTER
+};
+
+/* FBC minimum CompressionRatio*/
+enum fbc_compression_ratio {
+	FBC_COMPRESSION_NOT_USED = 0,
+	FBC_MINIMUM_COMPRESSION_RATIO_1 = 1,
+	FBC_MINIMUM_COMPRESSION_RATIO_2 = 2,
+	FBC_MINIMUM_COMPRESSION_RATIO_4 = 4,
+	FBC_MINIMUM_COMPRESSION_RATIO_8 = 8
+};
+
+/* VScalerEfficiency */
+enum v_scaler_efficiency {
+	V_SCALER_EFFICIENCY_LB36BPP = 0,
+	V_SCALER_EFFICIENCY_LB30BPP = 1,
+	V_SCALER_EFFICIENCY_LB24BPP = 2,
+	V_SCALER_EFFICIENCY_LB18BPP = 3
+};
+
+/* Parameters required for minimum Engine
+ * and minimum Display clock calculations*/
+struct min_clock_params {
+	uint32_t id;
+	uint32_t requested_pixel_clock; /* in KHz */
+	uint32_t actual_pixel_clock; /* in KHz */
+	struct view source_view;
+	struct view dest_view;
+	struct dc_timing_params timing_info;
+	struct dc_scaling_params scaling_info;
+	struct color_quality color_info;
+	enum signal_type signal_type;
+	enum dc_color_depth deep_color_depth;
+	enum v_scaler_efficiency scaler_efficiency;
+	bool line_buffer_prefetch_enabled;
+};
+
+/* Enumerations for Source selection of the Display clock */
+enum display_clock_source_select {
+	USE_PIXEL_CLOCK_PLL = 0,
+	USE_EXTERNAL_CLOCK,
+	USE_ENGINE_CLOCK
+};
+
+/* Result of Minimum System and Display clock calculations.
+ * Minimum System clock and Display clock, source and path to be used
+ * for Display clock*/
+struct minimum_clocks_calculation_result {
+	uint32_t min_sclk_khz;
+	uint32_t min_dclk_khz;
+	uint32_t min_mclk_khz;
+	uint32_t min_deep_sleep_sclk;
+};
+
+/* Enumeration of all clocks states */
+enum clocks_state {
+	CLOCKS_STATE_INVALID,
+	CLOCKS_STATE_ULTRA_LOW,
+	CLOCKS_STATE_LOW,
+	CLOCKS_STATE_NOMINAL,
+	CLOCKS_STATE_PERFORMANCE
+};
+
+/* Structure containing all state-dependent clocks
+ * (dependent on "enum clocks_state") */
+struct state_dependent_clocks {
+	uint32_t display_clk_khz;
+	uint32_t pixel_clk_khz;
+};
+
+struct display_clock_state {
+	uint32_t DFS_BYPASS_ACTIVE:1;
+};
+
+struct display_clock;
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+struct display_clock *dal_display_clock_dce110_create(
+	struct dc_context *ctx,
+	struct adapter_service *as);
+#endif
+
+void dal_display_clock_destroy(struct display_clock **to_destroy);
+bool dal_display_clock_validate(
+	struct display_clock *disp_clk,
+	struct min_clock_params *params);
+uint32_t dal_display_clock_calculate_min_clock(
+	struct display_clock *disp_clk,
+	uint32_t path_num,
+	struct min_clock_params *params);
+uint32_t dal_display_clock_get_validation_clock(struct display_clock *disp_clk);
+void dal_display_clock_set_clock(
+	struct display_clock *disp_clk,
+	uint32_t requested_clock_khz);
+uint32_t dal_display_clock_get_clock(struct display_clock *disp_clk);
+enum clocks_state dal_display_clock_get_min_clocks_state(
+	struct display_clock *disp_clk);
+enum clocks_state dal_display_clock_get_required_clocks_state(
+	struct display_clock *disp_clk,
+	struct state_dependent_clocks *req_clocks);
+bool dal_display_clock_set_min_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state clocks_state);
+uint32_t dal_display_clock_get_dp_ref_clk_frequency(
+	struct display_clock *disp_clk);
+/*the second parameter of "switchreferenceclock" is
+ * a dummy argument for all pre dce 6.0 versions*/
+void dal_display_clock_switch_reference_clock(
+	struct display_clock *disp_clk,
+	bool use_external_ref_clk,
+	uint32_t requested_clock_khz);
+void dal_display_clock_set_dp_ref_clock_source(
+	struct display_clock *disp_clk,
+	enum clock_source_id clk_src);
+void dal_display_clock_store_max_clocks_state(
+	struct display_clock *disp_clk,
+	enum clocks_state max_clocks_state);
+void dal_display_clock_set_clock_state(
+	struct display_clock *disp_clk,
+	struct display_clock_state clk_state);
+struct display_clock_state dal_display_clock_get_clock_state(
+	struct display_clock *disp_clk);
+uint32_t dal_display_clock_get_dfs_bypass_threshold(
+	struct display_clock *disp_clk);
+void dal_display_clock_invalid_clock_state(
+	struct display_clock *disp_clk);
+
+
+#endif /* __DISPLAY_CLOCK_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/display_path_interface.h b/drivers/gpu/drm/amd/dal/include/display_path_interface.h
new file mode 100644
index 000000000000..7bf2ef28f455
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/display_path_interface.h
@@ -0,0 +1,436 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DISPLAY_PATH_INTERFACE_H__
+#define __DISPLAY_PATH_INTERFACE_H__
+
+#include "display_path_types.h"
+#include "dcs_types.h"
+#include "grph_object_ctrl_defs.h"
+#include "signal_types.h"
+#include "controller_types.h"
+
+struct encoder;
+struct controller;
+struct connector;
+struct audio;
+struct clock_source;
+struct link_service;
+struct goc_link_service_data;
+struct drr_config;
+
+struct display_path;
+
+struct display_path *dal_display_path_create(void);
+
+struct display_path *dal_display_path_clone(
+	const struct display_path *self,
+	bool copy_active_state);
+
+void dal_display_path_destroy(
+	struct display_path **to_destroy);
+
+bool dal_display_path_validate(
+	struct display_path *path,
+	enum signal_type sink_signal);
+
+bool dal_display_path_add_link(
+	struct display_path *path,
+	struct encoder *encoder);
+
+bool dal_display_path_add_connector(
+	struct display_path *path,
+	struct connector *connector);
+
+struct connector *dal_display_path_get_connector(
+	struct display_path *path);
+
+int32_t dal_display_path_acquire(
+	struct display_path *path);
+
+bool dal_display_path_is_acquired(
+	const struct display_path *path);
+
+int32_t dal_display_path_get_ref_counter(
+	const struct display_path *path);
+
+int32_t dal_display_path_release(
+	struct display_path *path);
+
+void dal_display_path_release_resources(
+	struct display_path *path);
+
+void dal_display_path_acquire_links(
+	struct display_path *path);
+
+bool dal_display_path_is_source_blanked(
+	const struct display_path *path);
+
+bool dal_display_path_is_source_unblanked(
+	const struct display_path *path);
+
+void dal_display_path_set_source_blanked(
+	struct display_path *path,
+	enum display_tri_state state);
+
+bool dal_display_path_is_target_blanked(
+	const struct display_path *path);
+
+bool dal_display_path_is_target_unblanked(
+	const struct display_path *path);
+
+void dal_display_path_set_target_blanked(
+	struct display_path *path,
+	enum display_tri_state state);
+
+bool dal_display_path_is_target_powered_on(
+	const struct display_path *path);
+
+bool dal_display_path_is_target_powered_off(
+	const struct display_path *path);
+
+void dal_display_path_set_target_powered_on(
+	struct display_path *path,
+	enum display_tri_state state);
+
+bool dal_display_path_is_target_connected(
+	const struct display_path *path);
+
+void dal_display_path_set_target_connected(
+	struct display_path *path,
+	bool c);
+
+uint32_t dal_display_path_get_display_index(
+	const struct display_path *path);
+
+void dal_display_path_set_display_index(
+	struct display_path *path,
+	uint32_t index);
+
+struct connector_device_tag_info *dal_display_path_get_device_tag(
+	struct display_path *path);
+
+void dal_display_path_set_device_tag(
+	struct display_path *path,
+	struct connector_device_tag_info tag);
+
+enum clock_sharing_group dal_display_path_get_clock_sharing_group(
+	const struct display_path *path);
+
+void dal_display_path_set_clock_sharing_group(
+	struct display_path *path,
+	enum clock_sharing_group clock);
+
+union display_path_properties dal_display_path_get_properties(
+	const struct display_path *path);
+
+void dal_display_path_set_properties(
+	struct display_path *path,
+	union display_path_properties p);
+
+struct dcs *dal_display_path_get_dcs(
+	const struct display_path *path);
+
+void dal_display_path_set_dcs(
+	struct display_path *path,
+	struct dcs *dcs);
+
+uint32_t dal_display_path_get_number_of_links(
+	const struct display_path *path);
+
+void dal_display_path_set_controller(
+	struct display_path *path,
+	struct controller *controller);
+
+struct controller *dal_display_path_get_controller(
+	const struct display_path *path);
+
+void dal_display_path_set_clock_source(
+	struct display_path *path,
+	struct clock_source *clock);
+
+struct clock_source *dal_display_path_get_clock_source(
+	const struct display_path *path);
+
+void dal_display_path_set_alt_clock_source(
+	struct display_path *path,
+	struct clock_source *clock);
+
+struct clock_source *dal_display_path_get_alt_clock_source(
+	const struct display_path *path);
+
+void dal_display_path_set_fbc_info(
+	struct display_path *path,
+	struct fbc_info *clock);
+
+struct fbc_info *dal_display_path_get_fbc_info(
+	struct display_path *path);
+
+void dal_display_path_set_drr_config(
+	struct display_path *path,
+	struct drr_config *clock);
+
+void dal_display_path_get_drr_config(
+	const struct display_path *path,
+	struct drr_config *clock);
+
+void dal_display_path_set_static_screen_triggers(
+	struct display_path *path,
+	const struct static_screen_events *events);
+
+void dal_display_path_get_static_screen_triggers(
+	const struct display_path *path,
+	struct static_screen_events *events);
+
+bool dal_display_path_is_psr_supported(
+	const struct display_path *path);
+
+bool dal_display_path_is_drr_supported(
+	const struct display_path *path);
+
+void dal_display_path_set_link_service_data(
+	struct display_path *path,
+	uint32_t idx,
+	const struct goc_link_service_data *data);
+
+bool dal_display_path_get_link_service_data(
+	const struct display_path *path,
+	uint32_t idx,
+	struct goc_link_service_data *data);
+
+struct link_service *dal_display_path_get_link_query_interface(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_link_query_interface(
+	struct display_path *path,
+	uint32_t idx,
+	struct link_service *link);
+
+struct link_service *dal_display_path_get_link_config_interface(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct link_service *dal_display_path_get_link_service_interface(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_upstream_encoder(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_upstream_object(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_downstream_encoder(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct encoder *dal_display_path_get_downstream_object(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct audio *dal_display_path_get_audio(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_audio(
+	struct display_path *path,
+	uint32_t idx,
+	struct audio *a);
+
+struct audio *dal_display_path_get_audio_object(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_audio_active_state(
+	struct display_path *path,
+	uint32_t idx,
+	bool state);
+
+enum engine_id dal_display_path_get_stream_engine(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_stream_engine(
+	struct display_path *path,
+	uint32_t idx,
+	enum engine_id id);
+
+bool dal_display_path_is_link_active(
+	const struct display_path *path,
+	uint32_t idx);
+
+void dal_display_path_set_link_active_state(
+	struct display_path *path,
+	uint32_t idx,
+	bool state);
+
+enum signal_type dal_display_path_get_config_signal(
+	const struct display_path *path,
+	uint32_t idx);
+
+enum signal_type dal_display_path_get_query_signal(
+	const struct display_path *path,
+	uint32_t idx);
+
+struct link_service *dal_display_path_get_mst_link_service(
+	const struct display_path *path);
+
+void dal_display_path_set_sync_output_object(
+	struct display_path *path,
+	enum sync_source o_source,
+	struct encoder *o_object);
+
+struct encoder *dal_display_path_get_sync_output_object(
+	const struct display_path *path);
+
+void dal_display_path_set_stereo_sync_object(
+	struct display_path *path,
+	struct encoder *stereo_sync);
+
+struct encoder *dal_display_path_get_stereo_sync_object(
+	const struct display_path *path);
+
+void dal_display_path_set_sync_input_source(
+	struct display_path *path,
+	enum sync_source s);
+
+enum sync_source dal_display_path_get_sync_input_source(
+	const struct display_path *path);
+
+void dal_display_path_set_sync_output_source(
+	struct display_path *path,
+	enum sync_source s);
+
+enum sync_source dal_display_path_get_sync_output_source(
+	const struct display_path *path);
+
+bool dal_display_path_set_pixel_clock_safe_range(
+	struct display_path *path,
+	struct pixel_clock_safe_range *range);
+
+bool dal_display_path_get_pixel_clock_safe_range(
+	const struct display_path *path,
+	struct pixel_clock_safe_range *range);
+
+void dal_display_path_set_ddi_channel_mapping(
+	struct display_path *path,
+	union ddi_channel_mapping mapping);
+
+bool dal_display_path_set_sink_signal(
+	struct display_path *path,
+	enum signal_type sink_signal);
+
+enum signal_type dal_display_path_sink_signal_to_asic_signal(
+	struct display_path *path,
+	enum signal_type sink_signal);
+
+enum signal_type dal_display_path_sink_signal_to_link_signal(
+	struct display_path *path,
+	enum signal_type sink_signal,
+	uint32_t idx);
+
+enum signal_type dal_display_path_downstream_to_upstream_signal(
+	struct display_path *path,
+	enum signal_type signal,
+	uint32_t idx);
+
+bool dal_display_path_is_audio_present(
+	const struct display_path *path,
+	uint32_t *audio_pin);
+
+bool dal_display_path_is_dp_auth_supported(
+	struct display_path *path);
+
+bool dal_display_path_is_vce_supported(
+	const struct display_path *path);
+
+bool dal_display_path_is_sls_capable(
+	const struct display_path *path);
+
+bool dal_display_path_is_gen_lock_capable(
+	const struct display_path *path);
+
+struct transmitter_configuration dal_display_path_get_transmitter_configuration(
+	const struct display_path *path,
+	bool physical);
+
+bool dal_display_path_is_ss_supported(
+	const struct display_path *path);
+
+bool dal_display_path_is_ss_configurable(
+	const struct display_path *path);
+
+void dal_display_path_set_ss_support(
+	struct display_path *path,
+	bool s);
+
+enum signal_type dal_display_path_get_active_signal(
+	struct display_path *path,
+	uint32_t idx);
+
+bool dal_display_path_contains_object(
+	struct display_path *path,
+	struct graphics_object_id id);
+
+/* Multi-plane declarations.
+ * This structure should also be used for Stereo. */
+struct display_path_plane {
+	struct controller *controller;
+	/* During dal_tm_acquire_plane_resources() set blnd_mode, because
+	 * "layer index" is known at that point, and we must decide how
+	 * "controller" should do the blending */
+	enum blender_mode blnd_mode;
+	/* Some use-cases allow to power-gate FE.
+	 * For example, with Full Screen Video on Underlay we can
+	 * disable the 'root' plane.
+	 * This flag indicates that FE should be power-gated */
+	bool disabled;
+};
+
+bool dal_display_path_add_plane(
+	struct display_path *path,
+	struct display_path_plane *plane);
+
+uint8_t dal_display_path_get_number_of_planes(
+	const struct display_path *path);
+
+struct display_path_plane *dal_display_path_get_plane_at_index(
+	const struct display_path *path,
+	uint8_t index);
+
+struct controller *dal_display_path_get_controller_for_layer_index(
+	const struct display_path *path,
+	uint8_t layer_index);
+
+void dal_display_path_release_planes(
+	struct display_path *path);
+
+void dal_display_path_release_non_root_planes(
+	struct display_path *path);
+
+#endif /* __DISPLAY_PATH_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dmcu_interface.h b/drivers/gpu/drm/amd/dal/include/dmcu_interface.h
new file mode 100644
index 000000000000..c712cc25e731
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dmcu_interface.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DMCU_INTERFACE_H__
+#define __DAL_DMCU_INTERFACE_H__
+
+#include "grph_object_defs.h"
+#include "dmcu_types.h"
+
+/* Interface functions */
+
+/* DMCU setup related interface functions */
+struct dmcu *dal_dmcu_create(
+	struct dmcu_init_data *init_data);
+void dal_dmcu_destroy(struct dmcu **dmcu);
+void dal_dmcu_release_hw(struct dmcu *dmcu);
+
+void dal_dmcu_power_up(struct dmcu *dmcu);
+void dal_dmcu_power_down(struct dmcu *dmcu);
+
+void dal_dmcu_configure_wait_loop(
+		struct dmcu *dmcu,
+		uint32_t display_clock);
+
+/* PSR feature related interface functions */
+void dal_dmcu_psr_setup(
+		struct dmcu *dmcu,
+		struct dmcu_context *dmcu_context);
+void dal_dmcu_psr_enable(struct dmcu *dmcu);
+void dal_dmcu_psr_disable(struct dmcu *dmcu);
+void dal_dmcu_psr_block(struct dmcu *dmcu, bool block_psr);
+bool dal_dmcu_psr_is_blocked(struct dmcu *dmcu);
+void dal_dmcu_psr_set_level(
+		struct dmcu *dmcu,
+		union dmcu_psr_level psr_level);
+void dal_dmcu_psr_allow_power_down_crtc(
+		struct dmcu *dmcu,
+		bool should_allow_crtc_power_down);
+bool dal_dmcu_psr_submit_command(
+		struct dmcu *dmcu,
+		struct dmcu_context *dmcu_context,
+		struct dmcu_config_data *config_data);
+void dal_dmcu_psr_get_config_data(
+		struct dmcu *dmcu,
+		uint32_t v_total,
+		struct dmcu_config_data *config_data);
+
+/* ABM feature related interface functions */
+void dal_dmcu_abm_enable(
+		struct dmcu *dmcu,
+		enum controller_id controller_id,
+		uint32_t vsync_rate_hz);
+void dal_dmcu_abm_disable(struct dmcu *dmcu);
+bool dal_dmcu_abm_enable_smooth_brightness(struct dmcu *dmcu);
+bool dal_dmcu_abm_disable_smooth_brightness(struct dmcu *dmcu);
+void dal_dmcu_abm_varibright_control(
+		struct dmcu *dmcu,
+		const struct varibright_control *varibright_control);
+bool dal_dmcu_abm_set_backlight_level(
+		struct dmcu *dmcu,
+		uint8_t backlight_8_bit);
+uint8_t dal_dmcu_abm_get_user_backlight_level(struct dmcu *dmcu);
+uint8_t dal_dmcu_abm_get_current_backlight_level(struct dmcu *dmcu);
+
+#endif /* __DAL_DMCU_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dmcu_types.h b/drivers/gpu/drm/amd/dal/include/dmcu_types.h
new file mode 100644
index 000000000000..1f3107d5b9b8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dmcu_types.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DMCU_TYPES_H__
+#define __DAL_DMCU_TYPES_H__
+
+/* Forward declaration */
+struct dmcu;
+
+/* Required information for creation and initialization of a controller */
+struct dmcu_init_data {
+	struct dal_context *dal_context;
+	struct adapter_service *as;
+	uint32_t max_engine_clock_in_khz;
+};
+
+/* Interface structure defines */
+
+enum dmcu_action {
+	DMCU_ACTION_PSR_ENABLE,
+	DMCU_ACTION_PSR_EXIT,
+	DMCU_ACTION_PSR_RFB_UPDATE,
+	DMCU_ACTION_PSR_SET,
+	DMCU_ACTION_PSR_CLEAR_COUNT,
+	DMCU_ACTION_PSR_COUNT_REQUEST,
+	DMCU_ACTION_PSR_STATE_REQUEST,
+	DMCU_ACTION_PSR_SET_LEVEL,
+	DMCU_ACTION_PSR_ADVANCE_STATE,
+	DMCU_ACTION_PSR_SET_WAITLOOP
+};
+
+enum dmcu_output {
+	DMCU_OUTPUT_PSR_ACK,
+	DMCU_OUTPUT_PSR_NACK,
+	DMCU_OUTPUT_PSR_AUX_ERR,
+	DMCU_OUTPUT_PSR_COUNT_STATUS,
+	DMCU_OUTPUT_PSR_STATE_STATUS,
+	DMCU_OUTPUT_PSR_RFB_UPDATE_ERR,
+	DMCU_OUTPUT_PSR_ERR,
+	DMCU_OUTPUT_PSR_GET_REPLY,
+	DMCU_OUTPUT_PSR_ENTRY_ERROR,
+	DMCU_OUTPUT_PSR_LT_ERROR,
+	DMCU_OUTPUT_PSR_FORCE_SR_ERROR,
+	DMCU_OUTPUT_PSR_SDP_SEND_TIMEOUT
+};
+
+/* PSR states, based similarly on states defined in eDP specification. */
+enum psr_state {
+	STATE0,		/* PSR is disabled */
+	STATE1,		/* PSR is enabled, but inactive */
+	STATE1A,
+	STATE2,		/* PSR is transitioning to active state */
+	STATE2A,
+	STATE3,		/* PSR is active; Display is in self refresh */
+	STATE3INIT,
+	STATE4,		/* RFB single frame update */
+	STATE4A,
+	STATE4B,
+	STATE4C,
+	STATE4D,
+	STATE5,		/* Exiting from PSR active state */
+	STATE5A,
+	STATE5B,
+	STATE5C
+};
+
+enum phy_type {
+	PHY_TYPE_UNKNOWN = 1,
+	PHY_TYPE_PCIE_PHY = 2,
+	PHY_TYPE_UNIPHY = 3,
+};
+
+struct dmcu_context {
+	enum channel_id channel;
+	enum transmitter transmitter_id;
+	enum engine_id engine_id;
+	enum controller_id controller_id;
+	enum phy_type phy_type;
+	enum physical_phy_id smu_physical_phy_id;
+
+	/* Vertical total pixels from crtc timing.
+	 * This is used for static screen detection.
+	 * ie. If we want to detect half a frame,
+	 * we use this to determine the hyst lines.*/
+	uint32_t crtc_timing_vertical_total;
+
+	/* PSR supported from panel capabilities
+	 * and current display configuration */
+	bool psr_supported_display_config;
+
+	/* Whether fast link training is supported by the panel */
+	bool psr_exit_link_training_required;
+
+	/* If RFB setup time is greater than the total VBLANK time, it is not
+	 * possible for the sink to capture the video frame in the same frame
+	 * the SDP is sent. In this case, the frame capture indication bit
+	 * should be set and an extra static frame should be transmitted to
+	 * the sink */
+	bool psr_frame_capture_indication_required;
+
+	/* Set the last possible line SDP may be transmitted without violating
+	 * the RFB setup time */
+	bool sdp_transmit_line_num_deadline;
+
+	/* The VSync rate in Hz used to calculate the step size
+	 * for smooth brightness feature */
+	uint32_t vsync_rate_hz;
+};
+
+union dmcu_psr_level {
+	struct {
+		bool SKIP_CRC:1;
+		bool SKIP_DP_VID_STREAM_DISABLE:1;
+		bool SKIP_PHY_POWER_DOWN:1;
+		bool SKIP_AUX_ACK_CHECK:1;
+		bool SKIP_CRTC_DISABLE:1;
+		bool SKIP_AUX_RFB_CAPTURE_CHECK:1;
+		bool SKIP_SMU_NOTIFICATION:1;
+		bool SKIP_AUTO_STATE_ADVANCE:1;
+		bool DISABLE_PSR_ENTRY_ABORT:1;
+	} bits;
+	uint32_t u32all;
+};
+
+struct dmcu_config_data {
+	/* Command sent to DMCU. */
+	enum dmcu_action action;
+	/* PSR Level controls which HW blocks to power down during PSR active,
+	 * and also other sequence modifications. */
+	union dmcu_psr_level psr_level;
+	/* To indicate that first changed frame from active state should not
+	 * result in exit to inactive state, but instead perform an automatic
+	 * single frame RFB update. */
+	bool rfb_update_auto_en;
+	/* Number of consecutive static frames to detect before entering PSR
+	 * active state. */
+	uint32_t hyst_frames;
+	/* Partial frames before entering PSR active. Note this parameter is in
+	 * units of 100 lines. i.e. Wait a value of 5 means wait 500 additional
+	 * lines. */
+	uint32_t hyst_lines;
+	/* Number of repeated AUX retries before indicating failure to driver.
+	 * In a working case, first attempt to write/read AUX should pass. */
+	uint32_t aux_repeat;
+	/* Additional delay after remote frame capture before continuing to
+	 * power down. This is mainly for debug purposes to identify timing
+	 * issues. */
+	uint32_t frame_delay;
+	/* Controls how long the delay of a wait loop is. It should be tuned
+	 * to 1 us, and needs to be reconfigured every time DISPCLK changes. */
+	uint32_t wait_loop_num;
+};
+
+struct dmcu_output_data {
+	/* DMCU reply */
+	enum dmcu_output output;
+	/* The current PSR state. */
+	uint32_t psr_state;
+	/* The number of frames during PSR active state. */
+	uint32_t psr_count;
+};
+
+enum varibright_command {
+	VARIBRIGHT_CMD_SET_VB_LEVEL = 0,
+	VARIBRIGHT_CMD_USER_ENABLE,
+	VARIBRIGHT_CMD_POST_DISPLAY_CONFIG,
+	VARIBRIGHT_CMD_UNKNOWN
+};
+
+struct varibright_control {
+	enum varibright_command command;
+	uint8_t level;
+	bool enable;
+	bool activate;
+};
+
+#endif /* __DAL_DMCU_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/dpcd_defs.h b/drivers/gpu/drm/amd/dal/include/dpcd_defs.h
new file mode 100644
index 000000000000..bd410ccdc3a5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/dpcd_defs.h
@@ -0,0 +1,873 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DPCD_DEFS_H__
+#define __DAL_DPCD_DEFS_H__
+
+enum dpcd_address {
+/* addresses marked with 1.2 are only defined since DP 1.2 spec */
+
+	/* Reciever Capability Field */
+	DPCD_ADDRESS_DPCD_REV = 0x00000,
+	DPCD_ADDRESS_MAX_LINK_RATE = 0x00001,
+	DPCD_ADDRESS_MAX_LANE_COUNT = 0x00002,
+	DPCD_ADDRESS_MAX_DOWNSPREAD = 0x00003,
+	DPCD_ADDRESS_NORP = 0x00004,
+	DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT = 0x00005,
+	DPCD_ADDRESS_MAIN_LINK_CHANNEL_CODING = 0x00006,
+	DPCD_ADDRESS_DOWNSTREAM_PORT_COUNT = 0x00007,
+	DPCD_ADDRESS_RECEIVE_PORT0_CAP0 = 0x00008,
+	DPCD_ADDRESS_RECEIVE_PORT0_CAP1 = 0x00009,
+	DPCD_ADDRESS_RECEIVE_PORT1_CAP0 = 0x0000A,
+	DPCD_ADDRESS_RECEIVE_PORT1_CAP1 = 0x0000B,
+
+	DPCD_ADDRESS_I2C_SPEED_CNTL_CAP = 0x0000C,/*1.2*/
+	DPCD_ADDRESS_EDP_CONFIG_CAP = 0x0000D,/*1.2*/
+	DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL = 0x000E,/*1.2*/
+
+	DPCD_ADDRESS_MSTM_CAP = 0x00021,/*1.2*/
+
+	/* Audio Video Sync Data Feild */
+	DPCD_ADDRESS_AV_GRANULARITY = 0x0023,
+	DPCD_ADDRESS_AUDIO_DECODE_LATENCY1 = 0x0024,
+	DPCD_ADDRESS_AUDIO_DECODE_LATENCY2 = 0x0025,
+	DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY1 = 0x0026,
+	DPCD_ADDRESS_AUDIO_POSTPROCESSING_LATENCY2 = 0x0027,
+	DPCD_ADDRESS_VIDEO_INTERLACED_LATENCY = 0x0028,
+	DPCD_ADDRESS_VIDEO_PROGRESSIVE_LATENCY = 0x0029,
+	DPCD_ADDRESS_AUDIO_DELAY_INSERT1 = 0x0002B,
+	DPCD_ADDRESS_AUDIO_DELAY_INSERT2 = 0x0002C,
+	DPCD_ADDRESS_AUDIO_DELAY_INSERT3 = 0x0002D,
+
+	/* Audio capability */
+	DPCD_ADDRESS_NUM_OF_AUDIO_ENDPOINTS = 0x00022,
+
+	DPCD_ADDRESS_GUID_START = 0x00030,/*1.2*/
+	DPCD_ADDRESS_GUID_END = 0x0003f,/*1.2*/
+
+	DPCD_ADDRESS_PSR_SUPPORT_VER = 0x00070,
+	DPCD_ADDRESS_PSR_CAPABILITY = 0x00071,
+
+	DPCD_ADDRESS_DWN_STRM_PORT0_CAPS = 0x00080,/*1.2a*/
+
+	/* Link Configuration Field */
+	DPCD_ADDRESS_LINK_BW_SET = 0x00100,
+	DPCD_ADDRESS_LANE_COUNT_SET = 0x00101,
+	DPCD_ADDRESS_TRAINING_PATTERN_SET = 0x00102,
+	DPCD_ADDRESS_LANE0_SET = 0x00103,
+	DPCD_ADDRESS_LANE1_SET = 0x00104,
+	DPCD_ADDRESS_LANE2_SET = 0x00105,
+	DPCD_ADDRESS_LANE3_SET = 0x00106,
+	DPCD_ADDRESS_DOWNSPREAD_CNTL = 0x00107,
+	DPCD_ADDRESS_I2C_SPEED_CNTL = 0x00109,/*1.2*/
+
+	DPCD_ADDRESS_EDP_CONFIG_SET = 0x0010A,
+	DPCD_ADDRESS_LINK_QUAL_LANE0_SET = 0x0010B,
+	DPCD_ADDRESS_LINK_QUAL_LANE1_SET = 0x0010C,
+	DPCD_ADDRESS_LINK_QUAL_LANE2_SET = 0x0010D,
+	DPCD_ADDRESS_LINK_QUAL_LANE3_SET = 0x0010E,
+
+	DPCD_ADDRESS_LANE0_SET2 = 0x0010F,/*1.2*/
+	DPCD_ADDRESS_LANE2_SET2 = 0x00110,/*1.2*/
+
+	DPCD_ADDRESS_MSTM_CNTL = 0x00111,/*1.2*/
+
+	DPCD_ADDRESS_PSR_ENABLE_CFG = 0x0170,
+
+	/* Payload Table Configuration Field 1.2 */
+	DPCD_ADDRESS_PAYLOAD_ALLOCATE_SET = 0x001C0,
+	DPCD_ADDRESS_PAYLOAD_ALLOCATE_START_TIMESLOT = 0x001C1,
+	DPCD_ADDRESS_PAYLOAD_ALLOCATE_TIMESLOT_COUNT = 0x001C2,
+
+	DPCD_ADDRESS_SINK_COUNT = 0x0200,
+	DPCD_ADDRESS_DEVICE_SERVICE_IRQ_VECTOR = 0x0201,
+
+	/* Link / Sink Status Field */
+	DPCD_ADDRESS_LANE_01_STATUS = 0x00202,
+	DPCD_ADDRESS_LANE_23_STATUS = 0x00203,
+	DPCD_ADDRESS_LANE_ALIGN_STATUS_UPDATED = 0x0204,
+	DPCD_ADDRESS_SINK_STATUS = 0x0205,
+
+	/* Adjust Request Field */
+	DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1 = 0x0206,
+	DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3 = 0x0207,
+	DPCD_ADDRESS_ADJUST_REQUEST_POST_CURSOR2 = 0x020C,
+
+	/* Test Request Field */
+	DPCD_ADDRESS_TEST_REQUEST = 0x0218,
+	DPCD_ADDRESS_TEST_LINK_RATE = 0x0219,
+	DPCD_ADDRESS_TEST_LANE_COUNT = 0x0220,
+	DPCD_ADDRESS_TEST_PATTERN = 0x0221,
+	DPCD_ADDRESS_TEST_MISC1 = 0x0232,
+
+	/* Phy Test Pattern Field */
+	DPCD_ADDRESS_TEST_PHY_PATTERN = 0x0248,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_7_0 = 0x0250,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_15_8 = 0x0251,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_23_16 = 0x0252,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_31_24 = 0x0253,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_39_32 = 0x0254,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_47_40 = 0x0255,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_55_48 = 0x0256,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_63_56 = 0x0257,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_71_64 = 0x0258,
+	DPCD_ADDRESS_TEST_80BIT_CUSTOM_PATTERN_79_72 = 0x0259,
+
+	/* Test Response Field*/
+	DPCD_ADDRESS_TEST_RESPONSE = 0x0260,
+
+	/* Audio Test Pattern Field 1.2*/
+	DPCD_ADDRESS_TEST_AUDIO_MODE = 0x0271,
+	DPCD_ADDRESS_TEST_AUDIO_PATTERN_TYPE = 0x0272,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_1 = 0x0273,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_2 = 0x0274,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_3 = 0x0275,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_4 = 0x0276,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_5 = 0x0277,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_6 = 0x0278,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_7 = 0x0279,
+	DPCD_ADDRESS_TEST_AUDIO_PERIOD_CH_8 = 0x027A,
+
+	/* Payload Table Status Field */
+	DPCD_ADDRESS_PAYLOAD_TABLE_UPDATE_STATUS = 0x002C0,/*1.2*/
+	DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT1 = 0x002C1,/*1.2*/
+	DPCD_ADDRESS_VC_PAYLOAD_ID_SLOT63 = 0x002FF,/*1.2*/
+
+	/* Source Device Specific Field */
+	DPCD_ADDRESS_SOURCE_DEVICE_ID_START = 0x0300,
+	DPCD_ADDRESS_SOURCE_DEVICE_ID_END = 0x0301,
+	DPCD_ADDRESS_AMD_INTERNAL_DEBUG_START       = 0x030C,
+	DPCD_ADDRESS_AMD_INTERNAL_DEBUG_END         = 0x030F,
+	DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_START    = 0x0310,
+	DPCD_ADDRESS_SOURCE_SPECIFIC_TABLE_END      = 0x037F,
+	DPCD_ADDRESS_SOURCE_RESERVED_START         = 0x0380,
+	DPCD_ADDRESS_SOURCE_RESERVED_END           = 0x03FF,
+
+	/* Sink Device Specific Field */
+	DPCD_ADDRESS_SINK_DEVICE_ID_START = 0x0400,
+	DPCD_ADDRESS_SINK_DEVICE_ID_END = 0x0402,
+	DPCD_ADDRESS_SINK_DEVICE_STR_START = 0x0403,
+	DPCD_ADDRESS_SINK_DEVICE_STR_END = 0x0408,
+	DPCD_ADDRESS_SINK_REVISION_START = 0x409,
+	DPCD_ADDRESS_SINK_REVISION_END = 0x40B,
+
+	/* Branch Device Specific Field */
+	DPCD_ADDRESS_BRANCH_DEVICE_ID_START = 0x0500,
+	DPCD_ADDRESS_BRANCH_DEVICE_ID_END = 0x0502,
+	DPCD_ADDRESS_BRANCH_DEVICE_STR_START = 0x0503,
+	DPCD_ADDRESS_BRANCH_DEVICE_STR_END = 0x0508,
+
+	DPCD_ADDRESS_POWER_STATE = 0x0600,
+
+	/* EDP related */
+	DPCD_ADDRESS_EDP_REV = 0x0700,
+	DPCD_ADDRESS_EDP_CAPABILITY = 0x0701,
+	DPCD_ADDRESS_EDP_BACKLIGHT_ADJUST_CAP = 0x0702,
+	DPCD_ADDRESS_EDP_GENERAL_CAP2 = 0x0703,
+
+	DPCD_ADDRESS_EDP_DISPLAY_CONTROL = 0x0720,
+	DPCD_ADDRESS_EDP_BACKLIGHT_SET = 0x0721,
+	DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_MSB = 0x0722,
+	DPCD_ADDRESS_EDP_BACKLIGHT_BRIGHTNESS_LSB = 0x0723,
+	DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT = 0x0724,
+	DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MIN = 0x0725,
+	DPCD_ADDRESS_EDP_PWMGEN_BIT_COUNT_CAP_MAX = 0x0726,
+	DPCD_ADDRESS_EDP_BACKLIGHT_CONTROL_STATUS = 0x0727,
+	DPCD_ADDRESS_EDP_BACKLIGHT_FREQ_SET = 0x0728,
+	DPCD_ADDRESS_EDP_REVERVED = 0x0729,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MSB = 0x072A,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_MID = 0x072B,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MIN_LSB = 0x072C,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MSB = 0x072D,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_MID = 0x072E,
+	DPCD_ADDRESS_EDP_BACKLIGNT_FREQ_CAP_MAX_LSB = 0x072F,
+
+	DPCD_ADDRESS_EDP_DBC_MINIMUM_BRIGHTNESS_SET = 0x0732,
+	DPCD_ADDRESS_EDP_DBC_MAXIMUM_BRIGHTNESS_SET = 0x0733,
+
+	/* Sideband MSG Buffers 1.2 */
+	DPCD_ADDRESS_DOWN_REQ_START = 0x01000,
+	DPCD_ADDRESS_DOWN_REQ_END = 0x011ff,
+
+	DPCD_ADDRESS_UP_REP_START = 0x01200,
+	DPCD_ADDRESS_UP_REP_END = 0x013ff,
+
+	DPCD_ADDRESS_DOWN_REP_START = 0x01400,
+	DPCD_ADDRESS_DOWN_REP_END = 0x015ff,
+
+	DPCD_ADDRESS_UP_REQ_START = 0x01600,
+	DPCD_ADDRESS_UP_REQ_END = 0x017ff,
+
+	/* ESI (Event Status Indicator) Field 1.2 */
+	DPCD_ADDRESS_SINK_COUNT_ESI = 0x02002,
+	DPCD_ADDRESS_DEVICE_IRQ_ESI0 = 0x02003,
+	DPCD_ADDRESS_DEVICE_IRQ_ESI1 = 0x02004,
+	/*@todo move dpcd_address_Lane01Status back here*/
+
+	DPCD_ADDRESS_PSR_ERROR_STATUS = 0x2006,
+	DPCD_ADDRESS_PSR_EVENT_STATUS = 0x2007,
+	DPCD_ADDRESS_PSR_SINK_STATUS = 0x2008,
+	DPCD_ADDRESS_PSR_DBG_REGISTER0 = 0x2009,
+	DPCD_ADDRESS_PSR_DBG_REGISTER1 = 0x200A,
+
+	/* Travis specific addresses */
+	DPCD_ADDRESS_TRAVIS_SINK_DEV_SEL = 0x5f0,
+	DPCD_ADDRESS_TRAVIS_SINK_ACCESS_OFFSET	= 0x5f1,
+	DPCD_ADDRESS_TRAVIS_SINK_ACCESS_REG = 0x5f2,
+};
+
+enum dpcd_revision {
+	DPCD_REV_10 = 0x10,
+	DPCD_REV_11 = 0x11,
+	DPCD_REV_12 = 0x12
+};
+
+enum dp_pwr_state {
+	DP_PWR_STATE_D0 = 1,/* direct HW translation! */
+	DP_PWR_STATE_D3
+};
+
+/* these are the types stored at DOWNSTREAMPORT_PRESENT */
+enum dpcd_downstream_port_type {
+	DOWNSTREAM_DP = 0,
+	DOWNSTREAM_VGA,
+	DOWNSTREAM_DVI_HDMI,
+	DOWNSTREAM_NONDDC /* has no EDID (TV,CV) */
+};
+
+enum dpcd_link_test_patterns {
+	LINK_TEST_PATTERN_NONE = 0,
+	LINK_TEST_PATTERN_COLOR_RAMP,
+	LINK_TEST_PATTERN_VERTICAL_BARS,
+	LINK_TEST_PATTERN_COLOR_SQUARES
+};
+
+enum dpcd_test_color_format {
+	TEST_COLOR_FORMAT_RGB = 0,
+	TEST_COLOR_FORMAT_YCBCR422,
+	TEST_COLOR_FORMAT_YCBCR444
+};
+
+enum dpcd_test_bit_depth {
+	TEST_BIT_DEPTH_6 = 0,
+	TEST_BIT_DEPTH_8,
+	TEST_BIT_DEPTH_10,
+	TEST_BIT_DEPTH_12,
+	TEST_BIT_DEPTH_16
+};
+
+/* PHY (encoder) test patterns
+The order of test patterns follows DPCD register PHY_TEST_PATTERN (0x248) */
+enum dpcd_phy_test_patterns {
+	PHY_TEST_PATTERN_NONE = 0,
+	PHY_TEST_PATTERN_D10_2,
+	PHY_TEST_PATTERN_SYMBOL_ERROR,
+	PHY_TEST_PATTERN_PRBS7,
+	PHY_TEST_PATTERN_80BIT_CUSTOM,/* For DP1.2 only */
+	PHY_TEST_PATTERN_HBR2_COMPLIANCE_EYE/* For DP1.2 only */
+};
+
+enum dpcd_test_dyn_range {
+	TEST_DYN_RANGE_VESA = 0,
+	TEST_DYN_RANGE_CEA
+};
+
+enum dpcd_audio_test_pattern {
+	AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0,/* direct HW translation */
+	AUDIO_TEST_PATTERN_SAWTOOTH
+};
+
+enum dpcd_audio_sampling_rate {
+	AUDIO_SAMPLING_RATE_32KHZ = 0,/* direct HW translation */
+	AUDIO_SAMPLING_RATE_44_1KHZ,
+	AUDIO_SAMPLING_RATE_48KHZ,
+	AUDIO_SAMPLING_RATE_88_2KHZ,
+	AUDIO_SAMPLING_RATE_96KHZ,
+	AUDIO_SAMPLING_RATE_176_4KHZ,
+	AUDIO_SAMPLING_RATE_192KHZ
+};
+
+enum dpcd_audio_channels {
+	AUDIO_CHANNELS_1 = 0,/* direct HW translation */
+	AUDIO_CHANNELS_2,
+	AUDIO_CHANNELS_3,
+	AUDIO_CHANNELS_4,
+	AUDIO_CHANNELS_5,
+	AUDIO_CHANNELS_6,
+	AUDIO_CHANNELS_7,
+	AUDIO_CHANNELS_8,
+
+	AUDIO_CHANNELS_COUNT
+};
+
+enum dpcd_audio_test_pattern_periods {
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_NOTUSED = 0,/* direct HW translation */
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_3,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_6,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_12,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_24,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_48,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_96,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_192,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_384,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_768,
+	DPCD_AUDIO_TEST_PATTERN_PERIOD_1536
+};
+
+/* This enum is for programming DPCD TRAINING_PATTERN_SET */
+enum dpcd_training_patterns {
+	DPCD_TRAINING_PATTERN_VIDEOIDLE = 0,/* direct HW translation! */
+	DPCD_TRAINING_PATTERN_1,
+	DPCD_TRAINING_PATTERN_2,
+	DPCD_TRAINING_PATTERN_3
+};
+
+/* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus
+It defines the possible PSR states. */
+enum dpcd_psr_sink_states {
+	PSR_SINK_STATE_INACTIVE = 0,
+	PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SOURCE_TIMING = 1,
+	PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB = 2,
+	PSR_SINK_STATE_ACTIVE_CAPTURE_DISPLAY_ON_SINK_TIMING = 3,
+	PSR_SINK_STATE_ACTIVE_CAPTURE_TIMING_RESYNC = 4,
+	PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7,
+};
+
+/* This enum defines the Panel's eDP revision at DPCD 700h
+ * 00h = eDP v1.1 or lower
+ * 01h = eDP v1.2
+ * 02h = eDP v1.3 (PSR support starts here)
+ * 03h = eDP v1.4
+ * If unknown revision, treat as eDP v1.1, meaning least functionality set.
+ * This enum has values matched to eDP spec, thus values should not change.
+ */
+enum dpcd_edp_revision {
+	DPCD_EDP_REVISION_EDP_V1_1 = 0,
+	DPCD_EDP_REVISION_EDP_V1_2 = 1,
+	DPCD_EDP_REVISION_EDP_V1_3 = 2,
+	DPCD_EDP_REVISION_EDP_V1_4 = 3,
+	DPCD_EDP_REVISION_EDP_UNKNOWN = DPCD_EDP_REVISION_EDP_V1_1,
+};
+
+union dpcd_rev {
+	struct {
+		uint8_t MINOR:4;
+		uint8_t MAJOR:4;
+	} bits;
+	uint8_t raw;
+};
+
+union max_lane_count {
+	struct {
+		uint8_t MAX_LANE_COUNT:5;
+		uint8_t POST_LT_ADJ_REQ_SUPPORTED:1;
+		uint8_t TPS3_SUPPORTED:1;
+		uint8_t ENHANCED_FRAME_CAP:1;
+	} bits;
+	uint8_t raw;
+};
+
+union max_down_spread {
+	struct {
+		uint8_t MAX_DOWN_SPREAD:1;
+		uint8_t RESERVED:5;
+		uint8_t NO_AUX_HANDSHAKE_LINK_TRAINING:1;
+		uint8_t RESERVED1:1;
+	} bits;
+	uint8_t raw;
+};
+
+union mstm_cap {
+	struct {
+		uint8_t MST_CAP:1;
+		uint8_t RESERVED:7;
+	} bits;
+	uint8_t raw;
+};
+
+union mstm_cntl {
+	struct {
+		uint8_t MST_EN:1;
+		uint8_t UP_REQ_EN:1;
+		uint8_t UPSTREAM_IS_SRC:1;
+		uint8_t RESERVED:5;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_count_set {
+	struct {
+		uint8_t LANE_COUNT_SET:5;
+		uint8_t POST_LT_ADJ_REQ_GRANTED:1;
+		uint8_t RESERVED:1;
+		uint8_t ENHANCED_FRAMING:1;
+	} bits;
+	uint8_t raw;
+};
+
+/* for DPCD_ADDRESS_I2C_SPEED_CNTL_CAP
+ * and DPCD_ADDRESS_I2C_SPEED_CNTL
+ */
+union i2c_speed {
+	struct {
+		uint8_t _1KBPS:1;
+		uint8_t _5KBPS:1;
+		uint8_t _10KBPS:1;
+		uint8_t _100KBPS:1;
+		uint8_t _400KBPS:1;
+		uint8_t _1MBPS:1;
+		uint8_t reserved:2;
+	} bits;
+	uint8_t raw;
+};
+
+union payload_table_update_status {
+	struct {
+		uint8_t VC_PAYLOAD_TABLE_UPDATED:1;
+		uint8_t ACT_HANDLED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union device_irq_esi_0 {
+	struct {
+		uint8_t REMOTE_CONTROL_CMD_PENDING:1;
+		uint8_t AUTOMATED_TEST_REQUEST:1;
+		uint8_t CP_IRQ:1;
+		uint8_t MCCS_IRQ:1;
+		uint8_t DOWN_REP_MSG_RDY:1;
+		uint8_t UP_REQ_MSG_RDY:1;
+		uint8_t SINK_SPECIFIC_IRQ:1;
+		uint8_t RESERVED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_status {
+	struct {
+		uint8_t CR_DONE_0:1;
+		uint8_t CHANNEL_EQ_DONE_0:1;
+		uint8_t SYMBOL_LOCKED_0:1;
+		uint8_t RESERVED0:1;
+		uint8_t CR_DONE_1:1;
+		uint8_t CHANNEL_EQ_DONE_1:1;
+		uint8_t SYMBOL_LOCKED_1:1;
+		uint8_t RESERVED_1:1;
+	} bits;
+	uint8_t raw;
+};
+
+union device_service_irq {
+	struct {
+		uint8_t REMOTE_CONTROL_CMD_PENDING:1;
+		uint8_t AUTOMATED_TEST:1;
+		uint8_t CP_IRQ:1;
+		uint8_t MCCS_IRQ:1;
+		uint8_t DOWN_REP_MSG_RDY:1;
+		uint8_t UP_REQ_MSG_RDY:1;
+		uint8_t SINK_SPECIFIC:1;
+		uint8_t reserved:1;
+	} bits;
+	uint8_t raw;
+};
+
+union downstream_port {
+	struct {
+		uint8_t PRESENT:1;
+		uint8_t TYPE:2;
+		uint8_t FORMAT_CONV:1;
+		uint8_t DETAILED_CAPS:1;
+		uint8_t RESERVED:3;
+	} bits;
+	uint8_t raw;
+};
+
+union sink_count {
+	struct {
+		uint8_t SINK_COUNT:6;
+		uint8_t CPREADY:1;
+		uint8_t RESERVED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_align_status_updated {
+	struct {
+		uint8_t INTERLANE_ALIGN_DONE:1;
+		uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1;
+		uint8_t RESERVED:4;
+		uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1;
+		uint8_t LINK_STATUS_UPDATED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union lane_adjust {
+	struct {
+		uint8_t VOLTAGE_SWING_LANE:2;
+		uint8_t PRE_EMPHASIS_LANE:2;
+		uint8_t RESERVED:4;
+	} bits;
+	uint8_t raw;
+};
+
+/* Automated test structures */
+union test_request {
+	struct {
+		uint8_t LINK_TRAINING:1;
+		uint8_t LINK_TEST_PATTERN:1;
+		uint8_t EDID_READ:1;
+		uint8_t PHY_TEST_PATTERN:1;
+		uint8_t AUDIO_TEST_PATTERN:1;
+		uint8_t AUDIO_TEST_NO_VIDEO:1;
+		uint8_t RESERVED:1;
+		uint8_t TEST_STEREO_3D:1;
+	} bits;
+	uint8_t raw;
+};
+
+union test_response {
+	struct {
+		uint8_t ACK:1;
+		uint8_t NO_ACK:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union link_test_pattern {
+	struct {
+		uint8_t PATTERN:2;/*DpcdLinkTestPatterns*/
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union test_misc {
+	struct dpcd_test_misc_bits {
+		uint8_t SYNC_CLOCK:1;
+		uint8_t CLR_FORMAT:2;/*DpcdTestColorFormat*/
+		uint8_t DYN_RANGE:1;/*DpcdTestDynRange*/
+		uint8_t YCBCR:1;/*DpcdTestYCbCrStandard*/
+		uint8_t BPC:3;/*DpcdTestBitDepth*/
+	} bits;
+	uint8_t raw;
+};
+
+union phy_test_pattern {
+	struct {
+		/* This field is 2 bits for DP1.1 and 3 bits for DP1.2.*/
+		uint8_t PATTERN:3;
+		uint8_t RESERVED:5;/* BY spec, bit7:2 is 0 for DP1.1.*/
+	} bits;
+	uint8_t raw;
+};
+
+union audio_test_mode {
+	struct {
+		uint8_t SAMPLING_RATE:4;
+		uint8_t CHANNEL_COUNT:4;
+	} bits;
+	uint8_t raw;
+};
+
+union audio_tes_tpattern_period {
+	struct {
+		uint8_t PATTERN_PERIOD:4;
+		uint8_t RESERVED:4;
+	} bits;
+	uint8_t raw;
+};
+
+struct audio_test_pattern_type {
+	uint8_t value;
+};
+
+union dpcd_training_pattern {
+	struct {
+		uint8_t TRAINING_PATTERN_SET:2;
+		uint8_t LINK_QUAL_PATTERN_SET:2;
+		uint8_t RECOVERED_CLOCK_OUT_EN:1;
+		uint8_t SCRAMBLING_DISABLE:1;
+		uint8_t RESERVED:2;
+	} bits;
+	uint8_t raw;
+};
+
+/* Training Lane is used to configure downstream DP device's voltage swing
+and pre-emphasis levels*/
+/* The DPCD addresses are from 0x103 to 0x106*/
+union dpcd_training_lane {
+	struct {
+		uint8_t VOLTAGE_SWING_SET:2;
+		uint8_t MAX_SWING_REACHED:1;
+		uint8_t PRE_EMPHASIS_SET:2;
+		uint8_t MAX_PRE_EMPHASIS_REACHED:1;
+		uint8_t RESERVED:2;
+	} bits;
+	uint8_t raw;
+};
+
+/*Training Lane Set 2 is used to configure downstream DP device's
+post cursor 2 level of Training Pattern 2 or 3*/
+/* The DPCD addresses are 0x10F (TRAINING_LANE0_1_SET2)
+and 0x110 (TRAINING_LANE2_3_SET2)*/
+union dpcd_training_lane_set2 {
+	struct {
+		uint8_t POST_CURSOR2_SET:2;
+		uint8_t MAX_POST_CURSOR2_REACHED:1;
+		uint8_t RESERVED:1;
+	} bits;
+	uint8_t raw;
+};
+
+union dpcd_psr_configuration {
+	struct {
+		uint8_t ENABLE:1;
+		uint8_t TRANSMITTER_ACTIVE_IN_PSR:1;
+		uint8_t CRC_VERIFICATION:1;
+		uint8_t FRAME_CAPTURE_INDICATION:1;
+		uint8_t LINE_CAPTURE_INDICATION:1;
+		uint8_t IRQ_HPD_WITH_CRC_ERROR:1;
+		uint8_t RESERVED:2;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_error_status {
+	struct {
+		uint8_t LINK_CRC_ERROR:1;
+		uint8_t RFB_STORAGE_ERROR:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_event_status_ind {
+	struct {
+		uint8_t SINK_PSR_CAP_CHANGE:1;
+		uint8_t RESERVED:7;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_sink_psr_status {
+	struct {
+		uint8_t SINK_SELF_REFRESH_STATUS:3;
+		uint8_t RESERVED:5;
+	} bits;
+	uint8_t raw;
+};
+
+/* EDP related 0x701 */
+union edp_generial_cap1 {
+	struct {
+		uint8_t TCON_BACKLIGHT_ADJUSTMENT_CAPABLE:1;
+		uint8_t BACKLIGHT_PIN_ENABLE_CAPABLE:1;
+		uint8_t BACKLIGHT_AUX_ENABLE_CAPABLE:1;
+		uint8_t PANEL_SELFTEST_PIN_ENABLE_CAPABLE:1;
+		uint8_t BACKLIGHT_SELFTEST_AUX_ENABLE_CAPABLE:1;
+		uint8_t FRC_ENABLE_CAPABLE:1;
+		uint8_t COLOR_ENGINE_CAPABLE:1;
+		/*bit 7, pane can be controlled by 0x600*/
+		uint8_t SET_POWER_CAPABLE:1;
+	} bits;
+	uint8_t raw;
+};
+
+/* TMDS-converter related */
+union dwnstream_port_caps_byte0 {
+	struct {
+		uint8_t DWN_STRM_PORTX_TYPE:3;
+		uint8_t DWN_STRM_PORTX_HPD:1;
+		uint8_t RESERVERD:4;
+	} bits;
+	uint8_t raw;
+};
+
+/* these are the detailed types stored at DWN_STRM_PORTX_CAP (00080h)*/
+enum dpcd_downstream_port_detailed_type {
+	DOWN_STREAM_DETAILED_DP = 0,
+	DOWN_STREAM_DETAILED_VGA,
+	DOWN_STREAM_DETAILED_DVI,
+	DOWN_STREAM_DETAILED_HDMI,
+	DOWN_STREAM_DETAILED_NONDDC,/* has no EDID (TV,CV)*/
+	DOWN_STREAM_DETAILED_DP_PLUS_PLUS
+};
+
+union dwnstream_port_caps_byte2 {
+	struct {
+		uint8_t MAX_BITS_PER_COLOR_COMPONENT:2;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+union dp_downstream_port_present {
+	uint8_t byte;
+	struct {
+		uint8_t PORT_PRESENT:1;
+		uint8_t PORT_TYPE:2;
+		uint8_t FMT_CONVERSION:1;
+		uint8_t DETAILED_CAPS:1;
+		uint8_t RESERVED:3;
+	} fields;
+};
+
+
+union dwnstream_port_caps_byte3_dvi {
+	struct {
+		uint8_t RESERVED1:1;
+		uint8_t DUAL_LINK:1;
+		uint8_t HIGH_COLOR_DEPTH:1;
+		uint8_t RESERVED2:5;
+	} bits;
+	uint8_t raw;
+};
+
+union dwnstream_port_caps_byte3_hdmi {
+	struct {
+		uint8_t FRAME_SEQ_TO_FRAME_PACK:1;
+		uint8_t RESERVED:7;
+	} bits;
+	uint8_t raw;
+};
+
+/*4-byte structure for detailed capabilities of a down-stream port
+(DP-to-TMDS converter).*/
+union dwnstream_portx_caps {
+	struct {
+		union dwnstream_port_caps_byte0 byte0;
+		uint8_t max_tmds_clk;/* byte1 */
+		union dwnstream_port_caps_byte2 byte2;
+
+		union {
+			union dwnstream_port_caps_byte3_dvi byte_dvi;
+			union dwnstream_port_caps_byte3_hdmi byte_hdmi;
+		} byte3;
+	} bytes;
+	uint8_t raw[4];
+};
+
+union sink_status {
+	struct {
+		uint8_t RX_PORT0_STATUS:1;
+		uint8_t RX_PORT1_STATUS:1;
+		uint8_t RESERVED:6;
+	} bits;
+	uint8_t raw;
+};
+
+/*6-byte structure corresponding to 6 registers (200h-205h)
+read during handling of HPD-IRQ*/
+union hpd_irq_data {
+	struct {
+		union sink_count sink_cnt;/* 200h */
+		union device_service_irq device_service_irq;/* 201h */
+		union lane_status lane01_status;/* 202h */
+		union lane_status lane23_status;/* 203h */
+		union lane_align_status_updated lane_status_updated;/* 204h */
+		union sink_status sink_status;
+	} bytes;
+	uint8_t raw[6];
+};
+
+union down_stream_port_count {
+	struct {
+		uint8_t DOWN_STR_PORT_COUNT:4;
+		uint8_t RESERVED:2; /*Bits 5:4 = RESERVED. Read all 0s.*/
+		/*Bit 6 = MSA_TIMING_PAR_IGNORED
+		0 = Sink device requires the MSA timing parameters
+		1 = Sink device is capable of rendering incoming video
+		 stream without MSA timing parameters*/
+		uint8_t IGNORE_MSA_TIMING_PARAM:1;
+		/*Bit 7 = OUI Support
+		0 = OUI not supported
+		1 = OUI supported
+		(OUI and Device Identification mandatory for DP 1.2)*/
+		uint8_t OUI_SUPPORT:1;
+	} bits;
+	uint8_t raw;
+};
+
+union down_spread_ctrl {
+	struct {
+		uint8_t RESERVED1:4;/* Bit 3:0 = RESERVED. Read all 0s*/
+	/* Bits 4 = SPREAD_AMP. Spreading amplitude
+	0 = Main link signal is not downspread
+	1 = Main link signal is downspread <= 0.5%
+	with frequency in the range of 30kHz ~ 33kHz*/
+		uint8_t SPREAD_AMP:1;
+		uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/
+	/*Bit 7 = MSA_TIMING_PAR_IGNORE_EN
+	0 = Source device will send valid data for the MSA Timing Params
+	1 = Source device may send invalid data for these MSA Timing Params*/
+		uint8_t IGNORE_MSA_TIMING_PARAM:1;
+	} bits;
+	uint8_t raw;
+};
+
+union dpcd_edp_config {
+	struct {
+		uint8_t PANEL_MODE_EDP:1;
+		uint8_t FRAMING_CHANGE_ENABLE:1;
+		uint8_t RESERVED:5;
+		uint8_t PANEL_SELF_TEST_ENABLE:1;
+	} bits;
+	uint8_t raw;
+};
+
+struct dp_device_vendor_id {
+	uint8_t ieee_oui[3];/*24-bit IEEE OUI*/
+	uint8_t ieee_device_id[6];/*usually 6-byte ASCII name*/
+};
+
+struct dp_sink_hw_fw_revision {
+	uint8_t ieee_hw_rev;
+	uint8_t ieee_fw_rev[2];
+};
+
+/*DPCD register of DP receiver capability field bits-*/
+union edp_configuration_cap {
+	struct {
+		uint8_t ALT_SCRAMBLER_RESET:1;
+		uint8_t FRAMING_CHANGE:1;
+		uint8_t RESERVED:1;
+		uint8_t DPCD_DISPLAY_CONTROL_CAPABLE:1;
+		uint8_t RESERVED2:4;
+	} bits;
+	uint8_t raw;
+};
+
+union psr_capabilities {
+	struct {
+		uint8_t EXIT_LT_NOT_REQ:1;
+		uint8_t RFB_SETUP_TIME:3;
+		uint8_t RESERVED:4;
+	} bits;
+	uint8_t raw;
+};
+
+#endif /* __DAL_DPCD_DEFS_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/encoder_interface.h b/drivers/gpu/drm/amd/dal/include/encoder_interface.h
new file mode 100644
index 000000000000..5fbf816cf96e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/encoder_interface.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of enc software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and enc permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_ENCODER_INTERFACE_H__
+#define __DAL_ENCODER_INTERFACE_H__
+
+#include "encoder_types.h"
+#include "adapter_service_interface.h"
+#include "fixed31_32.h"
+
+enum encoder_result {
+	ENCODER_RESULT_OK,
+	ENCODER_RESULT_ERROR,
+	ENCODER_RESULT_NOBANDWIDTH,
+	ENCODER_RESULT_SINKCONNECTIVITYCHANGED,
+};
+
+struct encoder_init_data {
+	struct adapter_service *adapter_service;
+	enum channel_id channel;
+	struct graphics_object_id connector;
+	enum hpd_source_id hpd_source;
+	/* TODO: in DAL2, here was pointer to EventManagerInterface */
+	struct graphics_object_id encoder;
+	struct dc_context *ctx;
+};
+
+/* forward declaration */
+struct encoder;
+
+struct encoder *dal_encoder_create(
+	const struct encoder_init_data *init_data);
+
+/* access graphics object base */
+const struct graphics_object_id dal_encoder_get_graphics_object_id(
+	const struct encoder *enc);
+
+/*
+ * Signal types support
+ */
+uint32_t dal_encoder_enumerate_input_signals(
+	const struct encoder *enc);
+uint32_t dal_encoder_enumerate_output_signals(
+	const struct encoder *enc);
+bool dal_encoder_is_input_signal_supported(
+	const struct encoder *enc,
+	enum signal_type signal);
+bool dal_encoder_is_output_signal_supported(
+	const struct encoder *enc,
+	enum signal_type signal);
+void dal_encoder_set_input_signals(
+	struct encoder *enc,
+	uint32_t signals);
+void dal_encoder_set_output_signals(
+	struct encoder *enc,
+	uint32_t signals);
+
+/*
+ * Programming interface
+ */
+/* perform power-up sequence (boot up, resume, recovery) */
+enum encoder_result dal_encoder_power_up(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* perform power-down (shut down, stand-by */
+enum encoder_result dal_encoder_power_down(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* setup encoder block (DIG, DVO, DAC), does not enables encoder */
+enum encoder_result dal_encoder_setup(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* activate transmitter,
+ * do preparation before enables the actual stream output */
+enum encoder_result dal_encoder_pre_enable_output(
+	struct encoder *enc,
+	const struct encoder_pre_enable_output_param *param);
+/* activate transmitter, enables actual stream output */
+enum encoder_result dal_encoder_enable_output(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* deactivate transmitter, disables stream output */
+enum encoder_result dal_encoder_disable_output(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* output blank data,
+ *prevents output of the actual surface data on active transmitter */
+enum encoder_result dal_encoder_blank(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* stop sending blank data,
+ * output the actual surface data on active transmitter */
+enum encoder_result dal_encoder_unblank(
+	struct encoder *enc,
+	const struct encoder_unblank_param *param);
+/* setup stereo signal from given controller */
+enum encoder_result dal_encoder_setup_stereo(
+	struct encoder *enc,
+	const struct encoder_3d_setup *setup);
+/* enable HSync/VSync output from given controller */
+enum encoder_result dal_encoder_enable_sync_output(
+	struct encoder *enc,
+	enum sync_source src);
+/* disable HSync/VSync output */
+enum encoder_result dal_encoder_disable_sync_output(
+	struct encoder *enc);
+/* action of encoder before DDC transaction */
+enum encoder_result dal_encoder_pre_ddc(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* action of encoder after DDC transaction */
+enum encoder_result dal_encoder_post_ddc(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* CRT DDC EDID polling interrupt interface */
+enum encoder_result dal_encoder_update_implementation(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* set test pattern signal */
+enum encoder_result dal_encoder_set_dp_phy_pattern(
+	struct encoder *enc,
+	const struct encoder_set_dp_phy_pattern_param *param);
+
+void dal_encoder_release_hw(struct encoder *enc);
+/*
+ * Information interface
+ */
+/* check whether sink is present based on SENSE detection,
+ * analog encoders will return true */
+bool dal_encoder_is_sink_present(
+	struct encoder *enc,
+	struct graphics_object_id downstream);
+/* detect load on the sink,
+ * for analog signal,
+ * load detection will be called for the specified signal */
+enum signal_type dal_encoder_detect_load(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* detect output sink type,
+ * for digital perform sense detection,
+ * for analog return encoder's signal type */
+enum signal_type dal_encoder_detect_sink(
+	struct encoder *enc,
+	struct graphics_object_id downstream);
+/* get transmitter id */
+enum transmitter dal_encoder_get_transmitter(
+	const struct encoder *enc);
+/*  */
+enum transmitter dal_encoder_get_paired_transmitter(
+	const struct encoder *enc);
+/*  */
+enum physical_phy_id dal_encoder_get_phy(
+	const struct encoder *enc);
+/*  */
+enum physical_phy_id dal_encoder_get_paired_phy(
+	const struct encoder *enc);
+/* reports if the encoder supports given link settings */
+bool dal_encoder_is_link_settings_supported(
+	struct encoder *enc,
+	const struct link_settings *link_settings);
+/* options and features supported by encoder */
+struct encoder_feature_support dal_encoder_get_supported_features(
+	const struct encoder *enc);
+/* reports list of supported stream engines */
+union supported_stream_engines dal_encoder_get_supported_stream_engines(
+	const struct encoder *enc);
+/* reports preferred stream engine */
+enum engine_id dal_encoder_get_preferred_stream_engine(
+	const struct encoder *enc);
+/* reports whether clock source can be used with enc encoder */
+bool dal_encoder_is_clock_source_supported(
+	const struct encoder *enc,
+	enum clock_source_id clock_source);
+/* check encoder capabilities to confirm
+ * specified timing is in the encoder limits
+ * when outputting certain signal */
+enum encoder_result dal_encoder_validate_output(
+	struct encoder *enc,
+	const struct encoder_output *output);
+/* retrieves sync source which outputs VSync signal from encoder */
+enum sync_source dal_encoder_get_vsync_output_source(
+	const struct encoder *enc);
+/*
+ * Adjustments
+ */
+/* update AVI info frame */
+void dal_encoder_update_info_frame(
+	struct encoder *enc,
+	const struct encoder_info_frame_param *param);
+/*  */
+void dal_encoder_stop_info_frame(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/*  */
+enum encoder_result dal_encoder_set_lcd_backlight_level(
+	struct encoder *enc,
+	uint32_t level);
+/* backlight control interface */
+enum encoder_result dal_encoder_backlight_control(
+	struct encoder *enc,
+	bool enable);
+/*
+ * DP MST programming
+ */
+/* update payload slot allocation for each DP MST stream */
+enum encoder_result dal_encoder_update_mst_alloc_table(
+	struct encoder *enc,
+	const struct dp_mst_stream_allocation_table *table,
+	bool is_removal);
+/* enable virtual channel stream with throttled value X.Y */
+enum encoder_result dal_encoder_enable_stream(
+	struct encoder *enc,
+	enum engine_id engine,
+	struct fixed31_32 throttled_vcp_size);
+/* disable virtual channel stream */
+enum encoder_result dal_encoder_disable_stream(
+	struct encoder *enc,
+	enum engine_id engine);
+void dal_encoder_set_multi_path(struct encoder *enc, bool is_multi_path);
+/*
+ * Test harness
+ */
+/* check whether Test Pattern enabled */
+bool dal_encoder_is_test_pattern_enabled(
+	struct encoder *enc,
+	enum engine_id engine);
+/* set lane parameters */
+enum encoder_result dal_encoder_set_lane_settings(
+	struct encoder *enc,
+	const struct encoder_context *ctx,
+	const struct link_training_settings *link_settings);
+/* get lane parameters */
+enum encoder_result dal_encoder_get_lane_settings(
+	struct encoder *enc,
+	const struct encoder_context *ctx,
+	struct link_training_settings *link_settings);
+/* enable master clock of HPD interrupt */
+void dal_encoder_enable_hpd(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+/* disable all HPD interrupts */
+void dal_encoder_disable_hpd(
+	struct encoder *enc,
+	const struct encoder_context *ctx);
+
+/* get current HW state - used for optimization code path only */
+enum clock_source_id dal_encoder_get_active_clock_source(
+	const struct encoder *enc);
+enum engine_id dal_encoder_get_active_engine(
+	const struct encoder *enc);
+
+/* destroy encoder instance */
+void dal_encoder_destroy(
+	struct encoder **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/fixed31_32.h b/drivers/gpu/drm/amd/dal/include/fixed31_32.h
new file mode 100644
index 000000000000..507f9f639099
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/fixed31_32.h
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_FIXED31_32_H__
+#define __DAL_FIXED31_32_H__
+
+/*
+ * @brief
+ * Arithmetic operations on real numbers
+ * represented as fixed-point numbers.
+ * There are: 1 bit for sign,
+ * 31 bit for integer part,
+ * 32 bits for fractional part.
+ *
+ * @note
+ * Currently, overflows and underflows are asserted;
+ * no special result returned.
+ */
+
+struct fixed31_32 {
+	int64_t value;
+};
+
+/*
+ * @brief
+ * Useful constants
+ */
+
+static const struct fixed31_32 dal_fixed31_32_zero = { 0 };
+static const struct fixed31_32 dal_fixed31_32_epsilon = { 1LL };
+static const struct fixed31_32 dal_fixed31_32_half = { 0x80000000LL };
+static const struct fixed31_32 dal_fixed31_32_one = { 0x100000000LL };
+
+static const struct fixed31_32 dal_fixed31_32_pi = { 13493037705LL };
+static const struct fixed31_32 dal_fixed31_32_two_pi = { 26986075409LL };
+static const struct fixed31_32 dal_fixed31_32_e = { 11674931555LL };
+static const struct fixed31_32 dal_fixed31_32_ln2 = { 2977044471LL };
+static const struct fixed31_32 dal_fixed31_32_ln2_div_2 = { 1488522236LL };
+
+/*
+ * @brief
+ * Initialization routines
+ */
+
+/*
+ * @brief
+ * result = numerator / denominator
+ */
+struct fixed31_32 dal_fixed31_32_from_fraction(
+	int64_t numerator,
+	int64_t denominator);
+
+/*
+ * @brief
+ * result = arg
+ */
+struct fixed31_32 dal_fixed31_32_from_int(
+	int64_t arg);
+
+/*
+ * @brief
+ * Unary operators
+ */
+
+/*
+ * @brief
+ * result = -arg
+ */
+struct fixed31_32 dal_fixed31_32_neg(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = abs(arg) := (arg >= 0) ? arg : -arg
+ */
+struct fixed31_32 dal_fixed31_32_abs(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Binary relational operators
+ */
+
+/*
+ * @brief
+ * result = arg1 < arg2
+ */
+bool dal_fixed31_32_lt(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = arg1 <= arg2
+ */
+bool dal_fixed31_32_le(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = arg1 == arg2
+ */
+bool dal_fixed31_32_eq(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2
+ */
+struct fixed31_32 dal_fixed31_32_min(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1
+ */
+struct fixed31_32 dal_fixed31_32_max(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ *          | min_value, when arg <= min_value
+ * result = | arg, when min_value < arg < max_value
+ *          | max_value, when arg >= max_value
+ */
+struct fixed31_32 dal_fixed31_32_clamp(
+	struct fixed31_32 arg,
+	struct fixed31_32 min_value,
+	struct fixed31_32 max_value);
+
+/*
+ * @brief
+ * Binary shift operators
+ */
+
+/*
+ * @brief
+ * result = arg << shift
+ */
+struct fixed31_32 dal_fixed31_32_shl(
+	struct fixed31_32 arg,
+	uint8_t shift);
+
+/*
+ * @brief
+ * result = arg >> shift
+ */
+struct fixed31_32 dal_fixed31_32_shr(
+	struct fixed31_32 arg,
+	uint8_t shift);
+
+/*
+ * @brief
+ * Binary additive operators
+ */
+
+/*
+ * @brief
+ * result = arg1 + arg2
+ */
+struct fixed31_32 dal_fixed31_32_add(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = arg1 - arg2
+ */
+struct fixed31_32 dal_fixed31_32_sub_int(
+	struct fixed31_32 arg1,
+	int32_t arg2);
+
+/*
+ * @brief
+ * result = arg1 - arg2
+ */
+struct fixed31_32 dal_fixed31_32_sub(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * Binary multiplicative operators
+ */
+
+/*
+ * @brief
+ * result = arg1 * arg2
+ */
+struct fixed31_32 dal_fixed31_32_mul_int(
+	struct fixed31_32 arg1,
+	int32_t arg2);
+
+/*
+ * @brief
+ * result = arg1 * arg2
+ */
+struct fixed31_32 dal_fixed31_32_mul(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * result = square(arg) := arg * arg
+ */
+struct fixed31_32 dal_fixed31_32_sqr(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = arg1 / arg2
+ */
+struct fixed31_32 dal_fixed31_32_div_int(
+	struct fixed31_32 arg1,
+	int64_t arg2);
+
+/*
+ * @brief
+ * result = arg1 / arg2
+ */
+struct fixed31_32 dal_fixed31_32_div(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * Reciprocal function
+ */
+
+/*
+ * @brief
+ * result = reciprocal(arg) := 1 / arg
+ *
+ * @note
+ * No special actions taken in case argument is zero.
+ */
+struct fixed31_32 dal_fixed31_32_recip(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Trigonometric functions
+ */
+
+/*
+ * @brief
+ * result = sinc(arg) := sin(arg) / arg
+ *
+ * @note
+ * Argument specified in radians,
+ * internally it's normalized to [-2pi...2pi] range.
+ */
+struct fixed31_32 dal_fixed31_32_sinc(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = sin(arg)
+ *
+ * @note
+ * Argument specified in radians,
+ * internally it's normalized to [-2pi...2pi] range.
+ */
+struct fixed31_32 dal_fixed31_32_sin(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = cos(arg)
+ *
+ * @note
+ * Argument specified in radians
+ * and should be in [-2pi...2pi] range -
+ * passing arguments outside that range
+ * will cause incorrect result!
+ */
+struct fixed31_32 dal_fixed31_32_cos(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Transcendent functions
+ */
+
+/*
+ * @brief
+ * result = exp(arg)
+ *
+ * @note
+ * Currently, function is verified for abs(arg) <= 1.
+ */
+struct fixed31_32 dal_fixed31_32_exp(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = log(arg)
+ *
+ * @note
+ * Currently, abs(arg) should be less than 1.
+ * No normalization is done.
+ * Currently, no special actions taken
+ * in case of invalid argument(s). Take care!
+ */
+struct fixed31_32 dal_fixed31_32_log(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * Power function
+ */
+
+/*
+ * @brief
+ * result = pow(arg1, arg2)
+ *
+ * @note
+ * Currently, abs(arg1) should be less than 1. Take care!
+ */
+struct fixed31_32 dal_fixed31_32_pow(
+	struct fixed31_32 arg1,
+	struct fixed31_32 arg2);
+
+/*
+ * @brief
+ * Rounding functions
+ */
+
+/*
+ * @brief
+ * result = floor(arg) := greatest integer lower than or equal to arg
+ */
+int32_t dal_fixed31_32_floor(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = round(arg) := integer nearest to arg
+ */
+int32_t dal_fixed31_32_round(
+	struct fixed31_32 arg);
+
+/*
+ * @brief
+ * result = ceil(arg) := lowest integer greater than or equal to arg
+ */
+int32_t dal_fixed31_32_ceil(
+	struct fixed31_32 arg);
+
+/* the following two function are used in scaler hw programming to convert fixed
+ * point value to format 2 bits from integer part and 19 bits from fractional
+ * part. The same applies for u0d19, 0 bits from integer part and 19 bits from
+ * fractional
+ */
+
+uint32_t dal_fixed31_32_u2d19(
+	struct fixed31_32 arg);
+
+uint32_t dal_fixed31_32_u0d19(
+	struct fixed31_32 arg);
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/fixed32_32.h b/drivers/gpu/drm/amd/dal/include/fixed32_32.h
new file mode 100644
index 000000000000..f393e953e91a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/fixed32_32.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_FIXED32_32_H__
+#define __DAL_FIXED32_32_H__
+
+#include "dm_services_types.h"
+
+struct fixed32_32 {
+	uint64_t value;
+};
+
+static const struct fixed32_32 dal_fixed32_32_zero = { 0 };
+static const struct fixed32_32 dal_fixed32_32_one = { 0x100000000LL };
+static const struct fixed32_32 dal_fixed32_32_half = { 0x80000000LL };
+
+struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d);
+struct fixed32_32 dal_fixed32_32_from_int(uint32_t value);
+struct fixed32_32 dal_fixed32_32_add(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_add_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_sub(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_sub_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_mul(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_mul_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_div(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_div_int(
+	struct fixed32_32 lhs,
+	uint32_t rhs);
+struct fixed32_32 dal_fixed32_32_min(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+struct fixed32_32 dal_fixed32_32_max(
+	struct fixed32_32 lhs,
+	struct fixed32_32 rhs);
+bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs);
+bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs);
+bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs);
+bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs);
+bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs);
+bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs);
+bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs);
+uint32_t dal_fixed32_32_ceil(struct fixed32_32 value);
+uint32_t dal_fixed32_32_floor(struct fixed32_32 value);
+uint32_t dal_fixed32_32_round(struct fixed32_32 value);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/gpio_interface.h b/drivers/gpu/drm/amd/dal/include/gpio_interface.h
new file mode 100644
index 000000000000..a084d7923e2f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/gpio_interface.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_INTERFACE_H__
+#define __DAL_GPIO_INTERFACE_H__
+
+#include "gpio_types.h"
+#include "grph_object_defs.h"
+
+struct gpio;
+
+/* Open the handle for future use */
+enum gpio_result dal_gpio_open(
+	struct gpio *gpio,
+	enum gpio_mode mode);
+
+enum gpio_result dal_gpio_open_ex(
+	struct gpio *gpio,
+	enum gpio_mode mode,
+	void *options);
+
+/* Get high or low from the pin */
+enum gpio_result dal_gpio_get_value(
+	const struct gpio *gpio,
+	uint32_t *value);
+
+/* Set pin high or low */
+enum gpio_result dal_gpio_set_value(
+	const struct gpio *gpio,
+	uint32_t value);
+
+/* Get current mode */
+enum gpio_mode dal_gpio_get_mode(
+	const struct gpio *gpio);
+
+/* Change mode of the handle */
+enum gpio_result dal_gpio_change_mode(
+	struct gpio *gpio,
+	enum gpio_mode mode);
+
+/* Get the GPIO id */
+enum gpio_id dal_gpio_get_id(
+	const struct gpio *gpio);
+
+/* Get the GPIO enum */
+uint32_t dal_gpio_get_enum(
+	const struct gpio *gpio);
+
+/* Set the GPIO pin configuration */
+enum gpio_result dal_gpio_set_config(
+	struct gpio *gpio,
+	const struct gpio_config_data *config_data);
+
+/* Obtain GPIO pin info */
+enum gpio_result dal_gpio_get_pin_info(
+	const struct gpio *gpio,
+	struct gpio_pin_info *pin_info);
+
+/* Obtain GPIO sync source */
+enum sync_source dal_gpio_get_sync_source(
+	const struct gpio *gpio);
+
+/* Obtain GPIO pin output state (active low or active high) */
+enum gpio_pin_output_state dal_gpio_get_output_state(
+	const struct gpio *gpio);
+
+/* Close the handle */
+void dal_gpio_close(
+	struct gpio *gpio);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h b/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
new file mode 100644
index 000000000000..3f1b923c1885
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/gpio_service_interface.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_SERVICE_INTERFACE_H__
+#define __DAL_GPIO_SERVICE_INTERFACE_H__
+
+#include "gpio_types.h"
+#include "gpio_interface.h"
+#include "ddc_interface.h"
+#include "irq_interface.h"
+
+struct gpio_service;
+
+struct gpio_service *dal_gpio_service_create(
+	enum dce_version dce_version_major,
+	enum dce_version dce_version_minor,
+	struct dc_context *ctx);
+
+struct gpio *dal_gpio_service_create_gpio(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	enum gpio_pin_output_state output_state);
+
+struct gpio *dal_gpio_service_create_gpio_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state);
+
+void dal_gpio_service_destroy_gpio(
+	struct gpio **gpio);
+
+struct ddc *dal_gpio_service_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info);
+
+void dal_gpio_service_destroy_ddc(
+	struct ddc **ddc);
+
+struct irq *dal_gpio_service_create_irq(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask);
+
+struct irq *dal_gpio_service_create_irq_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en);
+
+void dal_gpio_service_destroy_irq(
+	struct irq **ptr);
+
+void dal_gpio_service_destroy(
+	struct gpio_service **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/gpio_types.h b/drivers/gpu/drm/amd/dal/include/gpio_types.h
new file mode 100644
index 000000000000..62548d6af006
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/gpio_types.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_TYPES_H__
+#define __DAL_GPIO_TYPES_H__
+
+#define BUNDLE_A_MASK 0x00FFF000L
+#define BUNDLE_B_MASK 0x00000FFFL
+
+/*
+ * gpio_result
+ *
+ * @brief
+ * The possible return codes that the GPIO object can return.
+ * These return codes can be generated
+ * directly by the GPIO object or from the GPIOPin object.
+ */
+enum gpio_result {
+	GPIO_RESULT_OK,
+	GPIO_RESULT_NULL_HANDLE,
+	GPIO_RESULT_INVALID_DATA,
+	GPIO_RESULT_DEVICE_BUSY,
+	GPIO_RESULT_OPEN_FAILED,
+	GPIO_RESULT_ALREADY_OPENED,
+	GPIO_RESULT_NON_SPECIFIC_ERROR
+};
+
+/*
+ * @brief
+ * Used to identify the specific GPIO device
+ *
+ * @notes
+ * These constants are used as indices in a vector.
+ * Thus they should start from zero and be contiguous.
+ */
+enum gpio_id {
+	GPIO_ID_UNKNOWN = (-1),
+	GPIO_ID_DDC_DATA,
+	GPIO_ID_DDC_CLOCK,
+	GPIO_ID_GENERIC,
+	GPIO_ID_HPD,
+	GPIO_ID_GPIO_PAD,
+	GPIO_ID_VIP_PAD,
+	GPIO_ID_SYNC,
+	GPIO_ID_GSL, /* global swap lock */
+	GPIO_ID_COUNT,
+	GPIO_ID_MIN = GPIO_ID_DDC_DATA,
+	GPIO_ID_MAX = GPIO_ID_GSL
+};
+
+#define GPIO_ENUM_UNKNOWN \
+	32
+
+struct gpio_pin_info {
+	uint32_t offset;
+	uint32_t offset_y;
+	uint32_t offset_en;
+	uint32_t offset_mask;
+
+	uint32_t mask;
+	uint32_t mask_y;
+	uint32_t mask_en;
+	uint32_t mask_mask;
+};
+
+enum gpio_pin_output_state {
+	GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW,
+	GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH,
+	GPIO_PIN_OUTPUT_STATE_DEFAULT = GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW
+};
+
+enum gpio_generic {
+	GPIO_GENERIC_UNKNOWN = (-1),
+	GPIO_GENERIC_A,
+	GPIO_GENERIC_B,
+	GPIO_GENERIC_C,
+	GPIO_GENERIC_D,
+	GPIO_GENERIC_E,
+	GPIO_GENERIC_F,
+	GPIO_GENERIC_G,
+	GPIO_GENERIC_COUNT,
+	GPIO_GENERIC_MIN = GPIO_GENERIC_A,
+	GPIO_GENERIC_MAX = GPIO_GENERIC_B
+};
+
+enum gpio_hpd {
+	GPIO_HPD_UNKNOWN = (-1),
+	GPIO_HPD_1,
+	GPIO_HPD_2,
+	GPIO_HPD_3,
+	GPIO_HPD_4,
+	GPIO_HPD_5,
+	GPIO_HPD_6,
+	GPIO_HPD_COUNT,
+	GPIO_HPD_MIN = GPIO_HPD_1,
+	GPIO_HPD_MAX = GPIO_HPD_6
+};
+
+enum gpio_gpio_pad {
+	GPIO_GPIO_PAD_UNKNOWN = (-1),
+	GPIO_GPIO_PAD_0,
+	GPIO_GPIO_PAD_1,
+	GPIO_GPIO_PAD_2,
+	GPIO_GPIO_PAD_3,
+	GPIO_GPIO_PAD_4,
+	GPIO_GPIO_PAD_5,
+	GPIO_GPIO_PAD_6,
+	GPIO_GPIO_PAD_7,
+	GPIO_GPIO_PAD_8,
+	GPIO_GPIO_PAD_9,
+	GPIO_GPIO_PAD_10,
+	GPIO_GPIO_PAD_11,
+	GPIO_GPIO_PAD_12,
+	GPIO_GPIO_PAD_13,
+	GPIO_GPIO_PAD_14,
+	GPIO_GPIO_PAD_15,
+	GPIO_GPIO_PAD_16,
+	GPIO_GPIO_PAD_17,
+	GPIO_GPIO_PAD_18,
+	GPIO_GPIO_PAD_19,
+	GPIO_GPIO_PAD_20,
+	GPIO_GPIO_PAD_21,
+	GPIO_GPIO_PAD_22,
+	GPIO_GPIO_PAD_23,
+	GPIO_GPIO_PAD_24,
+	GPIO_GPIO_PAD_25,
+	GPIO_GPIO_PAD_26,
+	GPIO_GPIO_PAD_27,
+	GPIO_GPIO_PAD_28,
+	GPIO_GPIO_PAD_29,
+	GPIO_GPIO_PAD_30,
+	GPIO_GPIO_PAD_COUNT,
+	GPIO_GPIO_PAD_MIN = GPIO_GPIO_PAD_0,
+	GPIO_GPIO_PAD_MAX = GPIO_GPIO_PAD_30
+};
+
+enum gpio_vip_pad {
+	GPIO_VIP_PAD_UNKNOWN = (-1),
+	/* following never used -
+	 * GPIO_ID_DDC_CLOCK::GPIO_DDC_LINE_VIP_PAD defined instead */
+	GPIO_VIP_PAD_SCL,
+	/* following never used -
+	 * GPIO_ID_DDC_DATA::GPIO_DDC_LINE_VIP_PAD defined instead */
+	GPIO_VIP_PAD_SDA,
+	GPIO_VIP_PAD_VHAD,
+	GPIO_VIP_PAD_VPHCTL,
+	GPIO_VIP_PAD_VIPCLK,
+	GPIO_VIP_PAD_VID,
+	GPIO_VIP_PAD_VPCLK0,
+	GPIO_VIP_PAD_DVALID,
+	GPIO_VIP_PAD_PSYNC,
+	GPIO_VIP_PAD_COUNT,
+	GPIO_VIP_PAD_MIN = GPIO_VIP_PAD_SCL,
+	GPIO_VIP_PAD_MAX = GPIO_VIP_PAD_PSYNC
+};
+
+enum gpio_sync {
+	GPIO_SYNC_UNKNOWN = (-1),
+	GPIO_SYNC_HSYNC_A,
+	GPIO_SYNC_VSYNC_A,
+	GPIO_SYNC_HSYNC_B,
+	GPIO_SYNC_VSYNC_B,
+	GPIO_SYNC_COUNT,
+	GPIO_SYNC_MIN = GPIO_SYNC_HSYNC_A,
+	GPIO_SYNC_MAX = GPIO_SYNC_VSYNC_B
+};
+
+enum gpio_gsl {
+	GPIO_GSL_UNKNOWN = (-1),
+	GPIO_GSL_GENLOCK_CLOCK,
+	GPIO_GSL_GENLOCK_VSYNC,
+	GPIO_GSL_SWAPLOCK_A,
+	GPIO_GSL_SWAPLOCK_B,
+	GPIO_GSL_COUNT,
+	GPIO_GSL_MIN = GPIO_GSL_GENLOCK_CLOCK,
+	GPIO_GSL_MAX = GPIO_GSL_SWAPLOCK_B
+};
+
+/*
+ * @brief
+ * Unique Id for DDC handle.
+ * Values are meaningful (used as indexes to array)
+ */
+enum gpio_ddc_line {
+	GPIO_DDC_LINE_UNKNOWN = (-1),
+	GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_DDC2,
+	GPIO_DDC_LINE_DDC3,
+	GPIO_DDC_LINE_DDC4,
+	GPIO_DDC_LINE_DDC5,
+	GPIO_DDC_LINE_DDC6,
+	GPIO_DDC_LINE_DDC_VGA,
+	GPIO_DDC_LINE_VIP_PAD,
+	GPIO_DDC_LINE_I2C_PAD = GPIO_DDC_LINE_VIP_PAD,
+	GPIO_DDC_LINE_COUNT,
+	GPIO_DDC_LINE_MIN = GPIO_DDC_LINE_DDC1,
+	GPIO_DDC_LINE_MAX = GPIO_DDC_LINE_I2C_PAD
+};
+
+/*
+ * @brief
+ * Identifies the mode of operation to open a GPIO device.
+ * A GPIO device (pin) can be programmed in only one of these modes at a time.
+ */
+enum gpio_mode {
+	GPIO_MODE_UNKNOWN = (-1),
+	GPIO_MODE_INPUT,
+	GPIO_MODE_OUTPUT,
+	GPIO_MODE_FAST_OUTPUT,
+	GPIO_MODE_HARDWARE,
+	GPIO_MODE_INTERRUPT
+};
+
+/*
+ * @brief
+ * Identifies the source of the signal when GPIO is in HW mode.
+ * get_signal_source() will return GPIO_SYGNAL_SOURCE__UNKNOWN
+ * when one of the following holds:
+ *    1. GPIO is input GPIO
+ *    2. GPIO is not opened in HW mode
+ *    3. GPIO does not have fixed signal source
+ *    (like DC_GenericA have mux instead fixed)
+ */
+enum gpio_signal_source {
+	GPIO_SIGNAL_SOURCE_UNKNOWN = (-1),
+	GPIO_SIGNAL_SOURCE_DACA_STEREO_SYNC,
+	GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC,
+	GPIO_SIGNAL_SOURCE_DACB_STEREO_SYNC,
+	GPIO_SIGNAL_SOURCE_DACA_HSYNC,
+	GPIO_SIGNAL_SOURCE_DACB_HSYNC,
+	GPIO_SIGNAL_SOURCE_DACA_VSYNC,
+	GPIO_SIGNAL_SOURCE_DACB_VSYNC,
+};
+
+enum gpio_stereo_source {
+	GPIO_STEREO_SOURCE_UNKNOWN = (-1),
+	GPIO_STEREO_SOURCE_D1,
+	GPIO_STEREO_SOURCE_D2,
+	GPIO_STEREO_SOURCE_D3,
+	GPIO_STEREO_SOURCE_D4,
+	GPIO_STEREO_SOURCE_D5,
+	GPIO_STEREO_SOURCE_D6
+};
+
+/*
+ * GPIO config
+ */
+
+enum gpio_config_type {
+	GPIO_CONFIG_TYPE_NONE,
+	GPIO_CONFIG_TYPE_DDC,
+	GPIO_CONFIG_TYPE_HPD,
+	GPIO_CONFIG_TYPE_GENERIC_MUX,
+	GPIO_CONFIG_TYPE_GSL_MUX,
+	GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE
+};
+
+/* DDC configuration */
+
+enum gpio_ddc_config_type {
+	GPIO_DDC_CONFIG_TYPE_MODE_AUX,
+	GPIO_DDC_CONFIG_TYPE_MODE_I2C,
+	GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT,
+	GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT,
+	GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING
+};
+
+struct gpio_ddc_config {
+	enum gpio_ddc_config_type type;
+	bool data_en_bit_present;
+	bool clock_en_bit_present;
+};
+
+/* HPD configuration */
+
+struct gpio_hpd_config {
+	uint32_t delay_on_connect; /* milliseconds */
+	uint32_t delay_on_disconnect; /* milliseconds */
+};
+
+struct gpio_generic_mux_config {
+	bool enable_output_from_mux;
+	enum gpio_signal_source mux_select;
+	enum gpio_stereo_source stereo_select;
+};
+
+enum gpio_gsl_mux_config_type {
+	GPIO_GSL_MUX_CONFIG_TYPE_DISABLE,
+	GPIO_GSL_MUX_CONFIG_TYPE_TIMING_SYNC,
+	GPIO_GSL_MUX_CONFIG_TYPE_FLIP_SYNC
+};
+
+struct gpio_gsl_mux_config {
+	enum gpio_gsl_mux_config_type type;
+	/* Actually sync_source type,
+	 * however we want to avoid inter-component includes here */
+	uint32_t gsl_group;
+};
+
+struct gpio_config_data {
+	enum gpio_config_type type;
+	union {
+		struct gpio_ddc_config ddc;
+		struct gpio_hpd_config hpd;
+		struct gpio_generic_mux_config generic_mux;
+		struct gpio_gsl_mux_config gsl_mux;
+	} config;
+};
+
+
+struct gpio_ddc_open_options {
+	bool en_bit_present;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_csc_types.h b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h
new file mode 100644
index 000000000000..711b458ff564
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_csc_types.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_CSC_TYPES_H__
+#define __DAL_GRPH_CSC_TYPES_H__
+
+#include "set_mode_types.h"
+
+enum color_space {
+	COLOR_SPACE_UNKNOWN,
+	COLOR_SPACE_SRGB_FULL_RANGE,
+	COLOR_SPACE_SRGB_LIMITED_RANGE,
+	COLOR_SPACE_YPBPR601,
+	COLOR_SPACE_YPBPR709,
+	COLOR_SPACE_YCBCR601,
+	COLOR_SPACE_YCBCR709,
+	COLOR_SPACE_YCBCR601_YONLY,
+	COLOR_SPACE_YCBCR709_YONLY,
+	COLOR_SPACE_N_MVPU_SUPER_AA,
+};
+
+enum grph_color_adjust_option {
+	GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
+	GRPH_COLOR_MATRIX_SW
+};
+
+enum grph_csc_adjust_item {
+	GRPH_ADJUSTMENT_CONTRAST = 1,
+	GRPH_ADJUSTMENT_SATURATION,
+	GRPH_ADJUSTMENT_BRIGHTNESS,
+	GRPH_ADJUSTMENT_HUE,
+	GRPH_ADJUSTMENT_COLOR_TEMPERATURE
+};
+
+#define CSC_TEMPERATURE_MATRIX_SIZE 9
+
+enum graphics_csc_adjust_type {
+	GRAPHICS_CSC_ADJUST_TYPE_BYPASS = 0,
+	GRAPHICS_CSC_ADJUST_TYPE_HW, /* without adjustments */
+	GRAPHICS_CSC_ADJUST_TYPE_SW  /*use adjustments */
+};
+
+enum graphics_gamut_adjust_type {
+	GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS = 0,
+	GRAPHICS_GAMUT_ADJUST_TYPE_HW, /* without adjustments */
+	GRAPHICS_GAMUT_ADJUST_TYPE_SW  /* use adjustments */
+};
+
+struct grph_csc_adjustment {
+	enum grph_color_adjust_option color_adjust_option;
+	enum color_space c_space;
+	int32_t grph_cont;
+	int32_t grph_sat;
+	int32_t grph_bright;
+	int32_t grph_hue;
+	int32_t adjust_divider;
+	int32_t temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE];
+	int32_t temperature_divider;
+	uint32_t lb_color_depth;
+	uint8_t gamma; /* gamma from Edid */
+	enum dc_color_depth color_depth; /* clean up to uint32_t */
+	enum pixel_format surface_pixel_format;
+	enum graphics_csc_adjust_type   csc_adjust_type;
+	enum graphics_gamut_adjust_type gamut_adjust_type;
+};
+
+struct default_adjustment {
+	uint32_t lb_color_depth;
+	enum color_space color_space;
+	enum dc_color_depth color_depth;
+	enum pixel_format surface_pixel_format;
+	enum graphics_csc_adjust_type csc_adjust_type;
+	bool force_hw_default;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
new file mode 100644
index 000000000000..2ed01bd43c37
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_object_ctrl_defs.h
@@ -0,0 +1,593 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_OBJECT_CTRL_DEFS_H__
+#define __DAL_GRPH_OBJECT_CTRL_DEFS_H__
+
+#include "grph_object_defs.h"
+
+/*
+ * #####################################################
+ * #####################################################
+ *
+ * These defines shared between asic_control/bios_parser and other
+ * DAL components
+ *
+ * #####################################################
+ * #####################################################
+ */
+
+enum tv_standard {
+	TV_STANDARD_UNKNOWN = 0, /* direct HW (mmBIOS_SCRATCH_2) translation! */
+	TV_STANDARD_NTSC,
+	TV_STANDARD_NTSCJ,
+	TV_STANDARD_PAL,
+	TV_STANDARD_PALM,
+	TV_STANDARD_PALCN,
+	TV_STANDARD_PALN,
+	TV_STANDARD_PAL60,
+	TV_STANDARD_SECAM
+};
+
+enum cv_standard {
+	CV_STANDARD_UNKNOWN = 0x0000,
+	CV_STANDARD_HD_MASK = 0x0800,		/* Flag mask HDTV output */
+	CV_STANDARD_SD_NTSC_MASK = 0x1000,	/* Flag mask NTSC output */
+	CV_STANDARD_SD_NTSC_M,		/* NTSC (North America) output 1001 */
+	CV_STANDARD_SD_NTSC_J,		/* NTSC (Japan) output 1002 */
+	CV_STANDARD_SD_480I,		/* SDTV 480i output 1003 */
+	CV_STANDARD_SD_480P,		/* SDTV 480p output 1004 */
+	CV_STANDARD_HD_720_60P = 0x1800,/* HDTV 720/60p output 1800 */
+	CV_STANDARD_HD_1080_60I,	/* HDTV 1080/60i output 1801 */
+	CV_STANDARD_SD_PAL_MASK = 0x2000,/* Flag mask PAL output */
+	CV_STANDARD_SD_PAL_B,			/* PAL B output 2001 */
+	CV_STANDARD_SD_PAL_D,			/* PAL D output 2002 */
+	CV_STANDARD_SD_PAL_G,			/* PAL G output 2003 */
+	CV_STANDARD_SD_PAL_H,			/* PAL H output 2004 */
+	CV_STANDARD_SD_PAL_I,			/* PAL I output 2005 */
+	CV_STANDARD_SD_PAL_M,			/* PAL M output 2006 */
+	CV_STANDARD_SD_PAL_N,			/* PAL N output 2007 */
+	CV_STANDARD_SD_PAL_N_COMB,	/* PAL Combination N output 2008 */
+	CV_STANDARD_SD_PAL_60,		/* PAL 60 output (test mode) 2009 */
+	CV_STANDARD_SD_576I,		/* SDTV 576i output 2010 */
+	CV_STANDARD_SD_576P,		/* SDTV 576p output 2011 */
+	CV_STANDARD_HD_720_50P = 0x2800,/* HDTV 720/50p output 2800 */
+	CV_STANDARD_HD_1080_50I,	/* HDTV 1080/50i output 2801 */
+	CV_STANDARD_SD_SECAM_MASK = 0x4000, /* Flag mask SECAM output */
+	CV_STANDARD_SD_SECAM_B,		/* SECAM B output 4001 */
+	CV_STANDARD_SD_SECAM_D,		/* SECAM D output 4002 */
+	CV_STANDARD_SD_SECAM_G,		/* SECAM G output 4003 */
+	CV_STANDARD_SD_SECAM_H,		/* SECAM H output 4004 */
+	CV_STANDARD_SD_SECAM_K,		/* SECAM K output 4005 */
+	CV_STANDARD_SD_SECAM_K1,	/* SECAM K1 output 4006 */
+	CV_STANDARD_SD_SECAM_L,		/* SECAM L output 4007 */
+	CV_STANDARD_SD_SECAM_L1		/* SECAM L1 output 4009 */
+};
+
+enum display_output_bit_depth {
+	PANEL_UNDEFINE = 0,
+	PANEL_6BIT_COLOR = 1,
+	PANEL_8BIT_COLOR = 2,
+	PANEL_10BIT_COLOR = 3,
+	PANEL_12BIT_COLOR = 4,
+	PANEL_16BIT_COLOR = 5,
+};
+
+enum lcd_scale {
+	/* No request to turn on LCD SCALER (Centering or Replication) */
+	LCD_SCALE_NONE = 0,
+	/* Request LCD SCALER in full panel mode */
+	LCD_SCALE_FULLPANEL,
+	/* Request LCD SCALER in aspect-ratio mode */
+	LCD_SCALE_ASPECTRATIO,
+
+	LCD_SCALE_UNKNOWN = (-1L),
+};
+
+/* Device type as abstracted by ATOM BIOS */
+enum dal_device_type {
+	DEVICE_TYPE_UNKNOWN = 0,
+	DEVICE_TYPE_LCD,
+	DEVICE_TYPE_CRT,
+	DEVICE_TYPE_DFP,
+	DEVICE_TYPE_CV,
+	DEVICE_TYPE_TV,
+	DEVICE_TYPE_CF,
+	DEVICE_TYPE_WIRELESS
+};
+
+/* Device ID as abstracted by ATOM BIOS */
+struct device_id {
+	enum dal_device_type device_type:16;
+	uint32_t enum_id:16;	/* 1 based enum */
+};
+
+struct graphics_object_i2c_info {
+	struct gpio_info {
+		uint32_t clk_mask_register_index;
+		uint32_t clk_en_register_index;
+		uint32_t clk_y_register_index;
+		uint32_t clk_a_register_index;
+		uint32_t data_mask_register_index;
+		uint32_t data_en_register_index;
+		uint32_t data_y_register_index;
+		uint32_t data_a_register_index;
+
+		uint32_t clk_mask_shift;
+		uint32_t clk_en_shift;
+		uint32_t clk_y_shift;
+		uint32_t clk_a_shift;
+		uint32_t data_mask_shift;
+		uint32_t data_en_shift;
+		uint32_t data_y_shift;
+		uint32_t data_a_shift;
+	} gpio_info;
+
+	bool i2c_hw_assist;
+	uint32_t i2c_line;
+	uint32_t i2c_engine_id;
+	uint32_t i2c_slave_address;
+};
+
+
+struct graphics_object_hpd_info {
+	uint8_t hpd_int_gpio_uid;
+	uint8_t hpd_active;
+};
+
+struct connector_device_tag_info {
+	uint32_t acpi_device;
+	struct device_id dev_id;
+};
+
+struct device_timing {
+	struct misc_info {
+		uint32_t HORIZONTAL_CUT_OFF:1;
+		/* 0=Active High, 1=Active Low */
+		uint32_t H_SYNC_POLARITY:1;
+		/* 0=Active High, 1=Active Low */
+		uint32_t V_SYNC_POLARITY:1;
+		uint32_t VERTICAL_CUT_OFF:1;
+		uint32_t H_REPLICATION_BY2:1;
+		uint32_t V_REPLICATION_BY2:1;
+		uint32_t COMPOSITE_SYNC:1;
+		uint32_t INTERLACE:1;
+		uint32_t DOUBLE_CLOCK:1;
+		uint32_t RGB888:1;
+		uint32_t GREY_LEVEL:2;
+		uint32_t SPATIAL:1;
+		uint32_t TEMPORAL:1;
+		uint32_t API_ENABLED:1;
+	} misc_info;
+
+	uint32_t pixel_clk; /* in KHz */
+	uint32_t horizontal_addressable;
+	uint32_t horizontal_blanking_time;
+	uint32_t vertical_addressable;
+	uint32_t vertical_blanking_time;
+	uint32_t horizontal_sync_offset;
+	uint32_t horizontal_sync_width;
+	uint32_t vertical_sync_offset;
+	uint32_t vertical_sync_width;
+	uint32_t horizontal_border;
+	uint32_t vertical_border;
+};
+
+struct supported_refresh_rate {
+	uint32_t REFRESH_RATE_30HZ:1;
+	uint32_t REFRESH_RATE_40HZ:1;
+	uint32_t REFRESH_RATE_48HZ:1;
+	uint32_t REFRESH_RATE_50HZ:1;
+	uint32_t REFRESH_RATE_60HZ:1;
+};
+
+struct embedded_panel_info {
+	struct device_timing lcd_timing;
+	uint32_t ss_id;
+	struct supported_refresh_rate supported_rr;
+	uint32_t drr_enabled;
+	uint32_t min_drr_refresh_rate;
+};
+
+struct embedded_panel_patch_mode {
+	uint32_t width;
+	uint32_t height;
+};
+
+struct firmware_info {
+	struct pll_info {
+		uint32_t crystal_frequency; /* in KHz */
+		uint32_t min_input_pxl_clk_pll_frequency; /* in KHz */
+		uint32_t max_input_pxl_clk_pll_frequency; /* in KHz */
+		uint32_t min_output_pxl_clk_pll_frequency; /* in KHz */
+		uint32_t max_output_pxl_clk_pll_frequency; /* in KHz */
+	} pll_info;
+
+	struct firmware_feature {
+		uint32_t memory_clk_ss_percentage;
+		uint32_t engine_clk_ss_percentage;
+	} feature;
+
+	uint32_t default_display_engine_pll_frequency; /* in KHz */
+	uint32_t external_clock_source_frequency_for_dp; /* in KHz */
+	uint32_t smu_gpu_pll_output_freq; /* in KHz */
+	uint8_t min_allowed_bl_level;
+	uint8_t remote_display_config;
+};
+
+/* direct HW (mmBIOS_SCRATCH_2) translation! */
+union tv_standard_support {
+	uint8_t u_all;
+	struct {
+		bool TV_SUPPORT_NTSC:1;
+		bool TV_SUPPORT_NTSCJ:1;
+
+		bool TV_SUPPORT_PAL:1;
+		bool TV_SUPPORT_PALM:1;
+		bool TV_SUPPORT_PALCN:1;
+		bool TV_SUPPORT_PALN:1;
+		bool TV_SUPPORT_PAL60:1;
+
+		bool TV_SUPPORT_SECAM:1;
+	} bits;
+};
+
+struct analog_tv_info {
+	union tv_standard_support tv_suppported;
+	union tv_standard_support tv_boot_up_default;
+};
+
+struct step_and_delay_info {
+    uint32_t step;
+    uint32_t delay;
+    uint32_t recommended_ref_div;
+};
+
+struct spread_spectrum_info {
+	struct spread_spectrum_type {
+		bool CENTER_MODE:1;
+		bool EXTERNAL:1;
+		bool STEP_AND_DELAY_INFO:1;
+	} type;
+
+	/* in unit of 0.01% (spreadPercentageDivider = 100),
+	otherwise in 0.001% units (spreadPercentageDivider = 1000); */
+	uint32_t spread_spectrum_percentage;
+	uint32_t spread_percentage_divider; /* 100 or 1000 */
+	uint32_t spread_spectrum_range; /* modulation freq (HZ)*/
+
+	union {
+		struct step_and_delay_info step_and_delay_info;
+		/* For mem/engine/uvd, Clock Out frequence (VCO ),
+		in unit of kHz. For TMDS/HDMI/LVDS, it is pixel clock,
+		for DP, it is link clock ( 270000 or 162000 ) */
+		uint32_t target_clock_range; /* in KHz */
+	};
+
+};
+
+struct graphics_object_encoder_cap_info {
+	uint32_t dp_hbr2_cap:1;
+	uint32_t dp_hbr2_validated:1;
+	uint32_t reserved:15;
+};
+
+struct din_connector_info {
+	uint32_t gpio_id;
+	bool gpio_tv_active_state;
+};
+
+/* Invalid channel mapping */
+enum { INVALID_DDI_CHANNEL_MAPPING = 0x0 };
+
+/**
+ * DDI PHY channel mapping reflecting XBAR setting
+ */
+union ddi_channel_mapping {
+	struct mapping {
+		uint8_t lane0:2;	/* Mapping for lane 0 */
+		uint8_t lane1:2;	/* Mapping for lane 1 */
+		uint8_t lane2:2;	/* Mapping for lane 2 */
+		uint8_t lane3:2;	/* Mapping for lane 3 */
+	} mapping;
+	uint8_t raw;
+};
+
+/**
+* Transmitter output configuration description
+*/
+struct transmitter_configuration_info {
+	/* DDI PHY ID for the transmitter */
+	enum transmitter transmitter_phy_id;
+	/* DDI PHY channel mapping reflecting crossbar setting */
+	union ddi_channel_mapping output_channel_mapping;
+};
+
+struct transmitter_configuration {
+	/* Configuration for the primary transmitter */
+	struct transmitter_configuration_info primary_transmitter_config;
+	/* Secondary transmitter configuration for Dual-link DVI */
+	struct transmitter_configuration_info secondary_transmitter_config;
+};
+
+
+/* These size should be sufficient to store info coming from BIOS */
+#define NUMBER_OF_UCHAR_FOR_GUID 16
+#define MAX_NUMBER_OF_EXT_DISPLAY_PATH 7
+#define NUMBER_OF_CSR_M3_ARB 10
+#define NUMBER_OF_DISP_CLK_VOLTAGE 4
+#define NUMBER_OF_AVAILABLE_SCLK 5
+
+/* V6 */
+struct integrated_info {
+	struct clock_voltage_caps {
+		/* The Voltage Index indicated by FUSE, same voltage index
+		shared with SCLK DPM fuse table */
+		uint32_t voltage_index;
+		/* Maximum clock supported with specified voltage index */
+		uint32_t max_supported_clk; /* in KHz */
+	} disp_clk_voltage[NUMBER_OF_DISP_CLK_VOLTAGE];
+
+	struct display_connection_info {
+		struct external_display_path {
+			/* A bit vector to show what devices are supported */
+			uint32_t device_tag;
+			/* 16bit device ACPI id. */
+			uint32_t device_acpi_enum;
+			/* A physical connector for displays to plug in,
+			using object connector definitions */
+			struct graphics_object_id device_connector_id;
+			/* An index into external AUX/DDC channel LUT */
+			uint8_t ext_aux_ddc_lut_index;
+			/* An index into external HPD pin LUT */
+			uint8_t ext_hpd_pin_lut_index;
+			/* external encoder object id */
+			struct graphics_object_id ext_encoder_obj_id;
+			/* XBAR mapping of the PHY channels */
+			union ddi_channel_mapping channel_mapping;
+		} path[MAX_NUMBER_OF_EXT_DISPLAY_PATH];
+
+		uint8_t gu_id[NUMBER_OF_UCHAR_FOR_GUID];
+		uint8_t checksum;
+	} ext_disp_conn_info; /* exiting long long time */
+
+	struct available_s_clk_list {
+		/* Maximum clock supported with specified voltage index */
+		uint32_t supported_s_clk; /* in KHz */
+		/* The Voltage Index indicated by FUSE for specified SCLK */
+		uint32_t voltage_index;
+		/* The Voltage ID indicated by FUSE for specified SCLK */
+		uint32_t voltage_id;
+	} avail_s_clk[NUMBER_OF_AVAILABLE_SCLK];
+
+	uint8_t memory_type;
+	uint8_t ma_channel_number;
+	uint32_t boot_up_engine_clock; /* in KHz */
+	uint32_t dentist_vco_freq; /* in KHz */
+	uint32_t boot_up_uma_clock; /* in KHz */
+	uint32_t boot_up_req_display_vector;
+	uint32_t other_display_misc;
+	uint32_t gpu_cap_info;
+	uint32_t sb_mmio_base_addr;
+	uint32_t system_config;
+	uint32_t cpu_cap_info;
+	uint32_t max_nb_voltage;
+	uint32_t min_nb_voltage;
+	uint32_t boot_up_nb_voltage;
+	uint32_t ext_disp_conn_info_offset;
+	uint32_t csr_m3_arb_cntl_default[NUMBER_OF_CSR_M3_ARB];
+	uint32_t csr_m3_arb_cntl_uvd[NUMBER_OF_CSR_M3_ARB];
+	uint32_t csr_m3_arb_cntl_fs3d[NUMBER_OF_CSR_M3_ARB];
+	uint32_t gmc_restore_reset_time;
+	uint32_t minimum_n_clk;
+	uint32_t idle_n_clk;
+	uint32_t ddr_dll_power_up_time;
+	uint32_t ddr_pll_power_up_time;
+	/* start for V6 */
+	uint32_t pcie_clk_ss_type;
+	uint32_t lvds_ss_percentage;
+	uint32_t lvds_sspread_rate_in_10hz;
+	uint32_t hdmi_ss_percentage;
+	uint32_t hdmi_sspread_rate_in_10hz;
+	uint32_t dvi_ss_percentage;
+	uint32_t dvi_sspread_rate_in_10_hz;
+	uint32_t sclk_dpm_boost_margin;
+	uint32_t sclk_dpm_throttle_margin;
+	uint32_t sclk_dpm_tdp_limit_pg;
+	uint32_t sclk_dpm_tdp_limit_boost;
+	uint32_t boost_engine_clock;
+	uint32_t boost_vid_2bit;
+	uint32_t enable_boost;
+	uint32_t gnb_tdp_limit;
+	/* Start from V7 */
+	uint32_t max_lvds_pclk_freq_in_single_link;
+	uint32_t lvds_misc;
+	uint32_t lvds_pwr_on_seq_dig_on_to_de_in_4ms;
+	uint32_t lvds_pwr_on_seq_de_to_vary_bl_in_4ms;
+	uint32_t lvds_pwr_off_seq_vary_bl_to_de_in4ms;
+	uint32_t lvds_pwr_off_seq_de_to_dig_on_in4ms;
+	uint32_t lvds_off_to_on_delay_in_4ms;
+	uint32_t lvds_pwr_on_seq_vary_bl_to_blon_in_4ms;
+	uint32_t lvds_pwr_off_seq_blon_to_vary_bl_in_4ms;
+	uint32_t lvds_reserved1;
+	uint32_t lvds_bit_depth_control_val;
+};
+
+/**
+* Power source ids.
+*/
+enum power_source {
+	POWER_SOURCE_AC = 0,
+	POWER_SOURCE_DC,
+	POWER_SOURCE_LIMITED_POWER,
+	POWER_SOURCE_LIMITED_POWER_2,
+	POWER_SOURCE_MAX
+};
+
+struct bios_event_info {
+	uint32_t thermal_state;
+	uint32_t backlight_level;
+	enum power_source powerSource;
+	bool has_thermal_state_changed;
+	bool has_power_source_changed;
+	bool has_forced_mode_changed;
+	bool forced_mode;
+	bool backlight_changed;
+};
+
+union stereo_3d_support {
+	struct {
+		/* HW can alter left and right image sequentially */
+		uint32_t FRAME_ALTERNATE:1;
+		/* Frame Alternate + HW can integrate stereosync
+		signal into TMDS stream */
+		uint32_t DVI_FRAME_ALT:1;
+		/* Frame Alternate + HW can integrate stereosync
+		signal into DP stream */
+		uint32_t DISPLAY_PORT_FRAME_ALT:1;
+		/* Frame Alternate + HW can drive stereosync signal
+		on separate line */
+		uint32_t SIDEBAND_FRAME_ALT:1;
+		/* SW allowed to pack left and right image into single frame.
+		Used for HDMI only, DP has it's own flags. */
+		uint32_t SW_FRAME_PACK:1;
+		/* HW can pack left and right image into single HDMI frame */
+		uint32_t PROGRESSIVE_FRAME_PACK:1;
+		/* HW can pack left and right interlaced images into
+		single HDMI frame */
+		uint32_t INTERLACE_FRAME_PACK:1;
+		/* HW can pack left and right images into single DP frame */
+		uint32_t DISPLAY_PORT_FRAME_PACK:1;
+		/* SW can pack left and right images into single DP frame */
+		uint32_t DISPLAY_PORT_SW_FRAME_PACK:1;
+		/* HW can mix left and right images into single image */
+		uint32_t INTERLEAVE:1;
+		/* HW can mix left and right interlaced images
+		into single image */
+		uint32_t INTERLACE_INTERLEAVE:1;
+		/* Allow display-based formats (whatever supported)
+		in WS stereo mode */
+		uint32_t DISPLAY_3DIN_WS_MODE:1;
+		/* Side-by-side, packed by application/driver into 2D frame */
+		uint32_t SIDE_BY_SIDE_SW_PACKED:1;
+		/* Top-and-bottom, packed by application/driver into 2D frame */
+		uint32_t TOP_AND_BOTTOM_SW_PACKED:1;
+	} bits;
+	uint32_t u_all;
+};
+
+/* Bitvector and bitfields of possible optimizations
+ #IMPORTANT# Keep bitfields match bitvector! */
+enum optimization_feature {
+	/* Don't do HW programming on panels that were enabled by VBIOS */
+	OF_SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY = 0x1,
+	OF_SKIP_RESET_OF_ALL_HW_ON_S3RESUME = 0x2,
+	OF_SKIP_HW_RESET_OF_EMBEDDED_DISPLAY_ON_S3RESUME = 0x4,
+	OF_SKIP_POWER_UP_VBIOS_ENABLED_ENCODER = 0x8,
+	/* Do not turn off VCC while powering down on boot or resume */
+	OF_KEEP_VCC_DURING_POWER_DOWN_ON_BOOT_OR_RESUME = 0x10,
+	/* Do not turn off VCC while performing SetMode */
+	OF_KEEP_VCC_DURING_SET_MODE = 0x20,
+	OF_DO_NOT_WAIT_FOR_HPD_LOW = 0x40,
+	OF_SKIP_POWER_DOWN_INACTIVE_ENCODER = 0x80
+};
+
+union optimization_flags {
+	struct {
+		/* Don't do HW programming if panels were enabled by VBIOS */
+		uint32_t SKIP_HW_PROGRAMMING_ON_ENABLED_EMBEDDED_DISPLAY:1;
+		uint32_t SKIP_RESET_OF_ALL_HW_ON_S3RESUME:1;
+		uint32_t SKIP_HW_RESET_OF_EMBEDDED_DISPLAY_ON_S3RESUME:1;
+		uint32_t SKIP_POWER_UP_VBIOS_ENABLED_ENCODER:1;
+		/* Do not turn off VCC while powering down on boot or resume */
+		uint32_t KEEP_VCC_DURING_POWER_DOWN_ON_BOOT_OR_RESUME:1;
+		/* Do not turn off VCC while performing SetMode */
+		uint32_t KEEP_VCC_DURING_SET_MODE:1;
+		uint32_t DO_NOT_WAIT_FOR_HPD_LOW:1;
+	} bits;
+	uint32_t u_all;
+};
+
+/* Bitvector and bitfields of performance measurements
+ #IMPORTANT# Keep bitfields match bitvector! */
+enum perf_measure {
+	PERF_MEASURE_ADAPTER_POWER_STATE = 0x1,
+	PERF_MEASURE_DISPLAY_POWER_STATE = 0x2,
+	PERF_MEASURE_SET_MODE_SEQ = 0x4,
+	PERF_MEASURE_DETECT_AT_RESUME = 0x8,
+	PERF_MEASURE_MEMORY_READ_CONTROL = 0x10,
+};
+
+union perf_measure_flags {
+	struct {
+		uint32_t ADAPTER_POWER_STATE:1;
+		uint32_t DISPLAY_POWER_STATE:1;
+		uint32_t SET_MODE_SEQ:1;
+		uint32_t DETECT_AT_RESUME:1;
+		uint32_t MEMORY_READ_CONTROL:1;
+
+	} bits;
+	uint32_t u_all;
+};
+
+enum {
+	PERF_MEASURE_POWERCODE_OFFSET = 0x0,
+	PERF_MEASURE_POWER_CODE_MASK = 0xFF,
+	PERF_MEASURE_POWER_STATE_OFFSET = 8,
+	PERF_MEASURE_POWER_STATE_MASK = 0x000FF00,
+	PERF_MEASURE_PREV_POWER_STATE_OFFSET = 16,
+	PERF_MEASURE_PREV_POWER_STATE_MASK = 0x00FF0000,
+	PERF_MEASURE_DISPLAY_INDEX_OFFSET = 24,
+	PERF_MEASURE_DISPLAY_INDEX_MASK = 0xFF000000
+};
+
+enum {
+	HDMI_PIXEL_CLOCK_IN_KHZ_297 = 297000,
+	TMDS_PIXEL_CLOCK_IN_KHZ_165 = 165000
+};
+
+/*
+ * DFS-bypass flag
+ */
+/* Copy of SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS from atombios.h */
+enum {
+	DFS_BYPASS_ENABLE = 0x10
+};
+
+enum {
+	INVALID_BACKLIGHT = -1
+};
+
+struct panel_backlight_boundaries {
+	uint32_t min_signal_level;
+	uint32_t max_signal_level;
+};
+
+struct panel_backlight_default_levels {
+	uint32_t ac_level_percentage;
+	uint32_t dc_level_percentage;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_defs.h b/drivers/gpu/drm/amd/dal/include/grph_object_defs.h
new file mode 100644
index 000000000000..a1e468fbbb2b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_object_defs.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_OBJECT_DEFS_H__
+#define __DAL_GRPH_OBJECT_DEFS_H__
+
+#include "grph_object_id.h"
+
+/* ********************************************************************
+ * ********************************************************************
+ *
+ *  These defines shared between All Graphics Objects
+ *
+ * ********************************************************************
+ * ********************************************************************
+ */
+
+/* HPD unit id - HW direct translation */
+enum hpd_source_id {
+	HPD_SOURCEID1 = 0,
+	HPD_SOURCEID2,
+	HPD_SOURCEID3,
+	HPD_SOURCEID4,
+	HPD_SOURCEID5,
+	HPD_SOURCEID6,
+
+	HPD_SOURCEID_COUNT,
+	HPD_SOURCEID_UNKNOWN
+};
+
+/* DDC unit id - HW direct translation */
+enum channel_id {
+	CHANNEL_ID_UNKNOWN = 0,
+	CHANNEL_ID_DDC1,
+	CHANNEL_ID_DDC2,
+	CHANNEL_ID_DDC3,
+	CHANNEL_ID_DDC4,
+	CHANNEL_ID_DDC5,
+	CHANNEL_ID_DDC6,
+	CHANNEL_ID_DDC_VGA,
+	CHANNEL_ID_I2C_PAD,
+	CHANNEL_ID_COUNT
+};
+
+#define DECODE_CHANNEL_ID(ch_id) \
+	(ch_id) == CHANNEL_ID_DDC1 ? "CHANNEL_ID_DDC1" : \
+	(ch_id) == CHANNEL_ID_DDC2 ? "CHANNEL_ID_DDC2" : \
+	(ch_id) == CHANNEL_ID_DDC3 ? "CHANNEL_ID_DDC3" : \
+	(ch_id) == CHANNEL_ID_DDC4 ? "CHANNEL_ID_DDC4" : \
+	(ch_id) == CHANNEL_ID_DDC5 ? "CHANNEL_ID_DDC5" : \
+	(ch_id) == CHANNEL_ID_DDC6 ? "CHANNEL_ID_DDC6" : \
+	(ch_id) == CHANNEL_ID_DDC_VGA ? "CHANNEL_ID_DDC_VGA" : \
+	(ch_id) == CHANNEL_ID_I2C_PAD ? "CHANNEL_ID_I2C_PAD" : "Invalid"
+
+enum transmitter {
+	TRANSMITTER_UNKNOWN = (-1L),
+	TRANSMITTER_UNIPHY_A,
+	TRANSMITTER_UNIPHY_B,
+	TRANSMITTER_UNIPHY_C,
+	TRANSMITTER_UNIPHY_D,
+	TRANSMITTER_UNIPHY_E,
+	TRANSMITTER_UNIPHY_F,
+	TRANSMITTER_NUTMEG_CRT,
+	TRANSMITTER_TRAVIS_CRT,
+	TRANSMITTER_TRAVIS_LCD,
+	TRANSMITTER_UNIPHY_G,
+	TRANSMITTER_COUNT
+};
+
+enum physical_phy_id {
+	PHY_ID_UNKNOWN = (-1L),
+	PHY_ID_0,
+	PHY_ID_1,
+	PHY_ID_2,
+	PHY_ID_3,
+	PHY_ID_4,
+	PHY_ID_5,
+	PHY_ID_6,
+	PHY_ID_7,
+	PHY_ID_8,
+	PHY_ID_9,
+	PHY_ID_COUNT
+};
+
+/* Generic source of the synchronisation input/output signal */
+/* Can be used for flow control, stereo sync, timing sync, frame sync, etc */
+enum sync_source {
+	SYNC_SOURCE_NONE = 0,
+
+	/* Source based on controllers */
+	SYNC_SOURCE_CONTROLLER0,
+	SYNC_SOURCE_CONTROLLER1,
+	SYNC_SOURCE_CONTROLLER2,
+	SYNC_SOURCE_CONTROLLER3,
+	SYNC_SOURCE_CONTROLLER4,
+	SYNC_SOURCE_CONTROLLER5,
+
+	/* Source based on GSL group */
+	SYNC_SOURCE_GSL_GROUP0,
+	SYNC_SOURCE_GSL_GROUP1,
+	SYNC_SOURCE_GSL_GROUP2,
+
+	/* Source based on GSL IOs */
+	/* These IOs normally used as GSL input/output */
+	SYNC_SOURCE_GSL_IO_FIRST,
+	SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK = SYNC_SOURCE_GSL_IO_FIRST,
+	SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC,
+	SYNC_SOURCE_GSL_IO_SWAPLOCK_A,
+	SYNC_SOURCE_GSL_IO_SWAPLOCK_B,
+	SYNC_SOURCE_GSL_IO_LAST = SYNC_SOURCE_GSL_IO_SWAPLOCK_B,
+
+	/* Source based on regular IOs */
+	SYNC_SOURCE_IO_FIRST,
+	SYNC_SOURCE_IO_GENERIC_A = SYNC_SOURCE_IO_FIRST,
+	SYNC_SOURCE_IO_GENERIC_B,
+	SYNC_SOURCE_IO_GENERIC_C,
+	SYNC_SOURCE_IO_GENERIC_D,
+	SYNC_SOURCE_IO_GENERIC_E,
+	SYNC_SOURCE_IO_GENERIC_F,
+	SYNC_SOURCE_IO_HPD1,
+	SYNC_SOURCE_IO_HPD2,
+	SYNC_SOURCE_IO_HSYNC_A,
+	SYNC_SOURCE_IO_VSYNC_A,
+	SYNC_SOURCE_IO_HSYNC_B,
+	SYNC_SOURCE_IO_VSYNC_B,
+	SYNC_SOURCE_IO_LAST = SYNC_SOURCE_IO_VSYNC_B,
+
+	/* Misc. flow control sources */
+	SYNC_SOURCE_DUAL_GPU_PIN
+};
+
+enum trigger_edge {
+	TRIGGER_EDGE_RISING = 0,
+	TRIGGER_EDGE_FALLING,
+	TRIGGER_EDGE_BOTH,
+	TRIGGER_EDGE_DEFAULT
+};
+
+/* Parameters to enable CRTC trigger */
+struct trigger_params {
+	enum sync_source source;
+	enum trigger_edge edge;
+};
+
+/* CRTC Static Screen event triggers */
+struct static_screen_events {
+	union {
+		/* event mask to enable/disable various
+		   trigger sources for static screen detection */
+		struct {
+			/* Force event high */
+			uint32_t FRAME_START:1;
+			/* Cursor register change */
+			uint32_t CURSOR_MOVE:1;
+			/* Memory write to any client other than MCIF */
+			uint32_t MEM_WRITE:1;
+			/* Memory write to hit memory region 0 */
+			uint32_t MEM_REGION0_WRITE:1;
+			/* Memory write to hit memory region 1 */
+			uint32_t MEM_REGION1_WRITE:1;
+			/* Memory write to hit memory region 2 */
+			uint32_t MEM_REGION2_WRITE:1;
+			/* Memory write to hit memory region 3 */
+			uint32_t MEM_REGION3_WRITE:1;
+			/* Graphics Surface Update Pending */
+			uint32_t GFX_UPDATE:1;
+			/* Overlay Surface Update Pending */
+			uint32_t OVL_UPDATE:1;
+			/* Compressed surface invalidated in FBC */
+			uint32_t INVALIDATE_FBC_SURFACE:1;
+			/* Register pending update in any double buffered
+			register group in the display pipe
+			(i.e. Blender, DCP, or SCL) */
+			uint32_t REG_PENDING_UPDATE:1;
+			/* Crtc_trig_a: Based on signal from any other CRTC */
+			uint32_t CRTC_TRIG_A:1;
+			/* Crtc_trig_b: Based on signal from any other CRTC */
+			uint32_t CRTC_TRIG_B:1;
+			/* Readback of CRTC nominal vertical count register
+			by driver  indicates that OS may be trying to change
+			mode or contents of the display therefore need to
+			switch to higher refresh rate */
+			uint32_t READBACK_NOMINAL_VERTICAL:1;
+			/* Readback of CRTC dynamic vertical count register
+			by driver  indicates that OS may be trying to change
+			mode or contents of the display therefore need to
+			switch to higher refresh rate */
+			uint32_t READBACK_DYNAMIC_VERTICAL:1;
+			/* Reserved */
+			uint32_t RESERVED:1;
+		} bits;
+		uint32_t u_all;
+	};
+};
+
+
+/*
+ * ***************************************************************
+ * ********************* Register programming sequences ********
+ * ***************************************************************
+ */
+
+/* GPIO/Register access sequences */
+enum io_register_sequence {
+	/* GLSync sequences to access SwapReady & SwapRequest
+	GPIOs - GLSync Connector parameter */
+	IO_REG_SEQUENCE_SWAPREADY_SET = 0,
+	IO_REG_SEQUENCE_SWAPREADY_RESET,
+	IO_REG_SEQUENCE_SWAPREADY_READ,
+	IO_REG_SEQUENCE_SWAPREQUEST_SET,
+	IO_REG_SEQUENCE_SWAPREQUEST_RESET,
+	IO_REG_SEQUENCE_SWAPREQUEST_READ,
+
+	/* Frame synchronization start/stop - display index parameter */
+	IO_REG_SEQUENCE_FRAMELOCK_STOP,
+	IO_REG_SEQUENCE_FRAMELOCK_START,
+
+	/* Flip lock/unlock - GLSync Connector parameter */
+	IO_REG_SEQUENCE_GLOBALSWAP_LOCK,
+	IO_REG_SEQUENCE_GLOBALSWAP_UNLOCK,
+
+	IO_REG_SEQUENCEENUM_MAX
+};
+
+#define IO_REGISTER_SEQUENCE_MAX_LENGTH 5
+
+/*
+ *****************************************************************************
+ *                             struct io_register
+ *****************************************************************************
+ * Generic struct for read/write register or GPIO.
+ * It allows controlling only some bit section of register, rather then the
+ * whole one.
+ * For write operation should be used as following:
+ *   1. data  = READ(Base + RegisterOffset)
+ *   2. data &= ANDMask
+ *   3. data |= ORMask
+ *   4. WRITE(Base + RegisterOffset, data)
+ *
+ * Note: In case of regular register, ANDMask will be typically 0.
+ *	In case of GPIO, ANDMask will have typically all bits set
+ *	except the specific GPIO bit.
+ *
+ * For read operation should be used as following:
+ *   1. data   = READ(Base + RegisterOffset)
+ *   2. data  &= ANDMask
+ *   3. data >>= BitShift
+ *
+ * Note: In case of regular register, ANDMask will be typically 0xFFFFFFFF.
+ *	In case of GPIO, ANDMask will have typically only specific GPIO bit set
+ *
+ * Note: Base Address is not exposed in this structure due to
+ *	security consideration.
+ */
+
+/*
+ * The generic sequence to program/access registers or GPIOs.
+ * There could be 2 types of sequences - read and write.
+ * Read sequence may have 0 or more writes and in the end one read
+ * Write sequence may have 1 or more writes.
+ */
+struct io_reg_sequence {
+	/* Ordered array of register to program */
+	struct {
+		/* Offset of memory mapped register or GPIO */
+		uint32_t register_offset;
+		/* Mask to use at AND operation (Mandatory, comes
+		before OR operation) */
+		uint32_t and_mask;
+		union {
+			/* Mask to use at OR operation (For write
+			sequence only, comes after AND operation) */
+			uint32_t or_mask;
+			/* Number of bits to shift to get the actual value
+			(For read  sequence only, comes after AND operation) */
+			uint32_t bit_shift;
+		};
+	} io_registers[IO_REGISTER_SEQUENCE_MAX_LENGTH];
+
+	uint32_t steps_num; /* Total number of r/w steps in the sequence */
+};
+
+/* Sequence ID - uniqly defines sequence on single adapter */
+struct io_reg_sequence_id {
+	enum io_register_sequence sequence; /* Sequence enumeration Index/ID */
+	union {
+		/* Refers to object to which the sequence applies.*/
+		uint32_t index;
+		uint32_t display_index;
+		uint32_t controller_index;
+		uint32_t glsync_connector_index;
+	};
+};
+
+struct fbc_info {
+	bool fbc_enable;
+	bool lpt_enable;
+};
+
+/* Event to request TM change IRQ registration state */
+struct hotplug_irq_data {
+	bool disable;
+	struct graphics_object_id connector;
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/grph_object_id.h b/drivers/gpu/drm/amd/dal/include/grph_object_id.h
new file mode 100644
index 000000000000..372e46c9f0dd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/grph_object_id.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GRPH_OBJECT_ID_H__
+#define __DAL_GRPH_OBJECT_ID_H__
+
+/* Types of graphics objects */
+enum object_type {
+	OBJECT_TYPE_UNKNOWN  = 0,
+
+	/* Direct ATOM BIOS translation */
+	OBJECT_TYPE_GPU,
+	OBJECT_TYPE_ENCODER,
+	OBJECT_TYPE_CONNECTOR,
+	OBJECT_TYPE_ROUTER,
+	OBJECT_TYPE_GENERIC,
+
+	/* Driver specific */
+	OBJECT_TYPE_AUDIO,
+	OBJECT_TYPE_CONTROLLER,
+	OBJECT_TYPE_CLOCK_SOURCE,
+	OBJECT_TYPE_ENGINE,
+
+	OBJECT_TYPE_COUNT
+};
+
+/* Enumeration inside one type of graphics objects */
+enum object_enum_id {
+	ENUM_ID_UNKNOWN = 0,
+	ENUM_ID_1,
+	ENUM_ID_2,
+	ENUM_ID_3,
+	ENUM_ID_4,
+	ENUM_ID_5,
+	ENUM_ID_6,
+	ENUM_ID_7,
+
+	ENUM_ID_COUNT
+};
+
+/* Generic object ids */
+enum generic_id {
+	GENERIC_ID_UNKNOWN = 0,
+	GENERIC_ID_MXM_OPM,
+	GENERIC_ID_GLSYNC,
+	GENERIC_ID_STEREO,
+
+	GENERIC_ID_COUNT
+};
+
+/* Controller object ids */
+enum controller_id {
+	CONTROLLER_ID_UNDEFINED = 0,
+	CONTROLLER_ID_D0,
+	CONTROLLER_ID_D1,
+	CONTROLLER_ID_D2,
+	CONTROLLER_ID_D3,
+	CONTROLLER_ID_D4,
+	CONTROLLER_ID_D5,
+	CONTROLLER_ID_UNDERLAY0,
+	CONTROLLER_ID_MAX = CONTROLLER_ID_UNDERLAY0
+};
+
+#define IS_UNDERLAY_CONTROLLER(ctrlr_id) (ctrlr_id >= CONTROLLER_ID_UNDERLAY0)
+
+/*
+ * ClockSource object ids.
+ * We maintain the order matching (more or less) ATOM BIOS
+ * to improve optimized acquire
+ */
+enum clock_source_id {
+	CLOCK_SOURCE_ID_UNDEFINED = 0,
+	CLOCK_SOURCE_ID_PLL0,
+	CLOCK_SOURCE_ID_PLL1,
+	CLOCK_SOURCE_ID_PLL2,
+	CLOCK_SOURCE_ID_EXTERNAL, /* ID (Phy) ref. clk. for DP */
+	CLOCK_SOURCE_ID_DCPLL,
+	CLOCK_SOURCE_ID_DFS,	/* DENTIST */
+	CLOCK_SOURCE_ID_VCE,	/* VCE does not need a real PLL */
+	/* Used to distinguish between programming pixel clock and ID (Phy) clock */
+	CLOCK_SOURCE_ID_DP_DTO,
+
+	CLOCK_SOURCE_COMBO_PHY_PLL0,
+	CLOCK_SOURCE_COMBO_PHY_PLL1,
+	CLOCK_SOURCE_COMBO_PHY_PLL2,
+	CLOCK_SOURCE_COMBO_PHY_PLL3,
+	CLOCK_SOURCE_COMBO_PHY_PLL4,
+	CLOCK_SOURCE_COMBO_PHY_PLL5,
+	CLOCK_SOURCE_COMBO_DISPLAY_PLL0
+};
+
+
+/* Encoder object ids */
+enum encoder_id {
+	ENCODER_ID_UNKNOWN = 0,
+
+	/* Radeon Class Display Hardware */
+	ENCODER_ID_INTERNAL_LVDS,
+	ENCODER_ID_INTERNAL_TMDS1,
+	ENCODER_ID_INTERNAL_TMDS2,
+	ENCODER_ID_INTERNAL_DAC1,
+	ENCODER_ID_INTERNAL_DAC2,	/* TV/CV DAC */
+
+	/* External Third Party Encoders */
+	ENCODER_ID_INTERNAL_LVTM1,	/* not used for Radeon */
+	ENCODER_ID_INTERNAL_HDMI,
+
+	/* Kaledisope (KLDSCP) Class Display Hardware */
+	ENCODER_ID_INTERNAL_KLDSCP_TMDS1,
+	ENCODER_ID_INTERNAL_KLDSCP_DAC1,
+	ENCODER_ID_INTERNAL_KLDSCP_DAC2,	/* Shared with CV/TV and CRT */
+	/* External TMDS (dual link) */
+	ENCODER_ID_EXTERNAL_MVPU_FPGA,	/* MVPU FPGA chip */
+	ENCODER_ID_INTERNAL_DDI,
+	ENCODER_ID_INTERNAL_UNIPHY,
+	ENCODER_ID_INTERNAL_KLDSCP_LVTMA,
+	ENCODER_ID_INTERNAL_UNIPHY1,
+	ENCODER_ID_INTERNAL_UNIPHY2,
+	ENCODER_ID_EXTERNAL_NUTMEG,
+	ENCODER_ID_EXTERNAL_TRAVIS,
+
+	ENCODER_ID_INTERNAL_WIRELESS,	/* Internal wireless display encoder */
+	ENCODER_ID_INTERNAL_UNIPHY3,
+	ENCODER_ID_INTERNAL_VIRTUAL,
+};
+
+
+/* Connector object ids */
+enum connector_id {
+	CONNECTOR_ID_UNKNOWN = 0,
+	CONNECTOR_ID_SINGLE_LINK_DVII = 1,
+	CONNECTOR_ID_DUAL_LINK_DVII = 2,
+	CONNECTOR_ID_SINGLE_LINK_DVID = 3,
+	CONNECTOR_ID_DUAL_LINK_DVID = 4,
+	CONNECTOR_ID_VGA = 5,
+	CONNECTOR_ID_HDMI_TYPE_A = 12,
+	CONNECTOR_ID_LVDS = 14,
+	CONNECTOR_ID_PCIE = 16,
+	CONNECTOR_ID_HARDCODE_DVI = 18,
+	CONNECTOR_ID_DISPLAY_PORT = 19,
+	CONNECTOR_ID_EDP = 20,
+	CONNECTOR_ID_MXM = 21,
+	CONNECTOR_ID_WIRELESS = 22,
+	CONNECTOR_ID_MIRACAST = 23,
+
+	CONNECTOR_ID_VIRTUAL = 100
+};
+
+
+/* Audio object ids */
+enum audio_id {
+	AUDIO_ID_UNKNOWN = 0,
+	AUDIO_ID_INTERNAL_AZALIA
+};
+
+
+/* Engine object ids */
+enum engine_id {
+	ENGINE_ID_DIGA,
+	ENGINE_ID_DIGB,
+	ENGINE_ID_DIGC,
+	ENGINE_ID_DIGD,
+	ENGINE_ID_DIGE,
+	ENGINE_ID_DIGF,
+	ENGINE_ID_DIGG,
+	ENGINE_ID_DACA,
+	ENGINE_ID_DACB,
+	ENGINE_ID_VCE,	/* wireless display pseudo-encoder */
+	ENGINE_ID_VIRTUAL,
+
+	ENGINE_ID_COUNT,
+	ENGINE_ID_UNKNOWN = (-1L)
+};
+
+union supported_stream_engines {
+	struct {
+		uint32_t ENGINE_ID_DIGA:1;
+		uint32_t ENGINE_ID_DIGB:1;
+		uint32_t ENGINE_ID_DIGC:1;
+		uint32_t ENGINE_ID_DIGD:1;
+		uint32_t ENGINE_ID_DIGE:1;
+		uint32_t ENGINE_ID_DIGF:1;
+		uint32_t ENGINE_ID_DIGG:1;
+		uint32_t ENGINE_ID_DACA:1;
+		uint32_t ENGINE_ID_DACB:1;
+		uint32_t ENGINE_ID_VCE:1;
+	} engine;
+	uint32_t u_all;
+};
+
+enum transmitter_color_depth {
+	TRANSMITTER_COLOR_DEPTH_24 = 0,  /* 8  bits */
+	TRANSMITTER_COLOR_DEPTH_30,      /* 10 bits */
+	TRANSMITTER_COLOR_DEPTH_36,      /* 12 bits */
+	TRANSMITTER_COLOR_DEPTH_48       /* 16 bits */
+};
+
+/*
+ *****************************************************************************
+ * graphics_object_id struct
+ *
+ * graphics_object_id is a very simple struct wrapping 32bit Graphics
+ * Object identication
+ *
+ * This struct should stay very simple
+ *  No dependencies at all (no includes)
+ *  No debug messages or asserts
+ *  No #ifndef and preprocessor directives
+ *  No grow in space (no more data member)
+ *****************************************************************************
+ */
+
+struct graphics_object_id {
+	uint32_t  id:8;
+	uint32_t  enum_id:4;
+	uint32_t  type:4;
+	uint32_t  reserved:16; /* for padding. total size should be u32 */
+};
+
+/* some simple functions for convenient graphics_object_id handle */
+
+static inline struct graphics_object_id dal_graphics_object_id_init(
+	uint32_t id,
+	enum object_enum_id enum_id,
+	enum object_type type)
+{
+	struct graphics_object_id result = {
+		id, enum_id, type, 0
+	};
+
+	return result;
+}
+
+bool dal_graphics_object_id_is_valid(
+	struct graphics_object_id id);
+bool dal_graphics_object_id_is_equal(
+	struct graphics_object_id id1,
+	struct graphics_object_id id2);
+uint32_t dal_graphics_object_id_to_uint(
+	struct graphics_object_id id);
+
+
+enum controller_id dal_graphics_object_id_get_controller_id(
+	struct graphics_object_id id);
+enum clock_source_id dal_graphics_object_id_get_clock_source_id(
+	struct graphics_object_id id);
+enum encoder_id dal_graphics_object_id_get_encoder_id(
+	struct graphics_object_id id);
+enum connector_id dal_graphics_object_id_get_connector_id(
+	struct graphics_object_id id);
+enum audio_id dal_graphics_object_id_get_audio_id(
+	struct graphics_object_id id);
+enum engine_id dal_graphics_object_id_get_engine_id(
+	struct graphics_object_id id);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h b/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
new file mode 100644
index 000000000000..ddd78d6c97e3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/hw_sequencer_interface.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_SEQUENCER_INTERFACE_H__
+#define __DAL_HW_SEQUENCER_INTERFACE_H__
+
+#include "hw_sequencer_types.h"
+#include "hw_adjustment_types.h"
+#include "include/display_clock_interface.h"
+#include "include/scaler_types.h"
+#include "include/grph_csc_types.h"
+#include "plane_types.h"
+
+#include "adapter_service_interface.h"
+
+enum hwss_result {
+	HWSS_RESULT_OK,
+	HWSS_RESULT_ERROR,
+	HWSS_RESULT_NO_BANDWIDTH,
+	HWSS_RESULT_OUT_OF_RANGE,
+	HWSS_RESULT_NOT_SUPPORTED,
+	HWSS_RESULT_UNKNOWN
+};
+
+struct hws_init_data {
+	struct adapter_service *as;
+	struct dal_context *dal_context;
+};
+
+/* TODO: below is three almost equal structures.
+ * We should decide what to do with them */
+struct blank_stream_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	struct hw_crtc_timing timing;
+	struct link_settings link_settings;
+};
+
+struct enable_stream_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	struct hw_crtc_timing timing;
+	struct link_settings link_settings;
+
+	const struct hw_path_mode *path_mode;
+};
+
+struct enable_link_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	struct hw_crtc_timing timing;
+	struct link_settings link_settings;
+
+	bool optimized_programming;
+	const struct hw_path_mode *path_mode;
+};
+
+struct validate_link_param {
+	const struct display_path *display_path;
+	uint32_t link_idx;
+	struct link_settings link_settings;
+};
+
+struct set_dp_phy_pattern_param {
+	struct display_path *display_path;
+	uint32_t link_idx;
+	enum dp_test_pattern test_pattern;
+	const uint8_t *custom_pattern;
+	uint32_t cust_pattern_size;
+};
+
+struct hw_global_objects;
+struct hw_sequencer;
+struct hw_adjustment;
+struct hw_path_mode_set;
+struct hw_path_mode;
+struct hwss_build_params;
+struct controller;
+
+void dal_hw_sequencer_mute_audio_endpoint(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	bool mute);
+
+void dal_hw_sequencer_enable_audio_endpoint(
+	struct hw_sequencer *hws,
+	struct link_settings *ls,
+	struct display_path *display_path,
+	bool enable);
+
+enum hwss_result dal_hw_sequencer_reset_audio_device(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum hwss_result dal_hw_sequencer_validate_link(
+	struct hw_sequencer *hws,
+	const struct validate_link_param *param);
+
+bool dal_hw_sequencer_is_supported_dp_training_pattern3(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	uint32_t link_idx);
+
+enum hwss_result dal_hw_sequencer_set_dp_phy_pattern(
+	struct hw_sequencer *hws,
+	const struct set_dp_phy_pattern_param *param);
+
+enum hwss_result dal_hw_sequencer_set_lane_settings(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	const struct link_training_settings *link_settings);
+
+void dal_hw_sequencer_set_test_pattern(
+	struct hw_sequencer *hws,
+	struct hw_path_mode *path_mode,
+	enum dp_test_pattern test_pattern,
+	const struct link_training_settings *link_settings,
+	const uint8_t *custom_pattern,
+	uint8_t cust_pattern_size);
+
+bool dal_hw_sequencer_has_audio_bandwidth_changed(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *old,
+	const struct hw_path_mode *new);
+
+void dal_hw_sequencer_enable_azalia_audio_jack_presence(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_disable_azalia_audio_jack_presence(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_enable_memory_requests(
+	struct hw_sequencer *hws,
+	struct hw_path_mode *path_mode);
+
+void dal_hw_sequencer_update_info_packets(
+	struct hw_sequencer *hws,
+	struct hw_path_mode *path_mode);
+
+/* Static validation for a SINGLE path mode.
+ * Already "active" paths (if any) are NOT taken into account. */
+enum hwss_result dal_hw_sequencer_validate_display_path_mode(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *path_mode);
+
+/* Validation for a SET of path modes, including Video Memory Bandwidth
+ * validation. */
+enum hwss_result dal_hw_sequencer_validate_display_hwpms(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set);
+
+struct hw_adjustment_gamma_ramp;
+
+enum hwss_result dal_hw_sequencer_set_gamma_ramp_adjustment(
+	struct hw_sequencer *hws,
+	const struct display_path *display_path,
+	struct hw_adjustment_gamma_ramp *adjusment);
+
+enum hwss_result dal_hw_sequencer_set_color_control_adjustment(
+	struct hw_sequencer *hws,
+	struct controller *crtc,
+	struct hw_adjustment_color_control *adjustment);
+
+enum hwss_result dal_hw_sequencer_set_vertical_sync_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+enum hwss_result dal_hw_sequencer_set_horizontal_sync_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+enum hwss_result dal_hw_sequencer_set_composite_sync_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+enum hwss_result dal_hw_sequencer_enable_sync_output(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum hwss_result dal_hw_sequencer_disable_sync_output(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum hwss_result dal_hw_sequencer_set_backlight_adjustment(
+	struct hw_sequencer *hws,
+	struct display_path *display_path,
+	struct hw_adjustment_value *adjustment);
+
+void dal_hw_sequencer_disable_memory_requests(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *path_mode);
+
+enum hwss_result dal_hw_sequencer_enable_link(
+	struct hw_sequencer *hws,
+	const struct enable_link_param *in);
+
+void dal_hw_sequencer_disable_link(
+	struct hw_sequencer *hws,
+	const struct enable_link_param *in);
+
+void dal_hw_sequencer_enable_stream(
+	struct hw_sequencer *hws,
+	const struct enable_stream_param *in);
+
+void dal_hw_sequencer_disable_stream(
+	struct hw_sequencer *hws,
+	const struct enable_stream_param *in);
+
+void dal_hw_sequencer_blank_stream(
+	struct hw_sequencer *hws,
+	const struct blank_stream_param *in);
+
+void dal_hw_sequencer_unblank_stream(
+	struct hw_sequencer *hws,
+	const struct blank_stream_param *in);
+
+enum hwss_result dal_hw_sequencer_set_clocks_and_clock_state(
+		struct hw_sequencer *hws,
+		struct hw_global_objects *g_obj,
+		const struct minimum_clocks_calculation_result *min_clk_in,
+		enum clocks_state required_clocks_state);
+
+enum hwss_result dal_hw_sequencer_set_mode(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set);
+
+enum signal_type dal_hw_sequencer_detect_sink(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+enum signal_type dal_hw_sequencer_detect_load(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+bool dal_hw_sequencer_is_sink_present(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_psr_setup(
+	struct hw_sequencer *hws,
+	const struct hw_path_mode *path_mode,
+	const struct psr_caps *psr_caps);
+
+void dal_hw_sequencer_psr_enable(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_psr_disable(
+	struct hw_sequencer *hws,
+	struct display_path *display_path);
+
+void dal_hw_sequencer_program_drr(
+		struct hw_sequencer *hws,
+		const struct hw_path_mode *path_mode);
+
+enum hwss_result dal_hw_sequencer_set_safe_displaymark(
+		struct hw_sequencer *hws,
+		struct hw_path_mode_set *path_set);
+
+enum hwss_result dal_hw_sequencer_set_displaymark(
+		struct hw_sequencer *hws,
+		struct hw_path_mode_set *path_set);
+
+void dal_hw_sequencer_destroy(struct hw_sequencer **hws);
+
+struct hw_sequencer *dal_hw_sequencer_create(
+		struct hws_init_data *hws_init_data);
+
+enum hwss_result dal_hw_sequencer_set_overscan_adj(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *set,
+	struct hw_underscan_adjustment_data *hw_underscan);
+
+bool dal_hw_sequencer_enable_line_buffer_power_gating(
+	struct line_buffer *lb,
+	enum controller_id id,
+	enum pixel_type pixel_type,
+	uint32_t src_pixel_width,
+	uint32_t dst_pixel_width,
+	struct scaling_taps *taps,
+	enum lb_pixel_depth lb_depth,
+	uint32_t src_height,
+	uint32_t dst_height,
+	bool interlaced);
+
+void dal_hw_sequencer_build_scaler_parameter(
+	const struct hw_path_mode *path_mode,
+	const struct scaling_taps *taps,
+	bool build_timing_required,
+	struct scaler_data *scaler_data);
+
+void dal_hw_sequencer_update_info_frame(
+	const struct hw_path_mode *hw_path_mode);
+
+enum hwss_result dal_hw_sequencer_set_bit_depth_reduction_adj(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	union hw_adjustment_bit_depth_reduction *bit_depth);
+
+bool dal_hw_sequencer_is_support_custom_gamut_adj(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	enum hw_surface_type surface_type);
+
+enum hwss_result dal_hw_sequencer_get_hw_color_adj_range(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	struct hw_color_control_range *hw_color_range);
+
+bool dal_hw_sequencer_is_support_custom_gamma_coefficients(
+	struct hw_sequencer *hws,
+	struct display_path *disp_path,
+	enum hw_surface_type surface_type);
+
+enum hwss_result dal_hw_sequencer_build_csc_adjust(
+	struct hw_sequencer *hws,
+	struct hw_adjustment_color_control *color_control,
+	struct grph_csc_adjustment *adjust);
+
+void dal_hw_sequencer_build_gamma_ramp_adj_params(
+		const struct hw_adjustment_gamma_ramp *adjusment,
+		struct gamma_parameters *gamma_param,
+		struct gamma_ramp *ramp);
+
+void translate_from_hw_to_controller_regamma(
+		const struct hw_regamma_lut *hw_regamma,
+		struct regamma_lut *regamma);
+
+void dal_hw_sequencer_enable_wireless_idle_detection(
+		struct hw_sequencer *hws,
+		bool enable);
+
+/* Cursor interface */
+enum hwss_result dal_hw_sequencer_set_cursor_position(
+		struct hw_sequencer *hws,
+		struct display_path *dp,
+		const struct dc_cursor_position *position);
+
+enum hwss_result dal_hw_sequencer_set_cursor_attributes(
+		struct hw_sequencer *hws,
+		struct display_path *dp,
+		const struct dc_cursor_attributes *attributes);
+
+/* Underlay/MPO interface */
+enum hwss_result dal_hw_sequencer_set_plane_config(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set,
+	uint32_t display_index);
+
+bool dal_hw_sequencer_update_plane_address(
+	struct hw_sequencer *hws,
+	struct display_path *dp,
+	uint32_t num_planes,
+	struct plane_addr_flip_info *info);
+
+void dal_hw_sequencer_prepare_to_release_planes(
+	struct hw_sequencer *hws,
+	struct hw_path_mode_set *path_set,
+	uint32_t display_index);
+
+#endif /* __DAL_HW_SEQUENCER_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
new file mode 100644
index 000000000000..ad7b90605d75
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/hw_sequencer_types.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_SEQUENCER_TYPES_H__
+#define __DAL_HW_SEQUENCER_TYPES_H__
+
+#include "signal_types.h"
+#include "grph_object_defs.h"
+#include "link_service_types.h"
+
+struct color_quality {
+	uint32_t bpp_graphics;
+	uint32_t bpp_backend_video;
+};
+
+enum {
+	HW_MAX_NUM_VIEWPORTS = 2,
+	HW_CURRENT_PIPE_INDEX = 0,
+	HW_OTHER_PIPE_INDEX = 1
+};
+
+struct hw_view_port_adjustment {
+	int32_t start_adjustment;
+	int32_t width;
+
+	enum controller_id controller_id;
+};
+
+struct hw_view_port_adjustments {
+	uint32_t view_ports_num;
+	struct hw_view_port_adjustment adjustments[HW_MAX_NUM_VIEWPORTS];
+};
+
+/* Timing standard */
+enum hw_timing_standard {
+	HW_TIMING_STANDARD_UNDEFINED,
+	HW_TIMING_STANDARD_DMT,
+	HW_TIMING_STANDARD_GTF,
+	HW_TIMING_STANDARD_CVT,
+	HW_TIMING_STANDARD_CVT_RB,
+	HW_TIMING_STANDARD_CEA770,
+	HW_TIMING_STANDARD_CEA861,
+	HW_TIMING_STANDARD_HDMI,
+	HW_TIMING_STANDARD_TV_NTSC,
+	HW_TIMING_STANDARD_TV_NTSC_J,
+	HW_TIMING_STANDARD_TV_PAL,
+	HW_TIMING_STANDARD_TV_PAL_M,
+	HW_TIMING_STANDARD_TV_PAL_CN,
+	HW_TIMING_STANDARD_TV_SECAM,
+	/* for explicit timings from VBIOS, EDID etc. */
+	HW_TIMING_STANDARD_EXPLICIT
+};
+
+/* TODO: identical to struct crtc_ranged_timing_control
+ * defined in inc\timing_generator_types.h */
+struct hw_ranged_timing_control {
+	/* set to 1 to force dynamic counter V_COUNT
+	 * to lock to constant rate counter V_COUNT_NOM
+	 * on page flip event in dynamic refresh mode
+	 * when switching from a low refresh rate to nominal refresh rate */
+	bool force_lock_on_event;
+	/* set to 1 to force CRTC2 (slave) to lock to CRTC1 (master) VSync
+	 * in order to overlap their blank regions for MC clock changes */
+	bool lock_to_master_vsync;
+
+	/* set to 1 to program Static Screen Detection Masks
+	 * without enabling dynamic refresh rate */
+	bool program_static_screen_mask;
+	/* set to 1 to program Dynamic Refresh Rate */
+	bool program_dynamic_refresh_rate;
+	/* set to 1 to force disable Dynamic Refresh Rate */
+	bool force_disable_drr;
+
+	/* event mask to enable/disable various trigger sources
+	 * for static screen detection */
+	struct static_screen_events event_mask;
+
+	/* Number of consecutive static screen frames before static state is
+	 * asserted. */
+	uint32_t static_frame_count;
+};
+
+/* define the structure of Dynamic Refresh Mode */
+struct hw_ranged_timing {
+	/* defines the minimum possible vertical dimension of display timing
+	 * for CRTC as supported by the panel */
+	uint32_t vertical_total_min;
+	/* defines the maximum possible vertical dimension of display timing
+	 * for CRTC as supported by the panel */
+	uint32_t vertical_total_max;
+
+	struct hw_ranged_timing_control control;
+};
+
+/* CRTC timing structure */
+struct hw_crtc_timing {
+	uint32_t h_total;
+	uint32_t h_addressable;
+	uint32_t h_overscan_left;
+	uint32_t h_overscan_right;
+	uint32_t h_sync_start;
+	uint32_t h_sync_width;
+
+	uint32_t v_total;
+	uint32_t v_addressable;
+	uint32_t v_overscan_top;
+	uint32_t v_overscan_bottom;
+	uint32_t v_sync_start;
+	uint32_t v_sync_width;
+
+	struct hw_ranged_timing ranged_timing;
+
+	/* in KHz */
+	uint32_t pixel_clock;
+
+	enum hw_timing_standard timing_standard;
+	enum dc_color_depth color_depth;
+	enum dc_pixel_encoding pixel_encoding;
+
+	struct {
+		uint32_t INTERLACED:1;
+		uint32_t DOUBLESCAN:1;
+		uint32_t PIXEL_REPETITION:4; /* 1...10 */
+		uint32_t HSYNC_POSITIVE_POLARITY:1;
+		uint32_t VSYNC_POSITIVE_POLARITY:1;
+		/* frame should be packed for 3D
+		 * (currently this refers to HDMI 1.4a FramePacking format */
+		uint32_t HORZ_COUNT_BY_TWO:1;
+		uint32_t PACK_3D_FRAME:1;
+		/* 0 - left eye polarity, 1 - right eye polarity */
+		uint32_t RIGHT_EYE_3D_POLARITY:1;
+		/* DVI-DL High-Color mode */
+		uint32_t HIGH_COLOR_DL_MODE:1;
+		uint32_t Y_ONLY:1;
+		/* HDMI 2.0 - Support scrambling for TMDS character
+		 * rates less than or equal to 340Mcsc */
+		uint32_t LTE_340MCSC_SCRAMBLE:1;
+	} flags;
+};
+
+struct hw_scaling_info {
+	struct view src;
+	struct view dst;
+	enum signal_type signal;
+};
+
+enum hw_color_space {
+	HW_COLOR_SPACE_UNKNOWN = 0,
+	HW_COLOR_SPACE_SRGB_FULL_RANGE,
+	HW_COLOR_SPACE_SRGB_LIMITED_RANGE,
+	HW_COLOR_SPACE_YPBPR601,
+	HW_COLOR_SPACE_YPBPR709,
+	HW_COLOR_SPACE_YCBCR601,
+	HW_COLOR_SPACE_YCBCR709,
+	HW_COLOR_SPACE_YCBCR601_YONLY,
+	HW_COLOR_SPACE_YCBCR709_YONLY,
+	HW_COLOR_SPACE_NMVPU_SUPERAA,
+};
+
+enum hw_overlay_color_space {
+	HW_OVERLAY_COLOR_SPACE_UNKNOWN,
+	HW_OVERLAY_COLOR_SPACE_BT709,
+	HW_OVERLAY_COLOR_SPACE_BT601,
+	HW_OVERLAY_COLOR_SPACE_SMPTE240,
+	HW_OVERLAY_COLOR_SPACE_RGB
+};
+
+enum hw_overlay_backend_bpp {
+	HW_OVERLAY_BACKEND_BPP_UNKNOWN,
+	HW_OVERLAY_BACKEND_BPP32_FULL_BANDWIDTH,
+	HW_OVERLAY_BACKEND_BPP16_FULL_BANDWIDTH,
+	HW_OVERLAY_BACKEND_BPP32_HALF_BANDWIDTH,
+};
+enum hw_overlay_format {
+	HW_OVERLAY_FORMAT_UNKNOWN,
+	HW_OVERLAY_FORMAT_YUY2,
+	HW_OVERLAY_FORMAT_UYVY,
+	HW_OVERLAY_FORMAT_RGB565,
+	HW_OVERLAY_FORMAT_RGB555,
+	HW_OVERLAY_FORMAT_RGB32,
+	HW_OVERLAY_FORMAT_YUV444,
+	HW_OVERLAY_FORMAT_RGB32_2101010
+};
+
+enum hw_scale_options {
+	HW_SCALE_OPTION_UNKNOWN,
+	HW_SCALE_OPTION_OVERSCAN, /* multimedia pass through mode */
+	HW_SCALE_OPTION_UNDERSCAN
+};
+
+enum hw_stereo_format {
+	HW_STEREO_FORMAT_NONE = 0,
+	HW_STEREO_FORMAT_SIDE_BY_SIDE = 1,
+	HW_STEREO_FORMAT_TOP_AND_BOTTOM = 2,
+	HW_STEREO_FORMAT_FRAME_ALTERNATE = 3,
+	HW_STEREO_FORMAT_ROW_INTERLEAVED = 5,
+	HW_STEREO_FORMAT_COLUMN_INTERLEAVED = 6,
+	HW_STEREO_FORMAT_CHECKER_BOARD = 7 /* the same as pixel interleave */
+};
+
+enum hw_dithering_options {
+	HW_DITHERING_OPTION_UNKNOWN,
+	HW_DITHERING_OPTION_SKIP_PROGRAMMING,
+	HW_DITHERING_OPTION_ENABLE,
+	HW_DITHERING_OPTION_DISABLE
+};
+
+struct hw_stereo_mixer_params {
+	bool sub_sampling;
+	bool single_pipe;
+};
+
+
+
+struct hw_action_flags {
+	uint32_t RESYNC_PATH:1;
+	uint32_t TIMING_CHANGED:1;
+	uint32_t PIXEL_ENCODING_CHANGED:1;
+	uint32_t GAMUT_CHANGED:1;
+	uint32_t TURN_OFF_VCC:1;
+};
+
+enum hw_sync_request {
+	HW_SYNC_REQUEST_NONE = 0,
+	HW_SYNC_REQUEST_SET_INTERPATH,
+	HW_SYNC_REQUEST_SET_GL_SYNC_GENLOCK,
+	HW_SYNC_REQUEST_SET_GL_SYNC_FREE_RUN,
+	HW_SYNC_REQUEST_SET_GL_SYNC_SHADOW,
+	HW_SYNC_REQUEST_RESET_GLSYNC,
+	HW_SYNC_REQUEST_RESYNC_GLSYNC,
+	HW_SYNC_REQUEST_SET_STEREO3D
+};
+
+struct hw_sync_info {
+	enum hw_sync_request sync_request;
+	uint32_t target_pixel_clock; /* in KHz */
+	enum sync_source sync_source;
+};
+
+/* TODO hw_info_frame and hw_info_packet structures are same as in encoder
+ * merge it*/
+struct hw_info_packet {
+	bool valid;
+	uint8_t hb0;
+	uint8_t hb1;
+	uint8_t hb2;
+	uint8_t hb3;
+	uint8_t sb[28];
+};
+
+struct hw_info_frame {
+	/* Auxiliary Video Information */
+	struct hw_info_packet avi_info_packet;
+	struct hw_info_packet gamut_packet;
+	struct hw_info_packet vendor_info_packet;
+	/* Source Product Description */
+	struct hw_info_packet spd_packet;
+	/* Video Stream Configuration */
+	struct hw_info_packet vsc_packet;
+};
+
+
+enum channel_command_type {
+	CHANNEL_COMMAND_I2C,
+	CHANNEL_COMMAND_I2C_OVER_AUX,
+	CHANNEL_COMMAND_AUX
+};
+
+
+/* maximum TMDS transmitter pixel clock is 165 MHz. So it is KHz */
+#define	TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
+#define	NATIVE_HDMI_MAX_PIXEL_CLOCK_IN_KHZ 297000
+
+struct hw_adjustment_range {
+	int32_t hw_default;
+	int32_t min;
+	int32_t max;
+	int32_t step;
+	uint32_t divider; /* (actually HW range is min/divider; divider !=0) */
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/i2caux_interface.h b/drivers/gpu/drm/amd/dal/include/i2caux_interface.h
new file mode 100644
index 000000000000..ac16fa056c69
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/i2caux_interface.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_I2CAUX_INTERFACE_H__
+#define __DAL_I2CAUX_INTERFACE_H__
+
+#include "ddc_interface.h"
+#include "adapter_service_interface.h"
+
+
+#define DEFAULT_AUX_MAX_DATA_SIZE 16
+#define AUX_MAX_DEFER_WRITE_RETRY 20
+
+struct aux_payload {
+	/* set following flag to read/write I2C data,
+	 * reset it to read/write DPCD data */
+	bool i2c_over_aux;
+	/* set following flag to write data,
+	 * reset it to read data */
+	bool write;
+	uint32_t address;
+	uint8_t length;
+	uint8_t *data;
+};
+
+struct aux_command {
+	struct aux_payload *payloads;
+	uint8_t number_of_payloads;
+
+	/* expressed in milliseconds
+	 * zero means "use default value" */
+	uint32_t defer_delay;
+
+	/* zero means "use default value" */
+	uint32_t max_defer_write_retry;
+};
+
+union aux_config {
+	struct {
+		uint32_t ALLOW_AUX_WHEN_HPD_LOW:1;
+	} bits;
+	uint32_t raw;
+};
+
+struct i2caux;
+
+struct i2caux *dal_i2caux_create(
+	struct adapter_service *as,
+	struct dc_context *ctx);
+
+bool dal_i2caux_submit_i2c_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct i2c_command *cmd);
+
+bool dal_i2caux_submit_aux_command(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	struct aux_command *cmd);
+
+void dal_i2caux_keep_engine_power_up(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	bool keep_power_up);
+
+bool dal_i2caux_start_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+bool dal_i2caux_stop_gtc_sync(
+	struct i2caux *i2caux,
+	struct ddc *ddc);
+
+void dal_i2caux_configure_aux(
+	struct i2caux *i2caux,
+	struct ddc *ddc,
+	union aux_config cfg);
+
+void dal_i2caux_destroy(
+	struct i2caux **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/irq_interface.h b/drivers/gpu/drm/amd/dal/include/irq_interface.h
new file mode 100644
index 000000000000..0faa48fabf95
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/irq_interface.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_INTERFACE_H__
+#define __DAL_IRQ_INTERFACE_H__
+
+#include "gpio_types.h"
+
+struct irq;
+
+enum gpio_result dal_irq_open(
+	struct irq *irq);
+
+enum gpio_result dal_irq_get_value(
+	const struct irq *irq,
+	uint32_t *value);
+
+enum dc_irq_source dal_irq_get_source(
+	const struct irq *irq);
+
+enum dc_irq_source dal_irq_get_rx_source(
+	const struct irq *irq);
+
+enum gpio_result dal_irq_setup_hpd_filter(
+	struct irq *irq,
+	struct gpio_hpd_config *config);
+
+void dal_irq_close(
+	struct irq *irq);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/irq_service_interface.h b/drivers/gpu/drm/amd/dal/include/irq_service_interface.h
new file mode 100644
index 000000000000..7ae4aebb738d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/irq_service_interface.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_SERVICE_INTERFACE_H__
+#define __DAL_IRQ_SERVICE_INTERFACE_H__
+
+#include "include/adapter_service_types.h"
+
+struct irq_service_init_data {
+	struct dc_context *ctx;
+};
+
+struct irq_service *dal_irq_service_create(
+	enum dce_version version,
+	struct irq_service_init_data *init_data);
+
+void dal_irq_service_destroy(struct irq_service **irq_service);
+
+bool dal_irq_service_set(
+	struct irq_service *irq_service,
+	enum dc_irq_source source,
+	bool enable);
+
+bool dal_irq_service_ack(
+	struct irq_service *irq_service,
+	enum dc_irq_source source);
+
+enum dc_irq_source dal_irq_service_to_irq_source(
+		struct irq_service *irq_service,
+		uint32_t src_id,
+		uint32_t ext_id);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/link_service_interface.h b/drivers/gpu/drm/amd/dal/include/link_service_interface.h
new file mode 100644
index 000000000000..2ac93119cc02
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/link_service_interface.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LINK_SERVICE_INTERFACE_H__
+#define __DAL_LINK_SERVICE_INTERFACE_H__
+
+#include "include/link_service_types.h"
+
+/* forward declaration */
+struct link_service;
+struct hw_crtc_timing;
+struct hw_path_mode;
+struct display_path;
+struct hw_path_mode_set;
+struct link_training_preference;
+enum ddc_result;
+
+struct link_service *dal_link_service_create(
+	struct link_service_init_data *init_data);
+
+void dal_link_service_destroy(
+	struct link_service **ls);
+
+enum link_service_type dal_ls_get_link_service_type(
+	struct link_service *link_service);
+
+bool dal_ls_validate_mode_timing(
+	struct link_service *ls,
+	uint32_t display_index,
+	const struct hw_crtc_timing *timing,
+	struct link_validation_flags flags);
+
+bool dal_ls_get_mst_sink_info(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct mst_sink_info *sink_info);
+
+bool dal_ls_get_gtc_sync_status(
+	struct link_service *ls);
+
+bool dal_ls_enable_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_disable_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *poath_mode);
+
+bool dal_ls_optimized_enable_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct display_path *display_path);
+
+void dal_ls_update_stream_features(
+	struct link_service *ls,
+	const struct hw_path_mode *path_mode);
+
+bool dal_ls_blank_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_unblank_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_pre_mode_change(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_post_mode_change(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_power_on_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+bool dal_ls_power_off_stream(
+	struct link_service *ls,
+	uint32_t display_index,
+	struct hw_path_mode *path_mode);
+
+void dal_ls_retrain_link(
+	struct link_service *ls,
+	struct hw_path_mode_set *path_set);
+
+bool dal_ls_get_current_link_setting(
+	struct link_service *ls,
+	struct link_settings *link_settings);
+
+void dal_ls_connect_link(
+	struct link_service *ls,
+	const struct display_path *display_path,
+	bool initial_detection);
+
+void dal_ls_disconnect_link(
+	struct link_service *ls);
+
+bool dal_ls_is_mst_network_present(
+	struct link_service *ls);
+
+void dal_ls_invalidate_down_stream_devices(
+	struct link_service *ls);
+
+bool dal_ls_are_mst_displays_cofunctional(
+	struct link_service *ls,
+	const uint32_t *array_display_index,
+	uint32_t len);
+
+bool dal_ls_is_sink_present_at_display_index(
+	struct link_service *ls,
+	uint32_t display_index);
+
+struct ddc_service *dal_ls_obtain_mst_ddc_service(
+	struct link_service *ls,
+	uint32_t display_index);
+
+void dal_ls_release_mst_ddc_service(
+	struct link_service *ls,
+	struct ddc_service *ddc_service);
+
+void dal_ls_release_hw(
+	struct link_service *ls);
+
+bool dal_ls_associate_link(
+	struct link_service *ls,
+	uint32_t display_index,
+	uint32_t link_index,
+	bool is_internal_link);
+
+bool dal_dpsst_ls_set_overridden_trained_link_settings(
+	struct link_service *ls,
+	const struct link_settings *link_settings);
+
+void dal_dpsst_ls_set_link_training_preference(
+	struct link_service *ls,
+	const struct link_training_preference *ltp);
+
+struct link_training_preference
+	dal_dpsst_ls_get_link_training_preference(
+	struct link_service *ls);
+
+bool dal_ls_should_send_notification(
+	struct link_service *ls);
+
+uint32_t dal_ls_get_notification_display_index(
+	struct link_service *ls);
+
+enum ddc_result dal_dpsst_ls_read_dpcd_data(
+	struct link_service *ls,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t size);
+
+enum ddc_result dal_dpsst_ls_write_dpcd_data(
+	struct link_service *ls,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t size);
+
+bool dal_ls_is_link_psr_supported(struct link_service *ls);
+
+bool dal_ls_is_stream_drr_supported(struct link_service *ls);
+
+void dal_ls_set_link_psr_capabilities(
+		struct link_service *ls,
+		struct psr_caps *psr_caps);
+
+void dal_ls_get_link_psr_capabilities(
+		struct link_service *ls,
+		struct psr_caps *psr_caps);
+
+#endif /* __DAL_LINK_SERVICE_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/link_service_types.h b/drivers/gpu/drm/amd/dal/include/link_service_types.h
new file mode 100644
index 000000000000..d2e6256695fb
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/link_service_types.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LINK_SERVICE_TYPES_H__
+#define __DAL_LINK_SERVICE_TYPES_H__
+
+#include "grph_object_id.h"
+#include "dpcd_defs.h"
+#include "dal_types.h"
+#include "irq_types.h"
+
+/*struct mst_mgr_callback_object;*/
+struct ddc;
+struct irq_manager;
+
+enum {
+	MAX_CONTROLLER_NUM = 6
+};
+
+enum link_service_type {
+	LINK_SERVICE_TYPE_LEGACY = 0,
+	LINK_SERVICE_TYPE_DP_SST,
+	LINK_SERVICE_TYPE_DP_MST,
+	LINK_SERVICE_TYPE_MAX
+};
+
+struct link_validation_flags {
+	uint32_t DYNAMIC_VALIDATION:1;
+	uint32_t CANDIDATE_TIMING:1;
+	uint32_t START_OF_VALIDATION:1;
+};
+
+/* Post Cursor 2 is optional for transmitter
+ * and it applies only to the main link operating at HBR2
+ */
+enum post_cursor2 {
+	POST_CURSOR2_DISABLED = 0,	/* direct HW translation! */
+	POST_CURSOR2_LEVEL1,
+	POST_CURSOR2_LEVEL2,
+	POST_CURSOR2_LEVEL3,
+	POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3,
+};
+
+enum voltage_swing {
+	VOLTAGE_SWING_LEVEL0 = 0,	/* direct HW translation! */
+	VOLTAGE_SWING_LEVEL1,
+	VOLTAGE_SWING_LEVEL2,
+	VOLTAGE_SWING_LEVEL3,
+	VOLTAGE_SWING_MAX_LEVEL = VOLTAGE_SWING_LEVEL3
+};
+
+enum pre_emphasis {
+	PRE_EMPHASIS_DISABLED = 0,	/* direct HW translation! */
+	PRE_EMPHASIS_LEVEL1,
+	PRE_EMPHASIS_LEVEL2,
+	PRE_EMPHASIS_LEVEL3,
+	PRE_EMPHASIS_MAX_LEVEL = PRE_EMPHASIS_LEVEL3
+};
+
+enum dpcd_value_mask {
+	DPCD_VALUE_MASK_MAX_LANE_COUNT_LANE_COUNT = 0x1F,
+	DPCD_VALUE_MASK_MAX_LANE_COUNT_TPS3_SUPPORTED = 0x40,
+	DPCD_VALUE_MASK_MAX_LANE_COUNT_ENHANCED_FRAME_EN = 0x80,
+	DPCD_VALUE_MASK_MAX_DOWNSPREAD = 0x01,
+	DPCD_VALUE_MASK_LANE_ALIGN_STATUS_INTERLANE_ALIGN_DONE = 0x01
+};
+
+enum dp_power_state {
+	DP_POWER_STATE_D0 = 1,
+	DP_POWER_STATE_D3
+};
+
+enum dpcd_downstream_port_types {
+	DPCD_DOWNSTREAM_DP,
+	DPCD_DOWNSTREAM_VGA,
+	DPCD_DOWNSTREAM_DVI_HDMI,
+	/* has no EDID (TV, CV) */
+	DPCD_DOWNSTREAM_NON_DDC
+};
+
+enum edp_revision {
+	/* eDP version 1.1 or lower */
+	EDP_REVISION_11 = 0x00,
+	/* eDP version 1.2 */
+	EDP_REVISION_12 = 0x01,
+	/* eDP version 1.3 */
+	EDP_REVISION_13 = 0x02
+};
+
+enum lane_count {
+	LANE_COUNT_UNKNOWN = 0,
+	LANE_COUNT_ONE = 1,
+	LANE_COUNT_TWO = 2,
+	LANE_COUNT_FOUR = 4,
+	LANE_COUNT_EIGHT = 8,
+	LANE_COUNT_DP_MAX = LANE_COUNT_FOUR
+};
+
+/* This is actually a reference clock (27MHz) multiplier
+ * 162MBps bandwidth for 1.62GHz like rate,
+ * 270MBps for 2.70GHz,
+ * 324MBps for 3.24Ghz,
+ * 540MBps for 5.40GHz
+ */
+enum link_rate {
+	LINK_RATE_UNKNOWN = 0,
+	LINK_RATE_LOW = 0x06,
+	LINK_RATE_HIGH = 0x0A,
+	LINK_RATE_RBR2 = 0x0C,
+	LINK_RATE_HIGH2 = 0x14
+};
+
+enum {
+	LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/
+};
+
+enum link_spread {
+	LINK_SPREAD_DISABLED = 0x00,
+	/* 0.5 % downspread 30 kHz */
+	LINK_SPREAD_05_DOWNSPREAD_30KHZ = 0x10,
+	/* 0.5 % downspread 33 kHz */
+	LINK_SPREAD_05_DOWNSPREAD_33KHZ = 0x11
+};
+
+/* DPCD_ADDR_DOWNSTREAM_PORT_PRESENT register value */
+union dpcd_downstream_port {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t PRESENT:1;
+		uint8_t TYPE:2;
+		uint8_t FORMAT_CONV:1;
+		uint8_t RESERVED:4;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t RESERVED:4;
+		uint8_t FORMAT_CONV:1;
+		uint8_t TYPE:2;
+		uint8_t PRESENT:1;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+/* DPCD_ADDR_SINK_COUNT register value */
+union dpcd_sink_count {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t SINK_COUNT:6;
+		uint8_t CP_READY:1;
+		uint8_t RESERVED:1;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t RESERVED:1;
+		uint8_t CP_READY:1;
+		uint8_t SINK_COUNT:6;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+struct link_settings {
+	enum lane_count lane_count;
+	enum link_rate link_rate;
+	enum link_spread link_spread;
+};
+
+struct lane_settings {
+	enum voltage_swing VOLTAGE_SWING;
+	enum pre_emphasis PRE_EMPHASIS;
+	enum post_cursor2 POST_CURSOR2;
+};
+
+struct link_training_settings {
+	struct link_settings link_settings;
+	struct lane_settings lane_settings[LANE_COUNT_DP_MAX];
+	bool allow_invalid_msa_timing_param;
+};
+
+enum hw_dp_training_pattern {
+	HW_DP_TRAINING_PATTERN_1 = 0,
+	HW_DP_TRAINING_PATTERN_2,
+	HW_DP_TRAINING_PATTERN_3
+};
+
+/*TODO: Move this enum test harness*/
+/* Test patterns*/
+enum dp_test_pattern {
+	/* Input data is pass through Scrambler
+	 * and 8b10b Encoder straight to output*/
+	DP_TEST_PATTERN_VIDEO_MODE = 0,
+	/* phy test patterns*/
+	DP_TEST_PATTERN_D102,
+	DP_TEST_PATTERN_SYMBOL_ERROR,
+	DP_TEST_PATTERN_PRBS7,
+
+	DP_TEST_PATTERN_80BIT_CUSTOM,
+	DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE,
+
+	/* Link Training Patterns */
+	DP_TEST_PATTERN_TRAINING_PATTERN1,
+	DP_TEST_PATTERN_TRAINING_PATTERN2,
+	DP_TEST_PATTERN_TRAINING_PATTERN3,
+
+	/* link test patterns*/
+	DP_TEST_PATTERN_COLOR_SQUARES,
+	DP_TEST_PATTERN_COLOR_SQUARES_CEA,
+	DP_TEST_PATTERN_VERTICAL_BARS,
+	DP_TEST_PATTERN_HORIZONTAL_BARS,
+	DP_TEST_PATTERN_COLOR_RAMP,
+
+	/* audio test patterns*/
+	DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED,
+	DP_TEST_PATTERN_AUDIO_SAWTOOTH,
+
+	DP_TEST_PATTERN_UNSUPPORTED
+};
+
+enum dp_panel_mode {
+	/* not required */
+	DP_PANEL_MODE_DEFAULT,
+	/* standard mode for eDP */
+	DP_PANEL_MODE_EDP,
+	/* external chips specific settings */
+	DP_PANEL_MODE_SPECIAL
+};
+
+/**
+ * @brief LinkServiceInitOptions to set certain bits
+ */
+struct link_service_init_options {
+	uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1;
+};
+
+/**
+ * @brief data required to initialize LinkService
+ */
+struct link_service_init_data {
+	/* number of displays indices which the MST Mgr would manange*/
+	uint32_t num_of_displays;
+	enum link_service_type link_type;
+	/*struct mst_mgr_callback_object*topology_change_callback;*/
+	/* native aux access */
+	struct ddc_service *dpcd_access_srv;
+	/* for calling HWSS to program HW */
+	struct hw_sequencer *hwss;
+	/* the source which to register IRQ on */
+	enum dc_irq_source irq_src_hpd_rx;
+	enum dc_irq_source irq_src_dp_sink;
+	/* other init options such as SW Workarounds */
+	struct link_service_init_options init_options;
+	uint32_t connector_enum_id;
+	struct graphics_object_id connector_id;
+	struct adapter_service *adapter_service;
+	struct dc_context *ctx;
+	struct topology_mgr *tm;
+};
+
+/**
+ * @brief LinkServiceInitOptions to set certain bits
+ */
+struct LinkServiceInitOptions {
+	uint32_t APPLY_MISALIGNMENT_BUG_WORKAROUND:1;
+};
+
+/* DPCD_ADDR_TRAINING_LANEx_SET registers value */
+union dpcd_training_lane_set {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t VOLTAGE_SWING_SET:2;
+		uint8_t MAX_SWING_REACHED:1;
+		uint8_t PRE_EMPHASIS_SET:2;
+		uint8_t MAX_PRE_EMPHASIS_REACHED:1;
+		/* following is reserved in DP 1.1 */
+		uint8_t POST_CURSOR2_SET:2;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t POST_CURSOR2_SET:2;
+		uint8_t MAX_PRE_EMPHASIS_REACHED:1;
+		uint8_t PRE_EMPHASIS_SET:2;
+		uint8_t MAX_SWING_REACHED:1;
+		uint8_t VOLTAGE_SWING_SET:2;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+/* DPCD_ADDR_TRAINING_LANEx_SET2 registers value - since DP 1.2 */
+union dpcd_training_lanes_set2 {
+	struct {
+#if defined(LITTLEENDIAN_CPU)
+		uint8_t LANE0_POST_CURSOR2_SET:2;
+		uint8_t LANE0_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE0_RESERVED:1;
+		uint8_t LANE1_POST_CURSOR2_SET:2;
+		uint8_t LANE1_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE1_RESERVED:1;
+#elif defined(BIGENDIAN_CPU)
+		uint8_t LANE1_RESERVED:1;
+		uint8_t LANE1_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE1_POST_CURSOR2_SET:2;
+		uint8_t LANE0_RESERVED:1;
+		uint8_t LANE0_MAX_POST_CURSOR2_REACHED:1;
+		uint8_t LANE0_POST_CURSOR2_SET:2;
+#else
+	#error ARCH not defined!
+#endif
+	} bits;
+
+	uint8_t raw;
+};
+
+/**
+ * @brief represent the 16 byte
+ *  global unique identifier
+ */
+struct mst_guid {
+	uint8_t ids[16];
+};
+
+/**
+ * @brief represents the relative address used
+ * to identify a node in MST topology network
+ */
+struct mst_rad {
+	/* number of links. rad[0] up to
+	 * rad [linkCount - 1] are valid. */
+	uint32_t rad_link_count;
+	/* relative address. rad[0] is the
+	 * first device connected to the source.	*/
+	uint8_t rad[15];
+	/* extra 10 bytes for underscores; for e.g.:2_1_8*/
+	int8_t rad_str[25];
+};
+
+/**
+ * @brief this structure is used to report
+ * properties associated to a sink device
+ */
+struct mst_sink_info {
+	/* global unique identifier */
+	struct mst_guid guid;
+	/* relative address */
+	struct mst_rad  rad;
+	/* total bandwidth available on the DP connector */
+	uint32_t total_available_bandwidth_in_mbps;
+	/* bandwidth allocated to the sink device. */
+	uint32_t allocated_bandwidth_in_mbps;
+	/* bandwidth consumed to support for the current mode. */
+	uint32_t consumed_bandwidth_in_mbps;
+};
+
+/**
+ * @brief represent device information in MST topology
+ */
+struct mst_device_info {
+	/* global unique identifier*/
+	struct mst_guid guid;
+	/* relative address*/
+	struct mst_rad  rad;
+};
+
+/* DP MST stream allocation (payload bandwidth number) */
+struct dp_mst_stream_allocation {
+	uint8_t vcp_id;
+	/* number of slots required for the DP stream in
+	 * transport packet */
+	uint8_t slot_count;
+};
+
+/* DP MST stream allocation table */
+struct dp_mst_stream_allocation_table {
+	/* number of DP video streams */
+	int stream_count;
+	/* array of stream allocations */
+	struct dp_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM];
+};
+
+struct dp_test_event_data {
+	/*size of parameters (starting from params) in bytes*/
+	uint32_t size;
+	/*parameters block*/
+	uint32_t params[1];
+};
+
+struct psr_caps {
+	/* These parameters are from PSR capabilities reported by Sink DPCD. */
+	uint8_t psr_version;
+	uint32_t psr_rfb_setup_time;
+	bool psr_exit_link_training_req;
+
+	/* These parameters are calculated in Driver, based on display timing
+	 * and Sink capabilities.
+	 * If VBLANK region is too small and Sink takes a long time to power up
+	 * Remote Frame Buffer, it may take an extra frame to enter PSR */
+	bool psr_frame_capture_indication_req;
+	uint32_t psr_sdp_transmit_line_num_deadline;
+};
+
+#endif /*__DAL_LINK_SERVICE_TYPES_H__*/
diff --git a/drivers/gpu/drm/amd/dal/include/logger_interface.h b/drivers/gpu/drm/amd/dal/include/logger_interface.h
new file mode 100644
index 000000000000..4d945eabb07f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/logger_interface.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LOGGER_INTERFACE_H__
+#define __DAL_LOGGER_INTERFACE_H__
+
+#include "logger_types.h"
+
+struct dal_logger;
+struct dc_context;
+union logger_flags;
+
+/*
+ * TODO: This logger functionality needs to be implemented and reworked.
+ */
+
+
+/*
+ *
+ * DAL logger functionality
+ *
+ */
+
+struct dal_logger *dal_logger_create(struct dc_context *ctx);
+
+uint32_t dal_logger_destroy(struct dal_logger **logger);
+
+uint32_t dal_logger_get_mask(
+	struct dal_logger *logger,
+	enum log_major lvl_major, enum log_minor lvl_minor);
+
+uint32_t dal_logger_set_mask(
+		struct dal_logger *logger,
+		enum log_major lvl_major, enum log_minor lvl_minor);
+
+uint32_t dal_logger_get_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major);
+
+void dal_logger_set_masks(
+	struct dal_logger *logger,
+	enum log_major lvl_major, uint32_t log_mask);
+
+uint32_t dal_logger_unset_mask(
+		struct dal_logger *logger,
+		enum log_major lvl_major, enum log_minor lvl_minor);
+
+bool dal_logger_should_log(
+		struct dal_logger *logger,
+		enum log_major major,
+		enum log_minor minor);
+
+uint32_t dal_logger_get_flags(
+		struct dal_logger *logger);
+
+void dal_logger_set_flags(
+		struct dal_logger *logger,
+		union logger_flags flags);
+
+void dal_logger_write(
+		struct dal_logger *logger,
+		enum log_major major,
+		enum log_minor minor,
+		const char *msg,
+		...);
+
+void dal_logger_append(
+		struct log_entry *entry,
+		const char *msg,
+		...);
+
+uint32_t dal_logger_read(
+		struct dal_logger *logger,
+		uint32_t output_buffer_size,
+		char *output_buffer,
+		uint32_t *bytes_read,
+		bool single_line);
+
+void dal_logger_open(
+		struct dal_logger *logger,
+		struct log_entry *entry,
+		enum log_major major,
+		enum log_minor minor);
+
+void dal_logger_close(struct log_entry *entry);
+
+uint32_t dal_logger_get_buffer_size(struct dal_logger *logger);
+
+uint32_t dal_logger_set_buffer_size(
+		struct dal_logger *logger,
+		uint32_t new_size);
+
+const struct log_major_info *dal_logger_enum_log_major_info(
+		struct dal_logger *logger,
+		unsigned int enum_index);
+
+const struct log_minor_info *dal_logger_enum_log_minor_info(
+		struct dal_logger *logger,
+		enum log_major major,
+		unsigned int enum_index);
+
+/* Any function which is empty or have incomplete implementation should be
+ * marked by this macro.
+ * Note that the message will be printed exactly once for every function
+ * it is used in order to avoid repeating of the same message. */
+#define DAL_LOGGER_NOT_IMPL(log_minor, fmt, ...) \
+{ \
+	static bool print_not_impl = true; \
+\
+	if (print_not_impl == true) { \
+		print_not_impl = false; \
+		dal_logger_write(ctx->logger, LOG_MAJOR_WARNING, \
+		log_minor, "DAL_NOT_IMPL: " fmt, ##__VA_ARGS__); \
+	} \
+}
+
+/******************************************************************************
+ * Convenience macros to save on typing.
+ *****************************************************************************/
+
+#define DC_ERROR(...) \
+	dal_logger_write(dc_ctx->logger, \
+		LOG_MAJOR_ERROR, LOG_MINOR_COMPONENT_DC, \
+		__VA_ARGS__);
+
+#define DC_SYNC_INFO(...) \
+	dal_logger_write(dc_ctx->logger, \
+		LOG_MAJOR_SYNC, LOG_MINOR_SYNC_TIMING, \
+		__VA_ARGS__);
+
+#endif /* __DAL_LOGGER_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/logger_types.h b/drivers/gpu/drm/amd/dal/include/logger_types.h
new file mode 100644
index 000000000000..614799907e19
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/logger_types.h
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_LOGGER_TYPES_H__
+#define __DAL_LOGGER_TYPES_H__
+
+
+/*
+ * TODO: This logger functionality needs to be implemented and reworked.
+ */
+
+
+struct dal_logger;
+
+enum log_major {
+/*00*/
+	LOG_MAJOR_ERROR = 0,	/*< DAL subcomponent error MSG*/
+/*01*/  LOG_MAJOR_WARNING,	/*< DAL subcomponent warning MSG*/
+/*02*/  LOG_MAJOR_INTERFACE_TRACE,/*< DAL subcomponent interface tracing*/
+/*03*/  LOG_MAJOR_HW_TRACE,	/*< Log ASIC register read/write,
+				* ATOMBIOS exec table call and delays*/
+
+/*04*/  LOG_MAJOR_MST,		/*< related to multi-stream*/
+/*05*/  LOG_MAJOR_DCS,		/*< related to Dcs*/
+/*06*/  LOG_MAJOR_DCP,		/*< related to Dcp grph and ovl,gamam and csc*/
+/*07*/  LOG_MAJOR_BIOS,		/*< related to BiosParser*/
+/*08*/  LOG_MAJOR_REGISTER,	/*< register access*/
+/*09*/  LOG_MAJOR_INFO_PACKETS,	/*< info packets*/
+/*10*/  LOG_MAJOR_DSAT,		/*< related
+				*	to Display System Analysis Tool*/
+/*11*/  LOG_MAJOR_EC,		/*< External Components - MCIL Events/queries,
+				*	PPLib notifications/queries*/
+/*12*/  LOG_MAJOR_BWM,		/*< related to Bandwidth Manager*/
+/*13*/  LOG_MAJOR_MODE_ENUM,	/*< related to mode enumeration*/
+/*14*/  LOG_MAJOR_I2C_AUX,	/*< i2c and aux channel log*/
+/*15*/  LOG_MAJOR_LINE_BUFFER,	/*< Line Buffer object logging activity*/
+/*16*/  LOG_MAJOR_HWSS,		/*< HWSS object logging activity*/
+/*17*/  LOG_MAJOR_OPTIMIZATION,	/*< Optimization code path*/
+/*18*/  LOG_MAJOR_PERF_MEASURE,	/*< Performance measurement dumps*/
+/*19*/  LOG_MAJOR_SYNC,		/*< related to HW and SW Synchronization*/
+/*20*/  LOG_MAJOR_BACKLIGHT,	/*< related to backlight */
+/*21*/  LOG_MAJOR_INTERRUPTS,	/*< logging for all interrupts */
+
+/*22*/  LOG_MAJOR_TM,		/*< related to Topology Manager*/
+/*23*/  LOG_MAJOR_DISPLAY_SERVICE, /*< related to Display Service*/
+/*24*/	LOG_MAJOR_FEATURE_OVERRIDE,	/*< related to features*/
+/*25*/	LOG_MAJOR_DETECTION,	/*< related to detection*/
+	LOG_MAJOR_COUNT,	/*< count of the Major categories*/
+};
+
+/**
+* @brief defines minor switch for logging.  each of these define sub category
+*        of log message per LogMajor
+*/
+
+
+enum log_minor {
+
+	/* Special case for 'all' checkbox */
+	LOG_MINOR_MASK_ALL = (uint32_t)-1, /* 0xFFFFFFFF */
+/**
+* @brief defines minor category for
+*         LOG_MAJOR_ERROR,
+*         LOG_MAJOR_WARNING,
+*         LOG_MAJOR_INTERFACE_TRACE
+*
+* @note  each DAL subcomponent should have a corresponding enum
+*/
+	LOG_MINOR_COMPONENT_LINK_SERVICE = 0,
+	LOG_MINOR_COMPONENT_DAL_INTERFACE,
+	LOG_MINOR_COMPONENT_HWSS,
+	LOG_MINOR_COMPONENT_ADAPTER_SERVICE,
+	LOG_MINOR_COMPONENT_DISPLAY_SERVICE,
+	LOG_MINOR_COMPONENT_TOPOLOGY_MANAGER,
+	LOG_MINOR_COMPONENT_ENCODER,
+	LOG_MINOR_COMPONENT_I2C_AUX,
+	LOG_MINOR_COMPONENT_AUDIO,
+	LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE,
+	LOG_MINOR_COMPONENT_DMCU,
+	LOG_MINOR_COMPONENT_GPU,
+	LOG_MINOR_COMPONENT_CONTROLLER,
+	LOG_MINOR_COMPONENT_ISR,
+	LOG_MINOR_COMPONENT_BIOS,
+	LOG_MINOR_COMPONENT_DC,
+	LOG_MINOR_COMPONENT_IRQ_SERVICE,
+
+/**
+* @brief define minor category for LogMajor_HardwareTrace
+*
+* @note  defines functionality based HW programming trace
+*/
+	LOG_MINOR_HW_TRACE_MST = 0,
+	LOG_MINOR_HW_TRACE_TRAVIS,
+	LOG_MINOR_HW_TRACE_HOTPLUG,
+	LOG_MINOR_HW_TRACE_LINK_TRAINING,
+	LOG_MINOR_HW_TRACE_SET_MODE,
+	LOG_MINOR_HW_TRACE_RESUME_S3,
+	LOG_MINOR_HW_TRACE_RESUME_S4,
+	LOG_MINOR_HW_TRACE_BOOTUP,
+	LOG_MINOR_HW_TRACE_AUDIO,
+	LOG_MINOR_HW_TRACE_HPD_IRQ,
+	LOG_MINOR_HW_TRACE_INTERRUPT,
+	LOG_MINOR_HW_TRACE_MPO,
+
+/**
+* @brief defines minor category for LogMajor_Mst
+*
+* @note  define sub functionality related to MST
+*/
+	LOG_MINOR_MST_IRQ_HPD_RX = 0,
+	LOG_MINOR_MST_IRQ_TIMER,
+	LOG_MINOR_MST_NATIVE_AUX,
+	LOG_MINOR_MST_SIDEBAND_MSG,
+	LOG_MINOR_MST_MSG_TRANSACTION,
+	LOG_MINOR_MST_SIDEBAND_MSG_PARSED,
+	LOG_MINOR_MST_MSG_TRANSACTION_PARSED,
+	LOG_MINOR_MST_AUX_MSG_DPCD_ACCESS,
+	LOG_MINOR_MST_PROGRAMMING,
+	LOG_MINOR_MST_TOPOLOGY_DISCOVERY,
+	LOG_MINOR_MST_CONVERTER_CAPS,
+
+/**
+* @brief defines minor category for LogMajor_DCS
+*
+* @note  should define sub functionality related to Dcs
+*/
+	LOG_MINOR_DCS_EDID_EMULATOR = 0,
+	LOG_MINOR_DCS_DONGLE_DETECTION,
+
+/**
+* @brief defines minor category for DCP
+*
+* @note  should define sub functionality related to Dcp
+*/
+	LOG_MINOR_DCP_GAMMA_GRPH = 0,
+	LOG_MINOR_DCP_GAMMA_OVL,
+	LOG_MINOR_DCP_CSC_GRPH,
+	LOG_MINOR_DCP_CSC_OVL,
+	LOG_MINOR_DCP_SCALER,
+	LOG_MINOR_DCP_SCALER_TABLES,
+/**
+* @brief defines minor category for LogMajor_Bios
+*
+* @note define sub functionality related to BiosParser
+*/
+	LOG_MINOR_BIOS_CMD_TABLE = 0,
+/**
+* @brief defines minor category for LogMajor_Bios
+*
+* @note define sub functionality related to BiosParser
+*/
+	LOG_MINOR_REGISTER_INDEX = 0,
+/**
+* @brief defines minor category for info packets
+*
+*/
+	LOG_MINOR_INFO_PACKETS_HDMI = 0,
+
+/**
+* @brief defines minor category for LOG_MAJOR_DSAT
+*
+* @note define sub functionality related to Display System Analysis Tool
+*/
+	LOG_MINOR_DSAT_LOGGER = 0,
+	LOG_MINOR_DSAT_GET_EDID,
+	LOG_MINOR_DSAT_EDID_OVERRIDE,
+	LOG_MINOR_DSAT_SET_ADJUSTMENTS,
+	LOG_MINOR_DSAT_GET_ADJUSTMENTS,
+
+/**
+* @brief defines minor category for LOG_MAJOR_EC
+*
+* @note define sub functionality related to External components notifications
+*/
+	LOG_MINOR_EC_PPLIB_NOTIFY = 0,
+	LOG_MINOR_EC_PPLIB_QUERY,
+
+/**
+* @brief defines minor category for LOG_MAJOR_BWM
+*
+* @note define sub functionality related to Bandwidth Manager
+*/
+	LOG_MINOR_BWM_MODE_VALIDATION = 0,
+	LOG_MINOR_BWM_REQUIRED_BANDWIDTH_CALCS,
+
+/**
+* @brief define minor category for LogMajor_ModeEnum
+*
+* @note  defines functionality mode enumeration trace
+*/
+	LOG_MINOR_MODE_ENUM_BEST_VIEW_CANDIDATES = 0,
+	LOG_MINOR_MODE_ENUM_VIEW_SOLUTION,
+	LOG_MINOR_MODE_ENUM_TS_LIST_BUILD,
+	LOG_MINOR_MODE_ENUM_TS_LIST,
+	LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST,
+	LOG_MINOR_MODE_ENUM_MASTER_VIEW_LIST_UPDATE,
+
+/**
+* @brief defines minor category for LogMajor_I2C_AUX
+*
+* @note define sub functionality related to I2c and Aux Channel Log
+*/
+	LOG_MINOR_I2C_AUX_LOG = 0,
+	LOG_MINOR_I2C_AUX_AUX_TIMESTAMP,
+	LOG_MINOR_I2C_AUX_CFG,
+
+/**
+* @brief defines minor category for LogMajor_LineBuffer
+*
+* @note define sub functionality related to LineBuffer
+*/
+	LOG_MINOR_LINE_BUFFER_POWERGATING = 0,
+
+/**
+* @brief defines minor category for LogMajor_HWSS
+*
+* @note define sub functionality related to HWSS
+*/
+	LOG_MINOR_HWSS_TAPS_VALIDATION = 0,
+
+/**
+* @brief defines minor category for LogMajor_Optimization
+*
+* @note define sub functionality related to Optimization
+*/
+	LOG_MINOR_OPTMZ_GENERAL = 0,
+	LOG_MINOR_OPTMZ_DO_NOT_TURN_OFF_VCC_DURING_SET_MODE,
+
+/**
+* @brief defines minor category for LogMajor_PerfMeasure
+*
+* @note define sub functionality related to Performance measurement dumps
+*/
+	LOG_MINOR_PERF_MEASURE_GENERAL = 0,
+	LOG_MINOR_PERF_MEASURE_HEAP_MEMORY,
+
+/**
+* @brief defines minor category for LogMajor_Sync
+*
+* @note define sub functionality related to HW and SW Synchronization
+*/
+	LOG_MINOR_SYNC_HW_CLOCK_ADJUST = 0,
+	LOG_MINOR_SYNC_TIMING,
+
+/**
+* @brief defines minor category for LogMajor_Backlight
+*
+* @note define sub functionality related to backlight (including VariBright)
+*/
+	LOG_MINOR_BACKLIGHT_BRIGHTESS_CAPS = 0,
+	LOG_MINOR_BACKLIGHT_DMCU_DELTALUT,
+	LOG_MINOR_BACKLIGHT_DMCU_BUILD_DELTALUT,
+	LOG_MINOR_BACKLIGHT_INTERFACE,
+	LOG_MINOR_BACKLIGHT_LID,
+
+/**
+* @brief defines minor category for LOG_MAJOR_TM
+*
+* @note define sub functionality related to Topology Manager
+*/
+	LOG_MINOR_TM_INFO = 0,
+	LOG_MINOR_TM_IFACE_TRACE,
+	LOG_MINOR_TM_RESOURCES,
+	LOG_MINOR_TM_ENCODER_CTL,
+	LOG_MINOR_TM_ENG_ASN,
+	LOG_MINOR_TM_CONTROLLER_ASN,
+	LOG_MINOR_TM_PWR_GATING,
+	LOG_MINOR_TM_BUILD_DSP_PATH,
+	LOG_MINOR_TM_DISPLAY_DETECT,
+	LOG_MINOR_TM_LINK_SRV,
+	LOG_MINOR_TM_NOT_IMPLEMENTED,
+	LOG_MINOR_TM_COFUNC_PATH,
+
+/**
+* @brief defines minor category for LOG_MAJOR_DISPLAY_SERVICE
+*
+* @note define sub functionality related to Display Service
+*/
+	LOG_MINOR_DS_MODE_SETTING = 0,
+
+/**
+* @brief defines minor category for LOG_MAJOR_FEATURE_OVERRIDE
+*
+* @note define sub functionality related to features in adapter service
+*/
+	LOG_MINOR_FEATURE_OVERRIDE = 0,
+
+/**
+* @brief defines minor category for LOG_MAJOR_DETECTION
+*
+* @note define sub functionality related to detection
+*/
+	LOG_MINOR_DETECTION_EDID_PARSER = 0,
+	LOG_MINOR_DETECTION_DP_CAPS,
+};
+
+union logger_flags {
+	struct {
+		uint32_t ENABLE_CONSOLE:1; /* Print to console */
+		uint32_t ENABLE_BUFFER:1; /* Print to buffer */
+		uint32_t RESERVED:30;
+	} bits;
+	uint32_t value;
+};
+
+struct log_entry {
+
+	struct dal_logger *logger;
+	enum log_major major;
+	enum log_minor minor;
+
+	char *buf;
+	uint32_t buf_offset;
+	uint32_t max_buf_bytes;
+};
+
+/**
+* Structure for enumerating LogMajors and LogMinors
+*/
+
+#define MAX_MAJOR_NAME_LEN 32
+#define MAX_MINOR_NAME_LEN 32
+
+struct log_major_info {
+	enum log_major major;
+	char major_name[MAX_MAJOR_NAME_LEN];
+};
+
+struct log_minor_info {
+	enum log_minor minor;
+	char minor_name[MAX_MINOR_NAME_LEN];
+};
+
+#endif /* __DAL_LOGGER_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/scaler_types.h b/drivers/gpu/drm/amd/dal/include/scaler_types.h
new file mode 100644
index 000000000000..db52dbc72383
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/scaler_types.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SCALER_TYPES_H__
+#define __DAL_SCALER_TYPES_H__
+
+#include "signal_types.h"
+#include "fixed31_32.h"
+#include "dc_types.h"
+
+enum pixel_type {
+	PIXEL_TYPE_30BPP = 1,
+	PIXEL_TYPE_20BPP
+};
+
+/*overscan or window*/
+struct overscan_info {
+	uint32_t left;
+	uint32_t right;
+	uint32_t top;
+	uint32_t bottom;
+};
+
+struct mp_scaling_data {
+	struct rect viewport;
+	struct view dst_res;
+	struct overscan_info overscan;
+	struct scaling_taps taps;
+	struct scaling_ratios ratios;
+};
+
+struct scaler_validation_params {
+	uint32_t INTERLACED:1;
+	uint32_t CHROMA_SUB_SAMPLING:1;
+
+	uint32_t line_buffer_size;
+	uint32_t display_clock; /* in KHz */
+	uint32_t actual_pixel_clock; /* in KHz */
+	struct view source_view;
+	struct view dest_view;
+	enum signal_type signal_type;
+
+	struct scaling_taps taps_requested;
+	enum pixel_format pixel_format;
+	enum dc_rotation_angle rotation;
+};
+
+struct adjustment_factor {
+	int32_t adjust;	 /* Actual adjustment value * lDivider */
+	uint32_t divider;
+};
+
+struct sharpness_adjustment {
+	int32_t sharpness;
+	bool enable_sharpening;
+};
+
+enum scaling_options {
+	SCALING_BYPASS = 0,
+	SCALING_ENABLE
+};
+
+/* same as Hw register */
+enum filter_type {
+	FILTER_TYPE_V_LOW_PASS = 0x0,
+	FILTER_TYPE_V_HIGH_PASS = 0x1,
+	FILTER_TYPE_H_LUMA = 0x2,
+	FILTER_TYPE_H_CHROMA = 0x3
+};
+
+/* Validation Result enumeration */
+enum scaler_validation_code {
+	SCALER_VALIDATION_OK = 0,
+	SCALER_VALIDATION_INVALID_INPUT_PARAMETERS,
+	SCALER_VALIDATION_SCALING_RATIO_NOT_SUPPORTED,
+	SCALER_VALIDATION_SOURCE_VIEW_WIDTH_EXCEEDING_LIMIT,
+	SCALER_VALIDATION_DISPLAY_CLOCK_BELOW_PIXEL_CLOCK,
+	SCALER_VALIDATION_FAILURE_PREDEFINED_TAPS_NUMBER
+};
+
+
+#define FILTER_TYPE_MASK 0x0000000FL
+#define TWO_TAPS 2
+
+struct init_int_and_frac {
+	uint32_t integer;
+	uint32_t fraction;
+};
+
+struct scl_ratios_inits {
+	uint32_t bottom_enable;
+	uint32_t h_int_scale_ratio;
+	uint32_t v_int_scale_ratio;
+	struct init_int_and_frac h_init;
+	struct init_int_and_frac v_init;
+	struct init_int_and_frac v_init_bottom;
+};
+
+union scaler_flags {
+	uint32_t raw;
+	struct {
+		uint32_t INTERLACED:1;
+		uint32_t DOUBLE_SCAN_MODE:1;
+		/* this one is legacy flag only used in DCE80 */
+		uint32_t RGB_COLOR_SPACE:1;
+		uint32_t PIPE_LOCK_REQ:1;
+		/* 4 */
+		uint32_t WIDE_DISPLAY:1;
+		uint32_t OTHER_PIPE:1;
+		uint32_t SHOULD_PROGRAM_VIEWPORT:1;
+		uint32_t SHOULD_UNLOCK:1;
+		/* 8 */
+		uint32_t SHOULD_PROGRAM_ALPHA:1;
+		uint32_t SHOW_COLOURED_BORDER:1;
+
+		uint32_t  RESERVED:22;
+	} bits;
+};
+
+struct scaler_data {
+	struct view src_res;
+	struct view dst_res;
+	struct overscan_info overscan;
+	struct scaling_taps taps;
+	struct adjustment_factor scale_ratio_hp_factor;
+	struct adjustment_factor scale_ratio_lp_factor;
+	enum pixel_type pixel_type; /*legacy*/
+	struct sharpness_adjustment sharp_gain;
+
+	union scaler_flags flags;
+	int32_t h_sharpness;
+	int32_t v_sharpness;
+
+	struct view src_res_wide_display;
+	struct view dst_res_wide_display;
+
+	/* it is here because of the HW bug in NI (UBTS #269539)
+	causes glitches in this VBI signal. It shouldn't change after
+	initialization, kind of a const */
+	const struct hw_crtc_timing *hw_crtc_timing;
+
+	struct rect viewport;
+
+	enum pixel_format dal_pixel_format;/*plane concept*/
+	/*stereoformat TODO*/
+	/*hwtotation TODO*/
+
+	const struct scaling_ratios *ratios;
+};
+
+enum bypass_type {
+	/* 00 - 00 - Manual Centering, Manual Replication */
+	BYPASS_TYPE_MANUAL = 0,
+	/* 01 - 01 - Auto-Centering, No Replication */
+	BYPASS_TYPE_AUTO_CENTER = 1,
+	/* 02 - 10 - Auto-Centering, Auto-Replication */
+	BYPASS_TYPE_AUTO_REPLICATION = 3
+};
+
+struct replication_factor {
+	uint32_t h_manual;
+	uint32_t v_manual;
+};
+
+enum ram_filter_type {
+	FILTER_TYPE_RGB_Y_VERTICAL = 0,	/* 0 - RGB/Y Vertical filter */
+	FILTER_TYPE_CBCR_VERTICAL = 1,	/* 1 - CbCr  Vertical filter */
+	FILTER_TYPE_RGB_Y_HORIZONTAL   = 2, /* 1 - RGB/Y Horizontal filter */
+	FILTER_TYPE_CBCR_HORIZONTAL   = 3, /* 3 - CbCr  Horizontal filter */
+	FILTER_TYPE_ALPHA_VERTICAL    = 4, /* 4 - Alpha Vertical filter. */
+	FILTER_TYPE_ALPHA_HORIZONTAL  = 5, /* 5 - Alpha Horizontal filter. */
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/set_mode_types.h b/drivers/gpu/drm/amd/dal/include/set_mode_types.h
new file mode 100644
index 000000000000..97160fe7484c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/set_mode_types.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_SET_MODE_TYPES_H__
+#define __DAL_SET_MODE_TYPES_H__
+
+#include "dc_types.h"
+
+
+/* GTC group number */
+enum gtc_group {
+	GTC_GROUP_DISABLED,
+	GTC_GROUP_1,
+	GTC_GROUP_2,
+	GTC_GROUP_3,
+	GTC_GROUP_4,
+	GTC_GROUP_5,
+	GTC_GROUP_6,
+	GTC_GROUP_MAX
+};
+
+/* Info frame packet status */
+enum info_frame_flag {
+	INFO_PACKET_PACKET_INVALID = 0,
+	INFO_PACKET_PACKET_VALID = 1,
+	INFO_PACKET_PACKET_RESET = 2,
+	INFO_PACKET_PACKET_UPDATE_SCAN_TYPE = 8
+};
+
+/* Info frame types */
+enum info_frame_type {
+	INFO_FRAME_GAMUT = 0x0A,
+	INFO_FRAME_VENDOR_INFO = 0x81,
+	INFO_FRAME_AVI = 0x82
+};
+
+/* Info frame versions */
+enum info_frame_version {
+	INFO_FRAME_VERSION_1 = 1,
+	INFO_FRAME_VERSION_2 = 2,
+	INFO_FRAME_VERSION_3 = 3
+};
+
+/* Info frame size */
+enum info_frame_size {
+	INFO_FRAME_SIZE_AVI = 13,
+	INFO_FRAME_SIZE_VENDOR = 25,
+	INFO_FRAME_SIZE_AUDIO = 10
+};
+
+struct hdmi_info_frame_header {
+	uint8_t info_frame_type;
+	uint8_t version;
+	uint8_t length;
+};
+
+#pragma pack(push)
+#pragma pack(1)
+
+struct info_packet_raw_data {
+	uint8_t hb0;
+	uint8_t hb1;
+	uint8_t hb2;
+	uint8_t sb[28]; /* sb0~sb27 */
+};
+
+union hdmi_info_packet {
+	struct avi_info_frame {
+		struct hdmi_info_frame_header header;
+
+		uint8_t CHECK_SUM:8;
+
+		uint8_t S0_S1:2;
+		uint8_t B0_B1:2;
+		uint8_t A0:1;
+		uint8_t Y0_Y1_Y2:3;
+
+		uint8_t R0_R3:4;
+		uint8_t M0_M1:2;
+		uint8_t C0_C1:2;
+
+		uint8_t SC0_SC1:2;
+		uint8_t Q0_Q1:2;
+		uint8_t EC0_EC2:3;
+		uint8_t ITC:1;
+
+		uint8_t VIC0_VIC7:8;
+
+		uint8_t PR0_PR3:4;
+		uint8_t CN0_CN1:2;
+		uint8_t YQ0_YQ1:2;
+
+		uint16_t bar_top;
+		uint16_t bar_bottom;
+		uint16_t bar_left;
+		uint16_t bar_right;
+
+		uint8_t reserved[14];
+	} bits;
+
+	struct info_packet_raw_data packet_raw_data;
+};
+
+struct info_packet {
+	enum info_frame_flag flags;
+	union hdmi_info_packet info_packet_hdmi;
+};
+
+struct info_frame {
+	struct info_packet avi_info_packet;
+	struct info_packet gamut_packet;
+	struct info_packet vendor_info_packet;
+	struct info_packet spd_info_packet;
+};
+
+
+
+#pragma pack(pop)
+
+#endif /* __DAL_SET_MODE_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/signal_types.h b/drivers/gpu/drm/amd/dal/include/signal_types.h
new file mode 100644
index 000000000000..a50f7ed74a33
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/signal_types.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_SIGNAL_TYPES_H__
+#define __DC_SIGNAL_TYPES_H__
+
+enum signal_type {
+	SIGNAL_TYPE_NONE		= 0L,		/* no signal */
+	SIGNAL_TYPE_DVI_SINGLE_LINK	= (1 << 0),
+	SIGNAL_TYPE_DVI_DUAL_LINK	= (1 << 1),
+	SIGNAL_TYPE_HDMI_TYPE_A		= (1 << 2),
+	SIGNAL_TYPE_LVDS		= (1 << 3),
+	SIGNAL_TYPE_RGB			= (1 << 4),
+	SIGNAL_TYPE_DISPLAY_PORT	= (1 << 5),
+	SIGNAL_TYPE_DISPLAY_PORT_MST	= (1 << 6),
+	SIGNAL_TYPE_EDP			= (1 << 7),
+	SIGNAL_TYPE_WIRELESS		= (1 << 8),	/* Wireless Display */
+	SIGNAL_TYPE_VIRTUAL		= (1 << 9),	/* Virtual Display */
+
+	SIGNAL_TYPE_COUNT		= 10,
+	SIGNAL_TYPE_ALL			= (1 << SIGNAL_TYPE_COUNT) - 1
+};
+
+/* help functions for signal types manipulation */
+bool dc_is_hdmi_signal(enum signal_type signal);
+bool dc_is_dp_sst_signal(enum signal_type signal);
+bool dc_is_dp_signal(enum signal_type signal);
+bool dc_is_dp_external_signal(enum signal_type signal);
+bool dc_is_analog_signal(enum signal_type signal);
+bool dc_is_embedded_signal(enum signal_type signal);
+bool dc_is_dvi_signal(enum signal_type signal);
+bool dc_is_dvi_single_link_signal(enum signal_type signal);
+bool dc_is_dual_link_signal(enum signal_type signal);
+bool dc_is_audio_capable_signal(enum signal_type signal);
+bool dc_is_digital_encoder_compatible_signal(enum signal_type signal);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/vector.h b/drivers/gpu/drm/amd/dal/include/vector.h
new file mode 100644
index 000000000000..8233b7c22a07
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/vector.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_VECTOR_H__
+#define __DAL_VECTOR_H__
+
+struct vector {
+	uint8_t *container;
+	uint32_t struct_size;
+	uint32_t count;
+	uint32_t capacity;
+	struct dc_context *ctx;
+};
+
+bool dal_vector_construct(
+	struct vector *vector,
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size);
+
+struct vector *dal_vector_create(
+	struct dc_context *ctx,
+	uint32_t capacity,
+	uint32_t struct_size);
+
+/* 'initial_value' is optional. If initial_value not supplied,
+ * each "structure" in the vector will contain zeros by default. */
+struct vector *dal_vector_presized_create(
+	struct dc_context *ctx,
+	uint32_t size,
+	void *initial_value,
+	uint32_t struct_size);
+
+void dal_vector_destruct(
+	struct vector *vector);
+
+void dal_vector_destroy(
+	struct vector **vector);
+
+uint32_t dal_vector_get_count(
+	const struct vector *vector);
+
+/* dal_vector_insert_at
+ * reallocate container if necessary
+ * then shell items at right and insert
+ * return if the container modified
+ * do not check that index belongs to container
+ * since the function is private and index is going to be calculated
+ * either with by function or as get_count+1 */
+bool dal_vector_insert_at(
+	struct vector *vector,
+	const void *what,
+	uint32_t position);
+
+bool dal_vector_append(
+	struct vector *vector,
+	const void *item);
+
+/* operator[] */
+void *dal_vector_at_index(
+	const struct vector *vector,
+	uint32_t index);
+
+void dal_vector_set_at_index(
+	const struct vector *vector,
+	const void *what,
+	uint32_t index);
+
+/* create a clone (copy) of a vector */
+struct vector *dal_vector_clone(
+	const struct vector *vector_other);
+
+/* dal_vector_remove_at_index
+ * Shifts elements on the right from remove position to the left,
+ * removing an element at position by overwrite means*/
+bool dal_vector_remove_at_index(
+	struct vector *vector,
+	uint32_t index);
+
+uint32_t dal_vector_capacity(const struct vector *vector);
+
+bool dal_vector_reserve(struct vector *vector, uint32_t capacity);
+
+void dal_vector_clear(struct vector *vector);
+
+/***************************************************************************
+ * Macro definitions of TYPE-SAFE versions of vector set/get functions.
+ ***************************************************************************/
+
+#define DAL_VECTOR_INSERT_AT(vector_type, type_t) \
+	static bool vector_type##_vector_insert_at( \
+		struct vector *vector, \
+		type_t what, \
+		uint32_t position) \
+{ \
+	return dal_vector_insert_at(vector, what, position); \
+}
+
+#define DAL_VECTOR_APPEND(vector_type, type_t) \
+	static bool vector_type##_vector_append( \
+		struct vector *vector, \
+		type_t item) \
+{ \
+	return dal_vector_append(vector, item); \
+}
+
+/* Note: "type_t" is the ONLY token accepted by "checkpatch.pl" and by
+ * "checkcommit" as *return type*.
+ * For uniformity reasons "type_t" is used for all type-safe macro
+ * definitions here. */
+#define DAL_VECTOR_AT_INDEX(vector_type, type_t) \
+	static type_t vector_type##_vector_at_index( \
+		const struct vector *vector, \
+		uint32_t index) \
+{ \
+	return dal_vector_at_index(vector, index); \
+}
+
+#define DAL_VECTOR_SET_AT_INDEX(vector_type, type_t) \
+	static void vector_type##_vector_set_at_index( \
+		const struct vector *vector, \
+		type_t what, \
+		uint32_t index) \
+{ \
+	dal_vector_set_at_index(vector, what, index); \
+}
+
+#endif /* __DAL_VECTOR_H__ */
diff --git a/drivers/gpu/drm/amd/dal/include/video_csc_types.h b/drivers/gpu/drm/amd/dal/include/video_csc_types.h
new file mode 100644
index 000000000000..c229f5a7a325
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/video_csc_types.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_VIDEO_CSC_TYPES_H__
+#define __DAL_VIDEO_CSC_TYPES_H__
+
+#include "video_gamma_types.h"
+
+enum ovl_alpha_blending_mode {
+	OVL_ALPHA_PER_PIXEL_GRPH_ALPHA_MODE = 0,
+	OVL_ALPHA_PER_PIXEL_OVL_ALPHA_MODE
+};
+
+enum ovl_color_space {
+	OVL_COLOR_SPACE_UNKNOWN = 0,
+	OVL_COLOR_SPACE_RGB,
+	OVL_COLOR_SPACE_YUV601,
+	OVL_COLOR_SPACE_YUV709
+};
+
+enum ovl_surface_format {
+	OVL_SURFACE_FORMAT_UNKNOWN = 0,
+	OVL_SURFACE_FORMAT_YUY2,
+	OVL_SURFACE_FORMAT_UYVY,
+	OVL_SURFACE_FORMAT_RGB565,
+	OVL_SURFACE_FORMAT_RGB555,
+	OVL_SURFACE_FORMAT_RGB32,
+	OVL_SURFACE_FORMAT_YUV444,
+	OVL_SURFACE_FORMAT_RGB32_2101010
+};
+
+struct ovl_color_adjust_option {
+	uint32_t ALLOW_OVL_RGB_ADJUST:1;
+	uint32_t ALLOW_OVL_TEMPERATURE:1;
+	uint32_t FULL_RANGE:1; /* 0 for limited range it'is default for YUV */
+	uint32_t OVL_MATRIX:1;
+	uint32_t RESERVED:28;
+};
+
+struct overlay_adjust_item {
+	int32_t adjust; /* InInteger */
+	int32_t adjust_divider;
+};
+
+enum overlay_csc_adjust_type {
+	OVERLAY_CSC_ADJUST_TYPE_BYPASS = 0,
+	OVERLAY_CSC_ADJUST_TYPE_HW, /* without adjustments */
+	OVERLAY_CSC_ADJUST_TYPE_SW  /* use adjustments */
+};
+
+enum overlay_gamut_adjust_type {
+	OVERLAY_GAMUT_ADJUST_TYPE_BYPASS = 0,
+	OVERLAY_GAMUT_ADJUST_TYPE_SW /* use adjustments */
+};
+
+#define TEMPERATURE_MATRIX_SIZE 9
+#define MAXTRIX_SIZE TEMPERATURE_MAXTRIX_SIZE
+#define MAXTRIX_SIZE_WITH_OFFSET 12
+
+/* overlay adjustment input */
+union ovl_csc_flag {
+	uint32_t u_all;
+	struct {
+		uint32_t CONFIG_IS_CHANGED:1;
+		uint32_t RESERVED:31;
+	} bits;
+};
+
+struct ovl_csc_adjustment {
+	enum ovl_color_space ovl_cs;
+	struct ovl_color_adjust_option ovl_option;
+	enum dc_color_depth display_color_depth;
+	uint32_t lb_color_depth;
+	enum pixel_format desktop_surface_pixel_format;
+	enum ovl_surface_format ovl_sf;
+	/* API adjustment */
+	struct overlay_adjust_item overlay_brightness;
+	struct overlay_adjust_item overlay_gamma;
+	struct overlay_adjust_item overlay_contrast;
+	struct overlay_adjust_item overlay_saturation;
+	struct overlay_adjust_item overlay_hue; /* unit in degree from API. */
+	int32_t f_temperature[TEMPERATURE_MATRIX_SIZE];
+	uint32_t temperature_divider;
+	/* OEM/Application matrix related. */
+	int32_t matrix[MAXTRIX_SIZE_WITH_OFFSET];
+	uint32_t matrix_divider;
+
+	/* DCE50 parameters */
+	struct regamma_lut regamma;
+	enum overlay_gamma_adjust adjust_gamma_type;
+	enum overlay_csc_adjust_type adjust_csc_type;
+	enum overlay_gamut_adjust_type adjust_gamut_type;
+	union ovl_csc_flag flag;
+
+};
+
+enum ovl_csc_adjust_item {
+	OVERLAY_BRIGHTNESS = 0,
+	OVERLAY_GAMMA,
+	OVERLAY_CONTRAST,
+	OVERLAY_SATURATION,
+	OVERLAY_HUE,
+	OVERLAY_ALPHA,
+	OVERLAY_ALPHA_PER_PIX,
+	OVERLAY_COLOR_TEMPERATURE
+};
+
+struct input_csc_matrix {
+	enum color_space color_space;
+	uint16_t regval[12];
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/include/video_gamma_types.h b/drivers/gpu/drm/amd/dal/include/video_gamma_types.h
new file mode 100644
index 000000000000..6f9cd3fda21d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/include/video_gamma_types.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_VIDEO_GAMMA_TYPES_H__
+#define __DAL_VIDEO_GAMMA_TYPES_H__
+
+#include "set_mode_types.h"
+#include "gamma_types.h"
+
+enum overlay_gamma_adjust {
+	OVERLAY_GAMMA_ADJUST_BYPASS,
+	OVERLAY_GAMMA_ADJUST_HW, /* without adjustments */
+	OVERLAY_GAMMA_ADJUST_SW /* use adjustments */
+
+};
+
+union video_gamma_flag {
+	struct {
+		uint32_t CONFIG_IS_CHANGED:1;
+		uint32_t RESERVED:31;
+	} bits;
+	uint32_t u_all;
+};
+
+struct overlay_gamma_parameters {
+	union video_gamma_flag flag;
+	int32_t ovl_gamma_cont;
+	enum overlay_gamma_adjust adjust_type;
+	enum pixel_format desktop_surface;
+	struct regamma_lut regamma;
+
+	/* here we grow with parameters if necessary */
+};
+
+#endif
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v3 05/26] drm/amd/dal: GPIO (General Purpose IO)
  2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 01/26] drm/amd/dal: Add dal headers Harry Wentland
@ 2016-02-29 21:56   ` Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 07/26] drm/amd/dal: BIOS Parser Harry Wentland
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-29 21:56 UTC (permalink / raw)
  To: dri-devel

v3 changes:
- expose I2C through i2c_adapter and route dal i2c calls through this

Manages all DCE GPIO pins. The pins are represented as generic IO
handles as well as handles dedicated for certain functions, such as
DDC, HPD, and DVO.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/gpio/Makefile           |  32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c | 882 +++++++++++++++++++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h |  46 ++
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c |  81 ++
 .../drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h |  32 +
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c | 366 +++++++++
 .../gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h |  47 ++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.c   | 400 ++++++++++
 .../amd/dal/dc/gpio/dce110/hw_translate_dce110.h   |  34 +
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c              | 290 +++++++
 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h              |  38 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c  |  97 +++
 .../drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h  |  34 +
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.c  |  65 ++
 .../amd/dal/dc/gpio/diagnostics/hw_factory_diag.h  |  32 +
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c  | 101 +++
 .../drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h  |  35 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.c    |  41 +
 .../dal/dc/gpio/diagnostics/hw_translate_diag.h    |  34 +
 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h             |  48 ++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c        | 279 +++++++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c     | 386 +++++++++
 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h     |  57 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c           | 104 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h           |  60 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c       |  93 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h       |  71 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c          | 407 ++++++++++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h          | 129 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c      |  92 +++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h      |  47 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c      |  85 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h      |  79 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c           |  87 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h           |  45 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c     |  77 ++
 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h     |  50 ++
 drivers/gpu/drm/amd/dal/dc/gpio/irq.c              | 180 +++++
 drivers/gpu/drm/amd/dal/dc/gpio/irq.h              |  42 +
 39 files changed, 5105 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/gpio/irq.h

diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/Makefile b/drivers/gpu/drm/amd/dal/dc/gpio/Makefile
new file mode 100644
index 000000000000..2507bb564946
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/Makefile
@@ -0,0 +1,32 @@
+#
+# Makefile for the 'gpio' sub-component of DAL.
+# It provides the control and status of HW GPIO pins.
+
+GPIO = ddc.o gpio_base.o gpio_service.o hw_ddc.o hw_factory.o \
+       hw_gpio.o hw_gpio_pad.o hw_gpio_pin.o hw_hpd.o hw_translate.o irq.o
+
+AMD_DAL_GPIO = $(addprefix $(AMDDALPATH)/dc/gpio/,$(GPIO))
+
+AMD_DAL_FILES += $(AMD_DAL_GPIO)
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+GPIO_DCE110 = hw_translate_dce110.o hw_factory_dce110.o hw_hpd_dce110.o \
+	hw_ddc_dce110.o
+
+AMD_DAL_GPIO_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpio/dce110/,$(GPIO_DCE110))
+
+AMD_DAL_FILES += $(AMD_DAL_GPIO_DCE110)
+endif
+
+###############################################################################
+# Diagnostics on FPGA
+###############################################################################
+GPIO_DIAG_FPGA = hw_translate_diag.o hw_factory_diag.o hw_hpd_diag.o hw_ddc_diag.o
+
+AMD_DAL_GPIO_DIAG_FPGA = $(addprefix $(AMDDALPATH)/dc/gpio/diagnostics/,$(GPIO_DIAG_FPGA))
+
+AMD_DAL_FILES += $(AMD_DAL_GPIO_DIAG_FPGA)
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
new file mode 100644
index 000000000000..8ff899c5ad12
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.c
@@ -0,0 +1,882 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+
+/*
+ * Header of this unit
+ */
+#include "hw_ddc_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+#define ADDR_DDC_SETUP pin->addr.dc_i2c_ddc_setup
+/*
+ * This unit
+ */
+static void destruct(
+	struct hw_ddc_dce110 *pin)
+{
+	dal_hw_ddc_destruct(&pin->base);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_ddc_dce110 *pin = DDC_DCE110_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+struct hw_ddc_dce110_init {
+	struct hw_gpio_pin_reg hw_gpio_data_reg;
+	struct hw_ddc_mask hw_ddc_mask;
+	struct hw_ddc_dce110_addr hw_ddc_dce110_addr;
+};
+
+static const struct hw_ddc_dce110_init
+	hw_ddc_dce110_init_data[GPIO_DDC_LINE_COUNT] = {
+	/* GPIO_DDC_LINE_DDC1 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC1_MASK,
+				DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_A,
+				DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_EN,
+				DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_Y,
+				DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV_MASK,
+			DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK,
+			DC_GPIO_DDC1_MASK__AUX1_POL_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC1_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC2 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC2_MASK,
+				DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_A,
+				DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_EN,
+				DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_Y,
+				DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV_MASK,
+			DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK,
+			DC_GPIO_DDC2_MASK__AUX2_POL_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC2_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC3 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC3_MASK,
+				DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_A,
+				DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_EN,
+				DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_Y,
+				DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV_MASK,
+			DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK,
+			DC_GPIO_DDC3_MASK__AUX3_POL_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC3_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC4 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC4_MASK,
+				DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_A,
+				DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_EN,
+				DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_Y,
+				DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV_MASK,
+			DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK,
+			DC_GPIO_DDC4_MASK__AUX4_POL_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC4_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC5 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC5_MASK,
+				DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_A,
+				DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_EN,
+				DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_Y,
+				DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV_MASK,
+			DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK,
+			DC_GPIO_DDC5_MASK__AUX5_POL_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC5_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC6 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC6_MASK,
+				DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_A,
+				DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_EN,
+				DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_Y,
+				DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV_MASK,
+			DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK,
+			DC_GPIO_DDC6_MASK__AUX6_POL_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC6_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC_VGA */
+	{
+		{
+			{
+				mmDC_GPIO_DDCVGA_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_A,
+				DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_EN,
+				DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_Y,
+				DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV_MASK,
+			DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK,
+			DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDCVGA_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_I2CPAD */
+	{
+		{
+			{
+				mmDC_GPIO_I2CPAD_MASK,
+				DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_A,
+				DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_EN,
+				DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_Y,
+				DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_PD_DIS_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_RECV_MASK,
+			0,
+			0,
+			0
+		},
+		{
+			0
+		}
+	}
+};
+
+static const struct hw_ddc_dce110_init
+	hw_ddc_dce110_init_clock[GPIO_DDC_LINE_COUNT] = {
+	/* GPIO_DDC_LINE_DDC1 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC1_MASK,
+				DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_A,
+				DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_EN,
+				DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC1_Y,
+				DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV_MASK,
+			DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK,
+			DC_GPIO_DDC1_MASK__AUX1_POL_MASK,
+			DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC1_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC2 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC2_MASK,
+				DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_A,
+				DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_EN,
+				DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC2_Y,
+				DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV_MASK,
+			DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK,
+			DC_GPIO_DDC2_MASK__AUX2_POL_MASK,
+			DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC2_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC3 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC3_MASK,
+				DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_A,
+				DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_EN,
+				DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC3_Y,
+				DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV_MASK,
+			DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK,
+			DC_GPIO_DDC3_MASK__AUX3_POL_MASK,
+			DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC3_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC4 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC4_MASK,
+				DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_A,
+				DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_EN,
+				DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC4_Y,
+				DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV_MASK,
+			DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK,
+			DC_GPIO_DDC4_MASK__AUX4_POL_MASK,
+			DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC4_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC5 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC5_MASK,
+				DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_A,
+				DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_EN,
+				DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC5_Y,
+				DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV_MASK,
+			DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK,
+			DC_GPIO_DDC5_MASK__AUX5_POL_MASK,
+			DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC5_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC6 */
+	{
+		{
+			{
+				mmDC_GPIO_DDC6_MASK,
+				DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_A,
+				DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_EN,
+				DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDC6_Y,
+				DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV_MASK,
+			DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK,
+			DC_GPIO_DDC6_MASK__AUX6_POL_MASK,
+			DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDC6_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_DDC_VGA */
+	{
+		{
+			{
+				mmDC_GPIO_DDCVGA_MASK,
+				DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_A,
+				DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_EN,
+				DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN_MASK
+			},
+			{
+				mmDC_GPIO_DDCVGA_Y,
+				DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV_MASK,
+			DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK,
+			DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK,
+			DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK
+		},
+		{
+			mmDC_I2C_DDCVGA_SETUP
+		}
+	},
+	/* GPIO_DDC_LINE_I2CPAD */
+	{
+		{
+			{
+				mmDC_GPIO_I2CPAD_MASK,
+				DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_A,
+				DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_EN,
+				DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN_MASK
+			},
+			{
+				mmDC_GPIO_I2CPAD_Y,
+				DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y_MASK
+			}
+		},
+		{
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_PD_DIS_MASK,
+			DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_RECV_MASK,
+			0,
+			0,
+			0
+		},
+		{
+			0
+		}
+	}
+};
+
+static void setup_i2c_polling(
+	struct dc_context *ctx,
+	const uint32_t addr,
+	bool enable_detect,
+	bool detect_mode)
+{
+	uint32_t value;
+
+	value = dm_read_reg(ctx, addr);
+
+	set_reg_field_value(
+		value,
+		enable_detect,
+		DC_I2C_DDC1_SETUP,
+		DC_I2C_DDC1_ENABLE);
+
+	set_reg_field_value(
+		value,
+		enable_detect,
+		DC_I2C_DDC1_SETUP,
+		DC_I2C_DDC1_EDID_DETECT_ENABLE);
+
+	if (enable_detect)
+		set_reg_field_value(
+			value,
+			detect_mode,
+			DC_I2C_DDC1_SETUP,
+			DC_I2C_DDC1_EDID_DETECT_MODE);
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static enum gpio_result set_config(
+	struct hw_gpio_pin *ptr,
+	const struct gpio_config_data *config_data)
+{
+	struct hw_ddc_dce110 *pin = DDC_DCE110_FROM_BASE(ptr);
+	struct hw_gpio *hw_gpio = NULL;
+	uint32_t addr;
+	uint32_t regval;
+	uint32_t ddc_data_pd_en = 0;
+	uint32_t ddc_clk_pd_en = 0;
+	uint32_t aux_pad_mode = 0;
+
+	hw_gpio = &pin->base.base;
+
+	if (hw_gpio == NULL) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	/* switch dual mode GPIO to I2C/AUX mode */
+
+	addr = hw_gpio->pin_reg.DC_GPIO_DATA_MASK.addr;
+
+	regval = dm_read_reg(ptr->ctx, addr);
+
+	ddc_data_pd_en = get_reg_field_value(
+			regval,
+			DC_GPIO_DDC1_MASK,
+			DC_GPIO_DDC1DATA_PD_EN);
+
+	ddc_clk_pd_en = get_reg_field_value(
+			regval,
+			DC_GPIO_DDC1_MASK,
+			DC_GPIO_DDC1CLK_PD_EN);
+
+	aux_pad_mode = get_reg_field_value(
+			regval,
+			DC_GPIO_DDC1_MASK,
+			AUX_PAD1_MODE);
+
+	switch (config_data->config.ddc.type) {
+	case GPIO_DDC_CONFIG_TYPE_MODE_I2C:
+		/* On plug-in, there is a transient level on the pad
+		 * which must be discharged through the internal pull-down.
+		 * Enable internal pull-down, 2.5msec discharge time
+		 * is required for detection of AUX mode */
+		if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) {
+			if (!ddc_data_pd_en || !ddc_clk_pd_en) {
+				set_reg_field_value(
+					regval,
+					1,
+					DC_GPIO_DDC1_MASK,
+					DC_GPIO_DDC1DATA_PD_EN);
+
+				set_reg_field_value(
+					regval,
+					1,
+					DC_GPIO_DDC1_MASK,
+					DC_GPIO_DDC1CLK_PD_EN);
+
+				dm_write_reg(ptr->ctx, addr, regval);
+
+				if (config_data->type ==
+					GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
+					/* should not affect normal I2C R/W */
+					/* [anaumov] in DAL2, there was
+					 * dc_service_delay_in_microseconds(2500); */
+					dm_sleep_in_milliseconds(ptr->ctx, 3);
+			}
+		} else {
+			uint32_t reg2 = regval;
+			uint32_t sda_pd_dis = 0;
+			uint32_t scl_pd_dis = 0;
+
+			sda_pd_dis = get_reg_field_value(
+					reg2,
+					DC_GPIO_I2CPAD_MASK,
+					DC_GPIO_SDA_PD_DIS);
+
+			scl_pd_dis = get_reg_field_value(
+					reg2,
+					DC_GPIO_I2CPAD_MASK,
+					DC_GPIO_SCL_PD_DIS);
+
+			if (sda_pd_dis) {
+				sda_pd_dis = 0;
+
+				dm_write_reg(ptr->ctx, addr, reg2);
+
+				if (config_data->type ==
+					GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
+					/* should not affect normal I2C R/W */
+					/* [anaumov] in DAL2, there was
+					 * dc_service_delay_in_microseconds(2500); */
+					dm_sleep_in_milliseconds(ptr->ctx, 3);
+			}
+
+			if (!scl_pd_dis) {
+				scl_pd_dis = 1;
+
+				dm_write_reg(ptr->ctx, addr, reg2);
+
+				if (config_data->type ==
+					GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
+					/* should not affect normal I2C R/W */
+					/* [anaumov] in DAL2, there was
+					 * dc_service_delay_in_microseconds(2500); */
+					dm_sleep_in_milliseconds(ptr->ctx, 3);
+			}
+		}
+
+		if (aux_pad_mode) {
+			/* let pins to get de-asserted
+			 * before setting pad to I2C mode */
+			if (config_data->config.ddc.data_en_bit_present ||
+				config_data->config.ddc.clock_en_bit_present)
+				/* [anaumov] in DAL2, there was
+				 * dc_service_delay_in_microseconds(2000); */
+				dm_sleep_in_milliseconds(ptr->ctx, 2);
+
+			/* set the I2C pad mode */
+			/* read the register again,
+			 * some bits may have been changed */
+			regval = dm_read_reg(ptr->ctx, addr);
+
+			set_reg_field_value(
+				regval,
+				0,
+				DC_GPIO_DDC1_MASK,
+				AUX_PAD1_MODE);
+
+			dm_write_reg(ptr->ctx, addr, regval);
+		}
+
+		return GPIO_RESULT_OK;
+	case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
+		/* set the AUX pad mode */
+		if (!aux_pad_mode) {
+			set_reg_field_value(
+				regval,
+				1,
+				DC_GPIO_DDC1_MASK,
+				AUX_PAD1_MODE);
+
+			dm_write_reg(ptr->ctx, addr, regval);
+		}
+
+		return GPIO_RESULT_OK;
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
+		if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
+			(hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+			setup_i2c_polling(
+				ptr->ctx, ADDR_DDC_SETUP, 1, 0);
+			return GPIO_RESULT_OK;
+		}
+	break;
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
+		if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
+			(hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+			setup_i2c_polling(
+				ptr->ctx, ADDR_DDC_SETUP, 1, 1);
+			return GPIO_RESULT_OK;
+		}
+	break;
+	case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
+		if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
+			(hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
+			setup_i2c_polling(
+				ptr->ctx, ADDR_DDC_SETUP, 0, 0);
+			return GPIO_RESULT_OK;
+		}
+	break;
+	}
+
+	BREAK_TO_DEBUGGER();
+
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = dal_hw_ddc_open,
+	.get_value = dal_hw_gpio_get_value,
+	.set_value = dal_hw_gpio_set_value,
+	.set_config = set_config,
+	.change_mode = dal_hw_gpio_change_mode,
+	.close = dal_hw_gpio_close,
+};
+
+
+static bool construct(
+	struct hw_ddc_dce110 *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	const struct hw_ddc_dce110_init *init;
+
+	if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (!dal_hw_ddc_construct(&pin->base, id, en, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	pin->base.base.base.funcs = &funcs;
+
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+		init = hw_ddc_dce110_init_data + en;
+
+		pin->base.base.pin_reg = init->hw_gpio_data_reg;
+		pin->base.mask = init->hw_ddc_mask;
+		pin->addr = init->hw_ddc_dce110_addr;
+
+		return true;
+	case GPIO_ID_DDC_CLOCK:
+		init = hw_ddc_dce110_init_clock + en;
+
+		pin->base.base.pin_reg = init->hw_gpio_data_reg;
+		pin->base.mask = init->hw_ddc_mask;
+		pin->addr = init->hw_ddc_dce110_addr;
+
+		return true;
+	default:
+		ASSERT_CRITICAL(false);
+	}
+
+	return false;
+}
+
+struct hw_gpio_pin *dal_hw_ddc_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_ddc_dce110 *pin = dm_alloc(ctx, sizeof(struct hw_ddc_dce110));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
new file mode 100644
index 000000000000..683036984f6f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_ddc_dce110.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_DDC_DCE110_H__
+#define __DAL_HW_DDC_DCE110_H__
+
+struct hw_ddc_dce110_addr {
+	uint32_t dc_i2c_ddc_setup;
+};
+
+struct hw_ddc_dce110 {
+	struct hw_ddc base;
+	struct hw_ddc_dce110_addr addr;
+};
+
+#define DDC_DCE110_FROM_BASE(ddc_base) \
+	container_of((HW_DDC_FROM_BASE(ddc_base)), struct hw_ddc_dce110, base)
+
+struct hw_gpio_pin *dal_hw_ddc_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
new file mode 100644
index 000000000000..bdeb60173d0e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_factory.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+#include "../hw_hpd.h"
+
+#include "hw_factory_dce110.h"
+
+#include "hw_hpd_dce110.h"
+#include "hw_ddc_dce110.h"
+
+/* fucntion table */
+static const struct hw_factory_funcs funcs = {
+	.create_ddc_data = dal_hw_ddc_dce110_create,
+	.create_ddc_clock = dal_hw_ddc_dce110_create,
+	.create_generic = NULL,
+	.create_hpd = dal_hw_hpd_dce110_create,
+	.create_gpio_pad = NULL,
+	.create_sync = NULL,
+	.create_gsl = NULL,
+};
+
+/*
+ * dal_hw_factory_dce110_init
+ *
+ * @brief
+ * Initialize HW factory function pointers and pin info
+ *
+ * @param
+ * struct hw_factory *factory - [out] struct of function pointers
+ */
+void dal_hw_factory_dce110_init(struct hw_factory *factory)
+{
+	/*TODO check ASIC CAPs*/
+	factory->number_of_pins[GPIO_ID_DDC_DATA] = 8;
+	factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8;
+	factory->number_of_pins[GPIO_ID_GENERIC] = 7;
+	factory->number_of_pins[GPIO_ID_HPD] = 6;
+	factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31;
+	factory->number_of_pins[GPIO_ID_VIP_PAD] = 0;
+	factory->number_of_pins[GPIO_ID_SYNC] = 2;
+	factory->number_of_pins[GPIO_ID_GSL] = 4;
+
+	factory->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
new file mode 100644
index 000000000000..ecf06ed0d587
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_factory_dce110.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_DCE110_H__
+#define __DAL_HW_FACTORY_DCE110_H__
+
+/* Initialize HW factory function pointers and pin info */
+void dal_hw_factory_dce110_init(struct hw_factory *factory);
+
+#endif /* __DAL_HW_FACTORY_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
new file mode 100644
index 000000000000..a90115cdd55d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_hpd.h"
+
+/*
+ * Header of this unit
+ */
+#include "hw_hpd_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+/*
+ * This unit
+ */
+
+static void destruct(
+	struct hw_hpd_dce110 *pin)
+{
+	dal_hw_hpd_destruct(&pin->base);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+struct hw_gpio_generic_dce110_init {
+	struct hw_gpio_pin_reg hw_gpio_data_reg;
+	struct hw_hpd_dce110_addr addr;
+};
+
+static const struct hw_gpio_generic_dce110_init
+	hw_gpio_generic_dce110_init[GPIO_HPD_COUNT] = {
+	/* GPIO_HPD_1 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y_MASK
+			}
+		},
+		{
+			mmHPD0_DC_HPD_INT_STATUS,
+			mmHPD0_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_2 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y_MASK
+			}
+		},
+		{
+			mmHPD1_DC_HPD_INT_STATUS,
+			mmHPD1_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_3 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y_MASK
+			}
+		},
+		{
+			mmHPD2_DC_HPD_INT_STATUS,
+			mmHPD2_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_4 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y_MASK
+			}
+		},
+		{
+			mmHPD3_DC_HPD_INT_STATUS,
+			mmHPD3_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_5 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y_MASK
+			}
+		},
+		{
+			mmHPD4_DC_HPD_INT_STATUS,
+			mmHPD4_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	},
+	/* GPIO_HPD_6 */
+	{
+		{
+			{
+				mmDC_GPIO_HPD_MASK,
+				DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK_MASK
+			},
+			{
+				mmDC_GPIO_HPD_A,
+				DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK
+			},
+			{
+				mmDC_GPIO_HPD_EN,
+				DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN_MASK
+			},
+			{
+				mmDC_GPIO_HPD_Y,
+				DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y_MASK
+			}
+		},
+		{
+			mmHPD5_DC_HPD_INT_STATUS,
+			mmHPD5_DC_HPD_TOGGLE_FILT_CNTL
+		}
+	}
+};
+
+static enum gpio_result get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(ptr);
+
+	/* in Interrupt mode we ask for SENSE bit */
+
+	if (ptr->mode == GPIO_MODE_INTERRUPT) {
+		uint32_t regval;
+		uint32_t hpd_delayed = 0;
+		uint32_t hpd_sense = 0;
+
+		regval = dm_read_reg(
+				ptr->ctx,
+				pin->addr.DC_HPD_INT_STATUS);
+
+		hpd_delayed = get_reg_field_value(
+				regval,
+				DC_HPD_INT_STATUS,
+				DC_HPD_SENSE_DELAYED);
+
+		hpd_sense = get_reg_field_value(
+				regval,
+				DC_HPD_INT_STATUS,
+				DC_HPD_SENSE);
+
+		*value = hpd_delayed;
+		return GPIO_RESULT_OK;
+	}
+
+	/* in any other modes, operate as normal GPIO */
+
+	return dal_hw_gpio_get_value(ptr, value);
+}
+
+static enum gpio_result set_config(
+	struct hw_gpio_pin *ptr,
+	const struct gpio_config_data *config_data)
+{
+	struct hw_hpd_dce110 *pin = HPD_DCE110_FROM_BASE(ptr);
+
+	if (!config_data)
+		return GPIO_RESULT_INVALID_DATA;
+
+	{
+		uint32_t value;
+
+		value = dm_read_reg(
+			ptr->ctx,
+			pin->addr.DC_HPD_TOGGLE_FILT_CNTL);
+
+		set_reg_field_value(
+			value,
+			config_data->config.hpd.delay_on_connect / 10,
+			DC_HPD_TOGGLE_FILT_CNTL,
+			DC_HPD_CONNECT_INT_DELAY);
+
+		set_reg_field_value(
+			value,
+			config_data->config.hpd.delay_on_disconnect / 10,
+			DC_HPD_TOGGLE_FILT_CNTL,
+			DC_HPD_DISCONNECT_INT_DELAY);
+
+		dm_write_reg(
+			ptr->ctx,
+			pin->addr.DC_HPD_TOGGLE_FILT_CNTL,
+			value);
+
+	}
+
+	return GPIO_RESULT_OK;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = dal_hw_gpio_open,
+	.get_value = get_value,
+	.set_value = dal_hw_gpio_set_value,
+	.set_config = set_config,
+	.change_mode = dal_hw_gpio_change_mode,
+	.close = dal_hw_gpio_close,
+};
+
+static bool construct(
+	struct hw_hpd_dce110 *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	const struct hw_gpio_generic_dce110_init *init;
+
+	if (id != GPIO_ID_HPD) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if ((en < GPIO_HPD_MIN) || (en > GPIO_HPD_MAX)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	if (!dal_hw_hpd_construct(&pin->base, id, en, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	pin->base.base.base.funcs = &funcs;
+
+	init = hw_gpio_generic_dce110_init + en;
+
+	pin->base.base.pin_reg = init->hw_gpio_data_reg;
+
+	pin->addr = init->addr;
+
+	return true;
+}
+
+struct hw_gpio_pin *dal_hw_hpd_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_hpd_dce110 *pin = dm_alloc(ctx, sizeof(struct hw_hpd_dce110));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
new file mode 100644
index 000000000000..d032f4b9c91e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_hpd_dce110.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_HPD_DCE110_H__
+#define __DAL_HW_HPD_DCE110_H__
+
+struct hw_hpd_dce110_addr {
+	uint32_t DC_HPD_INT_STATUS;
+	uint32_t DC_HPD_TOGGLE_FILT_CNTL;
+};
+
+struct hw_hpd_dce110 {
+	struct hw_hpd base;
+	struct hw_hpd_dce110_addr addr;
+};
+
+#define HPD_DCE110_FROM_BASE(hpd_base) \
+	container_of((HW_HPD_FROM_BASE(hpd_base)), struct hw_hpd_dce110, base)
+
+struct hw_gpio_pin *dal_hw_hpd_dce110_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif /*__DAL_HW_HPD_DCE110_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
new file mode 100644
index 000000000000..b058f4d22708
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_translate.h"
+
+/*
+ * Header of this unit
+ */
+#include "hw_translate_dce110.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#include "../hw_gpio_pin.h"
+
+#include "dce/dce_11_0_d.h"
+#include "dce/dce_11_0_sh_mask.h"
+
+static bool offset_to_id(
+	uint32_t offset,
+	uint32_t mask,
+	enum gpio_id *id,
+	uint32_t *en)
+{
+	switch (offset) {
+	/* GENERIC */
+	case mmDC_GPIO_GENERIC_A:
+		*id = GPIO_ID_GENERIC;
+		switch (mask) {
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK:
+			*en = GPIO_GENERIC_A;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK:
+			*en = GPIO_GENERIC_B;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK:
+			*en = GPIO_GENERIC_C;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK:
+			*en = GPIO_GENERIC_D;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK:
+			*en = GPIO_GENERIC_E;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK:
+			*en = GPIO_GENERIC_F;
+			return true;
+		case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK:
+			*en = GPIO_GENERIC_G;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* HPD */
+	case mmDC_GPIO_HPD_A:
+		*id = GPIO_ID_HPD;
+		switch (mask) {
+		case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK:
+			*en = GPIO_HPD_1;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK:
+			*en = GPIO_HPD_2;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK:
+			*en = GPIO_HPD_3;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK:
+			*en = GPIO_HPD_4;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK:
+			*en = GPIO_HPD_5;
+			return true;
+		case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK:
+			*en = GPIO_HPD_6;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* SYNCA */
+	case mmDC_GPIO_SYNCA_A:
+		*id = GPIO_ID_SYNC;
+		switch (mask) {
+		case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK:
+			*en = GPIO_SYNC_HSYNC_A;
+			return true;
+		case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK:
+			*en = GPIO_SYNC_VSYNC_A;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* mmDC_GPIO_GENLK_MASK */
+	case mmDC_GPIO_GENLK_A:
+		*id = GPIO_ID_GSL;
+		switch (mask) {
+		case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK:
+			*en = GPIO_GSL_GENLOCK_CLOCK;
+			return true;
+		case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK:
+			*en = GPIO_GSL_GENLOCK_VSYNC;
+			return true;
+		case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK:
+			*en = GPIO_GSL_SWAPLOCK_A;
+			return true;
+		case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK:
+			*en = GPIO_GSL_SWAPLOCK_B;
+			return true;
+		default:
+			ASSERT_CRITICAL(false);
+			return false;
+		}
+	break;
+	/* DDC */
+	/* we don't care about the GPIO_ID for DDC
+	 * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK
+	 * directly in the create method */
+	case mmDC_GPIO_DDC1_A:
+		*en = GPIO_DDC_LINE_DDC1;
+		return true;
+	case mmDC_GPIO_DDC2_A:
+		*en = GPIO_DDC_LINE_DDC2;
+		return true;
+	case mmDC_GPIO_DDC3_A:
+		*en = GPIO_DDC_LINE_DDC3;
+		return true;
+	case mmDC_GPIO_DDC4_A:
+		*en = GPIO_DDC_LINE_DDC4;
+		return true;
+	case mmDC_GPIO_DDC5_A:
+		*en = GPIO_DDC_LINE_DDC5;
+		return true;
+	case mmDC_GPIO_DDC6_A:
+		*en = GPIO_DDC_LINE_DDC6;
+		return true;
+	case mmDC_GPIO_DDCVGA_A:
+		*en = GPIO_DDC_LINE_DDC_VGA;
+		return true;
+	/* GPIO_I2CPAD */
+	case mmDC_GPIO_I2CPAD_A:
+		*en = GPIO_DDC_LINE_I2C_PAD;
+		return true;
+	/* Not implemented */
+	case mmDC_GPIO_PWRSEQ_A:
+	case mmDC_GPIO_PAD_STRENGTH_1:
+	case mmDC_GPIO_PAD_STRENGTH_2:
+	case mmDC_GPIO_DEBUG:
+		return false;
+	/* UNEXPECTED */
+	default:
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+}
+
+static bool id_to_offset(
+	enum gpio_id id,
+	uint32_t en,
+	struct gpio_pin_info *info)
+{
+	bool result = true;
+
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+		info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK;
+		switch (en) {
+		case GPIO_DDC_LINE_DDC1:
+			info->offset = mmDC_GPIO_DDC1_A;
+		break;
+		case GPIO_DDC_LINE_DDC2:
+			info->offset = mmDC_GPIO_DDC2_A;
+		break;
+		case GPIO_DDC_LINE_DDC3:
+			info->offset = mmDC_GPIO_DDC3_A;
+		break;
+		case GPIO_DDC_LINE_DDC4:
+			info->offset = mmDC_GPIO_DDC4_A;
+		break;
+		case GPIO_DDC_LINE_DDC5:
+			info->offset = mmDC_GPIO_DDC5_A;
+		break;
+		case GPIO_DDC_LINE_DDC6:
+			info->offset = mmDC_GPIO_DDC6_A;
+		break;
+		case GPIO_DDC_LINE_DDC_VGA:
+			info->offset = mmDC_GPIO_DDCVGA_A;
+		break;
+		case GPIO_DDC_LINE_I2C_PAD:
+			info->offset = mmDC_GPIO_I2CPAD_A;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_DDC_CLOCK:
+		info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK;
+		switch (en) {
+		case GPIO_DDC_LINE_DDC1:
+			info->offset = mmDC_GPIO_DDC1_A;
+		break;
+		case GPIO_DDC_LINE_DDC2:
+			info->offset = mmDC_GPIO_DDC2_A;
+		break;
+		case GPIO_DDC_LINE_DDC3:
+			info->offset = mmDC_GPIO_DDC3_A;
+		break;
+		case GPIO_DDC_LINE_DDC4:
+			info->offset = mmDC_GPIO_DDC4_A;
+		break;
+		case GPIO_DDC_LINE_DDC5:
+			info->offset = mmDC_GPIO_DDC5_A;
+		break;
+		case GPIO_DDC_LINE_DDC6:
+			info->offset = mmDC_GPIO_DDC6_A;
+		break;
+		case GPIO_DDC_LINE_DDC_VGA:
+			info->offset = mmDC_GPIO_DDCVGA_A;
+		break;
+		case GPIO_DDC_LINE_I2C_PAD:
+			info->offset = mmDC_GPIO_I2CPAD_A;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_GENERIC:
+		info->offset = mmDC_GPIO_GENERIC_A;
+		switch (en) {
+		case GPIO_GENERIC_A:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK;
+		break;
+		case GPIO_GENERIC_B:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK;
+		break;
+		case GPIO_GENERIC_C:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK;
+		break;
+		case GPIO_GENERIC_D:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK;
+		break;
+		case GPIO_GENERIC_E:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK;
+		break;
+		case GPIO_GENERIC_F:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK;
+		break;
+		case GPIO_GENERIC_G:
+			info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_HPD:
+		info->offset = mmDC_GPIO_HPD_A;
+		switch (en) {
+		case GPIO_HPD_1:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK;
+		break;
+		case GPIO_HPD_2:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK;
+		break;
+		case GPIO_HPD_3:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK;
+		break;
+		case GPIO_HPD_4:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK;
+		break;
+		case GPIO_HPD_5:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK;
+		break;
+		case GPIO_HPD_6:
+			info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_SYNC:
+		switch (en) {
+		case GPIO_SYNC_HSYNC_A:
+			info->offset = mmDC_GPIO_SYNCA_A;
+			info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK;
+		break;
+		case GPIO_SYNC_VSYNC_A:
+			info->offset = mmDC_GPIO_SYNCA_A;
+			info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK;
+		break;
+		case GPIO_SYNC_HSYNC_B:
+		case GPIO_SYNC_VSYNC_B:
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_GSL:
+		switch (en) {
+		case GPIO_GSL_GENLOCK_CLOCK:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK;
+		break;
+		case GPIO_GSL_GENLOCK_VSYNC:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask =
+				DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK;
+		break;
+		case GPIO_GSL_SWAPLOCK_A:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK;
+		break;
+		case GPIO_GSL_SWAPLOCK_B:
+			info->offset = mmDC_GPIO_GENLK_A;
+			info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK;
+		break;
+		default:
+			ASSERT_CRITICAL(false);
+			result = false;
+		}
+	break;
+	case GPIO_ID_VIP_PAD:
+	default:
+		ASSERT_CRITICAL(false);
+		result = false;
+	}
+
+	if (result) {
+		info->offset_y = info->offset + 2;
+		info->offset_en = info->offset + 1;
+		info->offset_mask = info->offset - 1;
+
+		info->mask_y = info->mask;
+		info->mask_en = info->mask;
+		info->mask_mask = info->mask;
+	}
+
+	return result;
+}
+
+/* function table */
+static const struct hw_translate_funcs funcs = {
+	.offset_to_id = offset_to_id,
+	.id_to_offset = id_to_offset,
+};
+
+/*
+ * dal_hw_translate_dce110_init
+ *
+ * @brief
+ * Initialize Hw translate function pointers.
+ *
+ * @param
+ * struct hw_translate *tr - [out] struct of function pointers
+ *
+ */
+void dal_hw_translate_dce110_init(struct hw_translate *tr)
+{
+	tr->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
new file mode 100644
index 000000000000..4d16e09853c8
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/dce110/hw_translate_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_DCE110_H__
+#define __DAL_HW_TRANSLATE_DCE110_H__
+
+struct hw_translate;
+
+/* Initialize Hw translate function pointers */
+void dal_hw_translate_dce110_init(struct hw_translate *tr);
+
+#endif /* __DAL_HW_TRANSLATE_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
new file mode 100644
index 000000000000..c3d8cdb44756
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+
+#include "include/gpio_interface.h"
+#include "include/ddc_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_gpio_pin.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+#include "gpio_service.h"
+#include "gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "ddc.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+enum gpio_result dal_ddc_open(
+	struct ddc *ddc,
+	enum gpio_mode mode,
+	enum gpio_ddc_config_type config_type)
+{
+	enum gpio_result result;
+
+	struct gpio_ddc_open_options data_options;
+	struct gpio_ddc_open_options clock_options;
+	struct gpio_config_data config_data;
+
+	result = dal_gpio_open_ex(ddc->pin_data, mode, &data_options);
+
+	if (result != GPIO_RESULT_OK) {
+		BREAK_TO_DEBUGGER();
+		return result;
+	}
+
+	result = dal_gpio_open_ex(ddc->pin_clock, mode, &clock_options);
+
+	if (result != GPIO_RESULT_OK) {
+		BREAK_TO_DEBUGGER();
+		goto failure;
+	}
+
+	/* DDC clock and data pins should belong
+	 * to the same DDC block id,
+	 * we use the data pin to set the pad mode. */
+
+	if (mode == GPIO_MODE_INPUT)
+		/* this is from detect_sink_type,
+		 * we need extra delay there */
+		config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
+	else
+		config_data.type = GPIO_CONFIG_TYPE_DDC;
+
+	config_data.config.ddc.type = config_type;
+	config_data.config.ddc.data_en_bit_present =
+		data_options.en_bit_present;
+	config_data.config.ddc.clock_en_bit_present =
+		clock_options.en_bit_present;
+
+	result = dal_gpio_set_config(ddc->pin_data, &config_data);
+
+	if (result == GPIO_RESULT_OK)
+		return result;
+
+	BREAK_TO_DEBUGGER();
+
+	dal_gpio_close(ddc->pin_clock);
+
+failure:
+	dal_gpio_close(ddc->pin_data);
+
+	return result;
+}
+
+enum gpio_result dal_ddc_get_clock(
+	const struct ddc *ddc,
+	uint32_t *value)
+{
+	return dal_gpio_get_value(ddc->pin_clock, value);
+}
+
+enum gpio_result dal_ddc_set_clock(
+	const struct ddc *ddc,
+	uint32_t value)
+{
+	return dal_gpio_set_value(ddc->pin_clock, value);
+}
+
+enum gpio_result dal_ddc_get_data(
+	const struct ddc *ddc,
+	uint32_t *value)
+{
+	return dal_gpio_get_value(ddc->pin_data, value);
+}
+
+enum gpio_result dal_ddc_set_data(
+	const struct ddc *ddc,
+	uint32_t value)
+{
+	return dal_gpio_set_value(ddc->pin_data, value);
+}
+
+enum gpio_result dal_ddc_change_mode(
+	struct ddc *ddc,
+	enum gpio_mode mode)
+{
+	enum gpio_result result;
+
+	enum gpio_mode original_mode =
+		dal_gpio_get_mode(ddc->pin_data);
+
+	result = dal_gpio_change_mode(ddc->pin_data, mode);
+
+	/* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
+	 * in case of failures;
+	 * set_mode() is so that, in case of failure,
+	 * we must explicitly set original mode */
+
+	if (result != GPIO_RESULT_OK)
+		goto failure;
+
+	result = dal_gpio_change_mode(ddc->pin_clock, mode);
+
+	if (result == GPIO_RESULT_OK)
+		return result;
+
+	dal_gpio_change_mode(ddc->pin_clock, original_mode);
+
+failure:
+	dal_gpio_change_mode(ddc->pin_data, original_mode);
+
+	return result;
+}
+
+bool dal_ddc_is_hw_supported(
+	const struct ddc *ddc)
+{
+	return ddc->hw_info.hw_supported;
+}
+
+enum gpio_ddc_line dal_ddc_get_line(
+	const struct ddc *ddc)
+{
+	return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
+}
+
+bool dal_ddc_check_line_aborted(
+	const struct ddc *self)
+{
+	/* No arbitration with VBIOS is performed since DCE 6.0 */
+
+	return false;
+}
+
+enum gpio_result dal_ddc_set_config(
+	struct ddc *ddc,
+	enum gpio_ddc_config_type config_type)
+{
+	struct gpio_config_data config_data;
+
+	config_data.type = GPIO_CONFIG_TYPE_DDC;
+
+	config_data.config.ddc.type = config_type;
+	config_data.config.ddc.data_en_bit_present = false;
+	config_data.config.ddc.clock_en_bit_present = false;
+
+	return dal_gpio_set_config(ddc->pin_data, &config_data);
+}
+
+void dal_ddc_close(
+	struct ddc *ddc)
+{
+	dal_gpio_close(ddc->pin_clock);
+	dal_gpio_close(ddc->pin_data);
+}
+
+/*
+ * @brief
+ * Creation and destruction
+ */
+
+struct ddc *dal_gpio_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info)
+{
+	enum gpio_id id;
+	uint32_t en;
+	struct ddc *ddc;
+
+	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
+		return NULL;
+
+	ddc = dm_alloc(service->ctx, sizeof(struct ddc));
+
+	if (!ddc) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	ddc->pin_data = dal_gpio_service_create_gpio_ex(
+		service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+
+	if (!ddc->pin_data) {
+		BREAK_TO_DEBUGGER();
+		goto failure_1;
+	}
+
+	ddc->pin_clock = dal_gpio_service_create_gpio_ex(
+		service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+
+	if (!ddc->pin_clock) {
+		BREAK_TO_DEBUGGER();
+		goto failure_2;
+	}
+
+	ddc->hw_info = *info;
+
+	ddc->ctx = service->ctx;
+
+	return ddc;
+
+failure_2:
+	dal_gpio_service_destroy_gpio(&ddc->pin_data);
+
+failure_1:
+	dm_free(service->ctx, ddc);
+
+	return NULL;
+}
+
+static void destruct(struct ddc *ddc)
+{
+	dal_ddc_close(ddc);
+	dal_gpio_service_destroy_gpio(&ddc->pin_data);
+	dal_gpio_service_destroy_gpio(&ddc->pin_clock);
+
+}
+
+void dal_gpio_destroy_ddc(
+	struct ddc **ddc)
+{
+	if (!ddc || !*ddc) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct(*ddc);
+	dm_free((*ddc)->ctx, *ddc);
+
+	*ddc = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
new file mode 100644
index 000000000000..500c3cdd3e56
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/ddc.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_DDC_H__
+#define __DAL_DDC_H__
+
+struct ddc *dal_gpio_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info);
+
+void dal_gpio_destroy_ddc(
+	struct ddc **ddc);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
new file mode 100644
index 000000000000..1dd31d86031c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+
+/*
+ * This unit
+ */
+static void destruct(
+	struct hw_ddc *pin)
+{
+	dal_hw_ddc_destruct(pin);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_ddc *pin = HW_DDC_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = NULL,
+	.get_value = NULL,
+	.set_value = NULL,
+	.set_config = NULL,
+	.change_mode = NULL,
+	.close = NULL,
+};
+
+static bool construct(
+	struct hw_ddc *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	pin->base.base.funcs = &funcs;
+	return true;
+}
+
+struct hw_gpio_pin *dal_hw_ddc_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_ddc *pin = dm_alloc(ctx, sizeof(struct hw_ddc));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
new file mode 100644
index 000000000000..7515aaf33ee3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_ddc_diag.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_DDC_DIAG_FPGA_H__
+#define __DAL_HW_DDC_DIAG_FPGA_H__
+
+struct hw_gpio_pin *dal_hw_ddc_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
new file mode 100644
index 000000000000..0690b4266002
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_factory.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+#include "../hw_hpd.h"
+
+/* function table */
+static const struct hw_factory_funcs funcs = {
+	.create_ddc_data = NULL,
+	.create_ddc_clock = NULL,
+	.create_generic = NULL,
+	.create_hpd = NULL,
+	.create_gpio_pad = NULL,
+	.create_sync = NULL,
+	.create_gsl = NULL,
+};
+
+void dal_hw_factory_diag_fpga_init(struct hw_factory *factory)
+{
+	factory->number_of_pins[GPIO_ID_DDC_DATA] = 8;
+	factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8;
+	factory->number_of_pins[GPIO_ID_GENERIC] = 7;
+	factory->number_of_pins[GPIO_ID_HPD] = 6;
+	factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31;
+	factory->number_of_pins[GPIO_ID_VIP_PAD] = 0;
+	factory->number_of_pins[GPIO_ID_SYNC] = 2;
+	factory->number_of_pins[GPIO_ID_GSL] = 4;
+	factory->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
new file mode 100644
index 000000000000..8a74f6adb8ee
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_factory_diag.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_DIAG_FPGA_H__
+#define __DAL_HW_FACTORY_DIAG_FPGA_H__
+
+/* Initialize HW factory function pointers and pin info */
+void dal_hw_factory_diag_fpga_init(struct hw_factory *factory);
+
+#endif /* __DAL_HW_FACTORY_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
new file mode 100644
index 000000000000..019e810ec31e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "../hw_gpio_pin.h"
+#include "../hw_gpio.h"
+#include "../hw_hpd.h"
+
+
+static void destruct(
+	struct hw_hpd *pin)
+{
+	dal_hw_hpd_destruct(pin);
+}
+
+static void destroy(
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_hpd *pin = HW_HPD_FROM_BASE(*ptr);
+
+	destruct(pin);
+
+	dm_free((*ptr)->ctx, pin);
+
+	*ptr = NULL;
+}
+
+static const struct hw_gpio_pin_funcs funcs = {
+	.destroy = destroy,
+	.open = NULL,
+	.get_value = NULL,
+	.set_value = NULL,
+	.set_config = NULL,
+	.change_mode = NULL,
+	.close = NULL,
+};
+
+static bool construct(
+	struct hw_hpd *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_hpd_construct(pin, id, en, ctx)) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	pin->base.base.funcs = &funcs;
+
+	return true;
+}
+
+struct hw_gpio_pin *dal_hw_hpd_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct hw_hpd *pin = dm_alloc(ctx, sizeof(struct hw_hpd));
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	if (construct(pin, id, en, ctx))
+		return &pin->base.base;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(ctx, pin);
+
+	return NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
new file mode 100644
index 000000000000..bfa2c24a987a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_hpd_diag.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_HPD_DIAG_FPGA_H__
+#define __DAL_HW_HPD_DIAG_FPGA_H__
+
+
+struct hw_gpio_pin *dal_hw_hpd_diag_fpga_create(
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+#endif /*__DAL_HW_HPD_DIAG_FPGA_H__*/
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
new file mode 100644
index 000000000000..177330ab157c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+
+#include "../hw_translate.h"
+
+
+/* function table */
+static const struct hw_translate_funcs funcs = {
+	.offset_to_id = NULL,
+	.id_to_offset = NULL,
+};
+
+void dal_hw_translate_diag_fpga_init(struct hw_translate *tr)
+{
+	tr->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
new file mode 100644
index 000000000000..4f053241fe96
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/diagnostics/hw_translate_diag.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013-16 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_DIAG_FPGA_H__
+#define __DAL_HW_TRANSLATE_DIAG_FPGA_H__
+
+struct hw_translate;
+
+/* Initialize Hw translate function pointers */
+void dal_hw_translate_diag_fpga_init(struct hw_translate *tr);
+
+#endif /* __DAL_HW_TRANSLATE_DIAG_FPGA_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h b/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
new file mode 100644
index 000000000000..7fcbb6972895
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_H__
+#define __DAL_GPIO_H__
+
+struct gpio {
+	struct gpio_service *service;
+	struct hw_gpio_pin *pin;
+	enum gpio_id id;
+	uint32_t en;
+	enum gpio_mode mode;
+	/* when GPIO comes from VBIOS, it has defined output state */
+	enum gpio_pin_output_state output_state;
+};
+
+struct gpio *dal_gpio_create(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state);
+
+void dal_gpio_destroy(
+	struct gpio **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
new file mode 100644
index 000000000000..7e16d631e671
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_base.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+
+#include "include/gpio_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_gpio_pin.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+#include "gpio_service.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "gpio.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Public API
+ */
+
+enum gpio_result dal_gpio_open(
+	struct gpio *gpio,
+	enum gpio_mode mode)
+{
+	return dal_gpio_open_ex(gpio, mode, NULL);
+}
+
+enum gpio_result dal_gpio_open_ex(
+	struct gpio *gpio,
+	enum gpio_mode mode,
+	void *options)
+{
+	if (gpio->pin) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_ALREADY_OPENED;
+	}
+
+	gpio->mode = mode;
+
+	return dal_gpio_service_open(
+		gpio->service, gpio->id, gpio->en, mode, options, &gpio->pin);
+}
+
+enum gpio_result dal_gpio_get_value(
+	const struct gpio *gpio,
+	uint32_t *value)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->get_value(gpio->pin, value);
+}
+
+enum gpio_result dal_gpio_set_value(
+	const struct gpio *gpio,
+	uint32_t value)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->set_value(gpio->pin, value);
+}
+
+enum gpio_mode dal_gpio_get_mode(
+	const struct gpio *gpio)
+{
+	return gpio->mode;
+}
+
+enum gpio_result dal_gpio_change_mode(
+	struct gpio *gpio,
+	enum gpio_mode mode)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->change_mode(gpio->pin, mode);
+}
+
+enum gpio_id dal_gpio_get_id(
+	const struct gpio *gpio)
+{
+	return gpio->id;
+}
+
+uint32_t dal_gpio_get_enum(
+	const struct gpio *gpio)
+{
+	return gpio->en;
+}
+
+enum gpio_result dal_gpio_set_config(
+	struct gpio *gpio,
+	const struct gpio_config_data *config_data)
+{
+	if (!gpio->pin) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_NULL_HANDLE;
+	}
+
+	return gpio->pin->funcs->set_config(gpio->pin, config_data);
+}
+
+enum gpio_result dal_gpio_get_pin_info(
+	const struct gpio *gpio,
+	struct gpio_pin_info *pin_info)
+{
+	return gpio->service->translate.funcs->id_to_offset(
+		gpio->id, gpio->en, pin_info) ?
+		GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA;
+}
+
+enum sync_source dal_gpio_get_sync_source(
+	const struct gpio *gpio)
+{
+	switch (gpio->id) {
+	case GPIO_ID_GENERIC:
+		switch (gpio->en) {
+		case GPIO_GENERIC_A:
+			return SYNC_SOURCE_IO_GENERIC_A;
+		case GPIO_GENERIC_B:
+			return SYNC_SOURCE_IO_GENERIC_B;
+		case GPIO_GENERIC_C:
+			return SYNC_SOURCE_IO_GENERIC_C;
+		case GPIO_GENERIC_D:
+			return SYNC_SOURCE_IO_GENERIC_D;
+		case GPIO_GENERIC_E:
+			return SYNC_SOURCE_IO_GENERIC_E;
+		case GPIO_GENERIC_F:
+			return SYNC_SOURCE_IO_GENERIC_F;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	case GPIO_ID_SYNC:
+		switch (gpio->en) {
+		case GPIO_SYNC_HSYNC_A:
+			return SYNC_SOURCE_IO_HSYNC_A;
+		case GPIO_SYNC_VSYNC_A:
+			return SYNC_SOURCE_IO_VSYNC_A;
+		case GPIO_SYNC_HSYNC_B:
+			return SYNC_SOURCE_IO_HSYNC_B;
+		case GPIO_SYNC_VSYNC_B:
+			return SYNC_SOURCE_IO_VSYNC_B;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	case GPIO_ID_HPD:
+		switch (gpio->en) {
+		case GPIO_HPD_1:
+			return SYNC_SOURCE_IO_HPD1;
+		case GPIO_HPD_2:
+			return SYNC_SOURCE_IO_HPD2;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	case GPIO_ID_GSL:
+		switch (gpio->en) {
+		case GPIO_GSL_GENLOCK_CLOCK:
+			return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK;
+		case GPIO_GSL_GENLOCK_VSYNC:
+			return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC;
+		case GPIO_GSL_SWAPLOCK_A:
+			return SYNC_SOURCE_GSL_IO_SWAPLOCK_A;
+		case GPIO_GSL_SWAPLOCK_B:
+			return SYNC_SOURCE_GSL_IO_SWAPLOCK_B;
+		default:
+			return SYNC_SOURCE_NONE;
+		}
+	break;
+	default:
+		return SYNC_SOURCE_NONE;
+	}
+}
+
+enum gpio_pin_output_state dal_gpio_get_output_state(
+	const struct gpio *gpio)
+{
+	return gpio->output_state;
+}
+
+void dal_gpio_close(
+	struct gpio *gpio)
+{
+	if (!gpio)
+		return;
+
+	dal_gpio_service_close(gpio->service, &gpio->pin);
+
+	gpio->mode = GPIO_MODE_UNKNOWN;
+}
+
+/*
+ * @brief
+ * Creation and destruction
+ */
+
+struct gpio *dal_gpio_create(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state)
+{
+	struct gpio *gpio = dm_alloc(service->ctx, sizeof(struct gpio));
+
+	if (!gpio) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	gpio->service = service;
+	gpio->pin = NULL;
+	gpio->id = id;
+	gpio->en = en;
+	gpio->mode = GPIO_MODE_UNKNOWN;
+	gpio->output_state = output_state;
+
+	return gpio;
+}
+
+void dal_gpio_destroy(
+	struct gpio **gpio)
+{
+	if (!gpio || !*gpio) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	dal_gpio_close(*gpio);
+
+	dm_free((*gpio)->service->ctx, *gpio);
+
+	*gpio = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
new file mode 100644
index 000000000000..6837898b3bfe
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+
+#include "dm_services.h"
+#include "include/gpio_interface.h"
+#include "include/ddc_interface.h"
+#include "include/irq_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "gpio_service.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#include "hw_gpio_pin.h"
+#include "gpio.h"
+#include "ddc.h"
+#include "irq.h"
+
+/*
+ * This unit
+ */
+
+/*
+ * @brief
+ * Public API.
+ */
+
+struct gpio_service *dal_gpio_service_create(
+	enum dce_version dce_version_major,
+	enum dce_version dce_version_minor,
+	struct dc_context *ctx)
+{
+	struct gpio_service *service;
+
+	uint32_t index_of_id;
+
+	service = dm_alloc(ctx, sizeof(struct gpio_service));
+
+	if (!service) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	if (!dal_hw_translate_init(&service->translate, dce_version_major,
+			dce_version_minor)) {
+		BREAK_TO_DEBUGGER();
+		goto failure_1;
+	}
+
+	if (!dal_hw_factory_init(&service->factory, dce_version_major,
+			dce_version_minor)) {
+		BREAK_TO_DEBUGGER();
+		goto failure_1;
+	}
+
+	/* allocate and initialize business storage */
+	{
+		const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+		index_of_id = 0;
+		service->ctx = ctx;
+
+		do {
+			uint32_t number_of_bits =
+				service->factory.number_of_pins[index_of_id];
+
+			uint32_t number_of_uints =
+				(number_of_bits + bits_per_uint - 1) /
+				bits_per_uint;
+
+			uint32_t *slot;
+
+			if (number_of_bits) {
+				uint32_t index_of_uint = 0;
+
+				slot = dm_alloc(
+					ctx,
+					number_of_uints * sizeof(uint32_t));
+
+				if (!slot) {
+					BREAK_TO_DEBUGGER();
+					goto failure_2;
+				}
+
+				do {
+					slot[index_of_uint] = 0;
+
+					++index_of_uint;
+				} while (index_of_uint < number_of_uints);
+			} else
+				slot = NULL;
+
+			service->busyness[index_of_id] = slot;
+
+			++index_of_id;
+		} while (index_of_id < GPIO_ID_COUNT);
+	}
+
+	return service;
+
+failure_2:
+	while (index_of_id) {
+		uint32_t *slot;
+
+		--index_of_id;
+
+		slot = service->busyness[index_of_id];
+
+		if (slot)
+			dm_free(ctx, slot);
+	};
+
+failure_1:
+	dm_free(ctx, service);
+
+	return NULL;
+}
+
+struct gpio *dal_gpio_service_create_gpio(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	enum gpio_pin_output_state output_state)
+{
+	enum gpio_id id;
+	uint32_t en;
+
+	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	return dal_gpio_create(service, id, en, output_state);
+}
+
+struct gpio *dal_gpio_service_create_gpio_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_pin_output_state output_state)
+{
+	return dal_gpio_create(service, id, en, output_state);
+}
+
+void dal_gpio_service_destroy_gpio(
+	struct gpio **gpio)
+{
+	dal_gpio_destroy(gpio);
+}
+
+struct ddc *dal_gpio_service_create_ddc(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask,
+	struct gpio_ddc_hw_info *info)
+{
+	return dal_gpio_create_ddc(service, offset, mask, info);
+}
+
+void dal_gpio_service_destroy_ddc(
+	struct ddc **ddc)
+{
+	dal_gpio_destroy_ddc(ddc);
+}
+
+struct irq *dal_gpio_service_create_irq(
+	struct gpio_service *service,
+	uint32_t offset,
+	uint32_t mask)
+{
+	enum gpio_id id;
+	uint32_t en;
+
+	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	return dal_gpio_create_irq(service, id, en);
+}
+
+struct irq *dal_gpio_service_create_irq_ex(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	return dal_gpio_create_irq(service, id, en);
+}
+
+void dal_gpio_service_destroy_irq(
+	struct irq **irq)
+{
+	dal_gpio_destroy_irq(irq);
+}
+
+void dal_gpio_service_destroy(
+	struct gpio_service **ptr)
+{
+	if (!ptr || !*ptr) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	/* free business storage */
+	{
+		uint32_t index_of_id = 0;
+
+		do {
+			uint32_t *slot = (*ptr)->busyness[index_of_id];
+
+			if (slot)
+				dm_free((*ptr)->ctx, slot);
+
+			++index_of_id;
+		} while (index_of_id < GPIO_ID_COUNT);
+	}
+
+	dm_free((*ptr)->ctx, *ptr);
+
+	*ptr = NULL;
+}
+
+/*
+ * @brief
+ * Private API.
+ */
+
+static bool is_pin_busy(
+	const struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+	const uint32_t *slot = service->busyness[id] + (en / bits_per_uint);
+
+	return 0 != (*slot & (1 << (en % bits_per_uint)));
+}
+
+static void set_pin_busy(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+	service->busyness[id][en / bits_per_uint] |=
+		(1 << (en % bits_per_uint));
+}
+
+static void set_pin_free(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
+
+	service->busyness[id][en / bits_per_uint] &=
+		~(1 << (en % bits_per_uint));
+}
+
+enum gpio_result dal_gpio_service_open(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_mode mode,
+	void *options,
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_gpio_pin *pin;
+
+	if (!service->busyness[id]) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_OPEN_FAILED;
+	}
+
+	if (is_pin_busy(service, id, en)) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_DEVICE_BUSY;
+	}
+
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+		pin = service->factory.funcs->create_ddc_data(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_DDC_CLOCK:
+		pin = service->factory.funcs->create_ddc_clock(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_GENERIC:
+		pin = service->factory.funcs->create_generic(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_HPD:
+		pin = service->factory.funcs->create_hpd(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_GPIO_PAD:
+		pin = service->factory.funcs->create_gpio_pad(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_SYNC:
+		pin = service->factory.funcs->create_sync(
+			service->ctx, id, en);
+	break;
+	case GPIO_ID_GSL:
+		pin = service->factory.funcs->create_gsl(
+			service->ctx, id, en);
+	break;
+	default:
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+
+	if (!pin) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+
+	if (!pin->funcs->open(pin, mode, options)) {
+		ASSERT_CRITICAL(false);
+		dal_gpio_service_close(service, &pin);
+		return GPIO_RESULT_OPEN_FAILED;
+	}
+
+	set_pin_busy(service, id, en);
+	*ptr = pin;
+	return GPIO_RESULT_OK;
+}
+
+void dal_gpio_service_close(
+	struct gpio_service *service,
+	struct hw_gpio_pin **ptr)
+{
+	struct hw_gpio_pin *pin;
+
+	if (!ptr) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	pin = *ptr;
+
+	if (pin) {
+		set_pin_free(service, pin->id, pin->en);
+
+		pin->funcs->close(pin);
+
+		pin->funcs->destroy(ptr);
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
new file mode 100644
index 000000000000..a17c4386668d
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/gpio_service.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_GPIO_SERVICE_H__
+#define __DAL_GPIO_SERVICE_H__
+
+struct hw_translate;
+struct hw_factory;
+
+struct gpio_service {
+	struct dc_context *ctx;
+	struct hw_translate translate;
+	struct hw_factory factory;
+	/*
+	 * @brief
+	 * Business storage.
+	 * For each member of 'enum gpio_id',
+	 * store array of bits (packed into uint32_t slots),
+	 * index individual bit by 'en' value */
+	uint32_t *busyness[GPIO_ID_COUNT];
+};
+
+enum gpio_result dal_gpio_service_open(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en,
+	enum gpio_mode mode,
+	void *options,
+	struct hw_gpio_pin **ptr);
+
+void dal_gpio_service_close(
+	struct gpio_service *service,
+	struct hw_gpio_pin **ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
new file mode 100644
index 000000000000..41e46a7dc001
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+#include "hw_gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_ddc.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define FROM_HW_GPIO(ptr) \
+	container_of((ptr), struct hw_ddc, base)
+
+#define FROM_HW_GPIO_PIN(ptr) \
+	FROM_HW_GPIO(container_of((ptr), struct hw_gpio, base))
+
+bool dal_hw_ddc_open(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode,
+	void *options)
+{
+	struct hw_ddc *pin = FROM_HW_GPIO_PIN(ptr);
+
+	uint32_t en;
+
+	if (!options) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	/* get the EN bit before overwriting it */
+
+	dal_hw_gpio_get_reg_value(
+		ptr->ctx,
+		&pin->base.pin_reg.DC_GPIO_DATA_EN,
+		&en);
+
+	((struct gpio_ddc_open_options *)options)->en_bit_present = (en != 0);
+
+	return dal_hw_gpio_open(ptr, mode, options);
+}
+
+bool dal_hw_ddc_construct(
+	struct hw_ddc *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_gpio_construct(&pin->base, id, en, ctx))
+		return false;
+
+	pin->mask.DC_GPIO_DDC_MASK_MASK = 0;
+	pin->mask.DC_GPIO_DDC_PD_EN_MASK = 0;
+	pin->mask.DC_GPIO_DDC_RECV_MASK = 0;
+	pin->mask.AUX_PAD_MODE_MASK = 0;
+	pin->mask.AUX_POL_MASK = 0;
+	pin->mask.DC_GPIO_DDCCLK_STR_MASK = 0;
+
+	return true;
+}
+
+void dal_hw_ddc_destruct(
+	struct hw_ddc *pin)
+{
+	dal_hw_gpio_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
new file mode 100644
index 000000000000..a3a727c58b83
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_ddc.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_DDC_H__
+#define __DAL_HW_DDC_H__
+
+struct hw_ddc_mask {
+	uint32_t DC_GPIO_DDC_MASK_MASK;
+	uint32_t DC_GPIO_DDC_PD_EN_MASK;
+	uint32_t DC_GPIO_DDC_RECV_MASK;
+	uint32_t AUX_PAD_MODE_MASK;
+	uint32_t AUX_POL_MASK;
+	uint32_t DC_GPIO_DDCCLK_STR_MASK;
+};
+
+struct hw_ddc {
+	struct hw_gpio base;
+	struct hw_ddc_mask mask;
+};
+
+#define HW_DDC_FROM_BASE(hw_gpio) \
+	container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_ddc, base)
+
+bool dal_hw_ddc_construct(
+	struct hw_ddc *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_ddc_destruct(
+	struct hw_ddc *pin);
+
+bool dal_hw_ddc_open(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode,
+	void *options);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
new file mode 100644
index 000000000000..e0f6ecfaf4a7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_factory.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/hw_factory_dce110.h"
+#endif
+
+#include "diagnostics/hw_factory_diag.h"
+
+/*
+ * This unit
+ */
+
+bool dal_hw_factory_init(
+	struct hw_factory *factory,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment)
+{
+	if (IS_FPGA_MAXIMUS_DC(dce_environment)) {
+		dal_hw_factory_diag_fpga_init(factory);
+		return true;
+	}
+
+	switch (dce_version) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		dal_hw_factory_dce110_init(factory);
+		return true;
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		dal_hw_factory_dce110_init(factory);
+		return true;
+#endif
+	default:
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+}
+
+void dal_hw_factory_destroy(
+	struct dc_context *ctx,
+	struct hw_factory **factory)
+{
+	if (!factory || !*factory) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	dm_free(ctx, *factory);
+
+	*factory = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
new file mode 100644
index 000000000000..1fa8b6d85f35
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_factory.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_H__
+#define __DAL_HW_FACTORY_H__
+
+struct hw_gpio_pin;
+
+struct hw_factory {
+	uint32_t number_of_pins[GPIO_ID_COUNT];
+
+	const struct hw_factory_funcs {
+		struct hw_gpio_pin *(*create_ddc_data)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_ddc_clock)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_generic)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_hpd)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_gpio_pad)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_sync)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+		struct hw_gpio_pin *(*create_gsl)(
+			struct dc_context *ctx,
+			enum gpio_id id,
+			uint32_t en);
+	} *funcs;
+};
+
+bool dal_hw_factory_init(
+	struct hw_factory *factory,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
new file mode 100644
index 000000000000..2a2262c7b107
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_gpio.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+enum gpio_result dal_hw_gpio_get_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t *value)
+{
+	*value = dm_read_reg(ctx, reg->addr);
+
+	*value &= reg->mask;
+
+	return GPIO_RESULT_OK;
+}
+
+enum gpio_result dal_hw_gpio_set_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t value)
+{
+	uint32_t prev_value;
+
+	if ((value & reg->mask) != value) {
+		BREAK_TO_DEBUGGER();
+		return GPIO_RESULT_INVALID_DATA;
+	}
+
+	prev_value = dm_read_reg(ctx, reg->addr);
+
+	prev_value &= ~reg->mask;
+	prev_value |= (value & reg->mask);
+
+	dm_write_reg(ctx, reg->addr, prev_value);
+
+	return GPIO_RESULT_OK;
+}
+
+uint32_t dal_hw_gpio_get_shift_from_mask(
+	uint32_t mask)
+{
+	uint32_t result = 0;
+
+	if (!mask)
+		return 32;
+
+	do {
+		if ((1 << result) & mask)
+			break;
+
+		++result;
+	} while (result < 32);
+
+	return result;
+}
+
+#define FROM_HW_GPIO_PIN(ptr) \
+	container_of((ptr), struct hw_gpio, base)
+
+static void store_registers(
+	struct hw_gpio *pin)
+{
+	dal_hw_gpio_get_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		&pin->store.mask);
+	dal_hw_gpio_get_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_A,
+		&pin->store.a);
+	dal_hw_gpio_get_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		&pin->store.en);
+
+	if (pin->mux_supported)
+		dal_hw_gpio_get_reg_value(
+			pin->base.ctx,
+			&pin->mux_reg.GPIO_MUX_CONTROL,
+			&pin->store.mux);
+}
+
+static void restore_registers(
+	struct hw_gpio *pin)
+{
+	dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->store.mask);
+	dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_A,
+		pin->store.a);
+	dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		pin->store.en);
+
+	if (pin->mux_supported)
+		dal_hw_gpio_set_reg_value(
+			pin->base.ctx,
+			&pin->mux_reg.GPIO_MUX_CONTROL,
+			pin->store.mux);
+}
+
+bool dal_hw_gpio_open(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode,
+	void *options)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	store_registers(pin);
+
+	ptr->opened = (pin->funcs->config_mode(pin, mode) == GPIO_RESULT_OK);
+
+	return ptr->opened;
+}
+
+enum gpio_result dal_hw_gpio_get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	const struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	enum gpio_result result;
+
+	switch (ptr->mode) {
+	case GPIO_MODE_INPUT:
+	case GPIO_MODE_OUTPUT:
+	case GPIO_MODE_HARDWARE:
+	case GPIO_MODE_FAST_OUTPUT:
+		result = dal_hw_gpio_get_reg_value(
+			ptr->ctx,
+			&pin->pin_reg.DC_GPIO_DATA_Y,
+			value);
+		/* Clients does not know that the value
+		 * comes from register and is shifted. */
+		if (result == GPIO_RESULT_OK)
+			*value >>= dal_hw_gpio_get_shift_from_mask(
+				pin->pin_reg.DC_GPIO_DATA_Y.mask);
+	break;
+	default:
+		result = GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+
+	return result;
+}
+
+enum gpio_result dal_hw_gpio_set_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	/* This is the public interface
+	 * where the input comes from client, not shifted yet
+	 * (because client does not know the shifts). */
+
+	switch (ptr->mode) {
+	case GPIO_MODE_OUTPUT:
+		return dal_hw_gpio_set_reg_value(
+			ptr->ctx,
+			&pin->pin_reg.DC_GPIO_DATA_A,
+			value << dal_hw_gpio_get_shift_from_mask(
+				pin->pin_reg.DC_GPIO_DATA_A.mask));
+	case GPIO_MODE_FAST_OUTPUT:
+		/* We use (EN) to faster switch (used in DDC GPIO).
+		 * So (A) is grounded, output is driven by (EN = 0)
+		 * to pull the line down (output == 0) and (EN=1)
+		 * then output is tri-state */
+		return dal_hw_gpio_set_reg_value(
+			ptr->ctx,
+			&pin->pin_reg.DC_GPIO_DATA_EN,
+			pin->pin_reg.DC_GPIO_DATA_EN.mask &
+			~(value << dal_hw_gpio_get_shift_from_mask(
+				pin->pin_reg.DC_GPIO_DATA_EN.mask)));
+	default:
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+enum gpio_result dal_hw_gpio_change_mode(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	return pin->funcs->config_mode(pin, mode);
+}
+
+void dal_hw_gpio_close(
+	struct hw_gpio_pin *ptr)
+{
+	struct hw_gpio *pin = FROM_HW_GPIO_PIN(ptr);
+
+	restore_registers(pin);
+
+	ptr->mode = GPIO_MODE_UNKNOWN;
+	ptr->opened = false;
+}
+
+static enum gpio_result config_mode_input(
+	struct hw_gpio *pin)
+{
+	enum gpio_result result;
+
+	/* turn off output enable, act as input pin;
+	 * program the pin as GPIO, mask out signal driven by HW */
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		0);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->pin_reg.DC_GPIO_DATA_MASK.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+static enum gpio_result config_mode_output(
+	struct hw_gpio *pin)
+{
+	enum gpio_result result;
+
+	/* turn on output enable, act as output pin;
+	 * program the pin as GPIO, mask out signal driven by HW */
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_EN,
+		pin->pin_reg.DC_GPIO_DATA_EN.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->pin_reg.DC_GPIO_DATA_MASK.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+static enum gpio_result config_mode_fast_output(
+	struct hw_gpio *pin)
+{
+	enum gpio_result result;
+
+	/* grounding the A register then use the EN register bit
+	 * will have faster effect on the rise time */
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_A, 0);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	result = dal_hw_gpio_set_reg_value(
+		pin->base.ctx,
+		&pin->pin_reg.DC_GPIO_DATA_MASK,
+		pin->pin_reg.DC_GPIO_DATA_MASK.mask);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+static enum gpio_result config_mode_hardware(
+	struct hw_gpio *pin)
+{
+	/* program the pin as tri-state, pin is driven by HW */
+
+	enum gpio_result result =
+		dal_hw_gpio_set_reg_value(
+			pin->base.ctx,
+			&pin->pin_reg.DC_GPIO_DATA_MASK,
+			0);
+
+	if (result != GPIO_RESULT_OK)
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+
+	return GPIO_RESULT_OK;
+}
+
+enum gpio_result dal_hw_gpio_config_mode(
+	struct hw_gpio *pin,
+	enum gpio_mode mode)
+{
+	pin->base.mode = mode;
+
+	switch (mode) {
+	case GPIO_MODE_INPUT:
+		return config_mode_input(pin);
+	case GPIO_MODE_OUTPUT:
+		return config_mode_output(pin);
+	case GPIO_MODE_FAST_OUTPUT:
+		return config_mode_fast_output(pin);
+	case GPIO_MODE_HARDWARE:
+		return config_mode_hardware(pin);
+	default:
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+const struct hw_gpio_funcs func = {
+	.config_mode = dal_hw_gpio_config_mode,
+};
+
+bool dal_hw_gpio_construct(
+	struct hw_gpio *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	struct hw_gpio_pin *base = &pin->base;
+
+	if (!dal_hw_gpio_pin_construct(base, id, en, ctx))
+		return false;
+
+	pin->funcs = &func;
+
+	pin->pin_reg.DC_GPIO_DATA_MASK.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_MASK.mask = 0;
+	pin->pin_reg.DC_GPIO_DATA_A.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_A.mask = 0;
+	pin->pin_reg.DC_GPIO_DATA_EN.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_EN.mask = 0;
+	pin->pin_reg.DC_GPIO_DATA_Y.addr = 0;
+	pin->pin_reg.DC_GPIO_DATA_Y.mask = 0;
+	pin->mux_reg.GPIO_MUX_CONTROL.addr = 0;
+	pin->mux_reg.GPIO_MUX_CONTROL.mask = 0;
+	pin->mux_reg.GPIO_MUX_STEREO_SEL.addr = 0;
+	pin->mux_reg.GPIO_MUX_STEREO_SEL.mask = 0;
+
+	pin->store.mask = 0;
+	pin->store.a = 0;
+	pin->store.en = 0;
+	pin->store.mux = 0;
+
+	pin->mux_supported = false;
+
+	return true;
+}
+
+void dal_hw_gpio_destruct(
+	struct hw_gpio *pin)
+{
+	dal_hw_gpio_pin_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
new file mode 100644
index 000000000000..44eb86e1cc32
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_GPIO_H__
+#define __DAL_HW_GPIO_H__
+
+struct addr_mask {
+	uint32_t addr;
+	uint32_t mask;
+};
+
+enum gpio_result dal_hw_gpio_get_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t *value);
+
+enum gpio_result dal_hw_gpio_set_reg_value(
+	struct dc_context *ctx,
+	const struct addr_mask *reg,
+	uint32_t value);
+
+uint32_t dal_hw_gpio_get_shift_from_mask(
+	uint32_t mask);
+
+struct hw_gpio;
+
+struct hw_gpio_funcs {
+	enum gpio_result (*config_mode)(
+		struct hw_gpio *pin,
+		enum gpio_mode mode);
+};
+
+/* Register indices are represented by member variables
+ * and are to be filled in by constructors of derived classes.
+ * These members permit the use of common code
+ * for programming registers, where the sequence is the same
+ * but register sets are different.
+ * Some GPIOs have HW mux which allows to choose
+ * what is the source of the signal in HW mode */
+
+struct hw_gpio_pin_reg {
+	struct addr_mask DC_GPIO_DATA_MASK;
+	struct addr_mask DC_GPIO_DATA_A;
+	struct addr_mask DC_GPIO_DATA_EN;
+	struct addr_mask DC_GPIO_DATA_Y;
+};
+
+struct hw_gpio_mux_reg {
+	struct addr_mask GPIO_MUX_CONTROL;
+	struct addr_mask GPIO_MUX_STEREO_SEL;
+};
+
+struct hw_gpio {
+	struct hw_gpio_pin base;
+	const struct hw_gpio_funcs *funcs;
+	struct hw_gpio_pin_reg pin_reg;
+	struct hw_gpio_mux_reg mux_reg;
+
+	/* variables to save register value */
+	struct {
+		uint32_t mask;
+		uint32_t a;
+		uint32_t en;
+		uint32_t mux;
+	} store;
+
+	/* GPIO MUX support */
+	bool mux_supported;
+};
+
+#define HW_GPIO_FROM_BASE(hw_gpio_pin) \
+	container_of((hw_gpio_pin), struct hw_gpio, base)
+
+bool dal_hw_gpio_construct(
+	struct hw_gpio *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+bool dal_hw_gpio_open(
+	struct hw_gpio_pin *pin,
+	enum gpio_mode mode,
+	void *options);
+
+enum gpio_result dal_hw_gpio_get_value(
+	const struct hw_gpio_pin *pin,
+	uint32_t *value);
+
+enum gpio_result dal_hw_gpio_config_mode(
+	struct hw_gpio *pin,
+	enum gpio_mode mode);
+
+void dal_hw_gpio_destruct(
+	struct hw_gpio *pin);
+
+enum gpio_result dal_hw_gpio_set_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value);
+
+enum gpio_result dal_hw_gpio_change_mode(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode);
+
+void dal_hw_gpio_close(
+	struct hw_gpio_pin *ptr);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
new file mode 100644
index 000000000000..2392f2ce353b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+#include "hw_gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_gpio_pad.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+#define FROM_HW_GPIO(ptr) \
+	container_of((ptr), struct hw_gpio_pad, base)
+
+#define FROM_HW_GPIO_PIN(ptr) \
+	FROM_HW_GPIO(container_of((ptr), struct hw_gpio, base))
+
+enum gpio_result dal_hw_gpio_pad_get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	const struct hw_gpio_pad *pin = FROM_HW_GPIO_PIN(ptr);
+
+	if (ptr->mode == GPIO_MODE_INTERRUPT)
+		/* in Interrupt mode, ask for interrupt status bit */
+		return dal_hw_gpio_get_reg_value(
+			ptr->ctx,
+			&pin->gpiopad_int_status,
+			value);
+	else
+		/* for any mode other than Interrupt,
+		 * gpio_pad operates as normal GPIO */
+		return dal_hw_gpio_get_value(ptr, value);
+}
+
+bool dal_hw_gpio_pad_construct(
+	struct hw_gpio_pad *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_gpio_construct(&pin->base, id, en, ctx))
+		return false;
+
+	pin->gpiopad_int_status.addr = 0;
+	pin->gpiopad_int_status.mask = 0;
+
+	return true;
+}
+
+void dal_hw_gpio_pad_destruct(
+	struct hw_gpio_pad *pin)
+{
+	dal_hw_gpio_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
new file mode 100644
index 000000000000..34b470a11464
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pad.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_GPIO_PAD_H__
+#define __DAL_HW_GPIO_PAD_H__
+
+struct hw_gpio_pad {
+	struct hw_gpio base;
+	struct addr_mask gpiopad_int_status;
+};
+
+bool dal_hw_gpio_pad_construct(
+	struct hw_gpio_pad *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_gpio_pad_destruct(
+	struct hw_gpio_pad *pin);
+
+enum gpio_result dal_hw_gpio_pad_get_value(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
new file mode 100644
index 000000000000..411ad89645e0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_gpio_pin.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+enum gpio_result dal_hw_gpio_pin_set_config(
+	struct hw_gpio_pin *pin,
+	const struct gpio_config_data *config_data)
+{
+	/* Attention!
+	 * You must override this method in derived class */
+
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+enum gpio_result dal_hw_gpio_pin_change_mode(
+	struct hw_gpio_pin *pin,
+	enum gpio_mode mode)
+{
+	/* Attention!
+	 * You must override this method in derived class */
+
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+bool dal_hw_gpio_pin_construct(
+	struct hw_gpio_pin *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	pin->ctx = ctx;
+	pin->id = id;
+	pin->en = en;
+	pin->mode = GPIO_MODE_UNKNOWN;
+	pin->opened = false;
+
+	return true;
+}
+
+void dal_hw_gpio_pin_destruct(
+	struct hw_gpio_pin *pin)
+{
+	ASSERT(!pin->opened);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
new file mode 100644
index 000000000000..d1f2f2712fe2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_gpio_pin.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_GPIO_PIN_H__
+#define __DAL_HW_GPIO_PIN_H__
+
+struct hw_gpio_pin;
+
+struct hw_gpio_pin_funcs {
+	void (*destroy)(
+		struct hw_gpio_pin **ptr);
+	bool (*open)(
+		struct hw_gpio_pin *pin,
+		enum gpio_mode mode,
+		void *options);
+	enum gpio_result (*get_value)(
+		const struct hw_gpio_pin *pin,
+		uint32_t *value);
+	enum gpio_result (*set_value)(
+		const struct hw_gpio_pin *pin,
+		uint32_t value);
+	enum gpio_result (*set_config)(
+		struct hw_gpio_pin *pin,
+		const struct gpio_config_data *config_data);
+	enum gpio_result (*change_mode)(
+		struct hw_gpio_pin *pin,
+		enum gpio_mode mode);
+	void (*close)(
+		struct hw_gpio_pin *pin);
+};
+
+struct hw_gpio_pin {
+	const struct hw_gpio_pin_funcs *funcs;
+	enum gpio_id id;
+	uint32_t en;
+	enum gpio_mode mode;
+	bool opened;
+	struct dc_context *ctx;
+};
+
+bool dal_hw_gpio_pin_construct(
+	struct hw_gpio_pin *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_gpio_pin_destruct(
+	struct hw_gpio_pin *pin);
+
+enum gpio_result dal_hw_gpio_pin_change_mode(
+	struct hw_gpio_pin *pin,
+	enum gpio_mode mode);
+
+enum gpio_result dal_hw_gpio_pin_set_config(
+	struct hw_gpio_pin *pin,
+	const struct gpio_config_data *config_data);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
new file mode 100644
index 000000000000..f072fd551b4a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+#include "hw_gpio_pin.h"
+#include "hw_gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_hpd.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+static enum gpio_result config_mode(
+	struct hw_gpio *pin,
+	enum gpio_mode mode)
+{
+	if (mode == GPIO_MODE_INTERRUPT) {
+		/* Interrupt mode supported only by HPD (IrqGpio) pins. */
+		pin->base.mode = mode;
+
+		return dal_hw_gpio_set_reg_value(
+			pin->base.ctx,
+			&pin->pin_reg.DC_GPIO_DATA_MASK,
+			0);
+	} else
+		/* For any mode other than Interrupt,
+		 * act as normal GPIO. */
+		return dal_hw_gpio_config_mode(pin, mode);
+}
+
+const struct hw_gpio_funcs hw_hpd_func = {
+	.config_mode = config_mode,
+};
+
+bool dal_hw_hpd_construct(
+	struct hw_hpd *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	if (!dal_hw_gpio_construct(&pin->base, id, en, ctx))
+		return false;
+	pin->base.funcs = &hw_hpd_func;
+	return true;
+}
+
+void dal_hw_hpd_destruct(
+	struct hw_hpd *pin)
+{
+	dal_hw_gpio_destruct(&pin->base);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
new file mode 100644
index 000000000000..3fb82df88802
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_hpd.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_HPD_H__
+#define __DAL_HW_HPD_H__
+
+struct hw_hpd {
+	struct hw_gpio base;
+};
+
+#define HW_HPD_FROM_BASE(hw_gpio) \
+	container_of((HW_GPIO_FROM_BASE(hw_gpio)), struct hw_hpd, base)
+
+bool dal_hw_hpd_construct(
+	struct hw_hpd *pin,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx);
+
+void dal_hw_hpd_destruct(
+	struct hw_hpd *pin);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
new file mode 100644
index 000000000000..215322e9d7e9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_types.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "hw_translate.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/hw_translate_dce110.h"
+#endif
+
+#include "diagnostics/hw_translate_diag.h"
+
+/*
+ * This unit
+ */
+
+bool dal_hw_translate_init(
+	struct hw_translate *translate,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment)
+{
+	if (IS_FPGA_MAXIMUS_DC(dce_environment)) {
+		dal_hw_translate_diag_fpga_init(translate);
+		return true;
+	}
+
+	switch (dce_version) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+#endif
+	case DCE_VERSION_11_0:
+		dal_hw_translate_dce110_init(translate);
+		return true;
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
new file mode 100644
index 000000000000..3a7d89ca1605
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/hw_translate.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_H__
+#define __DAL_HW_TRANSLATE_H__
+
+struct hw_translate_funcs {
+	bool (*offset_to_id)(
+		uint32_t offset,
+		uint32_t mask,
+		enum gpio_id *id,
+		uint32_t *en);
+	bool (*id_to_offset)(
+		enum gpio_id id,
+		uint32_t en,
+		struct gpio_pin_info *info);
+};
+
+struct hw_translate {
+	const struct hw_translate_funcs *funcs;
+};
+
+bool dal_hw_translate_init(
+	struct hw_translate *translate,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/irq.c b/drivers/gpu/drm/amd/dal/dc/gpio/irq.c
new file mode 100644
index 000000000000..debc2ea48ca1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/irq.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+/*
+ * Pre-requisites: headers required by header of this unit
+ */
+#include "include/gpio_interface.h"
+#include "include/irq_interface.h"
+#include "include/gpio_service_interface.h"
+#include "hw_gpio_pin.h"
+#include "hw_translate.h"
+#include "hw_factory.h"
+#include "gpio_service.h"
+#include "gpio.h"
+
+/*
+ * Header of this unit
+ */
+
+#include "irq.h"
+
+/*
+ * Post-requisites: headers required by this unit
+ */
+
+/*
+ * This unit
+ */
+
+enum gpio_result dal_irq_open(
+	struct irq *irq)
+{
+	return dal_gpio_open(irq->pin, GPIO_MODE_INTERRUPT);
+}
+
+enum gpio_result dal_irq_get_value(
+	const struct irq *irq,
+	uint32_t *value)
+{
+	return dal_gpio_get_value(irq->pin, value);
+}
+
+enum dc_irq_source dal_irq_get_source(
+	const struct irq *irq)
+{
+	enum gpio_id id = dal_gpio_get_id(irq->pin);
+
+	switch (id) {
+	case GPIO_ID_HPD:
+		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
+			dal_gpio_get_enum(irq->pin));
+	case GPIO_ID_GPIO_PAD:
+		return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
+			dal_gpio_get_enum(irq->pin));
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+enum dc_irq_source dal_irq_get_rx_source(
+	const struct irq *irq)
+{
+	enum gpio_id id = dal_gpio_get_id(irq->pin);
+
+	switch (id) {
+	case GPIO_ID_HPD:
+		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
+			dal_gpio_get_enum(irq->pin));
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+enum gpio_result dal_irq_setup_hpd_filter(
+	struct irq *irq,
+	struct gpio_hpd_config *config)
+{
+	struct gpio_config_data config_data;
+
+	if (!config)
+		return GPIO_RESULT_INVALID_DATA;
+
+	config_data.type = GPIO_CONFIG_TYPE_HPD;
+	config_data.config.hpd = *config;
+
+	return dal_gpio_set_config(irq->pin, &config_data);
+}
+
+void dal_irq_close(
+	struct irq *irq)
+{
+	dal_gpio_close(irq->pin);
+}
+
+/*
+ * @brief
+ * Creation and destruction
+ */
+
+struct irq *dal_gpio_create_irq(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en)
+{
+	struct irq *irq;
+
+	switch (id) {
+	case GPIO_ID_HPD:
+	case GPIO_ID_GPIO_PAD:
+	break;
+	default:
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	irq = dm_alloc(service->ctx, sizeof(struct irq));
+
+	if (!irq) {
+		ASSERT_CRITICAL(false);
+		return NULL;
+	}
+
+	irq->pin = dal_gpio_service_create_gpio_ex(
+		service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
+	irq->ctx = service->ctx;
+
+	if (irq->pin)
+		return irq;
+
+	ASSERT_CRITICAL(false);
+
+	dm_free(service->ctx, irq);
+
+	return NULL;
+}
+
+static void destruct(struct irq *irq)
+{
+	dal_irq_close(irq);
+	dal_gpio_service_destroy_gpio(&irq->pin);
+
+}
+
+void dal_gpio_destroy_irq(
+	struct irq **irq)
+{
+	if (!irq || !*irq) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	destruct(*irq);
+	dm_free((*irq)->ctx, *irq);
+
+	*irq = NULL;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/gpio/irq.h b/drivers/gpu/drm/amd/dal/dc/gpio/irq.h
new file mode 100644
index 000000000000..b69375cd8dc2
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/gpio/irq.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_IRQ_H__
+#define __DAL_IRQ_H__
+
+struct irq {
+	struct gpio *pin;
+	struct dc_context *ctx;
+};
+
+struct irq *dal_gpio_create_irq(
+	struct gpio_service *service,
+	enum gpio_id id,
+	uint32_t en);
+
+void dal_gpio_destroy_irq(
+	struct irq **ptr);
+
+#endif
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v3 07/26] drm/amd/dal: BIOS Parser
  2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 01/26] drm/amd/dal: Add dal headers Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
@ 2016-02-29 21:56   ` Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 24/26] drm/amd/dal: Add display core Harry Wentland
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-29 21:56 UTC (permalink / raw)
  To: dri-devel

Wrapper to access Video BIOS command and data tables

v3 changes:
- expose I2C through i2c_adapter and route dal i2c calls through this

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/bios/Makefile           |   26 +
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c      | 5030 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h      |   84 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.c   |  198 +
 .../gpu/drm/amd/dal/dc/bios/bios_parser_helper.h   |  108 +
 drivers/gpu/drm/amd/dal/dc/bios/command_table.c    | 2730 +++++++++++
 drivers/gpu/drm/amd/dal/dc/bios/command_table.h    |  117 +
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.c |  285 ++
 .../gpu/drm/amd/dal/dc/bios/command_table_helper.h |   90 +
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.c |  484 ++
 .../dal/dc/bios/dce110/bios_parser_helper_dce110.h |   34 +
 .../dc/bios/dce110/command_table_helper_dce110.c   |  366 ++
 .../dc/bios/dce110/command_table_helper_dce110.h   |   34 +
 13 files changed, 9586 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h

diff --git a/drivers/gpu/drm/amd/dal/dc/bios/Makefile b/drivers/gpu/drm/amd/dal/dc/bios/Makefile
new file mode 100644
index 000000000000..ddfe457e3a8b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for the 'bios' sub-component of DAL.
+# It provides the parsing and executing controls for atom bios image.
+
+BIOS = bios_parser.o bios_parser_helper.o command_table.o command_table_helper.o
+
+AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS))
+
+AMD_DAL_FILES += $(AMD_DAL_BIOS)
+
+ifndef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+AMD_DAL_FILES := $(filter-out $(AMDDALPATH)/dc/bios/bios_parser_helper.o,$(AMD_DAL_FILES))
+endif
+
+
+###############################################################################
+# DCE 11x
+###############################################################################
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+
+ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce110/bios_parser_helper_dce110.o
+endif
+
+AMD_DAL_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o
+endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
new file mode 100644
index 000000000000..586a5ee17705
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.c
@@ -0,0 +1,5030 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "dc_bios_types.h"
+#include "include/adapter_service_interface.h"
+#include "include/grph_object_ctrl_defs.h"
+#include "include/bios_parser_interface.h"
+#include "include/i2caux_interface.h"
+#include "include/logger_interface.h"
+
+#include "command_table.h"
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+#include "bios_parser_helper.h"
+#endif
+#include "command_table_helper.h"
+#include "bios_parser.h"
+#include "bios_parser_interface.h"
+
+#define THREE_PERCENT_OF_10000 300
+
+#define LAST_RECORD_TYPE 0xff
+
+/* GUID to validate external display connection info table (aka OPM module) */
+static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = {
+	0x91, 0x6E, 0x57, 0x09,
+	0x3F, 0x6D, 0xD2, 0x11,
+	0x39, 0x8E, 0x00, 0xA0,
+	0xC9, 0x69, 0x72, 0x3B};
+
+#define GET_IMAGE(type, offset) ((type *) get_image(bp, offset, sizeof(type)))
+#define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
+
+static uint8_t *get_image(struct bios_parser *bp, uint32_t offset,
+	uint32_t size);
+static uint32_t get_record_size(uint8_t *record);
+static uint32_t get_edid_size(const ATOM_FAKE_EDID_PATCH_RECORD *edid);
+static enum object_type object_type_from_bios_object_id(
+	uint32_t bios_object_id);
+static struct graphics_object_id object_id_from_bios_object_id(
+	uint32_t bios_object_id);
+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id);
+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id);
+static enum connector_id connector_id_from_bios_object_id(
+	uint32_t bios_object_id);
+static uint32_t id_from_bios_object_id(enum object_type type,
+	uint32_t bios_object_id);
+static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id);
+static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id);
+static void get_atom_data_table_revision(
+	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
+	struct atom_data_revision *tbl_revision);
+static uint32_t get_dst_number_from_object(struct bios_parser *bp,
+	ATOM_OBJECT *object);
+static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
+	uint16_t **id_list);
+static uint32_t get_dest_obj_list(struct bios_parser *bp,
+	ATOM_OBJECT *object, uint16_t **id_list);
+static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
+	struct graphics_object_id id);
+static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
+	ATOM_I2C_RECORD *record,
+	struct graphics_object_i2c_info *info);
+static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+	ATOM_OBJECT *object);
+static struct device_id device_type_from_device_id(uint16_t device_id);
+static uint32_t signal_to_ss_id(enum as_signal_type signal);
+static uint32_t get_support_mask_for_device_id(struct device_id device_id);
+static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object);
+static void process_ext_display_connection_info(struct bios_parser *bp);
+
+
+#define BIOS_IMAGE_SIZE_OFFSET 2
+#define BIOS_IMAGE_SIZE_UNIT 512
+
+/*****************************************************************************/
+static bool bios_parser_construct(
+	struct bios_parser *bp,
+	struct bp_init_data *init,
+	struct adapter_service *as);
+
+static uint8_t bios_parser_get_connectors_number(
+	struct dc_bios *dcb);
+
+static enum bp_result bios_parser_get_embedded_panel_info(
+	struct dc_bios *dcb,
+	struct embedded_panel_info *info);
+
+/*****************************************************************************/
+
+struct dc_bios *dal_bios_parser_create(
+	struct bp_init_data *init, struct adapter_service *as)
+{
+	struct bios_parser *bp = NULL;
+
+	bp = dm_alloc(init->ctx, sizeof(struct bios_parser));
+	if (!bp)
+		return NULL;
+
+	if (bios_parser_construct(bp, init, as))
+		return &bp->base;
+
+	dm_free(init->ctx, bp);
+	BREAK_TO_DEBUGGER();
+	return NULL;
+}
+
+static void destruct(struct bios_parser *bp)
+{
+	if (bp->bios_local_image)
+		dm_free(bp->ctx, bp->bios_local_image);
+}
+
+void dal_bios_parser_destroy(struct dc_bios **dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(*dcb);
+
+	if (!bp) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	destruct(bp);
+
+	dm_free((bp)->ctx, bp);
+	*dcb = NULL;
+}
+
+static void bios_parser_power_down(struct dc_bios *dcb)
+{
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	dal_bios_parser_set_scratch_lcd_scale(bp, bp->lcd_scale);
+#endif
+}
+
+static void bios_parser_power_up(struct dc_bios *dcb)
+{
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (bp->lcd_scale == LCD_SCALE_UNKNOWN)
+		bp->lcd_scale = dal_bios_parser_get_scratch_lcd_scale(bp);
+#endif
+}
+
+static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
+{
+	ATOM_OBJECT_TABLE *table;
+
+	uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
+
+	table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset);
+
+	if (!table)
+		return 0;
+	else
+		return table->ucNumberOfObjects;
+}
+
+static uint8_t bios_parser_get_encoders_number(struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	return get_number_of_objects(bp,
+		le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset));
+}
+
+static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	return get_number_of_objects(bp,
+		le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));
+}
+
+static uint32_t bios_parser_get_oem_ddc_lines_number(struct dc_bios *dcb)
+{
+	uint32_t number = 0;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (DATA_TABLES(OemInfo) != 0) {
+		ATOM_OEM_INFO *info;
+
+		info = GET_IMAGE(ATOM_OEM_INFO,
+			DATA_TABLES(OemInfo));
+
+		if (le16_to_cpu(info->sHeader.usStructureSize)
+			> sizeof(ATOM_COMMON_TABLE_HEADER)) {
+
+			number = (le16_to_cpu(info->sHeader.usStructureSize)
+				- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_I2C_ID_CONFIG_ACCESS);
+
+		}
+	}
+
+	return number;
+}
+
+static struct graphics_object_id bios_parser_get_encoder_id(
+	struct dc_bios *dcb,
+	uint32_t i)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct graphics_object_id object_id = dal_graphics_object_id_init(
+		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
+
+	uint32_t encoder_table_offset = bp->object_info_tbl_offset
+		+ le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
+
+	ATOM_OBJECT_TABLE *tbl =
+		GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
+
+	if (tbl && tbl->ucNumberOfObjects > i) {
+		const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID);
+
+		object_id = object_id_from_bios_object_id(id);
+	}
+
+	return object_id;
+}
+
+static struct graphics_object_id bios_parser_get_connector_id(
+	struct dc_bios *dcb,
+	uint8_t i)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct graphics_object_id object_id = dal_graphics_object_id_init(
+		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
+
+	uint32_t connector_table_offset = bp->object_info_tbl_offset
+		+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+
+	ATOM_OBJECT_TABLE *tbl =
+		GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset);
+
+	if (tbl && tbl->ucNumberOfObjects > i) {
+		const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID);
+
+		object_id = object_id_from_bios_object_id(id);
+	}
+
+	return object_id;
+}
+
+static uint32_t bios_parser_get_src_number(struct dc_bios *dcb,
+	struct graphics_object_id id)
+{
+	uint32_t offset;
+	uint8_t *number;
+	ATOM_OBJECT *object;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	object = get_bios_object(bp, id);
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+			+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	return *number;
+}
+
+static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb,
+	struct graphics_object_id id)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object = get_bios_object(bp, id);
+
+	return get_dst_number_from_object(bp, object);
+}
+
+static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
+	struct graphics_object_id object_id, uint32_t index,
+	struct graphics_object_id *src_object_id)
+{
+	uint32_t number;
+	uint16_t *id;
+	ATOM_OBJECT *object;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!src_object_id)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, object_id);
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return BP_RESULT_BADINPUT;
+	}
+
+	number = get_src_obj_list(bp, object, &id);
+
+	if (number <= index)
+		return BP_RESULT_BADINPUT;
+
+	*src_object_id = object_id_from_bios_object_id(id[index]);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb,
+	struct graphics_object_id object_id, uint32_t index,
+	struct graphics_object_id *dest_object_id)
+{
+	uint32_t number;
+	uint16_t *id;
+	ATOM_OBJECT *object;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!dest_object_id)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, object_id);
+
+	number = get_dest_obj_list(bp, object, &id);
+
+	if (number <= index)
+		return BP_RESULT_BADINPUT;
+
+	*dest_object_id = object_id_from_bios_object_id(id[index]);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_oem_ddc_info(struct dc_bios *dcb,
+	uint32_t index,
+	struct graphics_object_i2c_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (DATA_TABLES(OemInfo) != 0) {
+		ATOM_OEM_INFO *tbl;
+
+		tbl = GET_IMAGE(ATOM_OEM_INFO, DATA_TABLES(OemInfo));
+
+		if (le16_to_cpu(tbl->sHeader.usStructureSize)
+			> sizeof(ATOM_COMMON_TABLE_HEADER)) {
+			ATOM_I2C_RECORD record;
+			ATOM_I2C_ID_CONFIG_ACCESS *config;
+
+			dm_memset(&record, 0, sizeof(record));
+
+			config = &tbl->sucI2cId + index - 1;
+
+			record.sucI2cId.bfHW_Capable =
+				config->sbfAccess.bfHW_Capable;
+			record.sucI2cId.bfI2C_LineMux =
+				config->sbfAccess.bfI2C_LineMux;
+			record.sucI2cId.bfHW_EngineID =
+				config->sbfAccess.bfHW_EngineID;
+
+			return get_gpio_i2c_info(bp, &record, info);
+		}
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct graphics_object_i2c_info *info)
+{
+	uint32_t offset;
+	ATOM_OBJECT *object;
+	ATOM_COMMON_RECORD_HEADER *header;
+	ATOM_I2C_RECORD *record;
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, id);
+
+	if (!object)
+		return BP_RESULT_BADINPUT;
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return BP_RESULT_BADBIOSTABLE;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+			!header->ucRecordSize)
+			break;
+
+		if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
+			&& sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {
+			/* get the I2C info */
+			record = (ATOM_I2C_RECORD *) header;
+
+			if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)
+				return BP_RESULT_OK;
+		}
+
+		offset += header->ucRecordSize;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result get_voltage_ddc_info_v1(uint8_t *i2c_line,
+	ATOM_COMMON_TABLE_HEADER *header,
+	uint8_t *address)
+{
+	enum bp_result result = BP_RESULT_NORECORD;
+	ATOM_VOLTAGE_OBJECT_INFO *info =
+		(ATOM_VOLTAGE_OBJECT_INFO *) address;
+
+	uint8_t *voltage_current_object = (uint8_t *) &info->asVoltageObj[0];
+
+	while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
+		ATOM_VOLTAGE_OBJECT *object =
+			(ATOM_VOLTAGE_OBJECT *) voltage_current_object;
+
+		if ((object->ucVoltageType == SET_VOLTAGE_INIT_MODE) &&
+			(object->ucVoltageType &
+				VOLTAGE_CONTROLLED_BY_I2C_MASK)) {
+
+			*i2c_line = object->asControl.ucVoltageControlI2cLine
+					^ 0x90;
+			result = BP_RESULT_OK;
+			break;
+		}
+
+		voltage_current_object += object->ucSize;
+	}
+	return result;
+}
+
+static enum bp_result get_voltage_ddc_info_v3(uint8_t *i2c_line,
+	uint32_t index,
+	ATOM_COMMON_TABLE_HEADER *header,
+	uint8_t *address)
+{
+	enum bp_result result = BP_RESULT_NORECORD;
+	ATOM_VOLTAGE_OBJECT_INFO_V3_1 *info =
+		(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *) address;
+
+	uint8_t *voltage_current_object =
+		(uint8_t *) (&(info->asVoltageObj[0]));
+
+	while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
+		ATOM_I2C_VOLTAGE_OBJECT_V3 *object =
+			(ATOM_I2C_VOLTAGE_OBJECT_V3 *) voltage_current_object;
+
+		if (object->sHeader.ucVoltageMode ==
+			ATOM_INIT_VOLTAGE_REGULATOR) {
+			if (object->sHeader.ucVoltageType == index) {
+				*i2c_line = object->ucVoltageControlI2cLine
+						^ 0x90;
+				result = BP_RESULT_OK;
+				break;
+			}
+		}
+
+		voltage_current_object += le16_to_cpu(object->sHeader.usSize);
+	}
+	return result;
+}
+
+static enum bp_result bios_parser_get_thermal_ddc_info(
+	struct dc_bios *dcb,
+	uint32_t i2c_channel_id,
+	struct graphics_object_i2c_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_I2C_ID_CONFIG_ACCESS *config;
+	ATOM_I2C_RECORD record;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	config = (ATOM_I2C_ID_CONFIG_ACCESS *) &i2c_channel_id;
+
+	record.sucI2cId.bfHW_Capable = config->sbfAccess.bfHW_Capable;
+	record.sucI2cId.bfI2C_LineMux = config->sbfAccess.bfI2C_LineMux;
+	record.sucI2cId.bfHW_EngineID = config->sbfAccess.bfHW_EngineID;
+
+	return get_gpio_i2c_info(bp, &record, info);
+}
+
+static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb,
+	uint32_t index,
+	struct graphics_object_i2c_info *info)
+{
+	uint8_t i2c_line = 0;
+	enum bp_result result = BP_RESULT_NORECORD;
+	uint8_t *voltage_info_address;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision = {0};
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!DATA_TABLES(VoltageObjectInfo))
+		return result;
+
+	voltage_info_address = get_image(bp,
+		DATA_TABLES(VoltageObjectInfo),
+		sizeof(ATOM_COMMON_TABLE_HEADER));
+
+	header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address;
+
+	get_atom_data_table_revision(header, &revision);
+
+	switch (revision.major) {
+	case 1:
+	case 2:
+		result = get_voltage_ddc_info_v1(&i2c_line, header,
+			voltage_info_address);
+		break;
+	case 3:
+		if (revision.minor != 1)
+			break;
+		result = get_voltage_ddc_info_v3(&i2c_line, index, header,
+			voltage_info_address);
+		break;
+	}
+
+	if (result == BP_RESULT_OK)
+		result = bios_parser_get_thermal_ddc_info(dcb,
+			i2c_line, info);
+
+
+	return result;
+}
+
+enum bp_result bios_parser_get_ddc_info_for_i2c_line(struct bios_parser *bp,
+	uint8_t i2c_line, struct graphics_object_i2c_info *info)
+{
+	uint32_t offset;
+	ATOM_OBJECT *object;
+	ATOM_OBJECT_TABLE *table;
+	uint32_t i;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+
+	offset += bp->object_info_tbl_offset;
+
+	table = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
+
+	if (!table)
+		return BP_RESULT_BADBIOSTABLE;
+
+	for (i = 0; i < table->ucNumberOfObjects; i++) {
+		object = &table->asObjects[i];
+
+		if (!object) {
+			BREAK_TO_DEBUGGER(); /* Invalid object id */
+			return BP_RESULT_BADINPUT;
+		}
+
+		offset = le16_to_cpu(object->usRecordOffset)
+				+ bp->object_info_tbl_offset;
+
+		for (;;) {
+			ATOM_COMMON_RECORD_HEADER *header =
+				GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+			if (!header)
+				return BP_RESULT_BADBIOSTABLE;
+
+			offset += header->ucRecordSize;
+
+			if (LAST_RECORD_TYPE == header->ucRecordType ||
+				!header->ucRecordSize)
+				break;
+
+			if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
+				&& sizeof(ATOM_I2C_RECORD) <=
+				header->ucRecordSize) {
+				ATOM_I2C_RECORD *record =
+					(ATOM_I2C_RECORD *) header;
+
+				if (i2c_line != record->sucI2cId.bfI2C_LineMux)
+					continue;
+
+				/* get the I2C info */
+				if (get_gpio_i2c_info(bp, record, info) ==
+					BP_RESULT_OK)
+					return BP_RESULT_OK;
+			}
+		}
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct graphics_object_hpd_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object;
+	ATOM_HPD_INT_RECORD *record = NULL;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, id);
+
+	if (!object)
+		return BP_RESULT_BADINPUT;
+
+	record = get_hpd_record(bp, object);
+
+	if (record != NULL) {
+		info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;
+		info->hpd_active = record->ucPlugged_PinState;
+		return BP_RESULT_OK;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static uint32_t bios_parser_get_gpio_record(
+	struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct bp_gpio_cntl_info *gpio_record,
+	uint32_t record_size)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_COMMON_RECORD_HEADER *header = NULL;
+	ATOM_OBJECT_GPIO_CNTL_RECORD *record = NULL;
+	ATOM_OBJECT *object = get_bios_object(bp, id);
+	uint32_t offset;
+	uint32_t pins_number;
+	uint32_t i;
+
+	if (!object)
+		return 0;
+
+	/* Initialise offset */
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		/* Get record header */
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+		if (!header || header->ucRecordType == LAST_RECORD_TYPE ||
+			!header->ucRecordSize)
+			break;
+
+		/* If this is gpio control record - stop. We found the record */
+		if (header->ucRecordType == ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE
+			&& header->ucRecordSize
+				>= sizeof(ATOM_OBJECT_GPIO_CNTL_RECORD)) {
+			record = (ATOM_OBJECT_GPIO_CNTL_RECORD *) header;
+			break;
+		}
+
+		/* Advance to next record */
+		offset += header->ucRecordSize;
+	}
+
+	/* If we did not find a record - return */
+	if (!record)
+		return 0;
+
+	/* Extract gpio IDs from bios record (make sure we do not exceed passed
+	 *  array size) */
+	pins_number = (record->ucNumberOfPins < record_size ?
+			record->ucNumberOfPins : record_size);
+	for (i = 0; i < pins_number; i++) {
+		uint8_t output_state = ((record->asGpio[i].ucGPIO_PinState
+			& GPIO_PIN_OUTPUT_STATE_MASK)
+			>> GPIO_PIN_OUTPUT_STATE_SHIFT);
+		gpio_record[i].id = record->asGpio[i].ucGPIOID;
+
+		switch (output_state) {
+		case GPIO_PIN_STATE_ACTIVE_LOW:
+			gpio_record[i].state =
+				GPIO_PIN_OUTPUT_STATE_ACTIVE_LOW;
+			break;
+
+		case GPIO_PIN_STATE_ACTIVE_HIGH:
+			gpio_record[i].state =
+				GPIO_PIN_OUTPUT_STATE_ACTIVE_HIGH;
+			break;
+
+		default:
+			BREAK_TO_DEBUGGER(); /* Invalid Pin Output State */
+			break;
+		}
+	}
+
+	return pins_number;
+}
+
+enum bp_result bios_parser_get_device_tag_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object,
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)
+{
+	ATOM_COMMON_RECORD_HEADER *header;
+	uint32_t offset;
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return BP_RESULT_BADBIOSTABLE;
+
+		offset += header->ucRecordSize;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+			!header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=
+			header->ucRecordType)
+			continue;
+
+		if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)
+			continue;
+
+		*record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;
+		return BP_RESULT_OK;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_get_device_tag(
+	struct dc_bios *dcb,
+	struct graphics_object_id connector_object_id,
+	uint32_t device_tag_index,
+	struct connector_device_tag_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object;
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;
+	ATOM_CONNECTOR_DEVICE_TAG *device_tag;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	/* getBiosObject will return MXM object */
+	object = get_bios_object(bp, connector_object_id);
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return BP_RESULT_BADINPUT;
+	}
+
+	if (bios_parser_get_device_tag_record(bp, object, &record)
+		!= BP_RESULT_OK)
+		return BP_RESULT_NORECORD;
+
+	if (device_tag_index >= record->ucNumberOfDevice)
+		return BP_RESULT_NORECORD;
+
+	device_tag = &record->asDeviceTag[device_tag_index];
+
+	info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);
+	info->dev_id =
+		device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_firmware_info_v1_4(
+	struct bios_parser *bp,
+	struct firmware_info *info);
+static enum bp_result get_firmware_info_v2_1(
+	struct bios_parser *bp,
+	struct firmware_info *info);
+static enum bp_result get_firmware_info_v2_2(
+	struct bios_parser *bp,
+	struct firmware_info *info);
+
+static enum bp_result bios_parser_get_firmware_info(
+	struct dc_bios *dcb,
+	struct firmware_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision;
+
+	if (info && DATA_TABLES(FirmwareInfo)) {
+		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+			DATA_TABLES(FirmwareInfo));
+		get_atom_data_table_revision(header, &revision);
+		switch (revision.major) {
+		case 1:
+			switch (revision.minor) {
+			case 4:
+				result = get_firmware_info_v1_4(bp, info);
+				break;
+			default:
+				break;
+			}
+			break;
+
+		case 2:
+			switch (revision.minor) {
+			case 1:
+				result = get_firmware_info_v2_1(bp, info);
+				break;
+			case 2:
+				result = get_firmware_info_v2_2(bp, info);
+				break;
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	return result;
+}
+
+static enum bp_result get_firmware_info_v1_4(
+	struct bios_parser *bp,
+	struct firmware_info *info)
+{
+	ATOM_FIRMWARE_INFO_V1_4 *firmware_info =
+		GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,
+			DATA_TABLES(FirmwareInfo));
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!firmware_info)
+		return BP_RESULT_BADBIOSTABLE;
+
+	dm_memset(info, 0, sizeof(*info));
+
+	/* Pixel clock pll information. We need to convert from 10KHz units into
+	 * KHz units */
+	info->pll_info.crystal_frequency =
+		le16_to_cpu(firmware_info->usReferenceClock) * 10;
+	info->pll_info.min_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
+	info->pll_info.max_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
+	info->pll_info.min_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
+	info->pll_info.max_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
+
+	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
+		/* Since there is no information on the SS, report conservative
+		 * value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
+
+	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
+		/* Since there is no information on the SS,report conservative
+		 * value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_ss_info_v3_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info);
+
+static enum bp_result get_firmware_info_v2_1(
+	struct bios_parser *bp,
+	struct firmware_info *info)
+{
+	ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =
+		GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));
+	struct spread_spectrum_info internalSS;
+	uint32_t index;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!firmwareInfo)
+		return BP_RESULT_BADBIOSTABLE;
+
+	dm_memset(info, 0, sizeof(*info));
+
+	/* Pixel clock pll information. We need to convert from 10KHz units into
+	 * KHz units */
+	info->pll_info.crystal_frequency =
+		le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;
+	info->pll_info.min_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;
+	info->pll_info.max_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;
+	info->pll_info.min_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;
+	info->pll_info.max_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;
+	info->default_display_engine_pll_frequency =
+		le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;
+	info->external_clock_source_frequency_for_dp =
+		le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;
+	info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;
+
+	/* There should be only one entry in the SS info table for Memory Clock
+	 */
+	index = 0;
+	if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
+		/* Since there is no information for external SS, report
+		 *  conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+		ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {
+		if (internalSS.spread_spectrum_percentage) {
+			info->feature.memory_clk_ss_percentage =
+				internalSS.spread_spectrum_percentage;
+			if (internalSS.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.memory_clk_ss_percentage;
+				info->feature.memory_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	/* There should be only one entry in the SS info table for Engine Clock
+	 */
+	index = 1;
+	if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
+		/* Since there is no information for external SS, report
+		 * conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+		ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {
+		if (internalSS.spread_spectrum_percentage) {
+			info->feature.engine_clk_ss_percentage =
+				internalSS.spread_spectrum_percentage;
+			if (internalSS.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.engine_clk_ss_percentage;
+				info->feature.engine_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_firmware_info_v2_2(
+	struct bios_parser *bp,
+	struct firmware_info *info)
+{
+	ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
+	struct spread_spectrum_info internal_ss;
+	uint32_t index;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,
+		DATA_TABLES(FirmwareInfo));
+
+	if (!firmware_info)
+		return BP_RESULT_BADBIOSTABLE;
+
+	dm_memset(info, 0, sizeof(*info));
+
+	/* Pixel clock pll information. We need to convert from 10KHz units into
+	 * KHz units */
+	info->pll_info.crystal_frequency =
+		le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;
+	info->pll_info.min_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
+	info->pll_info.max_input_pxl_clk_pll_frequency =
+		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
+	info->pll_info.min_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
+	info->pll_info.max_output_pxl_clk_pll_frequency =
+		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
+	info->default_display_engine_pll_frequency =
+		le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;
+	info->external_clock_source_frequency_for_dp =
+		le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;
+
+	/* There should be only one entry in the SS info table for Memory Clock
+	 */
+	index = 0;
+	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
+		/* Since there is no information for external SS, report
+		 *  conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+			ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {
+		if (internal_ss.spread_spectrum_percentage) {
+			info->feature.memory_clk_ss_percentage =
+					internal_ss.spread_spectrum_percentage;
+			if (internal_ss.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.memory_clk_ss_percentage;
+				info->feature.memory_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	/* There should be only one entry in the SS info table for Engine Clock
+	 */
+	index = 1;
+	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
+		/* Since there is no information for external SS, report
+		 * conservative value 3% for bandwidth calculation */
+		/* unit of 0.01% */
+		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
+	else if (get_ss_info_v3_1(bp,
+			ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {
+		if (internal_ss.spread_spectrum_percentage) {
+			info->feature.engine_clk_ss_percentage =
+					internal_ss.spread_spectrum_percentage;
+			if (internal_ss.type.CENTER_MODE) {
+				/* if it is centermode, the exact SS Percentage
+				 * will be round up of half of the percentage
+				 * reported in the SS table */
+				++info->feature.engine_clk_ss_percentage;
+				info->feature.engine_clk_ss_percentage /= 2;
+			}
+		}
+	}
+
+	/* Remote Display */
+	info->remote_display_config = firmware_info->ucRemoteDisplayConfig;
+
+	/* Is allowed minimum BL level */
+	info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;
+	/* Used starting from CI */
+	info->smu_gpu_pll_output_freq =
+			(uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_ss_info_v3_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info)
+{
+	ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;
+	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
+	uint32_t table_size;
+	uint32_t i;
+	uint32_t table_index = 0;
+
+	if (!ss_info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return BP_RESULT_UNSUPPORTED;
+
+	ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
+		DATA_TABLES(ASIC_InternalSS_Info));
+	table_size =
+		(le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
+				- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
+				&ss_table_header_include->asSpreadSpectrum[0];
+
+	dm_memset(ss_info, 0, sizeof(struct spread_spectrum_info));
+
+	for (i = 0; i < table_size; i++) {
+		if (tbl[i].ucClockIndication != (uint8_t) id)
+			continue;
+
+		if (table_index != index) {
+			table_index++;
+			continue;
+		}
+		/* VBIOS introduced new defines for Version 3, same values as
+		 *  before, so now use these new ones for Version 3.
+		 * Shouldn't affect field VBIOS's V3 as define values are still
+		 *  same.
+		 * #define SS_MODE_V3_CENTRE_SPREAD_MASK                0x01
+		 * #define SS_MODE_V3_EXTERNAL_SS_MASK                  0x02
+
+		 * Old VBIOS defines:
+		 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001
+		 * #define ATOM_EXTERNAL_SS_MASK                  0x00000002
+		 */
+
+		if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode)
+			ss_info->type.EXTERNAL = true;
+
+		if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode)
+			ss_info->type.CENTER_MODE = true;
+
+		/* Older VBIOS (in field) always provides SS percentage in 0.01%
+		 * units set Divider to 100 */
+		ss_info->spread_percentage_divider = 100;
+
+		/* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */
+		if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK
+				& tbl[i].ucSpreadSpectrumMode)
+			ss_info->spread_percentage_divider = 1000;
+
+		ss_info->type.STEP_AND_DELAY_INFO = false;
+		/* convert [10KHz] into [KHz] */
+		ss_info->target_clock_range =
+				le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
+		ss_info->spread_spectrum_percentage =
+				(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
+		ss_info->spread_spectrum_range =
+				(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
+
+		return BP_RESULT_OK;
+	}
+	return BP_RESULT_NORECORD;
+}
+
+static enum bp_result bios_parser_transmitter_control(
+	struct dc_bios *dcb,
+	struct bp_transmitter_control *cntl)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.transmitter_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.transmitter_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_encoder_control(
+	struct dc_bios *dcb,
+	struct bp_encoder_control *cntl)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.dig_encoder_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.dig_encoder_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_adjust_pixel_clock(
+	struct dc_bios *dcb,
+	struct bp_adjust_pixel_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.adjust_display_pll)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.adjust_display_pll(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_pixel_clock(
+	struct dc_bios *dcb,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_pixel_clock)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_dce_clock(
+	struct dc_bios *dcb,
+	struct bp_set_dce_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_dce_clock)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_dce_clock(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_spread_spectrum_on_ppll(
+	struct dc_bios *dcb,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_spread_spectrum_on_ppll(
+			bp, bp_params, enable);
+
+}
+
+static enum bp_result bios_parser_program_crtc_timing(
+	struct dc_bios *dcb,
+	struct bp_hw_crtc_timing_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_crtc_timing)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
+}
+
+static enum bp_result bios_parser_program_display_engine_pll(
+	struct dc_bios *dcb,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.program_clock)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.program_clock(bp, bp_params);
+
+}
+
+static enum signal_type bios_parser_dac_load_detect(
+	struct dc_bios *dcb,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type display_signal)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.dac_load_detection)
+		return SIGNAL_TYPE_NONE;
+
+	return bp->cmd_tbl.dac_load_detection(bp, encoder, connector,
+		display_signal);
+}
+
+static enum bp_result bios_parser_get_divider_for_target_display_clock(
+	struct dc_bios *dcb,
+	struct bp_display_clock_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.compute_memore_engine_pll)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.compute_memore_engine_pll(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_crtc(
+	struct dc_bios *dcb,
+	enum controller_id id,
+	bool enable)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_crtc)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_crtc(bp, id, enable);
+}
+
+static enum bp_result bios_parser_blank_crtc(
+	struct dc_bios *dcb,
+	struct bp_blank_crtc_parameters *bp_params,
+	bool blank)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.blank_crtc)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.blank_crtc(bp, bp_params, blank);
+}
+
+static enum bp_result bios_parser_crtc_source_select(
+	struct dc_bios *dcb,
+	struct bp_crtc_source_select *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.select_crtc_source)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.select_crtc_source(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_overscan(
+	struct dc_bios *dcb,
+	struct bp_hw_crtc_overscan_parameters *bp_params)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.set_crtc_overscan)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.set_crtc_overscan(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_memory_requests(
+	struct dc_bios *dcb,
+	enum controller_id controller_id,
+	bool enable)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_crtc_mem_req)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_crtc_mem_req(bp, controller_id, enable);
+}
+
+static enum bp_result bios_parser_external_encoder_control(
+	struct dc_bios *dcb,
+	struct bp_external_encoder_control *cntl)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.external_encoder_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.external_encoder_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_enable_disp_power_gating(
+	struct dc_bios *dcb,
+	enum controller_id controller_id,
+	enum bp_pipe_control_action action)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_disp_power_gating)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
+		action);
+}
+
+static bool bios_parser_is_device_id_supported(
+	struct dc_bios *dcb,
+	struct device_id id)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	uint32_t mask = get_support_mask_for_device_id(id);
+
+	return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0;
+}
+
+static enum bp_result bios_parser_crt_control(
+	struct dc_bios *dcb,
+	enum engine_id engine_id,
+	bool enable,
+	uint32_t pixel_clock)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	uint8_t standard;
+
+	if (!bp->cmd_tbl.dac1_encoder_control &&
+		engine_id == ENGINE_ID_DACA)
+		return BP_RESULT_FAILURE;
+	if (!bp->cmd_tbl.dac2_encoder_control &&
+		engine_id == ENGINE_ID_DACB)
+		return BP_RESULT_FAILURE;
+	/* validate params */
+	switch (engine_id) {
+	case ENGINE_ID_DACA:
+	case ENGINE_ID_DACB:
+		break;
+	default:
+		/* unsupported engine */
+		return BP_RESULT_FAILURE;
+	}
+
+	standard = ATOM_DAC1_PS2; /* == ATOM_DAC2_PS2 */
+
+	if (enable) {
+		if (engine_id == ENGINE_ID_DACA) {
+			bp->cmd_tbl.dac1_encoder_control(bp, enable,
+				pixel_clock, standard);
+			if (bp->cmd_tbl.dac1_output_control != NULL)
+				bp->cmd_tbl.dac1_output_control(bp, enable);
+		} else {
+			bp->cmd_tbl.dac2_encoder_control(bp, enable,
+				pixel_clock, standard);
+			if (bp->cmd_tbl.dac2_output_control != NULL)
+				bp->cmd_tbl.dac2_output_control(bp, enable);
+		}
+	} else {
+		if (engine_id == ENGINE_ID_DACA) {
+			if (bp->cmd_tbl.dac1_output_control != NULL)
+				bp->cmd_tbl.dac1_output_control(bp, enable);
+			bp->cmd_tbl.dac1_encoder_control(bp, enable,
+				pixel_clock, standard);
+		} else {
+			if (bp->cmd_tbl.dac2_output_control != NULL)
+				bp->cmd_tbl.dac2_output_control(bp, enable);
+			bp->cmd_tbl.dac2_encoder_control(bp, enable,
+				pixel_clock, standard);
+		}
+	}
+
+	return BP_RESULT_OK;
+}
+
+static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	ATOM_COMMON_RECORD_HEADER *header;
+	uint32_t offset;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+			!header->ucRecordSize)
+			break;
+
+		if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType
+			&& sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize)
+			return (ATOM_HPD_INT_RECORD *) header;
+
+		offset += header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+/**
+ * Get I2C information of input object id
+ *
+ * search all records to find the ATOM_I2C_RECORD_TYPE record IR
+ */
+static ATOM_I2C_RECORD *get_i2c_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	ATOM_COMMON_RECORD_HEADER *record_header;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER();
+		/* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+			+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!record_header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == record_header->ucRecordType ||
+			0 == record_header->ucRecordSize)
+			break;
+
+		if (ATOM_I2C_RECORD_TYPE == record_header->ucRecordType &&
+			sizeof(ATOM_I2C_RECORD) <=
+			record_header->ucRecordSize) {
+			return (ATOM_I2C_RECORD *)record_header;
+		}
+
+		offset += record_header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+
+static enum bp_result get_ss_info_from_ss_info_table(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info);
+static enum bp_result get_ss_info_from_tbl(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info);
+/**
+ * bios_parser_get_spread_spectrum_info
+ * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
+ * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
+ * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,
+ * there is only one entry for each signal /ss id.  However, there is
+ * no planning of supporting multiple spread Sprectum entry for EverGreen
+ * @param [in] this
+ * @param [in] signal, ASSignalType to be converted to info index
+ * @param [in] index, number of entries that match the converted info index
+ * @param [out] ss_info, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_get_spread_spectrum_info(
+	struct dc_bios *dcb,
+	enum as_signal_type signal,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	uint32_t clk_id_ss = 0;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision tbl_revision;
+
+	if (!ss_info) /* check for bad input */
+		return BP_RESULT_BADINPUT;
+	/* signal translation */
+	clk_id_ss = signal_to_ss_id(signal);
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		if (!index)
+			return get_ss_info_from_ss_info_table(bp, clk_id_ss,
+				ss_info);
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+		DATA_TABLES(ASIC_InternalSS_Info));
+	get_atom_data_table_revision(header, &tbl_revision);
+
+	switch (tbl_revision.major) {
+	case 2:
+		switch (tbl_revision.minor) {
+		case 1:
+			/* there can not be more then one entry for Internal
+			 * SS Info table version 2.1 */
+			if (!index)
+				return get_ss_info_from_tbl(bp, clk_id_ss,
+						ss_info);
+			break;
+		default:
+			break;
+		}
+		break;
+
+	case 3:
+		switch (tbl_revision.minor) {
+		case 1:
+			return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info);
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+	/* there can not be more then one entry for SS Info table */
+	return result;
+}
+
+static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *info);
+
+/**
+ * get_ss_info_from_table
+ * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info table from the VBIOS
+ * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info.
+ *
+ * @param this
+ * @param id, spread sprectrum info index
+ * @param pSSinfo, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result get_ss_info_from_tbl(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info)
+{
+	if (!ss_info) /* check for bad input, if ss_info is not NULL */
+		return BP_RESULT_BADINPUT;
+	/* for SS_Info table only support DP and LVDS */
+	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
+		return get_ss_info_from_ss_info_table(bp, id, ss_info);
+	else
+		return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id,
+			ss_info);
+}
+
+/**
+ * get_ss_info_from_internal_ss_info_tbl_V2_1
+ * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1
+ * from the VBIOS
+ * There will not be multiple entry for Ver 2.1
+ *
+ * @param id, spread sprectrum info index
+ * @param pSSinfo, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *info)
+{
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header;
+	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
+	uint32_t tbl_size, i;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return result;
+
+	header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
+		DATA_TABLES(ASIC_InternalSS_Info));
+
+	dm_memset(info, 0, sizeof(struct spread_spectrum_info));
+
+	tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+					/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
+					&(header->asSpreadSpectrum[0]);
+	for (i = 0; i < tbl_size; i++) {
+		result = BP_RESULT_NORECORD;
+
+		if (tbl[i].ucClockIndication != (uint8_t)id)
+			continue;
+
+		if (ATOM_EXTERNAL_SS_MASK
+			& tbl[i].ucSpreadSpectrumMode) {
+			info->type.EXTERNAL = true;
+		}
+		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
+			& tbl[i].ucSpreadSpectrumMode) {
+			info->type.CENTER_MODE = true;
+		}
+		info->type.STEP_AND_DELAY_INFO = false;
+		/* convert [10KHz] into [KHz] */
+		info->target_clock_range =
+			le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
+		info->spread_spectrum_percentage =
+			(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
+		info->spread_spectrum_range =
+			(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
+		result = BP_RESULT_OK;
+		break;
+	}
+
+	return result;
+
+}
+
+/**
+ * get_ss_info_from_ss_info_table
+ * Get spread sprectrum information from the SS_Info table from the VBIOS
+ * if the pointer to info is NULL, indicate the caller what to know the number
+ * of entries that matches the id
+ * for, the SS_Info table, there should not be more than 1 entry match.
+ *
+ * @param [in] id, spread sprectrum id
+ * @param [out] pSSinfo, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result get_ss_info_from_ss_info_table(
+	struct bios_parser *bp,
+	uint32_t id,
+	struct spread_spectrum_info *ss_info)
+{
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	ATOM_SPREAD_SPECTRUM_INFO *tbl;
+	ATOM_COMMON_TABLE_HEADER *header;
+	uint32_t table_size;
+	uint32_t i;
+	uint32_t id_local = SS_ID_UNKNOWN;
+	struct atom_data_revision revision;
+
+	/* exist of the SS_Info table */
+	/* check for bad input, pSSinfo can not be NULL */
+	if (!DATA_TABLES(SS_Info) || !ss_info)
+		return result;
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));
+	get_atom_data_table_revision(header, &revision);
+
+	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
+
+	if (1 != revision.major || 2 > revision.minor)
+		return result;
+
+	/* have to convert from Internal_SS format to SS_Info format */
+	switch (id) {
+	case ASIC_INTERNAL_SS_ON_DP:
+		id_local = SS_ID_DP1;
+		break;
+	case ASIC_INTERNAL_SS_ON_LVDS:
+	{
+		struct embedded_panel_info panel_info;
+
+		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
+				== BP_RESULT_OK)
+			id_local = panel_info.ss_id;
+		break;
+	}
+	default:
+		break;
+	}
+
+	if (id_local == SS_ID_UNKNOWN)
+		return result;
+
+	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
+			sizeof(ATOM_COMMON_TABLE_HEADER)) /
+					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
+
+	for (i = 0; i < table_size; i++) {
+		if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)
+			continue;
+
+		dm_memset(ss_info, 0, sizeof(struct spread_spectrum_info));
+
+		if (ATOM_EXTERNAL_SS_MASK &
+				tbl->asSS_Info[i].ucSpreadSpectrumType)
+			ss_info->type.EXTERNAL = true;
+
+		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &
+				tbl->asSS_Info[i].ucSpreadSpectrumType)
+			ss_info->type.CENTER_MODE = true;
+
+		ss_info->type.STEP_AND_DELAY_INFO = true;
+		ss_info->spread_spectrum_percentage =
+			(uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);
+		ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;
+		ss_info->step_and_delay_info.delay =
+			tbl->asSS_Info[i].ucSS_Delay;
+		ss_info->step_and_delay_info.recommended_ref_div =
+			tbl->asSS_Info[i].ucRecommendedRef_Div;
+		ss_info->spread_spectrum_range =
+			(uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;
+
+		/* there will be only one entry for each display type in SS_info
+		 * table */
+		result = BP_RESULT_OK;
+		break;
+	}
+
+	return result;
+}
+static enum bp_result get_embedded_panel_info_v1_2(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info);
+static enum bp_result get_embedded_panel_info_v1_3(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info);
+
+static enum bp_result bios_parser_get_embedded_panel_info(
+	struct dc_bios *dcb,
+	struct embedded_panel_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_COMMON_TABLE_HEADER *hdr;
+
+	if (!DATA_TABLES(LCD_Info))
+		return BP_RESULT_FAILURE;
+
+	hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));
+
+	if (!hdr)
+		return BP_RESULT_BADBIOSTABLE;
+
+	switch (hdr->ucTableFormatRevision) {
+	case 1:
+		switch (hdr->ucTableContentRevision) {
+		case 0:
+		case 1:
+		case 2:
+			return get_embedded_panel_info_v1_2(bp, info);
+		case 3:
+			return get_embedded_panel_info_v1_3(bp, info);
+		default:
+			break;
+		}
+		default:
+			break;
+	}
+
+	return BP_RESULT_FAILURE;
+}
+
+static enum bp_result get_embedded_panel_info_v1_2(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info)
+{
+	ATOM_LVDS_INFO_V12 *lvds;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(LVDS_Info))
+		return BP_RESULT_UNSUPPORTED;
+
+	lvds =
+		GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
+
+	if (!lvds)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != lvds->sHeader.ucTableFormatRevision
+		|| 2 > lvds->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	dm_memset(info, 0, sizeof(struct embedded_panel_info));
+
+	/* We need to convert from 10KHz units into KHz units*/
+	info->lcd_timing.pixel_clk =
+		le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
+	/* usHActive does not include borders, according to VBIOS team*/
+	info->lcd_timing.horizontal_addressable =
+		le16_to_cpu(lvds->sLCDTiming.usHActive);
+	/* usHBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now.  May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.horizontal_blanking_time =
+			le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
+	/* usVActive does not include borders, according to VBIOS team*/
+	info->lcd_timing.vertical_addressable =
+			le16_to_cpu(lvds->sLCDTiming.usVActive);
+	/* usVBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now. May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.vertical_blanking_time =
+		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
+	info->lcd_timing.horizontal_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
+	info->lcd_timing.horizontal_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
+	info->lcd_timing.vertical_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
+	info->lcd_timing.vertical_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
+	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
+	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
+	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
+	info->lcd_timing.misc_info.H_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
+	info->lcd_timing.misc_info.V_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
+	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
+	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
+	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
+	info->lcd_timing.misc_info.COMPOSITE_SYNC =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
+	info->lcd_timing.misc_info.INTERLACE =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
+	info->lcd_timing.misc_info.DOUBLE_CLOCK =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
+	info->ss_id = lvds->ucSS_Id;
+
+	{
+		uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
+		/* Get minimum supported refresh rate*/
+		if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
+			info->supported_rr.REFRESH_RATE_30HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
+			info->supported_rr.REFRESH_RATE_40HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
+			info->supported_rr.REFRESH_RATE_48HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
+			info->supported_rr.REFRESH_RATE_50HZ = 1;
+		else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
+			info->supported_rr.REFRESH_RATE_60HZ = 1;
+	}
+
+	/*Drr panel support can be reported by VBIOS*/
+	if (LCDPANEL_CAP_DRR_SUPPORTED
+			& lvds->ucLCDPanel_SpecialHandlingCap)
+		info->drr_enabled = 1;
+
+	if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
+
+	if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.RGB888 = true;
+
+	info->lcd_timing.misc_info.GREY_LEVEL =
+		(uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
+			lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
+
+	if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.SPATIAL = true;
+
+	if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.TEMPORAL = true;
+
+	if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
+		info->lcd_timing.misc_info.API_ENABLED = true;
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_embedded_panel_info_v1_3(
+	struct bios_parser *bp,
+	struct embedded_panel_info *info)
+{
+	ATOM_LCD_INFO_V13 *lvds;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(LCD_Info))
+		return BP_RESULT_UNSUPPORTED;
+
+	lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
+
+	if (!lvds)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (!((1 == lvds->sHeader.ucTableFormatRevision)
+			&& (3 <= lvds->sHeader.ucTableContentRevision)))
+		return BP_RESULT_UNSUPPORTED;
+
+	dm_memset(info, 0, sizeof(struct embedded_panel_info));
+
+	/* We need to convert from 10KHz units into KHz units */
+	info->lcd_timing.pixel_clk =
+			le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
+	/* usHActive does not include borders, according to VBIOS team */
+	info->lcd_timing.horizontal_addressable =
+			le16_to_cpu(lvds->sLCDTiming.usHActive);
+	/* usHBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now.  May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.horizontal_blanking_time =
+		le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
+	/* usVActive does not include borders, according to VBIOS team*/
+	info->lcd_timing.vertical_addressable =
+		le16_to_cpu(lvds->sLCDTiming.usVActive);
+	/* usVBlanking_Time includes borders, so we should really be subtracting
+	 * borders duing this translation, but LVDS generally*/
+	/* doesn't have borders, so we should be okay leaving this as is for
+	 * now. May need to revisit if we ever have LVDS with borders*/
+	info->lcd_timing.vertical_blanking_time =
+		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
+	info->lcd_timing.horizontal_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
+	info->lcd_timing.horizontal_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
+	info->lcd_timing.vertical_sync_offset =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
+	info->lcd_timing.vertical_sync_width =
+		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
+	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
+	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
+	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
+	info->lcd_timing.misc_info.H_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
+	info->lcd_timing.misc_info.V_SYNC_POLARITY =
+		~(uint32_t)
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
+	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
+	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
+	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
+	info->lcd_timing.misc_info.COMPOSITE_SYNC =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
+	info->lcd_timing.misc_info.INTERLACE =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
+	info->lcd_timing.misc_info.DOUBLE_CLOCK =
+		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
+	info->ss_id = lvds->ucSS_Id;
+
+	/* Drr panel support can be reported by VBIOS*/
+	if (LCDPANEL_CAP_V13_DRR_SUPPORTED
+			& lvds->ucLCDPanel_SpecialHandlingCap)
+		info->drr_enabled = 1;
+
+	/* Get supported refresh rate*/
+	if (info->drr_enabled == 1) {
+		uint8_t min_rr =
+				lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
+		uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
+
+		if (min_rr != 0) {
+			if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_30HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_40HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_48HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_50HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
+				info->supported_rr.REFRESH_RATE_60HZ = 1;
+		} else {
+			if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
+				info->supported_rr.REFRESH_RATE_30HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
+				info->supported_rr.REFRESH_RATE_40HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
+				info->supported_rr.REFRESH_RATE_48HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
+				info->supported_rr.REFRESH_RATE_50HZ = 1;
+			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
+				info->supported_rr.REFRESH_RATE_60HZ = 1;
+		}
+	}
+
+	if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
+		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
+
+	if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
+		info->lcd_timing.misc_info.RGB888 = true;
+
+	info->lcd_timing.misc_info.GREY_LEVEL =
+			(uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
+				lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
+
+	return BP_RESULT_OK;
+}
+
+/**
+ * bios_parser_get_encoder_cap_info
+ *
+ * @brief
+ *  Get encoder capability information of input object id
+ *
+ * @param object_id, Object id
+ * @param object_id, encoder cap information structure
+ *
+ * @return Bios parser result code
+ *
+ */
+static enum bp_result bios_parser_get_encoder_cap_info(
+	struct dc_bios *dcb,
+	struct graphics_object_id object_id,
+	struct bp_encoder_cap_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_OBJECT *object;
+	ATOM_ENCODER_CAP_RECORD *record = NULL;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object = get_bios_object(bp, object_id);
+
+	if (!object)
+		return BP_RESULT_BADINPUT;
+
+	record = get_encoder_cap_record(bp, object);
+	if (!record)
+		return BP_RESULT_NORECORD;
+
+	info->DP_HBR2_CAP = record->usHBR2Cap;
+	info->DP_HBR2_EN = record->usHBR2En;
+	return BP_RESULT_OK;
+}
+
+/**
+ * get_encoder_cap_record
+ *
+ * @brief
+ *  Get encoder cap record for the object
+ *
+ * @param object, ATOM object
+ *
+ * @return atom encoder cap record
+ *
+ * @note
+ *  search all records to find the ATOM_ENCODER_CAP_RECORD record
+ */
+static ATOM_ENCODER_CAP_RECORD *get_encoder_cap_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	ATOM_COMMON_RECORD_HEADER *header;
+	uint32_t offset;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+					+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		offset += header->ucRecordSize;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				!header->ucRecordSize)
+			break;
+
+		if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
+			continue;
+
+		if (sizeof(ATOM_ENCODER_CAP_RECORD) <= header->ucRecordSize)
+			return (ATOM_ENCODER_CAP_RECORD *)header;
+	}
+
+	return NULL;
+}
+
+/**
+ * bios_parser_get_din_connector_info
+ * @brief
+ *   Get GPIO record for the DIN connector, this GPIO tells whether there is a
+ *    CV dumb dongle
+ *   attached to the DIN connector to perform load detection for the the
+ *    appropriate signal
+ *
+ * @param id - DIN connector object id
+ * @param info             - GPIO record infor
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_get_din_connector_info(
+	struct dc_bios *dcb,
+	struct graphics_object_id id,
+	struct din_connector_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_COMMON_RECORD_HEADER *header;
+	ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD *record = NULL;
+	ATOM_OBJECT *object;
+	uint32_t offset;
+	enum bp_result result = BP_RESULT_NORECORD;
+
+	/* no output buffer provided */
+	if (!info) {
+		BREAK_TO_DEBUGGER(); /* Invalid output buffer */
+		return BP_RESULT_BADINPUT;
+	}
+
+	object = get_bios_object(bp, id);
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */;
+		return BP_RESULT_BADINPUT;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+						+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header) {
+			result = BP_RESULT_BADBIOSTABLE;
+			break;
+		}
+
+		offset += header->ucRecordSize;
+
+		/* get out of the loop if no more records */
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				!header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD_TYPE !=
+				header->ucRecordType)
+			continue;
+
+		if (sizeof(ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD)
+				> header->ucRecordSize)
+			continue;
+
+		record = (ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD *)header;
+		result = BP_RESULT_OK;
+		break;
+	}
+
+	/* return if the record not found */
+	if (result != BP_RESULT_OK)
+		return result;
+
+	info->gpio_id = record->ucGPIOID;
+	info->gpio_tv_active_state = (record->ucTVActiveState != 0);
+
+	return result;
+}
+
+static uint32_t get_ss_entry_number(
+	struct bios_parser *bp,
+	uint32_t id);
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
+	struct bios_parser *bp,
+	uint32_t id);
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
+	struct bios_parser *bp,
+	uint32_t id);
+static uint32_t get_ss_entry_number_from_ss_info_tbl(
+	struct bios_parser *bp,
+	uint32_t id);
+
+/**
+ * BiosParserObject::GetNumberofSpreadSpectrumEntry
+ * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
+ * the VBIOS that match the SSid (to be converted from signal)
+ *
+ * @param[in] signal, ASSignalType to be converted to SSid
+ * @return number of SS Entry that match the signal
+ */
+static uint32_t bios_parser_get_ss_entry_number(
+	struct dc_bios *dcb,
+	enum as_signal_type signal)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	uint32_t ss_id = 0;
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision;
+
+	ss_id = signal_to_ss_id(signal);
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+			DATA_TABLES(ASIC_InternalSS_Info));
+	get_atom_data_table_revision(header, &revision);
+
+	switch (revision.major) {
+	case 2:
+		switch (revision.minor) {
+		case 1:
+			return get_ss_entry_number(bp, ss_id);
+		default:
+			break;
+		}
+		break;
+	case 3:
+		switch (revision.minor) {
+		case 1:
+			return
+				get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
+						bp, ss_id);
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+
+/**
+ * get_ss_entry_number_from_ss_info_tbl
+ * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
+ *
+ * @note There can only be one entry for each id for SS_Info Table
+ *
+ * @param [in] id, spread spectrum id
+ * @return number of SS Entry that match the id
+ */
+static uint32_t get_ss_entry_number_from_ss_info_tbl(
+	struct bios_parser *bp,
+	uint32_t id)
+{
+	ATOM_SPREAD_SPECTRUM_INFO *tbl;
+	ATOM_COMMON_TABLE_HEADER *header;
+	uint32_t table_size;
+	uint32_t i;
+	uint32_t number = 0;
+	uint32_t id_local = SS_ID_UNKNOWN;
+	struct atom_data_revision revision;
+
+	/* SS_Info table exist */
+	if (!DATA_TABLES(SS_Info))
+		return number;
+
+	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+			DATA_TABLES(SS_Info));
+	get_atom_data_table_revision(header, &revision);
+
+	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
+			DATA_TABLES(SS_Info));
+
+	if (1 != revision.major || 2 > revision.minor)
+		return number;
+
+	/* have to convert from Internal_SS format to SS_Info format */
+	switch (id) {
+	case ASIC_INTERNAL_SS_ON_DP:
+		id_local = SS_ID_DP1;
+		break;
+	case ASIC_INTERNAL_SS_ON_LVDS: {
+		struct embedded_panel_info panel_info;
+
+		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
+				== BP_RESULT_OK)
+			id_local = panel_info.ss_id;
+		break;
+	}
+	default:
+		break;
+	}
+
+	if (id_local == SS_ID_UNKNOWN)
+		return number;
+
+	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
+			sizeof(ATOM_COMMON_TABLE_HEADER)) /
+					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
+
+	for (i = 0; i < table_size; i++)
+		if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
+			number = 1;
+			break;
+		}
+
+	return number;
+}
+
+
+/**
+ * get_ss_entry_number
+ * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info table from the VBIOS
+ * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
+ * SS_Info.
+ *
+ * @param id, spread sprectrum info index
+ * @return Bios parser result code
+ */
+static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
+{
+	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
+		return get_ss_entry_number_from_ss_info_tbl(bp, id);
+
+	return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
+}
+
+/**
+ * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
+ * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
+ * Ver 2.1 from the VBIOS
+ * There will not be multiple entry for Ver 2.1
+ *
+ * @param id, spread sprectrum info index
+ * @return number of SS Entry that match the id
+ */
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
+	struct bios_parser *bp,
+	uint32_t id)
+{
+	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
+	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
+	uint32_t size;
+	uint32_t i;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return 0;
+
+	header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
+			DATA_TABLES(ASIC_InternalSS_Info));
+
+	size = (le16_to_cpu(header_include->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+						/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
+				&header_include->asSpreadSpectrum[0];
+	for (i = 0; i < size; i++)
+		if (tbl[i].ucClockIndication == (uint8_t)id)
+			return 1;
+
+	return 0;
+}
+/**
+ * get_ss_entry_number_from_internal_ss_info_table_V3_1
+ * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
+ * the VBIOS that matches id
+ *
+ * @param[in]  id, spread sprectrum id
+ * @return number of SS Entry that match the id
+ */
+static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
+	struct bios_parser *bp,
+	uint32_t id)
+{
+	uint32_t number = 0;
+	ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
+	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
+	uint32_t size;
+	uint32_t i;
+
+	if (!DATA_TABLES(ASIC_InternalSS_Info))
+		return number;
+
+	header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
+			DATA_TABLES(ASIC_InternalSS_Info));
+	size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
+			sizeof(ATOM_COMMON_TABLE_HEADER)) /
+					sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
+
+	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
+				&header_include->asSpreadSpectrum[0];
+
+	for (i = 0; i < size; i++)
+		if (tbl[i].ucClockIndication == (uint8_t)id)
+			number++;
+
+	return number;
+}
+
+static ATOM_FAKE_EDID_PATCH_RECORD *get_faked_edid_record(
+	struct bios_parser *bp)
+{
+	uint32_t size;
+	uint8_t *record;
+	ATOM_LVDS_INFO_V12 *info;
+
+	if (!DATA_TABLES(LVDS_Info))
+		return NULL;
+
+	info = GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
+
+	if (!info)
+		return NULL;
+
+	if (1 != info->sHeader.ucTableFormatRevision
+			|| 2 > info->sHeader.ucTableContentRevision)
+		return NULL;
+
+	if (!le16_to_cpu(info->usExtInfoTableOffset))
+		return NULL;
+
+	record = GET_IMAGE(uint8_t, DATA_TABLES(LVDS_Info)
+			+ le16_to_cpu(info->usExtInfoTableOffset));
+
+	if (!record)
+		return NULL;
+
+	for (;;) {
+		if (ATOM_RECORD_END_TYPE == *record)
+			return NULL;
+
+		if (LCD_FAKE_EDID_PATCH_RECORD_TYPE == *record)
+			break;
+
+		size = get_record_size(record);
+
+		if (!size)
+			return NULL;
+
+		record += size;
+	}
+
+	return (ATOM_FAKE_EDID_PATCH_RECORD *)record;
+}
+
+static enum bp_result bios_parser_get_faked_edid_len(
+	struct dc_bios *dcb,
+	uint32_t *len)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_FAKE_EDID_PATCH_RECORD *edid_record = get_faked_edid_record(bp);
+
+	if (!edid_record)
+		return BP_RESULT_NORECORD;
+
+	*len = get_edid_size(edid_record);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_faked_edid_buf(
+	struct dc_bios *dcb,
+	uint8_t *buff,
+	uint32_t len)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_FAKE_EDID_PATCH_RECORD *edid_record = get_faked_edid_record(bp);
+	uint32_t edid_size;
+
+	if (!edid_record)
+		return BP_RESULT_NORECORD;
+
+	edid_size = get_edid_size(edid_record);
+
+	if (len < edid_size)
+		return BP_RESULT_BADINPUT; /* buffer not big enough to fill */
+
+	dm_memmove(buff, &edid_record->ucFakeEDIDString, edid_size);
+
+	return BP_RESULT_OK;
+}
+
+/**
+ * bios_parser_get_gpio_pin_info
+ * Get GpioPin information of input gpio id
+ *
+ * @param gpio_id, GPIO ID
+ * @param info, GpioPin information structure
+ * @return Bios parser result code
+ * @note
+ *  to get the GPIO PIN INFO, we need:
+ *  1. get the GPIO_ID from other object table, see GetHPDInfo()
+ *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
+ *  offset/mask
+ */
+static enum bp_result bios_parser_get_gpio_pin_info(
+	struct dc_bios *dcb,
+	uint32_t gpio_id,
+	struct gpio_pin_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	ATOM_GPIO_PIN_LUT *header;
+	uint32_t count = 0;
+	uint32_t i = 0;
+
+	if (!DATA_TABLES(GPIO_Pin_LUT))
+		return BP_RESULT_BADBIOSTABLE;
+
+	header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT));
+	if (!header)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT)
+			> le16_to_cpu(header->sHeader.usStructureSize))
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != header->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	count = (le16_to_cpu(header->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
+	for (i = 0; i < count; ++i) {
+		if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
+			continue;
+
+		info->offset =
+			(uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
+		info->offset_y = info->offset + 2;
+		info->offset_en = info->offset + 1;
+		info->offset_mask = info->offset - 1;
+
+		info->mask = (uint32_t) (1 <<
+			header->asGPIO_Pin[i].ucGpioPinBitShift);
+		info->mask_y = info->mask + 2;
+		info->mask_en = info->mask + 1;
+		info->mask_mask = info->mask - 1;
+
+		return BP_RESULT_OK;
+	}
+
+	return BP_RESULT_NORECORD;
+}
+
+/**
+ * BiosParserObject::EnumEmbeddedPanelPatchMode
+ * Get embedded panel patch mode
+ *
+ * @param index, mode index
+ * @param info, embedded panel patch mode structure
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_enum_embedded_panel_patch_mode(
+	struct dc_bios *dcb,
+	uint32_t index,
+	struct embedded_panel_patch_mode *mode)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	uint32_t record_size;
+	uint32_t record_index;
+	uint8_t *record;
+	ATOM_LVDS_INFO_V12 *info;
+	ATOM_PATCH_RECORD_MODE *mode_record;
+	ATOM_MASTER_LIST_OF_DATA_TABLES *list_of_tables;
+
+	if (!mode)
+		return BP_RESULT_BADINPUT;
+
+	list_of_tables = &bp->master_data_tbl->ListOfDataTables;
+	if (!list_of_tables->LVDS_Info)
+		return BP_RESULT_UNSUPPORTED;
+
+	info = GET_IMAGE(ATOM_LVDS_INFO_V12, list_of_tables->LVDS_Info);
+
+	if (!info)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != info->sHeader.ucTableFormatRevision
+			|| 2 > info->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	if (!le16_to_cpu(info->usExtInfoTableOffset))
+		return BP_RESULT_UNSUPPORTED;
+
+	record = GET_IMAGE(uint8_t, list_of_tables->LVDS_Info +
+			le16_to_cpu(info->usExtInfoTableOffset));
+
+	if (!record)
+		return BP_RESULT_BADBIOSTABLE;
+
+	for (record_index = 0;;) {
+		if (ATOM_RECORD_END_TYPE == *record)
+			return BP_RESULT_NORECORD;
+
+		if (LCD_MODE_PATCH_RECORD_MODE_TYPE == *record) {
+			if (record_index == index)
+				break;
+			record_index++;
+		}
+
+		record_size = get_record_size(record);
+
+		if (!record_size)
+			return BP_RESULT_NORECORD;
+
+		record += record_size;
+	}
+
+	mode_record = (ATOM_PATCH_RECORD_MODE *) record;
+
+	mode->width = le16_to_cpu(mode_record->usHDisp);
+	mode->height = le16_to_cpu(mode_record->usVDisp);
+
+	return BP_RESULT_OK;
+}
+
+static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
+	ATOM_I2C_RECORD *record,
+	struct graphics_object_i2c_info *info)
+{
+	ATOM_GPIO_I2C_INFO *header;
+	uint32_t count = 0;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	/* get the GPIO_I2C info */
+	if (!DATA_TABLES(GPIO_I2C_Info))
+		return BP_RESULT_BADBIOSTABLE;
+
+	header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
+	if (!header)
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
+			> le16_to_cpu(header->sHeader.usStructureSize))
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (1 != header->sHeader.ucTableContentRevision)
+		return BP_RESULT_UNSUPPORTED;
+
+	/* get data count */
+	count = (le16_to_cpu(header->sHeader.usStructureSize)
+			- sizeof(ATOM_COMMON_TABLE_HEADER))
+				/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
+	if (count < record->sucI2cId.bfI2C_LineMux)
+		return BP_RESULT_BADBIOSTABLE;
+
+	/* get the GPIO_I2C_INFO */
+	info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
+	info->i2c_line = record->sucI2cId.bfI2C_LineMux;
+	info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
+	info->i2c_slave_address = record->ucI2CAddr;
+
+	info->gpio_info.clk_mask_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
+	info->gpio_info.clk_en_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
+	info->gpio_info.clk_y_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
+	info->gpio_info.clk_a_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
+	info->gpio_info.data_mask_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
+	info->gpio_info.data_en_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
+	info->gpio_info.data_y_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
+	info->gpio_info.data_a_register_index =
+			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
+
+	info->gpio_info.clk_mask_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
+	info->gpio_info.clk_en_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkEnShift;
+	info->gpio_info.clk_y_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
+	info->gpio_info.clk_a_shift =
+			header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
+	info->gpio_info.data_mask_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
+	info->gpio_info.data_en_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataEnShift;
+	info->gpio_info.data_y_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
+	info->gpio_info.data_a_shift =
+			header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
+
+	return BP_RESULT_OK;
+}
+
+static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
+	struct graphics_object_id id)
+{
+	uint32_t offset;
+	ATOM_OBJECT_TABLE *tbl;
+	uint32_t i;
+
+	switch (id.type) {
+	case OBJECT_TYPE_ENCODER:
+		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
+		break;
+
+	case OBJECT_TYPE_CONNECTOR:
+		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+		break;
+
+	case OBJECT_TYPE_ROUTER:
+		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
+		break;
+
+	case OBJECT_TYPE_GENERIC:
+		if (bp->object_info_tbl.revision.minor < 3)
+			return NULL;
+		offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
+		break;
+
+	default:
+		return NULL;
+	}
+
+	offset += bp->object_info_tbl_offset;
+
+	tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
+	if (!tbl)
+		return NULL;
+
+	for (i = 0; i < tbl->ucNumberOfObjects; i++)
+		if (dal_graphics_object_id_is_equal(id,
+				object_id_from_bios_object_id(
+						le16_to_cpu(tbl->asObjects[i].usObjectID))))
+			return &tbl->asObjects[i];
+
+	return NULL;
+}
+
+static uint32_t get_dest_obj_list(struct bios_parser *bp,
+	ATOM_OBJECT *object, uint16_t **id_list)
+{
+	uint32_t offset;
+	uint8_t *number;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+						+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	offset += sizeof(uint8_t);
+	offset += sizeof(uint16_t) * (*number);
+
+	number = GET_IMAGE(uint8_t, offset);
+	if ((!number) || (!*number))
+		return 0;
+
+	offset += sizeof(uint8_t);
+	*id_list = (uint16_t *)get_image(bp, offset,
+			*number * sizeof(uint16_t));
+
+	if (!*id_list)
+		return 0;
+
+	return *number;
+}
+
+static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
+	uint16_t **id_list)
+{
+	uint32_t offset;
+	uint8_t *number;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object id */
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+					+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	offset += sizeof(uint8_t);
+	*id_list = (uint16_t *)get_image(bp, offset,
+			*number * sizeof(uint16_t));
+
+	if (!*id_list)
+		return 0;
+
+	return *number;
+}
+
+static uint32_t get_dst_number_from_object(struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	uint8_t *number;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/
+		return 0;
+	}
+
+	offset = le16_to_cpu(object->usSrcDstTableOffset)
+					+ bp->object_info_tbl_offset;
+
+	number = GET_IMAGE(uint8_t, offset);
+	if (!number)
+		return 0;
+
+	offset += sizeof(uint8_t);
+	offset += sizeof(uint16_t) * (*number);
+
+	number = GET_IMAGE(uint8_t, offset);
+
+	if (!number)
+		return 0;
+
+	return *number;
+}
+
+static uint8_t *get_image(struct bios_parser *bp,
+	uint32_t offset,
+	uint32_t size)
+{
+	if (bp->bios && offset + size < bp->bios_size)
+		return bp->bios + offset;
+	else
+		return NULL;
+}
+
+static uint32_t get_record_size(uint8_t *record)
+{
+	switch (*record) {
+	case LCD_MODE_PATCH_RECORD_MODE_TYPE:
+		return sizeof(ATOM_PATCH_RECORD_MODE);
+
+	case LCD_RTS_RECORD_TYPE:
+		return sizeof(ATOM_LCD_RTS_RECORD);
+
+	case LCD_CAP_RECORD_TYPE:
+		return sizeof(ATOM_LCD_MODE_CONTROL_CAP);
+
+	case LCD_FAKE_EDID_PATCH_RECORD_TYPE: {
+		ATOM_FAKE_EDID_PATCH_RECORD *fake_record =
+				(ATOM_FAKE_EDID_PATCH_RECORD *) record;
+		uint32_t edid_size = get_edid_size(fake_record);
+
+		return sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + edid_size
+				- sizeof(fake_record->ucFakeEDIDString);
+	}
+
+	case LCD_PANEL_RESOLUTION_RECORD_TYPE:
+		return sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD);
+
+	default:
+		return 0;
+	}
+}
+
+static uint32_t get_edid_size(const ATOM_FAKE_EDID_PATCH_RECORD *edid)
+{
+	uint32_t length = edid->ucFakeEDIDLength;
+
+	if (length < 128)
+		length = length * 128;
+
+	return length;
+}
+
+static struct graphics_object_id object_id_from_bios_object_id(
+	uint32_t bios_object_id)
+{
+	enum object_type type;
+	enum object_enum_id enum_id;
+	struct graphics_object_id go_id = { 0 };
+
+	type = object_type_from_bios_object_id(bios_object_id);
+
+	if (OBJECT_TYPE_UNKNOWN == type)
+		return go_id;
+
+	enum_id = enum_id_from_bios_object_id(bios_object_id);
+
+	if (ENUM_ID_UNKNOWN == enum_id)
+		return go_id;
+
+	go_id = dal_graphics_object_id_init(
+			id_from_bios_object_id(type, bios_object_id), enum_id, type);
+
+	return go_id;
+}
+
+static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK)
+				>> OBJECT_TYPE_SHIFT;
+	enum object_type object_type;
+
+	switch (bios_object_type) {
+	case GRAPH_OBJECT_TYPE_GPU:
+		object_type = OBJECT_TYPE_GPU;
+		break;
+	case GRAPH_OBJECT_TYPE_ENCODER:
+		object_type = OBJECT_TYPE_ENCODER;
+		break;
+	case GRAPH_OBJECT_TYPE_CONNECTOR:
+		object_type = OBJECT_TYPE_CONNECTOR;
+		break;
+	case GRAPH_OBJECT_TYPE_ROUTER:
+		object_type = OBJECT_TYPE_ROUTER;
+		break;
+	case GRAPH_OBJECT_TYPE_GENERIC:
+		object_type = OBJECT_TYPE_GENERIC;
+		break;
+	default:
+		object_type = OBJECT_TYPE_UNKNOWN;
+		break;
+	}
+
+	return object_type;
+}
+
+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_enum_id =
+			(bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+	enum object_enum_id id;
+
+	switch (bios_enum_id) {
+	case GRAPH_OBJECT_ENUM_ID1:
+		id = ENUM_ID_1;
+		break;
+	case GRAPH_OBJECT_ENUM_ID2:
+		id = ENUM_ID_2;
+		break;
+	case GRAPH_OBJECT_ENUM_ID3:
+		id = ENUM_ID_3;
+		break;
+	case GRAPH_OBJECT_ENUM_ID4:
+		id = ENUM_ID_4;
+		break;
+	case GRAPH_OBJECT_ENUM_ID5:
+		id = ENUM_ID_5;
+		break;
+	case GRAPH_OBJECT_ENUM_ID6:
+		id = ENUM_ID_6;
+		break;
+	case GRAPH_OBJECT_ENUM_ID7:
+		id = ENUM_ID_7;
+		break;
+	default:
+		id = ENUM_ID_UNKNOWN;
+		break;
+	}
+
+	return id;
+}
+
+static uint32_t id_from_bios_object_id(enum object_type type,
+	uint32_t bios_object_id)
+{
+	switch (type) {
+	case OBJECT_TYPE_GPU:
+		return gpu_id_from_bios_object_id(bios_object_id);
+	case OBJECT_TYPE_ENCODER:
+		return (uint32_t)encoder_id_from_bios_object_id(bios_object_id);
+	case OBJECT_TYPE_CONNECTOR:
+		return (uint32_t)connector_id_from_bios_object_id(
+				bios_object_id);
+	case OBJECT_TYPE_GENERIC:
+		return generic_id_from_bios_object_id(bios_object_id);
+	default:
+		return 0;
+	}
+}
+
+static enum connector_id connector_id_from_bios_object_id(
+	uint32_t bios_object_id)
+{
+	uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id);
+
+	enum connector_id id;
+
+	switch (bios_connector_id) {
+	case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I:
+		id = CONNECTOR_ID_SINGLE_LINK_DVII;
+		break;
+	case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I:
+		id = CONNECTOR_ID_DUAL_LINK_DVII;
+		break;
+	case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D:
+		id = CONNECTOR_ID_SINGLE_LINK_DVID;
+		break;
+	case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D:
+		id = CONNECTOR_ID_DUAL_LINK_DVID;
+		break;
+	case CONNECTOR_OBJECT_ID_VGA:
+		id = CONNECTOR_ID_VGA;
+		break;
+	case CONNECTOR_OBJECT_ID_HDMI_TYPE_A:
+		id = CONNECTOR_ID_HDMI_TYPE_A;
+		break;
+	case CONNECTOR_OBJECT_ID_LVDS:
+		id = CONNECTOR_ID_LVDS;
+		break;
+	case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR:
+		id = CONNECTOR_ID_PCIE;
+		break;
+	case CONNECTOR_OBJECT_ID_HARDCODE_DVI:
+		id = CONNECTOR_ID_HARDCODE_DVI;
+		break;
+	case CONNECTOR_OBJECT_ID_DISPLAYPORT:
+		id = CONNECTOR_ID_DISPLAY_PORT;
+		break;
+	case CONNECTOR_OBJECT_ID_eDP:
+		id = CONNECTOR_ID_EDP;
+		break;
+	case CONNECTOR_OBJECT_ID_MXM:
+		id = CONNECTOR_ID_MXM;
+		break;
+	default:
+		id = CONNECTOR_ID_UNKNOWN;
+		break;
+	}
+
+	return id;
+}
+
+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id);
+	enum encoder_id id;
+
+	switch (bios_encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+		id = ENCODER_ID_INTERNAL_LVDS;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+		id = ENCODER_ID_INTERNAL_TMDS1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_TMDS2:
+		id = ENCODER_ID_INTERNAL_TMDS2;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+		id = ENCODER_ID_INTERNAL_DAC1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+		id = ENCODER_ID_INTERNAL_DAC2;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		id = ENCODER_ID_INTERNAL_LVTM1;
+		break;
+	case ENCODER_OBJECT_ID_HDMI_INTERNAL:
+		id = ENCODER_ID_INTERNAL_HDMI;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+		id = ENCODER_ID_INTERNAL_KLDSCP_DAC1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+		id = ENCODER_ID_INTERNAL_KLDSCP_DAC2;
+		break;
+	case ENCODER_OBJECT_ID_MVPU_FPGA:
+		id = ENCODER_ID_EXTERNAL_MVPU_FPGA;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_DDI:
+		id = ENCODER_ID_INTERNAL_DDI;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+		id = ENCODER_ID_INTERNAL_UNIPHY;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		id = ENCODER_ID_INTERNAL_UNIPHY1;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		id = ENCODER_ID_INTERNAL_UNIPHY2;
+		break;
+	case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */
+		id = ENCODER_ID_EXTERNAL_NUTMEG;
+		break;
+	case ENCODER_OBJECT_ID_TRAVIS:
+		id = ENCODER_ID_EXTERNAL_TRAVIS;
+		break;
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
+		id = ENCODER_ID_INTERNAL_UNIPHY3;
+		break;
+	default:
+		id = ENCODER_ID_UNKNOWN;
+		ASSERT(0);
+		break;
+	}
+
+	return id;
+}
+
+uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+}
+
+enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id)
+{
+	uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id);
+
+	enum generic_id id;
+
+	switch (bios_generic_id) {
+	case GENERIC_OBJECT_ID_MXM_OPM:
+		id = GENERIC_ID_MXM_OPM;
+		break;
+	case GENERIC_OBJECT_ID_GLSYNC:
+		id = GENERIC_ID_GLSYNC;
+		break;
+	case GENERIC_OBJECT_ID_STEREO_PIN:
+		id = GENERIC_ID_STEREO;
+		break;
+	default:
+		id = GENERIC_ID_UNKNOWN;
+		break;
+	}
+
+	return id;
+}
+
+static struct device_id device_type_from_device_id(uint16_t device_id)
+{
+
+	struct device_id result_device_id;
+
+	switch (device_id) {
+	case ATOM_DEVICE_LCD1_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_LCD;
+		result_device_id.enum_id = 1;
+		break;
+
+	case ATOM_DEVICE_LCD2_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_LCD;
+		result_device_id.enum_id = 2;
+		break;
+
+	case ATOM_DEVICE_CRT1_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_CRT;
+		result_device_id.enum_id = 1;
+		break;
+
+	case ATOM_DEVICE_CRT2_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_CRT;
+		result_device_id.enum_id = 2;
+		break;
+
+	case ATOM_DEVICE_DFP1_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 1;
+		break;
+
+	case ATOM_DEVICE_DFP2_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 2;
+		break;
+
+	case ATOM_DEVICE_DFP3_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 3;
+		break;
+
+	case ATOM_DEVICE_DFP4_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 4;
+		break;
+
+	case ATOM_DEVICE_DFP5_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 5;
+		break;
+
+	case ATOM_DEVICE_DFP6_SUPPORT:
+		result_device_id.device_type = DEVICE_TYPE_DFP;
+		result_device_id.enum_id = 6;
+		break;
+
+	default:
+		BREAK_TO_DEBUGGER(); /* Invalid device Id */
+		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
+		result_device_id.enum_id = 0;
+	}
+	return result_device_id;
+}
+
+static void get_atom_data_table_revision(
+	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
+	struct atom_data_revision *tbl_revision)
+{
+	if (!tbl_revision)
+		return;
+
+	/* initialize the revision to 0 which is invalid revision */
+	tbl_revision->major = 0;
+	tbl_revision->minor = 0;
+
+	if (!atom_data_tbl)
+		return;
+
+	tbl_revision->major =
+			(uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
+	tbl_revision->minor =
+			(uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
+}
+
+static uint32_t signal_to_ss_id(enum as_signal_type signal)
+{
+	uint32_t clk_id_ss = 0;
+
+	switch (signal) {
+	case AS_SIGNAL_TYPE_DVI:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
+		break;
+	case AS_SIGNAL_TYPE_HDMI:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
+		break;
+	case AS_SIGNAL_TYPE_LVDS:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
+		break;
+	case AS_SIGNAL_TYPE_DISPLAY_PORT:
+		clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
+		break;
+	case AS_SIGNAL_TYPE_GPU_PLL:
+		clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
+		break;
+	default:
+		break;
+	}
+	return clk_id_ss;
+}
+
+static uint32_t get_support_mask_for_device_id(struct device_id device_id)
+{
+	enum dal_device_type device_type = device_id.device_type;
+	uint32_t enum_id = device_id.enum_id;
+
+	switch (device_type) {
+	case DEVICE_TYPE_LCD:
+		switch (enum_id) {
+		case 1:
+			return ATOM_DEVICE_LCD1_SUPPORT;
+		case 2:
+			return ATOM_DEVICE_LCD2_SUPPORT;
+		default:
+			break;
+		}
+		break;
+		case DEVICE_TYPE_CRT:
+			switch (enum_id) {
+			case 1:
+				return ATOM_DEVICE_CRT1_SUPPORT;
+			case 2:
+				return ATOM_DEVICE_CRT2_SUPPORT;
+			default:
+				break;
+			}
+			break;
+			case DEVICE_TYPE_DFP:
+				switch (enum_id) {
+				case 1:
+					return ATOM_DEVICE_DFP1_SUPPORT;
+				case 2:
+					return ATOM_DEVICE_DFP2_SUPPORT;
+				case 3:
+					return ATOM_DEVICE_DFP3_SUPPORT;
+				case 4:
+					return ATOM_DEVICE_DFP4_SUPPORT;
+				case 5:
+					return ATOM_DEVICE_DFP5_SUPPORT;
+				case 6:
+					return ATOM_DEVICE_DFP6_SUPPORT;
+				default:
+					break;
+				}
+				break;
+				case DEVICE_TYPE_CV:
+					switch (enum_id) {
+					case 1:
+						return ATOM_DEVICE_CV_SUPPORT;
+					default:
+						break;
+					}
+					break;
+					case DEVICE_TYPE_TV:
+						switch (enum_id) {
+						case 1:
+							return ATOM_DEVICE_TV1_SUPPORT;
+						default:
+							break;
+						}
+						break;
+						default:
+							break;
+	};
+
+	/* Unidentified device ID, return empty support mask. */
+	return 0;
+}
+
+/**
+ *  HwContext interface for writing MM registers
+ */
+
+static bool i2c_read(
+	struct bios_parser *bp,
+	struct graphics_object_i2c_info *i2c_info,
+	uint8_t *buffer,
+	uint32_t length)
+{
+	struct ddc *ddc;
+	uint8_t offset[2] = { 0, 0 };
+	bool result = false;
+	struct i2c_command cmd;
+
+	ddc = dal_adapter_service_obtain_ddc_from_i2c_info(bp->as, i2c_info);
+
+	if (!ddc)
+		return result;
+
+	/*Using SW engine */
+	cmd.engine = I2C_COMMAND_ENGINE_SW;
+	cmd.speed = dal_adapter_service_get_sw_i2c_speed(bp->as);
+
+	{
+		struct i2c_payload payloads[] = {
+				{
+						.address = i2c_info->i2c_slave_address >> 1,
+						.data = offset,
+						.length = sizeof(offset),
+						.write = true
+				},
+				{
+						.address = i2c_info->i2c_slave_address >> 1,
+						.data = buffer,
+						.length = length,
+						.write = false
+				}
+		};
+
+		cmd.payloads = payloads;
+		cmd.number_of_payloads = ARRAY_SIZE(payloads);
+
+		/* TODO route this through drm i2c_adapter */
+		result = dal_i2caux_submit_i2c_command(
+				dal_adapter_service_get_i2caux(bp->as),
+				ddc,
+				&cmd);
+	}
+
+	dal_adapter_service_release_ddc(bp->as, ddc);
+
+	return result;
+}
+
+/**
+ * Read external display connection info table through i2c.
+ * validate the GUID and checksum.
+ *
+ * @return enum bp_result whether all data was sucessfully read
+ */
+static enum bp_result get_ext_display_connection_info(
+	struct bios_parser *bp,
+	ATOM_OBJECT *opm_object,
+	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl)
+{
+	bool config_tbl_present = false;
+	ATOM_I2C_RECORD *i2c_record = NULL;
+	uint32_t i = 0;
+
+	if (opm_object == NULL)
+		return BP_RESULT_BADINPUT;
+
+	i2c_record = get_i2c_record(bp, opm_object);
+
+	if (i2c_record != NULL) {
+		ATOM_GPIO_I2C_INFO *gpio_i2c_header;
+		struct graphics_object_i2c_info i2c_info;
+
+		gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO,
+				bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info);
+
+		if (NULL == gpio_i2c_header)
+			return BP_RESULT_BADBIOSTABLE;
+
+		if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) !=
+				BP_RESULT_OK)
+			return BP_RESULT_BADBIOSTABLE;
+
+		if (i2c_read(
+				bp,
+				&i2c_info,
+				(uint8_t *)ext_display_connection_info_tbl,
+				sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) {
+			config_tbl_present = true;
+		}
+	}
+
+	/* Validate GUID */
+	if (config_tbl_present)
+		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) {
+			if (ext_display_connection_info_tbl->ucGuid[i]
+														!= ext_display_connection_guid[i]) {
+				config_tbl_present = false;
+				break;
+			}
+		}
+
+	/* Validate checksum */
+	if (config_tbl_present) {
+		uint8_t check_sum = 0;
+		uint8_t *buf =
+				(uint8_t *)ext_display_connection_info_tbl;
+
+		for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO);
+				i++) {
+			check_sum += buf[i];
+		}
+
+		if (check_sum != 0)
+			config_tbl_present = false;
+	}
+
+	if (config_tbl_present)
+		return BP_RESULT_OK;
+	else
+		return BP_RESULT_FAILURE;
+}
+
+/*
+ * Gets the first device ID in the same group as the given ID for enumerating.
+ * For instance, if any DFP device ID is passed, returns the device ID for DFP1.
+ *
+ * The first device ID in the same group as the passed device ID, or 0 if no
+ * matching device group found.
+ */
+static uint32_t enum_first_device_id(uint32_t dev_id)
+{
+	/* Return the first in the group that this ID belongs to. */
+	if (dev_id & ATOM_DEVICE_CRT_SUPPORT)
+		return ATOM_DEVICE_CRT1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_DFP_SUPPORT)
+		return ATOM_DEVICE_DFP1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_LCD_SUPPORT)
+		return ATOM_DEVICE_LCD1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_TV_SUPPORT)
+		return ATOM_DEVICE_TV1_SUPPORT;
+	else if (dev_id & ATOM_DEVICE_CV_SUPPORT)
+		return ATOM_DEVICE_CV_SUPPORT;
+
+	/* No group found for this device ID. */
+
+	dm_error("%s: incorrect input %d\n", __func__, dev_id);
+	/* No matching support flag for given device ID */
+	return 0;
+}
+
+/*
+ * Gets the next device ID in the group for a given device ID.
+ *
+ * The current device ID being enumerated on.
+ *
+ * The next device ID in the group, or 0 if no device exists.
+ */
+static uint32_t enum_next_dev_id(uint32_t dev_id)
+{
+	/* Get next device ID in the group. */
+	switch (dev_id) {
+	case ATOM_DEVICE_CRT1_SUPPORT:
+		return ATOM_DEVICE_CRT2_SUPPORT;
+	case ATOM_DEVICE_LCD1_SUPPORT:
+		return ATOM_DEVICE_LCD2_SUPPORT;
+	case ATOM_DEVICE_DFP1_SUPPORT:
+		return ATOM_DEVICE_DFP2_SUPPORT;
+	case ATOM_DEVICE_DFP2_SUPPORT:
+		return ATOM_DEVICE_DFP3_SUPPORT;
+	case ATOM_DEVICE_DFP3_SUPPORT:
+		return ATOM_DEVICE_DFP4_SUPPORT;
+	case ATOM_DEVICE_DFP4_SUPPORT:
+		return ATOM_DEVICE_DFP5_SUPPORT;
+	case ATOM_DEVICE_DFP5_SUPPORT:
+		return ATOM_DEVICE_DFP6_SUPPORT;
+	}
+
+	/* Done enumerating through devices. */
+	return 0;
+}
+
+/*
+ * Returns the new device tag record for patched BIOS object.
+ *
+ * [IN] pExtDisplayPath - External display path to copy device tag from.
+ * [IN] deviceSupport - Bit vector for device ID support flags.
+ * [OUT] pDeviceTag - Device tag structure to fill with patched data.
+ *
+ * True if a compatible device ID was found, false otherwise.
+ */
+static bool get_patched_device_tag(
+	struct bios_parser *bp,
+	EXT_DISPLAY_PATH *ext_display_path,
+	uint32_t device_support,
+	ATOM_CONNECTOR_DEVICE_TAG *device_tag)
+{
+	uint32_t dev_id;
+	/* Use fallback behaviour if not supported. */
+	if (!bp->remap_device_tags) {
+		device_tag->ulACPIDeviceEnum =
+				cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
+		device_tag->usDeviceID =
+				cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceTag));
+		return true;
+	}
+
+	/* Find the first unused in the same group. */
+	dev_id = enum_first_device_id(le16_to_cpu(ext_display_path->usDeviceTag));
+	while (dev_id != 0) {
+		/* Assign this device ID if supported. */
+		if ((device_support & dev_id) != 0) {
+			device_tag->ulACPIDeviceEnum =
+					cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
+			device_tag->usDeviceID = cpu_to_le16((USHORT) dev_id);
+			return true;
+		}
+
+		dev_id = enum_next_dev_id(dev_id);
+	}
+
+	/* No compatible device ID found. */
+	return false;
+}
+
+/*
+ * Adds a device tag to a BIOS object's device tag record if there is
+ * matching device ID supported.
+ *
+ * pObject - Pointer to the BIOS object to add the device tag to.
+ * pExtDisplayPath - Display path to retrieve base device ID from.
+ * pDeviceSupport - Pointer to bit vector for supported device IDs.
+ */
+static void add_device_tag_from_ext_display_path(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object,
+	EXT_DISPLAY_PATH *ext_display_path,
+	uint32_t *device_support)
+{
+	/* Get device tag record for object. */
+	ATOM_CONNECTOR_DEVICE_TAG *device_tag = NULL;
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD *device_tag_record = NULL;
+	enum bp_result result =
+			bios_parser_get_device_tag_record(
+					bp, object, &device_tag_record);
+
+	if ((le16_to_cpu(ext_display_path->usDeviceTag) != CONNECTOR_OBJECT_ID_NONE)
+			&& (result == BP_RESULT_OK)) {
+		uint8_t index;
+
+		if ((device_tag_record->ucNumberOfDevice == 1) &&
+				(le16_to_cpu(device_tag_record->asDeviceTag[0].usDeviceID) == 0)) {
+			/*Workaround bug in current VBIOS releases where
+			 * ucNumberOfDevice = 1 but there is no actual device
+			 * tag data. This w/a is temporary until the updated
+			 * VBIOS is distributed. */
+			device_tag_record->ucNumberOfDevice =
+					device_tag_record->ucNumberOfDevice - 1;
+		}
+
+		/* Attempt to find a matching device ID. */
+		index = device_tag_record->ucNumberOfDevice;
+		device_tag = &device_tag_record->asDeviceTag[index];
+		if (get_patched_device_tag(
+				bp,
+				ext_display_path,
+				*device_support,
+				device_tag)) {
+			/* Update cached device support to remove assigned ID.
+			 */
+			*device_support &= ~le16_to_cpu(device_tag->usDeviceID);
+			device_tag_record->ucNumberOfDevice++;
+		}
+	}
+}
+
+/*
+ * Read out a single EXT_DISPLAY_PATH from the external display connection info
+ * table. The specific entry in the table is determined by the enum_id passed
+ * in.
+ *
+ * EXT_DISPLAY_PATH describing a single Configuration table entry
+ */
+
+#define INVALID_CONNECTOR 0xffff
+
+static EXT_DISPLAY_PATH *get_ext_display_path_entry(
+	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *config_table,
+	uint32_t bios_object_id)
+{
+	EXT_DISPLAY_PATH *ext_display_path;
+	uint32_t ext_display_path_index =
+			((bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT) - 1;
+
+	if (ext_display_path_index >= MAX_NUMBER_OF_EXT_DISPLAY_PATH)
+		return NULL;
+
+	ext_display_path = &config_table->sPath[ext_display_path_index];
+
+	if (le16_to_cpu(ext_display_path->usDeviceConnector) == INVALID_CONNECTOR)
+		ext_display_path->usDeviceConnector = cpu_to_le16(0);
+
+	return ext_display_path;
+}
+
+/*
+ * Get AUX/DDC information of input object id
+ *
+ * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
+ * IR
+ */
+static ATOM_CONNECTOR_AUXDDC_LUT_RECORD *get_ext_connector_aux_ddc_lut_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	ATOM_COMMON_RECORD_HEADER *header;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER();
+		/* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+					+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				0 == header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE ==
+				header->ucRecordType &&
+				sizeof(ATOM_CONNECTOR_AUXDDC_LUT_RECORD) <=
+				header->ucRecordSize)
+			return (ATOM_CONNECTOR_AUXDDC_LUT_RECORD *)(header);
+
+		offset += header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+/*
+ * Get AUX/DDC information of input object id
+ *
+ * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
+ * IR
+ */
+static ATOM_CONNECTOR_HPDPIN_LUT_RECORD *get_ext_connector_hpd_pin_lut_record(
+	struct bios_parser *bp,
+	ATOM_OBJECT *object)
+{
+	uint32_t offset;
+	ATOM_COMMON_RECORD_HEADER *header;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER();
+		/* Invalid object */
+		return NULL;
+	}
+
+	offset = le16_to_cpu(object->usRecordOffset)
+					+ bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
+
+		if (!header)
+			return NULL;
+
+		if (LAST_RECORD_TYPE == header->ucRecordType ||
+				0 == header->ucRecordSize)
+			break;
+
+		if (ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE ==
+				header->ucRecordType &&
+				sizeof(ATOM_CONNECTOR_HPDPIN_LUT_RECORD) <=
+				header->ucRecordSize)
+			return (ATOM_CONNECTOR_HPDPIN_LUT_RECORD *)header;
+
+		offset += header->ucRecordSize;
+	}
+
+	return NULL;
+}
+
+/*
+ * Check whether we need to patch the VBIOS connector info table with
+ * data from an external display connection info table.  This is
+ * necessary to support MXM boards with an OPM (output personality
+ * module).  With these designs, the VBIOS connector info table
+ * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
+ * the external connection info table through i2c and then looks up the
+ * connector ID to find the real connector type (e.g. DFP1).
+ *
+ */
+static enum bp_result patch_bios_image_from_ext_display_connection_info(
+	struct bios_parser *bp)
+{
+	ATOM_OBJECT_TABLE *connector_tbl;
+	uint32_t connector_tbl_offset;
+	struct graphics_object_id object_id;
+	ATOM_OBJECT *object;
+	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ext_display_connection_info_tbl;
+	EXT_DISPLAY_PATH *ext_display_path;
+	ATOM_CONNECTOR_AUXDDC_LUT_RECORD *aux_ddc_lut_record = NULL;
+	ATOM_I2C_RECORD *i2c_record = NULL;
+	ATOM_CONNECTOR_HPDPIN_LUT_RECORD *hpd_pin_lut_record = NULL;
+	ATOM_HPD_INT_RECORD *hpd_record = NULL;
+	ATOM_OBJECT_TABLE *encoder_table;
+	uint32_t encoder_table_offset;
+	ATOM_OBJECT *opm_object = NULL;
+	uint32_t i = 0;
+	struct graphics_object_id opm_object_id =
+			dal_graphics_object_id_init(
+					GENERIC_ID_MXM_OPM,
+					ENUM_ID_1,
+					OBJECT_TYPE_GENERIC);
+	ATOM_CONNECTOR_DEVICE_TAG_RECORD *dev_tag_record;
+	uint32_t cached_device_support =
+			le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport);
+
+	uint32_t dst_number;
+	uint16_t *dst_object_id_list;
+
+	opm_object = get_bios_object(bp, opm_object_id);
+	if (!opm_object)
+		return BP_RESULT_UNSUPPORTED;
+
+	dm_memset(&ext_display_connection_info_tbl, 0,
+			sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO));
+
+	connector_tbl_offset = bp->object_info_tbl_offset
+			+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+	connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
+
+	/* Read Connector info table from EEPROM through i2c */
+	if (get_ext_display_connection_info(
+			bp,
+			opm_object,
+			&ext_display_connection_info_tbl) != BP_RESULT_OK) {
+		if (bp->headless_no_opm) {
+			/* Failed to read OPM, remove all non-CF connectors. */
+			for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) {
+				object = &connector_tbl->asObjects[i];
+				object_id = object_id_from_bios_object_id(
+						le16_to_cpu(object->usObjectID));
+				if (OBJECT_TYPE_CONNECTOR == object_id.type)
+					object->usObjectID = cpu_to_le16(0);
+			}
+
+			return BP_RESULT_OK;
+		}
+
+		dal_logger_write(bp->ctx->logger,
+				LOG_MAJOR_BIOS,
+				LOG_MINOR_BIOS_CMD_TABLE,
+				"%s: Failed to read Connection Info Table", __func__);
+		return BP_RESULT_UNSUPPORTED;
+	}
+
+	/* Get pointer to AUX/DDC and HPD LUTs */
+	aux_ddc_lut_record =
+			get_ext_connector_aux_ddc_lut_record(bp, opm_object);
+	hpd_pin_lut_record =
+			get_ext_connector_hpd_pin_lut_record(bp, opm_object);
+
+	if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL))
+		return BP_RESULT_UNSUPPORTED;
+
+	/* Cache support bits for currently unmapped device types. */
+	if (bp->remap_device_tags) {
+		for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) {
+			uint32_t j;
+			/* Remove support for all non-MXM connectors. */
+			object = &connector_tbl->asObjects[i];
+			object_id = object_id_from_bios_object_id(
+					le16_to_cpu(object->usObjectID));
+			if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
+					(CONNECTOR_ID_MXM == object_id.id))
+				continue;
+
+			/* Remove support for all device tags. */
+			if (bios_parser_get_device_tag_record(
+					bp, object, &dev_tag_record) != BP_RESULT_OK)
+				continue;
+
+			for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) {
+				ATOM_CONNECTOR_DEVICE_TAG *device_tag =
+						&dev_tag_record->asDeviceTag[j];
+				cached_device_support &=
+						~le16_to_cpu(device_tag->usDeviceID);
+			}
+		}
+	}
+
+	/* Find all MXM connector objects and patch them with connector info
+	 * from the external display connection info table. */
+	for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
+		uint32_t j;
+
+		object = &connector_tbl->asObjects[i];
+		object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
+		if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
+				(CONNECTOR_ID_MXM != object_id.id))
+			continue;
+
+		/* Get the correct connection info table entry based on the enum
+		 * id. */
+		ext_display_path = get_ext_display_path_entry(
+				&ext_display_connection_info_tbl,
+				le16_to_cpu(object->usObjectID));
+		if (!ext_display_path)
+			return BP_RESULT_FAILURE;
+
+		/* Patch device connector ID */
+		object->usObjectID =
+				cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector));
+
+		/* Patch device tag, ulACPIDeviceEnum. */
+		add_device_tag_from_ext_display_path(
+				bp,
+				object,
+				ext_display_path,
+				&cached_device_support);
+
+		/* Patch HPD info */
+		if (ext_display_path->ucExtHPDPINLutIndex <
+				MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) {
+			hpd_record = get_hpd_record(bp, object);
+			if (hpd_record) {
+				uint8_t index =
+						ext_display_path->ucExtHPDPINLutIndex;
+				hpd_record->ucHPDIntGPIOID =
+						hpd_pin_lut_record->ucHPDPINMap[index];
+			} else {
+				BREAK_TO_DEBUGGER();
+				/* Invalid hpd record */
+				return BP_RESULT_FAILURE;
+			}
+		}
+
+		/* Patch I2C/AUX info */
+		if (ext_display_path->ucExtHPDPINLutIndex <
+				MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) {
+			i2c_record = get_i2c_record(bp, object);
+			if (i2c_record) {
+				uint8_t index =
+						ext_display_path->ucExtAUXDDCLutIndex;
+				i2c_record->sucI2cId =
+						aux_ddc_lut_record->ucAUXDDCMap[index];
+			} else {
+				BREAK_TO_DEBUGGER();
+				/* Invalid I2C record */
+				return BP_RESULT_FAILURE;
+			}
+		}
+
+		/* Merge with other MXM connectors that map to the same physical
+		 * connector. */
+		for (j = i + 1;
+				j < connector_tbl->ucNumberOfObjects; j++) {
+			ATOM_OBJECT *next_object;
+			struct graphics_object_id next_object_id;
+			EXT_DISPLAY_PATH *next_ext_display_path;
+
+			next_object = &connector_tbl->asObjects[j];
+			next_object_id = object_id_from_bios_object_id(
+					le16_to_cpu(next_object->usObjectID));
+
+			if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) &&
+					(CONNECTOR_ID_MXM == next_object_id.id))
+				continue;
+
+			next_ext_display_path = get_ext_display_path_entry(
+					&ext_display_connection_info_tbl,
+					le16_to_cpu(next_object->usObjectID));
+
+			if (next_ext_display_path == NULL)
+				return BP_RESULT_FAILURE;
+
+			/* Merge if using same connector. */
+			if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) ==
+					le16_to_cpu(ext_display_path->usDeviceConnector)) &&
+					(le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) {
+				/* Clear duplicate connector from table. */
+				next_object->usObjectID = cpu_to_le16(0);
+				add_device_tag_from_ext_display_path(
+						bp,
+						object,
+						ext_display_path,
+						&cached_device_support);
+			}
+		}
+	}
+
+	/* Find all encoders which have an MXM object as their destination.
+	 *  Replace the MXM object with the real connector Id from the external
+	 *  display connection info table */
+
+	encoder_table_offset = bp->object_info_tbl_offset
+			+ le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
+	encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
+
+	for (i = 0; i < encoder_table->ucNumberOfObjects; i++) {
+		uint32_t j;
+
+		object = &encoder_table->asObjects[i];
+
+		dst_number = get_dest_obj_list(bp, object, &dst_object_id_list);
+
+		for (j = 0; j < dst_number; j++) {
+			object_id = object_id_from_bios_object_id(
+					dst_object_id_list[j]);
+
+			if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
+					(CONNECTOR_ID_MXM != object_id.id))
+				continue;
+
+			/* Get the correct connection info table entry based on
+			 * the enum id. */
+			ext_display_path =
+					get_ext_display_path_entry(
+							&ext_display_connection_info_tbl,
+							dst_object_id_list[j]);
+
+			if (ext_display_path == NULL)
+				return BP_RESULT_FAILURE;
+
+			dst_object_id_list[j] =
+					le16_to_cpu(ext_display_path->usDeviceConnector);
+		}
+	}
+
+	return BP_RESULT_OK;
+}
+
+/*
+ * Check whether we need to patch the VBIOS connector info table with
+ * data from an external display connection info table.  This is
+ * necessary to support MXM boards with an OPM (output personality
+ * module).  With these designs, the VBIOS connector info table
+ * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
+ * the external connection info table through i2c and then looks up the
+ * connector ID to find the real connector type (e.g. DFP1).
+ *
+ */
+
+static void process_ext_display_connection_info(struct bios_parser *bp)
+{
+	ATOM_OBJECT_TABLE *connector_tbl;
+	uint32_t connector_tbl_offset;
+	struct graphics_object_id object_id;
+	ATOM_OBJECT *object;
+	bool mxm_connector_found = false;
+	bool null_entry_found = false;
+	uint32_t i = 0;
+
+	connector_tbl_offset = bp->object_info_tbl_offset +
+			le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
+	connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
+
+	/* Look for MXM connectors to determine whether we need patch the VBIOS
+	 * connector info table. Look for null entries to determine whether we
+	 * need to compact connector table. */
+	for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
+		object = &connector_tbl->asObjects[i];
+		object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
+
+		if ((OBJECT_TYPE_CONNECTOR == object_id.type) &&
+				(CONNECTOR_ID_MXM == object_id.id)) {
+			/* Once we found MXM connector - we can break */
+			mxm_connector_found = true;
+			break;
+		} else if (OBJECT_TYPE_CONNECTOR != object_id.type) {
+			/* We need to continue looping - to check if MXM
+			 * connector present */
+			null_entry_found = true;
+		}
+	}
+
+	/* Patch BIOS image */
+	if (mxm_connector_found || null_entry_found) {
+		uint32_t connectors_num = 0;
+		uint8_t *original_bios;
+		/* Step 1: Replace bios image with the new copy which will be
+		 * patched */
+		bp->bios_local_image = dm_alloc(bp->ctx, bp->bios_size);
+		if (bp->bios_local_image == NULL) {
+			BREAK_TO_DEBUGGER();
+			/* Failed to alloc bp->bios_local_image */
+			return;
+		}
+
+		dm_memmove(bp->bios_local_image, bp->bios, bp->bios_size);
+		original_bios = bp->bios;
+		bp->bios = bp->bios_local_image;
+		connector_tbl =
+				GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
+
+		/* Step 2: (only if MXM connector found) Patch BIOS image with
+		 * info from external module */
+		if (mxm_connector_found &&
+				patch_bios_image_from_ext_display_connection_info(bp) !=
+						BP_RESULT_OK) {
+			/* Patching the bios image has failed. We will copy
+			 * again original image provided and afterwards
+			 * only remove null entries */
+			dm_memmove(
+					bp->bios_local_image,
+					original_bios,
+					bp->bios_size);
+		}
+
+		/* Step 3: Compact connector table (remove null entries, valid
+		 * entries moved to beginning) */
+		for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
+			object = &connector_tbl->asObjects[i];
+			object_id = object_id_from_bios_object_id(
+					le16_to_cpu(object->usObjectID));
+
+			if (OBJECT_TYPE_CONNECTOR != object_id.type)
+				continue;
+
+			if (i != connectors_num) {
+				dm_memmove(
+						&connector_tbl->
+						asObjects[connectors_num],
+						object,
+						sizeof(ATOM_OBJECT));
+			}
+			++connectors_num;
+		}
+		connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num;
+	}
+}
+
+static void bios_parser_post_init(struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	process_ext_display_connection_info(bp);
+}
+
+static bool bios_parser_is_accelerated_mode(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	return bp->bios_helper->is_accelerated_mode(
+			bp->ctx);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+	return false;
+#endif
+}
+
+/**
+ * bios_parser_set_scratch_connected
+ *
+ * @brief
+ *  update VBIOS scratch register about connected displays
+ *
+ * @param
+ *  bool - update scratch register or just prepare info to be updated
+ *  bool - connection state
+ *  const ConnectorDeviceTagInfo* - pointer to device type and enum ID
+ */
+static void bios_parser_set_scratch_connected(
+	struct dc_bios *dcb,
+	struct graphics_object_id connector_id,
+	bool connected,
+	const struct connector_device_tag_info *device_tag)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_connected(
+			bp->ctx,
+			connector_id, connected, device_tag);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+/**
+ * bios_parser_set_scratch_critical_state
+ *
+ * @brief
+ *  update critical state bit in VBIOS scratch register
+ *
+ * @param
+ *  bool - to set or reset state
+ */
+static void bios_parser_set_scratch_critical_state(
+	struct dc_bios *dcb,
+	bool state)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_critical_state(
+			bp->ctx, state);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+static void bios_parser_set_scratch_acc_mode_change(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_acc_mode_change(
+			bp->ctx);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+/**
+ * bios_parser_prepare_scratch_active_and_requested
+ *
+ * @brief
+ *  update VBIOS scratch registers about active and requested displays
+ *
+ * @param
+ *  enum controller_id - controller Id
+ *  enum signal_type signal - signal type used on display
+ *  const struct connector_device_tag_info * - pointer to display type and
+ *  enum Id
+ */
+static void bios_parser_prepare_scratch_active_and_requested(
+	struct dc_bios *dcb,
+	enum controller_id controller_id,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->prepare_scratch_active_and_requested(
+			bp->ctx,
+			&bp->vbios_helper_data,
+			controller_id,
+			signal,
+			device_tag);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+static void bios_parser_set_scratch_active_and_requested(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+#ifdef CONFIG_DRM_AMD_DAL_VBIOS_PRESENT
+	bp->bios_helper->set_scratch_active_and_requested(
+			bp->ctx,
+			&bp->vbios_helper_data);
+#else
+	dal_logger_write(bp->ctx->logger,
+			LOG_MAJOR_BIOS,
+			LOG_MINOR_BIOS_CMD_TABLE,
+			"%s: VBIOS is not supported", __func__);
+#endif
+}
+
+/*
+ * get_integrated_info_v8
+ *
+ * @brief
+ * Get V8 integrated BIOS information
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result get_integrated_info_v8(
+	struct bios_parser *bp,
+	struct integrated_info *info)
+{
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
+	uint32_t i;
+
+	info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
+			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
+
+	if (info_v8 != NULL) {
+		info->boot_up_engine_clock =
+				le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
+		info->dentist_vco_freq =
+				le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
+		info->boot_up_uma_clock =
+				le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
+
+		for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->disp_clk_voltage[i].max_supported_clk =
+					le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
+							ulMaximumSupportedCLK) * 10;
+			info->disp_clk_voltage[i].voltage_index =
+					le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
+		}
+
+		info->boot_up_req_display_vector =
+				le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
+		info->gpu_cap_info =
+				le32_to_cpu(info_v8->ulGPUCapInfo);
+
+		/*
+		 * system_config: Bit[0] = 0 : PCIE power gating disabled
+		 *                       = 1 : PCIE power gating enabled
+		 *                Bit[1] = 0 : DDR-PLL shut down disabled
+		 *                       = 1 : DDR-PLL shut down enabled
+		 *                Bit[2] = 0 : DDR-PLL power down disabled
+		 *                       = 1 : DDR-PLL power down enabled
+		 */
+		info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
+		info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
+		info->boot_up_nb_voltage =
+				le16_to_cpu(info_v8->usBootUpNBVoltage);
+		info->ext_disp_conn_info_offset =
+				le16_to_cpu(info_v8->usExtDispConnInfoOffset);
+		info->memory_type = info_v8->ucMemoryType;
+		info->ma_channel_number = info_v8->ucUMAChannelNumber;
+		info->gmc_restore_reset_time =
+				le32_to_cpu(info_v8->ulGMCRestoreResetTime);
+
+		info->minimum_n_clk =
+				le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
+		for (i = 1; i < 4; ++i)
+			info->minimum_n_clk =
+					info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
+							info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
+
+		info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
+		info->ddr_dll_power_up_time =
+				le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
+		info->ddr_pll_power_up_time =
+				le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
+		info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
+		info->lvds_ss_percentage =
+				le16_to_cpu(info_v8->usLvdsSSPercentage);
+		info->lvds_sspread_rate_in_10hz =
+				le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
+		info->hdmi_ss_percentage =
+				le16_to_cpu(info_v8->usHDMISSPercentage);
+		info->hdmi_sspread_rate_in_10hz =
+				le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
+		info->dvi_ss_percentage =
+				le16_to_cpu(info_v8->usDVISSPercentage);
+		info->dvi_sspread_rate_in_10_hz =
+				le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
+
+		info->max_lvds_pclk_freq_in_single_link =
+				le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
+		info->lvds_misc = info_v8->ucLvdsMisc;
+		info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
+				info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
+		info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
+				info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
+		info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
+				info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
+		info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
+				info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
+		info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
+				info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
+		info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
+				info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
+		info->lvds_off_to_on_delay_in_4ms =
+				info_v8->ucLVDSOffToOnDelay_in4Ms;
+		info->lvds_bit_depth_control_val =
+				le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
+
+		for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->avail_s_clk[i].supported_s_clk =
+					le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
+			info->avail_s_clk[i].voltage_index =
+					le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
+			info->avail_s_clk[i].voltage_id =
+					le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
+		}
+
+		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
+			info->ext_disp_conn_info.gu_id[i] =
+					info_v8->sExtDispConnInfo.ucGuid[i];
+		}
+
+		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
+			info->ext_disp_conn_info.path[i].device_connector_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
+
+			info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
+
+			info->ext_disp_conn_info.path[i].device_tag =
+					le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
+			info->ext_disp_conn_info.path[i].device_acpi_enum =
+					le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
+			info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
+					info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
+			info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
+					info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
+			info->ext_disp_conn_info.path[i].channel_mapping.raw =
+					info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
+		}
+		info->ext_disp_conn_info.checksum =
+				info_v8->sExtDispConnInfo.ucChecksum;
+
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*
+ * get_integrated_info_v8
+ *
+ * @brief
+ * Get V8 integrated BIOS information
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result get_integrated_info_v9(
+	struct bios_parser *bp,
+	struct integrated_info *info)
+{
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
+	uint32_t i;
+
+	info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
+			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
+
+	if (info_v9 != NULL) {
+		info->boot_up_engine_clock =
+				le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
+		info->dentist_vco_freq =
+				le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
+		info->boot_up_uma_clock =
+				le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
+
+		for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->disp_clk_voltage[i].max_supported_clk =
+					le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
+			info->disp_clk_voltage[i].voltage_index =
+					le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
+		}
+
+		info->boot_up_req_display_vector =
+				le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
+		info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
+
+		/*
+		 * system_config: Bit[0] = 0 : PCIE power gating disabled
+		 *                       = 1 : PCIE power gating enabled
+		 *                Bit[1] = 0 : DDR-PLL shut down disabled
+		 *                       = 1 : DDR-PLL shut down enabled
+		 *                Bit[2] = 0 : DDR-PLL power down disabled
+		 *                       = 1 : DDR-PLL power down enabled
+		 */
+		info->system_config = le32_to_cpu(info_v9->ulSystemConfig);
+		info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
+		info->boot_up_nb_voltage =
+				le16_to_cpu(info_v9->usBootUpNBVoltage);
+		info->ext_disp_conn_info_offset =
+				le16_to_cpu(info_v9->usExtDispConnInfoOffset);
+		info->memory_type = info_v9->ucMemoryType;
+		info->ma_channel_number = info_v9->ucUMAChannelNumber;
+		info->gmc_restore_reset_time =
+				le32_to_cpu(info_v9->ulGMCRestoreResetTime);
+
+		info->minimum_n_clk =
+				le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
+		for (i = 1; i < 4; ++i)
+			info->minimum_n_clk =
+					info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
+							info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
+
+		info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
+		info->ddr_dll_power_up_time =
+				le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
+		info->ddr_pll_power_up_time =
+				le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
+		info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
+		info->lvds_ss_percentage =
+				le16_to_cpu(info_v9->usLvdsSSPercentage);
+		info->lvds_sspread_rate_in_10hz =
+				le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
+		info->hdmi_ss_percentage =
+				le16_to_cpu(info_v9->usHDMISSPercentage);
+		info->hdmi_sspread_rate_in_10hz =
+				le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
+		info->dvi_ss_percentage =
+				le16_to_cpu(info_v9->usDVISSPercentage);
+		info->dvi_sspread_rate_in_10_hz =
+				le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
+
+		info->max_lvds_pclk_freq_in_single_link =
+				le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
+		info->lvds_misc = info_v9->ucLvdsMisc;
+		info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
+				info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
+		info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
+				info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
+		info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
+				info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
+		info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
+				info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
+		info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
+				info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
+		info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
+				info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
+		info->lvds_off_to_on_delay_in_4ms =
+				info_v9->ucLVDSOffToOnDelay_in4Ms;
+		info->lvds_bit_depth_control_val =
+				le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
+
+		for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
+			/* Convert [10KHz] into [KHz] */
+			info->avail_s_clk[i].supported_s_clk =
+					le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
+			info->avail_s_clk[i].voltage_index =
+					le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
+			info->avail_s_clk[i].voltage_id =
+					le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
+		}
+
+		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
+			info->ext_disp_conn_info.gu_id[i] =
+					info_v9->sExtDispConnInfo.ucGuid[i];
+		}
+
+		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
+			info->ext_disp_conn_info.path[i].device_connector_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
+
+			info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
+					object_id_from_bios_object_id(
+							le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
+
+			info->ext_disp_conn_info.path[i].device_tag =
+					le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
+			info->ext_disp_conn_info.path[i].device_acpi_enum =
+					le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
+			info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
+					info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
+			info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
+					info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
+			info->ext_disp_conn_info.path[i].channel_mapping.raw =
+					info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
+		}
+		info->ext_disp_conn_info.checksum =
+				info_v9->sExtDispConnInfo.ucChecksum;
+
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*
+ * construct_integrated_info
+ *
+ * @brief
+ * Get integrated BIOS information based on table revision
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result construct_integrated_info(
+	struct bios_parser *bp,
+	struct integrated_info *info)
+{
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+
+	ATOM_COMMON_TABLE_HEADER *header;
+	struct atom_data_revision revision;
+
+	if (info != NULL &&
+			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
+		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
+				bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
+
+		get_atom_data_table_revision(header, &revision);
+
+		/* Don't need to check major revision as they are all 1 */
+		switch (revision.minor) {
+		case 8:
+			result = get_integrated_info_v8(bp, info);
+			break;
+		case 9:
+			result = get_integrated_info_v9(bp, info);
+			break;
+		default:
+			return result;
+
+		}
+	}
+
+	/* Sort voltage table from low to high*/
+	if (result == BP_RESULT_OK) {
+		struct clock_voltage_caps temp = {0, 0};
+		uint32_t i;
+		uint32_t j;
+
+		for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+			for (j = i; j > 0; --j) {
+				if (
+						info->disp_clk_voltage[j].max_supported_clk <
+						info->disp_clk_voltage[j-1].max_supported_clk) {
+					/* swap j and j - 1*/
+					temp = info->disp_clk_voltage[j-1];
+					info->disp_clk_voltage[j-1] =
+							info->disp_clk_voltage[j];
+					info->disp_clk_voltage[j] = temp;
+				}
+			}
+		}
+
+	}
+
+	return result;
+}
+
+
+static struct integrated_info *bios_parser_create_integrated_info(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct integrated_info *info = NULL;
+
+	info = dm_alloc(bp->ctx, sizeof(struct integrated_info));
+
+	if (info == NULL) {
+		ASSERT_CRITICAL(0);
+		return NULL;
+	}
+
+	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
+		return info;
+
+	dm_free(bp->ctx, info);
+
+	return NULL;
+}
+
+static void bios_parser_destroy_integrated_info(
+	struct dc_bios *dcb,
+	struct integrated_info **info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (info == NULL) {
+		ASSERT_CRITICAL(0);
+		return;
+	}
+
+	if (*info != NULL) {
+		dm_free(bp->ctx, *info);
+		*info = NULL;
+	}
+}
+
+/******************************************************************************
+ * Stub-functions */
+static bool is_lid_open(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static bool is_lid_status_changed(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static bool is_display_config_changed(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static void set_scratch_lcd_scale(
+	struct dc_bios *bios,
+	enum lcd_scale scale)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static enum lcd_scale get_scratch_lcd_scale(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return LCD_SCALE_NONE;
+}
+
+static void get_bios_event_info(
+	struct dc_bios *bios,
+	struct bios_event_info *info)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static void update_requested_backlight_level(
+	struct dc_bios *bios,
+	uint32_t backlight_8bit)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static uint32_t get_requested_backlight_level(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return 0;
+}
+
+static void take_backlight_control(
+	struct dc_bios *bios,
+	bool cntl)
+{
+	BREAK_TO_DEBUGGER();
+}
+
+static bool is_active_display(
+	struct dc_bios *bios,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag)
+{
+	BREAK_TO_DEBUGGER();
+	return false;
+}
+
+static enum controller_id get_embedded_display_controller_id(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return CONTROLLER_ID_UNDEFINED;
+}
+
+static uint32_t get_embedded_display_refresh_rate(
+	struct dc_bios *bios)
+{
+	BREAK_TO_DEBUGGER();
+	return 0;
+}
+
+/******************************************************************************/
+
+static const struct dc_vbios_funcs vbios_funcs = {
+	.get_connectors_number = bios_parser_get_connectors_number,
+
+	.power_down = bios_parser_power_down,
+
+	.power_up = bios_parser_power_up,
+
+	.get_encoders_number = bios_parser_get_encoders_number,
+
+	.get_oem_ddc_lines_number = bios_parser_get_oem_ddc_lines_number,
+
+	.get_encoder_id = bios_parser_get_encoder_id,
+
+	.get_connector_id = bios_parser_get_connector_id,
+
+	.get_src_number = bios_parser_get_src_number,
+
+	.get_dst_number = bios_parser_get_dst_number,
+
+	.get_gpio_record = bios_parser_get_gpio_record,
+
+	.get_src_obj = bios_parser_get_src_obj,
+
+	.get_dst_obj = bios_parser_get_dst_obj,
+
+	.get_i2c_info = bios_parser_get_i2c_info,
+
+	.get_oem_ddc_info = bios_parser_get_oem_ddc_info,
+
+	.get_voltage_ddc_info = bios_parser_get_voltage_ddc_info,
+
+	.get_thermal_ddc_info = bios_parser_get_thermal_ddc_info,
+
+	.get_hpd_info = bios_parser_get_hpd_info,
+
+	.get_device_tag = bios_parser_get_device_tag,
+
+	.get_firmware_info = bios_parser_get_firmware_info,
+
+	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
+
+	.get_ss_entry_number = bios_parser_get_ss_entry_number,
+
+	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
+
+	.enum_embedded_panel_patch_mode = bios_parser_enum_embedded_panel_patch_mode,
+
+	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
+
+	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
+
+	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
+
+	.get_faked_edid_len = bios_parser_get_faked_edid_len,
+
+	.get_faked_edid_buf = bios_parser_get_faked_edid_buf,
+
+	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,
+
+	.get_din_connector_info = bios_parser_get_din_connector_info,
+
+	.is_lid_open = is_lid_open,
+
+	.is_lid_status_changed = is_lid_status_changed,
+
+	.is_display_config_changed = is_display_config_changed,
+
+	.is_accelerated_mode = bios_parser_is_accelerated_mode,
+
+	.set_scratch_lcd_scale = set_scratch_lcd_scale,
+
+	.get_scratch_lcd_scale = get_scratch_lcd_scale,
+
+	.get_bios_event_info = get_bios_event_info,
+
+	.update_requested_backlight_level = update_requested_backlight_level,
+
+	.get_requested_backlight_level = get_requested_backlight_level,
+
+	.take_backlight_control = take_backlight_control,
+
+	.is_active_display = is_active_display,
+
+	.get_embedded_display_controller_id = get_embedded_display_controller_id,
+
+	.get_embedded_display_refresh_rate = get_embedded_display_refresh_rate,
+
+	.set_scratch_connected = bios_parser_set_scratch_connected,
+
+	.prepare_scratch_active_and_requested = bios_parser_prepare_scratch_active_and_requested,
+
+	.set_scratch_active_and_requested = bios_parser_set_scratch_active_and_requested,
+
+	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
+
+	.set_scratch_acc_mode_change = bios_parser_set_scratch_acc_mode_change,
+
+	.is_device_id_supported = bios_parser_is_device_id_supported,
+
+	/* COMMANDS */
+	.encoder_control = bios_parser_encoder_control,
+
+	.transmitter_control = bios_parser_transmitter_control,
+
+	.crt_control = bios_parser_crt_control,
+
+	.enable_crtc = bios_parser_enable_crtc,
+
+	.adjust_pixel_clock = bios_parser_adjust_pixel_clock,
+
+	.set_pixel_clock = bios_parser_set_pixel_clock,
+
+	.set_dce_clock = bios_parser_set_dce_clock,
+
+	.enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,
+
+	.program_crtc_timing = bios_parser_program_crtc_timing,
+
+	.blank_crtc = bios_parser_blank_crtc,
+
+	.set_overscan = bios_parser_set_overscan,
+
+	.crtc_source_select = bios_parser_crtc_source_select,
+
+	.program_display_engine_pll = bios_parser_program_display_engine_pll,
+
+	.get_divider_for_target_display_clock = bios_parser_get_divider_for_target_display_clock,
+
+	.dac_load_detect = bios_parser_dac_load_detect,
+
+	.enable_memory_requests = bios_parser_enable_memory_requests,
+
+	.external_encoder_control = bios_parser_external_encoder_control,
+
+	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
+
+	.post_init = bios_parser_post_init,
+
+	.create_integrated_info = bios_parser_create_integrated_info,
+
+	.destroy_integrated_info = bios_parser_destroy_integrated_info,
+};
+
+static bool bios_parser_construct(
+	struct bios_parser *bp,
+	struct bp_init_data *init,
+	struct adapter_service *as)
+{
+	uint16_t *rom_header_offset = NULL;
+	ATOM_ROM_HEADER *rom_header = NULL;
+	ATOM_OBJECT_HEADER *object_info_tbl;
+	enum dce_version dce_version;
+
+	if (!as)
+		return false;
+
+	if (!init)
+		return false;
+
+	if (!init->bios)
+		return false;
+
+	bp->base.funcs = &vbios_funcs;
+
+	dce_version = dal_adapter_service_get_dce_version(as);
+	bp->ctx = init->ctx;
+	bp->as = as;
+	bp->bios = init->bios;
+	bp->bios_size = bp->bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
+	bp->bios_local_image = NULL;
+	bp->lcd_scale = LCD_SCALE_UNKNOWN;
+
+	rom_header_offset =
+	GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
+
+	if (!rom_header_offset)
+		return false;
+
+	rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);
+
+	if (!rom_header)
+		return false;
+
+	bp->master_data_tbl =
+	GET_IMAGE(ATOM_MASTER_DATA_TABLE,
+		rom_header->usMasterDataTableOffset);
+
+	if (!bp->master_data_tbl)
+		return false;
+
+	bp->object_info_tbl_offset = DATA_TABLES(Object_Header);
+
+	if (!bp->object_info_tbl_offset)
+		return false;
+
+	object_info_tbl =
+	GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);
+
+	if (!object_info_tbl)
+		return false;
+
+	get_atom_data_table_revision(&object_info_tbl->sHeader,
+		&bp->object_info_tbl.revision);
+
+	if (bp->object_info_tbl.revision.major == 1
+		&& bp->object_info_tbl.revision.minor >= 3) {
+		ATOM_OBJECT_HEADER_V3 *tbl_v3;
+
+		tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,
+			bp->object_info_tbl_offset);
+		if (!tbl_v3)
+			return false;
+
+		bp->object_info_tbl.v1_3 = tbl_v3;
+	} else if (bp->object_info_tbl.revision.major == 1
+		&& bp->object_info_tbl.revision.minor >= 1)
+		bp->object_info_tbl.v1_1 = object_info_tbl;
+	else
+		return false;
+
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	bp->vbios_helper_data.active = 0;
+	bp->vbios_helper_data.requested = 0;
+	dal_bios_parser_init_bios_helper(bp, dce_version);
+#endif
+	dal_bios_parser_init_cmd_tbl(bp);
+	dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
+
+	return true;
+}
+
+/******************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
new file mode 100644
index 000000000000..f8fa10889fd9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_H__
+#define __DAL_BIOS_PARSER_H__
+
+#include "dc_bios_types.h"
+#include "bios_parser_helper.h"
+
+struct atom_data_revision {
+	uint32_t major;
+	uint32_t minor;
+};
+
+struct object_info_table {
+	struct atom_data_revision revision;
+	union {
+		ATOM_OBJECT_HEADER *v1_1;
+		ATOM_OBJECT_HEADER_V3 *v1_3;
+	};
+};
+
+enum spread_spectrum_id {
+	SS_ID_UNKNOWN = 0,
+	SS_ID_DP1 = 0xf1,
+	SS_ID_DP2 = 0xf2,
+	SS_ID_LVLINK_2700MHZ = 0xf3,
+	SS_ID_LVLINK_1620MHZ = 0xf4
+};
+
+struct bios_parser {
+	struct dc_bios base;
+	struct dc_context *ctx;
+	struct adapter_service *as;
+
+	struct object_info_table object_info_tbl;
+	uint32_t object_info_tbl_offset;
+	ATOM_MASTER_DATA_TABLE *master_data_tbl;
+
+	uint8_t *bios;
+	uint32_t bios_size;
+
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	const struct bios_parser_helper *bios_helper;
+	struct vbios_helper_data vbios_helper_data;
+#endif /* CONFIG_DRM_AMD_DAL_VBIOS_PRESENT */
+
+	const struct command_table_helper *cmd_helper;
+	struct cmd_tbl cmd_tbl;
+
+	uint8_t *bios_local_image;
+	enum lcd_scale lcd_scale;
+
+	bool remap_device_tags;
+	bool headless_no_opm;
+};
+
+/* Bios Parser from DC Bios */
+#define BP_FROM_DCB(dc_bios) \
+	container_of(dc_bios, struct bios_parser, base)
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
new file mode 100644
index 000000000000..0aa227aa557a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "bios_parser_helper.h"
+#include "command_table_helper.h"
+#include "command_table.h"
+#include "bios_parser.h"
+
+bool dal_bios_parser_init_bios_helper(
+	struct bios_parser *bp,
+	enum dce_version version)
+{
+	switch (version) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		bp->bios_helper = dal_bios_parser_helper_dce110_get_table();
+		return true;
+
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		bp->bios_helper = dal_bios_parser_helper_dce110_get_table();
+		return true;
+
+#endif
+	default:
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+bool dal_bios_parser_is_lid_open(
+	struct bios_parser *bp)
+{
+	const struct graphics_object_id encoder = dal_graphics_object_id_init(
+		ENCODER_ID_INTERNAL_UNIPHY,
+		ENUM_ID_UNKNOWN,
+		OBJECT_TYPE_UNKNOWN);
+	const struct graphics_object_id connector = dal_graphics_object_id_init(
+		CONNECTOR_ID_LVDS,
+		ENUM_ID_UNKNOWN,
+		OBJECT_TYPE_UNKNOWN);
+
+	enum signal_type signal;
+
+	/* check if VBIOS reported LCD as connected */
+	signal = bp->bios_helper->detect_sink(bp->ctx,
+		encoder, connector, SIGNAL_TYPE_LVDS);
+
+	if (signal == SIGNAL_TYPE_NONE)
+		return false;
+
+	return bp->bios_helper->is_lid_open(bp->ctx);
+}
+
+bool dal_bios_parser_is_lid_status_changed(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->is_lid_status_changed(
+			bp->ctx);
+}
+
+bool dal_bios_parser_is_display_config_changed(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->is_display_config_changed(
+			bp->ctx);
+}
+
+/**
+* dal_bios_parser_set_scratch_lcd_scale
+*
+* @brief
+*  update VBIOS scratch pad registers about LCD scale
+*
+* @param
+*  bool - to set to full panel mode or aspect-ratio mode
+*/
+void dal_bios_parser_set_scratch_lcd_scale(
+	struct bios_parser *bp,
+	enum lcd_scale scale)
+{
+	bp->bios_helper->set_scratch_lcd_scale(
+		bp->ctx, scale);
+}
+
+/**
+* dal_bios_parser_get_scratch_lcd_scale
+*
+* @brief
+*  get LCD Scale Mode from VBIOS scratch register
+*
+* @param
+*  NONE
+*/
+enum lcd_scale  dal_bios_parser_get_scratch_lcd_scale(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_scratch_lcd_scale(
+			bp->ctx);
+}
+
+void dal_bios_parser_get_bios_event_info(
+	struct bios_parser *bp,
+	struct bios_event_info *info)
+{
+	bp->bios_helper->get_bios_event_info(
+		bp->ctx, info);
+}
+
+/* ABM related */
+
+void dal_bios_parser_update_requested_backlight_level(
+	struct bios_parser *bp,
+	uint32_t backlight_8bit)
+{
+	bp->bios_helper->update_requested_backlight_level(
+		bp->ctx,
+		backlight_8bit);
+}
+
+uint32_t dal_bios_parser_get_requested_backlight_level(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_requested_backlight_level(
+			bp->ctx);
+}
+
+void dal_bios_parser_take_backlight_control(
+	struct bios_parser *bp,
+	bool cntl)
+{
+	bp->bios_helper->take_backlight_control(
+		bp->ctx, cntl);
+}
+
+/**
+ * dal_bios_parser_is_active_display
+ *  Check video bios active display.
+ */
+bool dal_bios_parser_is_active_display(
+	struct bios_parser *bp,
+	enum signal_type signal,
+	const struct connector_device_tag_info *device_tag)
+{
+	return bp->bios_helper->is_active_display(
+			bp->ctx, signal, device_tag);
+}
+
+/**
+ * dal_bios_parser_get_embedded_display_controller_id
+ * Get controller ID for embedded display from scratch registers
+ */
+enum controller_id dal_bios_parser_get_embedded_display_controller_id(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_embedded_display_controller_id(
+			bp->ctx);
+}
+
+/**
+ * dal_bios_parser_get_embedded_display_refresh_rate
+ * Get refresh rate for embedded display from scratch registers
+ */
+uint32_t dal_bios_parser_get_embedded_display_refresh_rate(
+	struct bios_parser *bp)
+{
+	return bp->bios_helper->get_embedded_display_refresh_rate(
+			bp->ctx);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
new file mode 100644
index 000000000000..1ad745561d15
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/bios_parser_helper.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_HELPER_H__
+#define __DAL_BIOS_PARSER_HELPER_H__
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce110/bios_parser_helper_dce110.h"
+#endif
+
+struct bios_parser;
+
+struct vbios_helper_data {
+	uint32_t active;
+	uint32_t requested;
+};
+
+struct bios_parser_helper {
+	enum signal_type (*detect_sink)(
+		struct dc_context *ctx,
+		struct graphics_object_id encoder,
+		struct graphics_object_id connector,
+		enum signal_type signal);
+	bool (*is_lid_open)(
+		struct dc_context *ctx);
+	bool (*is_lid_status_changed)(
+		struct dc_context *ctx);
+	bool (*is_display_config_changed)(
+		struct dc_context *ctx);
+	void (*set_scratch_acc_mode_change)(
+		struct dc_context *ctx);
+	bool (*is_accelerated_mode)(
+		struct dc_context *ctx);
+	void (*set_scratch_critical_state)(
+		struct dc_context *ctx,
+		bool state);
+	void (*prepare_scratch_active_and_requested)(
+		struct dc_context *ctx,
+		struct vbios_helper_data *data,
+		enum controller_id id, enum signal_type s,
+		const struct connector_device_tag_info *dev_tag);
+	void (*set_scratch_active_and_requested)(
+		struct dc_context *ctx,
+		struct vbios_helper_data *d);
+	void (*set_scratch_connected)(
+		struct dc_context *ctx,
+		struct graphics_object_id id,
+		bool connected,
+		const struct connector_device_tag_info *device_tag);
+	void (*set_scratch_lcd_scale)(
+		struct dc_context *ctx,
+		enum lcd_scale lcd_scale_request);
+	enum lcd_scale (*get_scratch_lcd_scale)(
+		struct dc_context *ctx);
+	uint32_t (*fmt_control)(
+		struct dc_context *ctx,
+		enum controller_id id, uint32_t *value);
+	uint32_t (*fmt_bit_depth_control)(
+		struct dc_context *ctx,
+		enum controller_id id,
+		uint32_t *value);
+	void (*get_bios_event_info)(
+		struct dc_context *ctx,
+		struct bios_event_info *info);
+	void (*take_backlight_control)(
+		struct dc_context *ctx, bool control);
+	uint32_t (*get_requested_backlight_level)(
+		struct dc_context *ctx);
+	void (*update_requested_backlight_level)(
+		struct dc_context *ctx,
+		uint32_t backlight_8bit);
+	bool (*is_active_display)(
+		struct dc_context *ctx,
+		enum signal_type signal,
+		const struct connector_device_tag_info *dev_tag);
+	enum controller_id (*get_embedded_display_controller_id)(
+		struct dc_context *ctx);
+	uint32_t (*get_embedded_display_refresh_rate)(
+		struct dc_context *ctx);
+};
+
+bool dal_bios_parser_init_bios_helper(
+	struct bios_parser *bp,
+	enum dce_version ver);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c
new file mode 100644
index 000000000000..3bc52f5bab24
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table.c
@@ -0,0 +1,2730 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_interface.h"
+
+#include "command_table.h"
+#include "command_table_helper.h"
+#include "bios_parser_helper.h"
+#include "bios_parser.h"
+
+#define EXEC_BIOS_CMD_TABLE(command, params)\
+	(cgs_atom_exec_cmd_table(bp->ctx->cgs_device, \
+		GetIndexIntoMasterTable(COMMAND, command), \
+		&params) == 0)
+
+#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
+	cgs_atom_get_cmd_table_revs(bp->ctx->cgs_device, \
+		GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
+
+#define BIOS_CMD_TABLE_PARA_REVISION(command)\
+	dm_bios_cmd_table_para_revision(bp->ctx, \
+		GetIndexIntoMasterTable(COMMAND, command))
+
+
+static void init_dig_encoder_control(struct bios_parser *bp);
+static void init_transmitter_control(struct bios_parser *bp);
+static void init_set_pixel_clock(struct bios_parser *bp);
+static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);
+static void init_adjust_display_pll(struct bios_parser *bp);
+static void init_dac_encoder_control(struct bios_parser *bp);
+static void init_dac_output_control(struct bios_parser *bp);
+static void init_dac_load_detection(struct bios_parser *bp);
+static void init_blank_crtc(struct bios_parser *bp);
+static void init_set_crtc_timing(struct bios_parser *bp);
+static void init_set_crtc_overscan(struct bios_parser *bp);
+static void init_select_crtc_source(struct bios_parser *bp);
+static void init_enable_crtc(struct bios_parser *bp);
+static void init_enable_crtc_mem_req(struct bios_parser *bp);
+static void init_compute_memore_engine_pll(struct bios_parser *bp);
+static void init_external_encoder_control(struct bios_parser *bp);
+static void init_enable_disp_power_gating(struct bios_parser *bp);
+static void init_program_clock(struct bios_parser *bp);
+static void init_set_dce_clock(struct bios_parser *bp);
+
+void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
+{
+	init_dig_encoder_control(bp);
+	init_transmitter_control(bp);
+	init_set_pixel_clock(bp);
+	init_enable_spread_spectrum_on_ppll(bp);
+	init_adjust_display_pll(bp);
+	init_dac_encoder_control(bp);
+	init_dac_output_control(bp);
+	init_dac_load_detection(bp);
+	init_blank_crtc(bp);
+	init_set_crtc_timing(bp);
+	init_set_crtc_overscan(bp);
+	init_select_crtc_source(bp);
+	init_enable_crtc(bp);
+	init_enable_crtc_mem_req(bp);
+	init_program_clock(bp);
+	init_compute_memore_engine_pll(bp);
+	init_external_encoder_control(bp);
+	init_enable_disp_power_gating(bp);
+	init_set_dce_clock(bp);
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  D I G E N C O D E R C O N T R O L
+ **
+ ********************************************************************************
+ *******************************************************************************/
+static enum bp_result encoder_control_digx_v3(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+
+static enum bp_result encoder_control_digx_v4(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+static void init_encoder_control_dig_v1(struct bios_parser *bp);
+
+static void init_dig_encoder_control(struct bios_parser *bp)
+{
+	uint32_t version =
+		BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl);
+
+	switch (version) {
+	case 4:
+		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;
+		break;
+	case 2:
+		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;
+		break;
+	default:
+		init_encoder_control_dig_v1(bp);
+		break;
+	}
+}
+
+static enum bp_result encoder_control_dig_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+static enum bp_result encoder_control_dig1_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+static enum bp_result encoder_control_dig2_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl);
+
+static void init_encoder_control_dig_v1(struct bios_parser *bp)
+{
+	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
+
+	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))
+		cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;
+	else
+		cmd_tbl->encoder_control_dig1 = NULL;
+
+	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))
+		cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;
+	else
+		cmd_tbl->encoder_control_dig2 = NULL;
+
+	cmd_tbl->dig_encoder_control = encoder_control_dig_v1;
+}
+
+static enum bp_result encoder_control_dig_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
+
+	if (cntl != NULL)
+		switch (cntl->engine_id) {
+		case ENGINE_ID_DIGA:
+			if (cmd_tbl->encoder_control_dig1 != NULL)
+				result =
+					cmd_tbl->encoder_control_dig1(bp, cntl);
+			break;
+		case ENGINE_ID_DIGB:
+			if (cmd_tbl->encoder_control_dig2 != NULL)
+				result =
+					cmd_tbl->encoder_control_dig2(bp, cntl);
+			break;
+
+		default:
+			break;
+		}
+
+	return result;
+}
+
+static enum bp_result encoder_control_dig1_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
+
+	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
+
+	if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result encoder_control_dig2_v1(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
+
+	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
+
+	if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result encoder_control_digx_v3(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0};
+
+	if (LANE_COUNT_FOUR < cntl->lanes_number)
+		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
+	else
+		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
+
+	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
+	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+	params.ucEncoderMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					cntl->signal,
+					cntl->enable_dp_audio);
+	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+
+	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+
+	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result encoder_control_digx_v4(
+	struct bios_parser *bp,
+	struct bp_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};
+
+	if (LANE_COUNT_FOUR < cntl->lanes_number)
+		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
+	else
+		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
+
+
+	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
+	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+	params.ucEncoderMode =
+			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
+					cntl->signal,
+					cntl->enable_dp_audio));
+	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+
+	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.usPixelClock =
+				cpu_to_le16((le32_to_cpu(params.usPixelClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+
+	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  TRANSMITTER CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result transmitter_control_v2(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v3(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v4(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v1_5(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+static enum bp_result transmitter_control_v1_6(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl);
+
+static void init_transmitter_control(struct bios_parser *bp)
+{
+	uint8_t frev;
+	uint8_t crev;
+
+	if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
+			frev, crev) != 0)
+		BREAK_TO_DEBUGGER();
+	switch (crev) {
+	case 2:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v3;
+		break;
+	case 4:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v4;
+		break;
+	case 5:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;
+		break;
+	case 6:
+		bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
+		break;
+	default:
+		bp->cmd_tbl.transmitter_control = NULL;
+		break;
+	}
+}
+
+static enum bp_result transmitter_control_v2(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;
+	enum connector_id connector_id =
+		dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (cntl->transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+	case TRANSMITTER_TRAVIS_LCD:
+		break;
+	default:
+		return BP_RESULT_BADINPUT;
+	}
+
+	switch (cntl->action) {
+	case TRANSMITTER_CONTROL_INIT:
+		if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||
+				(CONNECTOR_ID_DUAL_LINK_DVID == connector_id))
+			/* on INIT this bit should be set according to the
+			 * phisycal connector
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* connector object id */
+		params.usInitInfo =
+				cpu_to_le16((uint8_t)cntl->connector_obj_id.id);
+		break;
+	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
+		/* votage swing and pre-emphsis */
+		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
+		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
+		break;
+	default:
+		/* if dual-link */
+		if (LANE_COUNT_FOUR < cntl->lanes_number) {
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 20KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
+		} else
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 10KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+		break;
+	}
+
+	/* 00 - coherent mode
+	 * 01 - incoherent mode
+	 */
+
+	params.acConfig.fCoherentMode = cntl->coherent;
+
+	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
+			|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
+			|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
+		/* Bit2: Transmitter Link selection
+		 * =0 when bit0=0, single link A/C/E, when bit0=1,
+		 * master link A/C/E
+		 * =1 when bit0=0, single link B/D/F, when bit0=1,
+		 * master link B/D/F
+		 */
+		params.acConfig.ucLinkSel = 1;
+
+	if (ENGINE_ID_DIGB == cntl->engine_id)
+		/* Bit3: Transmitter data source selection
+		 * =0 DIGA is data source.
+		 * =1 DIGB is data source.
+		 * This bit is only useful when ucAction= ATOM_ENABLE
+		 */
+		params.acConfig.ucEncoderSel = 1;
+
+	if (CONNECTOR_ID_DISPLAY_PORT == connector_id)
+		/* Bit4: DP connector flag
+		 * =0 connector is none-DP connector
+		 * =1 connector is DP connector
+		 */
+		params.acConfig.fDPConnector = 1;
+
+	/* Bit[7:6]: Transmitter selection
+	 * =0 UNIPHY_ENCODER: UNIPHYA/B
+	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
+	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
+	 * =3 reserved
+	 */
+	params.acConfig.ucTransmitterSel =
+			(uint8_t)bp->cmd_helper->transmitter_bp_to_atom(
+					cntl->transmitter);
+
+	params.ucAction = (uint8_t)cntl->action;
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v3(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;
+	uint32_t pll_id;
+	enum connector_id conn_id =
+			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
+	const struct command_table_helper *cmd = bp->cmd_helper;
+	bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id)
+					|| (CONNECTOR_ID_DUAL_LINK_DVID == conn_id);
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (cntl->transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+	case TRANSMITTER_TRAVIS_LCD:
+		break;
+	default:
+		return BP_RESULT_BADINPUT;
+	}
+
+	if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))
+		return BP_RESULT_BADINPUT;
+
+	/* fill information based on the action */
+	switch (cntl->action) {
+	case TRANSMITTER_CONTROL_INIT:
+		if (dual_link_conn) {
+			/* on INIT this bit should be set according to the
+			 * phisycal connector
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+		}
+
+		/* connector object id */
+		params.usInitInfo =
+				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
+		break;
+	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
+		/* votage swing and pre-emphsis */
+		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
+		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
+		break;
+	default:
+		if (dual_link_conn && cntl->multi_path)
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* if dual-link */
+		if (LANE_COUNT_FOUR < cntl->lanes_number) {
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 20KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
+		} else {
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 10KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+			if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+				switch (cntl->color_depth) {
+				case COLOR_DEPTH_101010:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 30) / 24);
+					break;
+				case COLOR_DEPTH_121212:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 36) / 24);
+					break;
+				case COLOR_DEPTH_161616:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 48) / 24);
+					break;
+				default:
+					break;
+				}
+		}
+		break;
+	}
+
+	/* 00 - coherent mode
+	 * 01 - incoherent mode
+	 */
+
+	params.acConfig.fCoherentMode = cntl->coherent;
+
+	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
+		/* Bit2: Transmitter Link selection
+		 * =0 when bit0=0, single link A/C/E, when bit0=1,
+		 * master link A/C/E
+		 * =1 when bit0=0, single link B/D/F, when bit0=1,
+		 * master link B/D/F
+		 */
+		params.acConfig.ucLinkSel = 1;
+
+	if (ENGINE_ID_DIGB == cntl->engine_id)
+		/* Bit3: Transmitter data source selection
+		 * =0 DIGA is data source.
+		 * =1 DIGB is data source.
+		 * This bit is only useful when ucAction= ATOM_ENABLE
+		 */
+		params.acConfig.ucEncoderSel = 1;
+
+	/* Bit[7:6]: Transmitter selection
+	 * =0 UNIPHY_ENCODER: UNIPHYA/B
+	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
+	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
+	 * =3 reserved
+	 */
+	params.acConfig.ucTransmitterSel =
+			(uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);
+
+	params.ucLaneNum = (uint8_t)cntl->lanes_number;
+
+	params.acConfig.ucRefClkSource = (uint8_t)pll_id;
+
+	params.ucAction = (uint8_t)cntl->action;
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v4(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params;
+	uint32_t ref_clk_src_id;
+	enum connector_id conn_id =
+			dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
+	const struct command_table_helper *cmd = bp->cmd_helper;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (cntl->transmitter) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+	case TRANSMITTER_TRAVIS_LCD:
+		break;
+	default:
+		return BP_RESULT_BADINPUT;
+	}
+
+	if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))
+		return BP_RESULT_BADINPUT;
+
+	switch (cntl->action) {
+	case TRANSMITTER_CONTROL_INIT:
+	{
+		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
+				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
+			/* on INIT this bit should be set according to the
+			 * phisycal connector
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* connector object id */
+		params.usInitInfo =
+				cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
+	}
+	break;
+	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
+		/* votage swing and pre-emphsis */
+		params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select);
+		params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings);
+		break;
+	default:
+		if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
+				(CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
+			/* on ENABLE/DISABLE this bit should be set according to
+			 * actual timing (number of lanes)
+			 * Bit0: dual link connector flag
+			 * =0 connector is single link connector
+			 * =1 connector is dual link connector
+			 */
+			params.acConfig.fDualLinkConnector = 1;
+
+		/* if dual-link */
+		if (LANE_COUNT_FOUR < cntl->lanes_number)
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 20KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
+		else {
+			/* link rate, half for dual link
+			 * We need to convert from KHz units into 10KHz units
+			 */
+			params.usPixelClock =
+					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+
+			if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+				switch (cntl->color_depth) {
+				case COLOR_DEPTH_101010:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 30) / 24);
+					break;
+				case COLOR_DEPTH_121212:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 36) / 24);
+					break;
+				case COLOR_DEPTH_161616:
+					params.usPixelClock =
+							cpu_to_le16((le16_to_cpu(params.usPixelClock) * 48) / 24);
+					break;
+				default:
+					break;
+				}
+		}
+		break;
+	}
+
+	/* 00 - coherent mode
+	 * 01 - incoherent mode
+	 */
+
+	params.acConfig.fCoherentMode = cntl->coherent;
+
+	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)
+		|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))
+		/* Bit2: Transmitter Link selection
+		 * =0 when bit0=0, single link A/C/E, when bit0=1,
+		 * master link A/C/E
+		 * =1 when bit0=0, single link B/D/F, when bit0=1,
+		 * master link B/D/F
+		 */
+		params.acConfig.ucLinkSel = 1;
+
+	if (ENGINE_ID_DIGB == cntl->engine_id)
+		/* Bit3: Transmitter data source selection
+		 * =0 DIGA is data source.
+		 * =1 DIGB is data source.
+		 * This bit is only useful when ucAction= ATOM_ENABLE
+		 */
+		params.acConfig.ucEncoderSel = 1;
+
+	/* Bit[7:6]: Transmitter selection
+	 * =0 UNIPHY_ENCODER: UNIPHYA/B
+	 * =1 UNIPHY1_ENCODER: UNIPHYC/D
+	 * =2 UNIPHY2_ENCODER: UNIPHYE/F
+	 * =3 reserved
+	 */
+	params.acConfig.ucTransmitterSel =
+		(uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter));
+	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
+	params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id);
+	params.ucAction = (uint8_t)(cntl->action);
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v1_5(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	const struct command_table_helper *cmd = bp->cmd_helper;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params;
+
+	dm_memset(&params, 0, sizeof(params));
+	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
+	params.ucAction = (uint8_t)cntl->action;
+	params.ucLaneNum = (uint8_t)cntl->lanes_number;
+	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
+
+	params.ucDigMode =
+		cmd->signal_type_to_atom_dig_mode(cntl->signal);
+	params.asConfig.ucPhyClkSrcId =
+		cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id);
+	/* 00 - coherent mode */
+	params.asConfig.ucCoherentMode = cntl->coherent;
+	params.asConfig.ucHPDSel =
+		cmd->hpd_sel_to_atom(cntl->hpd_sel);
+	params.ucDigEncoderSel =
+		cmd->dig_encoder_sel_to_atom(cntl->engine_id);
+	params.ucDPLaneSet = (uint8_t) cntl->lane_settings;
+	params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10));
+	/*
+	 * In SI/TN case, caller have to set usPixelClock as following:
+	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
+	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
+	 * DVI single link mode: usPixelClock = pixel clock
+	 * DVI dual link mode: usPixelClock = pixel clock
+	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
+	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
+	 * LVDS mode: usPixelClock = pixel clock
+	 */
+	switch (cntl->signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.usSymClock =
+				cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.usSymClock =
+				cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.usSymClock =
+				cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result transmitter_control_v1_6(
+	struct bios_parser *bp,
+	struct bp_transmitter_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+	const struct command_table_helper *cmd = bp->cmd_helper;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
+
+	dm_memset(&params, 0, sizeof(params));
+	params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
+	params.ucAction = (uint8_t)cntl->action;
+
+	if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
+		params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
+	else
+		params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
+
+	params.ucLaneNum = (uint8_t)cntl->lanes_number;
+	params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
+	params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
+	params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
+	params.ulSymClock = cntl->pixel_clock/10;
+
+	/*
+	 * In SI/TN case, caller have to set usPixelClock as following:
+	 * DP mode: usPixelClock = DP_LINK_CLOCK/10
+	 * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
+	 * DVI single link mode: usPixelClock = pixel clock
+	 * DVI dual link mode: usPixelClock = pixel clock
+	 * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
+	 * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
+	 * LVDS mode: usPixelClock = pixel clock
+	 */
+	switch (cntl->signal) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		switch (cntl->color_depth) {
+		case COLOR_DEPTH_101010:
+			params.ulSymClock =
+				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
+			break;
+		case COLOR_DEPTH_121212:
+			params.ulSymClock =
+				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
+			break;
+		case COLOR_DEPTH_161616:
+			params.ulSymClock =
+				cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
+			break;
+		default:
+			break;
+		}
+		break;
+		default:
+			break;
+	}
+
+	if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
+		result = BP_RESULT_OK;
+#endif
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET PIXEL CLOCK
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result set_pixel_clock_v3(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result set_pixel_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result set_pixel_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result set_pixel_clock_v7(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+
+static void init_set_pixel_clock(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
+	case 3:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
+		break;
+	case 5:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
+		break;
+	case 6:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
+		break;
+	case 7:
+		bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
+		break;
+	default:
+		bp->cmd_tbl.set_pixel_clock = NULL;
+		break;
+	}
+}
+
+static enum bp_result set_pixel_clock_v3(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	PIXEL_CLOCK_PARAMETERS_V3 *params;
+	SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
+
+	dm_memset(&allocation, 0, sizeof(allocation));
+
+	if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
+		allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
+	else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
+		allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
+	else
+		return BP_RESULT_BADINPUT;
+
+	allocation.sPCLKInput.usRefDiv =
+			cpu_to_le16((uint16_t)bp_params->reference_divider);
+	allocation.sPCLKInput.usFbDiv =
+			cpu_to_le16((uint16_t)bp_params->feedback_divider);
+	allocation.sPCLKInput.ucFracFbDiv =
+			(uint8_t)bp_params->fractional_feedback_divider;
+	allocation.sPCLKInput.ucPostDiv =
+			(uint8_t)bp_params->pixel_clock_post_divider;
+
+	/* We need to convert from KHz units into 10KHz units */
+	allocation.sPCLKInput.usPixelClock =
+			cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
+
+	params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
+	params->ucTransmitterId =
+			bp->cmd_helper->encoder_id_to_atom(
+					dal_graphics_object_id_get_encoder_id(
+							bp_params->encoder_object_id));
+	params->ucEncoderMode =
+			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
+					bp_params->signal_type, false));
+
+	if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+		params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
+
+	if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
+		params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
+
+	if (CONTROLLER_ID_D1 != bp_params->controller_id)
+		params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
+
+	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
+/* video bios did not define this: */
+typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
+	PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
+	/* Caller doesn't need to init this portion */
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
+} SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
+#endif
+
+#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
+/* video bios did not define this: */
+typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
+	PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
+	/* Caller doesn't need to init this portion */
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
+} SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
+#endif
+
+static enum bp_result set_pixel_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
+	uint8_t controller_id;
+	uint32_t pll_id;
+
+	dm_memset(&clk, 0, sizeof(clk));
+
+	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+			&& bp->cmd_helper->controller_id_to_atom(
+					bp_params->controller_id, &controller_id)) {
+		clk.sPCLKInput.ucCRTC = controller_id;
+		clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
+		clk.sPCLKInput.ucRefDiv =
+				(uint8_t)(bp_params->reference_divider);
+		clk.sPCLKInput.usFbDiv =
+				cpu_to_le16((uint16_t)(bp_params->feedback_divider));
+		clk.sPCLKInput.ulFbDivDecFrac =
+				cpu_to_le32(bp_params->fractional_feedback_divider);
+		clk.sPCLKInput.ucPostDiv =
+				(uint8_t)(bp_params->pixel_clock_post_divider);
+		clk.sPCLKInput.ucTransmitterID =
+				bp->cmd_helper->encoder_id_to_atom(
+						dal_graphics_object_id_get_encoder_id(
+								bp_params->encoder_object_id));
+		clk.sPCLKInput.ucEncoderMode =
+				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+						bp_params->signal_type, false);
+
+		/* We need to convert from KHz units into 10KHz units */
+		clk.sPCLKInput.usPixelClock =
+				cpu_to_le16((uint16_t)(bp_params->target_pixel_clock / 10));
+
+		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
+
+		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_MISC_REF_DIV_SRC;
+
+		/* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
+		 * =1:30bpp, =2:32bpp
+		 * driver choose program it itself, i.e. here we program it
+		 * to 888 by default.
+		 */
+
+		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
+			result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+static enum bp_result set_pixel_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
+	uint8_t controller_id;
+	uint32_t pll_id;
+
+	dm_memset(&clk, 0, sizeof(clk));
+
+	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+			&& bp->cmd_helper->controller_id_to_atom(
+					bp_params->controller_id, &controller_id)) {
+		/* Note: VBIOS still wants to use ucCRTC name which is now
+		 * 1 byte in ULONG
+		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
+		 *{
+		 * target the pixel clock to drive the CRTC timing.
+		 * ULONG ulPixelClock:24;
+		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
+		 * previous version.
+		 * ATOM_CRTC1~6, indicate the CRTC controller to
+		 * ULONG ucCRTC:8;
+		 * drive the pixel clock. not used for DCPLL case.
+		 *}CRTC_PIXEL_CLOCK_FREQ;
+		 *union
+		 *{
+		 * pixel clock and CRTC id frequency
+		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
+		 * ULONG ulDispEngClkFreq; dispclk frequency
+		 *};
+		 */
+		clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
+		clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
+		clk.sPCLKInput.ucRefDiv =
+				(uint8_t) bp_params->reference_divider;
+		clk.sPCLKInput.usFbDiv =
+				cpu_to_le16((uint16_t) bp_params->feedback_divider);
+		clk.sPCLKInput.ulFbDivDecFrac =
+				cpu_to_le32(bp_params->fractional_feedback_divider);
+		clk.sPCLKInput.ucPostDiv =
+				(uint8_t) bp_params->pixel_clock_post_divider;
+		clk.sPCLKInput.ucTransmitterID =
+				bp->cmd_helper->encoder_id_to_atom(
+						dal_graphics_object_id_get_encoder_id(
+								bp_params->encoder_object_id));
+		clk.sPCLKInput.ucEncoderMode =
+				(uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
+						bp_params->signal_type, false);
+
+		/* We need to convert from KHz units into 10KHz units */
+		clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
+				cpu_to_le32(bp_params->target_pixel_clock / 10);
+
+		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
+		}
+
+		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
+			clk.sPCLKInput.ucMiscInfo |=
+					PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
+		}
+
+		/* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
+		 * 24bpp =1:30bpp, =2:32bpp
+		 * driver choose program it itself, i.e. here we pass required
+		 * target rate that includes deep color.
+		 */
+
+		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
+			result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+static enum bp_result set_pixel_clock_v7(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+	PIXEL_CLOCK_PARAMETERS_V7 clk;
+	uint8_t controller_id;
+	uint32_t pll_id;
+
+	dm_memset(&clk, 0, sizeof(clk));
+
+	if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+			&& bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
+		/* Note: VBIOS still wants to use ucCRTC name which is now
+		 * 1 byte in ULONG
+		 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
+		 *{
+		 * target the pixel clock to drive the CRTC timing.
+		 * ULONG ulPixelClock:24;
+		 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
+		 * previous version.
+		 * ATOM_CRTC1~6, indicate the CRTC controller to
+		 * ULONG ucCRTC:8;
+		 * drive the pixel clock. not used for DCPLL case.
+		 *}CRTC_PIXEL_CLOCK_FREQ;
+		 *union
+		 *{
+		 * pixel clock and CRTC id frequency
+		 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
+		 * ULONG ulDispEngClkFreq; dispclk frequency
+		 *};
+		 */
+		clk.ucCRTC = controller_id;
+		clk.ucPpll = (uint8_t) pll_id;
+		clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
+		clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
+
+		/* We need to convert from KHz units into 10KHz units */
+		clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock * 10);
+
+		clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
+
+		if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
+
+		if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
+
+		if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
+
+		if (bp_params->flags.SUPPORT_YUV_420)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
+
+		if (bp_params->flags.SET_XTALIN_REF_SRC)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
+
+		if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
+
+		if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
+			clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
+
+		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
+			result = BP_RESULT_OK;
+	}
+#endif
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE PIXEL CLOCK SS
+ **
+ ********************************************************************************
+ *******************************************************************************/
+static enum bp_result enable_spread_spectrum_on_ppll_v1(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable);
+static enum bp_result enable_spread_spectrum_on_ppll_v2(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable);
+static enum bp_result enable_spread_spectrum_on_ppll_v3(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable);
+
+static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
+	case 1:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
+				enable_spread_spectrum_on_ppll_v1;
+		break;
+	case 2:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
+				enable_spread_spectrum_on_ppll_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll =
+				enable_spread_spectrum_on_ppll_v3;
+		break;
+	default:
+		bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_spread_spectrum_on_ppll_v1(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if ((enable == true) && (bp_params->percentage > 0))
+		params.ucEnable = ATOM_ENABLE;
+	else
+		params.ucEnable = ATOM_DISABLE;
+
+	params.usSpreadSpectrumPercentage =
+			cpu_to_le16((uint16_t)bp_params->percentage);
+	params.ucSpreadSpectrumStep =
+			(uint8_t)bp_params->ver1.step;
+	params.ucSpreadSpectrumDelay =
+			(uint8_t)bp_params->ver1.delay;
+	/* convert back to unit of 10KHz */
+	params.ucSpreadSpectrumRange =
+			(uint8_t)(bp_params->ver1.range / 10000);
+
+	if (bp_params->flags.EXTERNAL_SS)
+		params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
+
+	if (bp_params->flags.CENTER_SPREAD)
+		params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
+
+	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
+		params.ucPpll = ATOM_PPLL1;
+	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
+		params.ucPpll = ATOM_PPLL2;
+	else
+		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
+
+	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result enable_spread_spectrum_on_ppll_v2(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
+	else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
+	else
+		BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
+
+	if ((enable == true) && (bp_params->percentage > 0)) {
+		params.ucEnable = ATOM_ENABLE;
+
+		params.usSpreadSpectrumPercentage =
+				cpu_to_le16((uint16_t)(bp_params->percentage));
+		params.usSpreadSpectrumStep =
+				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
+
+		if (bp_params->flags.EXTERNAL_SS)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
+
+		if (bp_params->flags.CENTER_SPREAD)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
+
+		/* Both amounts need to be left shifted first before bit
+		 * comparison. Otherwise, the result will always be zero here
+		 */
+		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
+				((bp_params->ds.feedback_amount <<
+						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
+						ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
+						((bp_params->ds.nfrac_amount <<
+								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
+								ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
+	} else
+		params.ucEnable = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result enable_spread_spectrum_on_ppll_v3(
+	struct bios_parser *bp,
+	struct bp_spread_spectrum_parameters *bp_params,
+	bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	switch (bp_params->pll_id) {
+	case CLOCK_SOURCE_ID_PLL0:
+		/* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
+		 * not for SI display clock.
+		 */
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
+		break;
+	case CLOCK_SOURCE_ID_PLL1:
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
+		break;
+
+	case CLOCK_SOURCE_ID_PLL2:
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
+		break;
+
+	case CLOCK_SOURCE_ID_DCPLL:
+		params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
+		break;
+
+	default:
+		BREAK_TO_DEBUGGER();
+		/* Unexpected PLL value!! */
+		return result;
+	}
+
+	if (enable == true) {
+		params.ucEnable = ATOM_ENABLE;
+
+		params.usSpreadSpectrumAmountFrac =
+				cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
+		params.usSpreadSpectrumStep =
+				cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
+
+		if (bp_params->flags.EXTERNAL_SS)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
+		if (bp_params->flags.CENTER_SPREAD)
+			params.ucSpreadSpectrumType |=
+					ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
+
+		/* Both amounts need to be left shifted first before bit
+		 * comparison. Otherwise, the result will always be zero here
+		 */
+		params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
+				((bp_params->ds.feedback_amount <<
+						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
+						ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
+						((bp_params->ds.nfrac_amount <<
+								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
+								ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
+	} else
+		params.ucEnable = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ADJUST DISPLAY PLL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result adjust_display_pll_v2(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params);
+static enum bp_result adjust_display_pll_v3(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params);
+
+static void init_adjust_display_pll(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
+	case 2:
+		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
+		break;
+	default:
+		bp->cmd_tbl.adjust_display_pll = NULL;
+		break;
+	}
+}
+
+static enum bp_result adjust_display_pll_v2(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
+
+	/* We need to convert from KHz units into 10KHz units and then convert
+	 * output pixel clock back 10KHz-->KHz */
+	uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
+
+	params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
+	params.ucTransmitterID =
+			bp->cmd_helper->encoder_id_to_atom(
+					dal_graphics_object_id_get_encoder_id(
+							bp_params->encoder_object_id));
+	params.ucEncodeMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					bp_params->signal_type, false);
+	return result;
+}
+
+static enum bp_result adjust_display_pll_v3(
+	struct bios_parser *bp,
+	struct bp_adjust_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
+	uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	/* We need to convert from KHz units into 10KHz units and then convert
+	 * output pixel clock back 10KHz-->KHz */
+	params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
+	params.sInput.ucTransmitterID =
+			bp->cmd_helper->encoder_id_to_atom(
+					dal_graphics_object_id_get_encoder_id(
+							bp_params->encoder_object_id));
+	params.sInput.ucEncodeMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					bp_params->signal_type, false);
+
+	if (bp_params->ss_enable == true)
+		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
+
+	if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
+		params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
+
+	if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
+		/* Convert output pixel clock back 10KHz-->KHz: multiply
+		 * original pixel clock in KHz by ratio
+		 * [output pxlClk/input pxlClk] */
+		uint64_t pixel_clk_10_khz_out =
+				(uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
+		uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
+
+		if (pixel_clk_10_kHz_in != 0) {
+			bp_params->adjusted_pixel_clock =
+					div_u64(pixel_clk * pixel_clk_10_khz_out,
+							pixel_clk_10_kHz_in);
+		} else {
+			bp_params->adjusted_pixel_clock = 0;
+			BREAK_TO_DEBUGGER();
+		}
+
+		bp_params->reference_divider = params.sOutput.ucRefDiv;
+		bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
+
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC ENCODER CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result dac1_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard);
+static enum bp_result dac2_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard);
+
+static void init_dac_encoder_control(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
+	case 1:
+		bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac1_encoder_control = NULL;
+		break;
+	}
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
+	case 1:
+		bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac2_encoder_control = NULL;
+		break;
+	}
+}
+
+static void dac_encoder_control_prepare_params(
+	DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard)
+{
+	params->ucDacStandard = dac_standard;
+	if (enable)
+		params->ucAction = ATOM_ENABLE;
+	else
+		params->ucAction = ATOM_DISABLE;
+
+	/* We need to convert from KHz units into 10KHz units
+	 * it looks as if the TvControl do not care about pixel clock
+	 */
+	params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
+}
+
+static enum bp_result dac1_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
+
+	dac_encoder_control_prepare_params(
+		&params,
+		enable,
+		pixel_clock,
+		dac_standard);
+
+	if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result dac2_encoder_control_v1(
+	struct bios_parser *bp,
+	bool enable,
+	uint32_t pixel_clock,
+	uint8_t dac_standard)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DAC_ENCODER_CONTROL_PS_ALLOCATION params;
+
+	dac_encoder_control_prepare_params(
+		&params,
+		enable,
+		pixel_clock,
+		dac_standard);
+
+	if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC OUTPUT CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+static enum bp_result dac1_output_control_v1(
+	struct bios_parser *bp,
+	bool enable);
+static enum bp_result dac2_output_control_v1(
+	struct bios_parser *bp,
+	bool enable);
+
+static void init_dac_output_control(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
+	case 1:
+		bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac1_output_control = NULL;
+		break;
+	}
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
+	case 1:
+		bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
+		break;
+	default:
+		bp->cmd_tbl.dac2_output_control = NULL;
+		break;
+	}
+}
+
+static enum bp_result dac1_output_control_v1(
+	struct bios_parser *bp, bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
+
+	if (enable)
+		params.ucAction = ATOM_ENABLE;
+	else
+		params.ucAction = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result dac2_output_control_v1(
+	struct bios_parser *bp, bool enable)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
+
+	if (enable)
+		params.ucAction = ATOM_ENABLE;
+	else
+		params.ucAction = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DAC LOAD DETECTION
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum signal_type dac_load_detection_v3(
+	struct bios_parser *bp,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type display_signal);
+
+static void init_dac_load_detection(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(DAC_LoadDetection)) {
+	case 3:
+		bp->cmd_tbl.dac_load_detection = dac_load_detection_v3;
+		break;
+	default:
+		bp->cmd_tbl.dac_load_detection = NULL;
+		break;
+	}
+}
+
+static enum signal_type dac_load_detection_v3(
+	struct bios_parser *bp,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type display_signal)
+{
+	DAC_LOAD_DETECTION_PS_ALLOCATION params;
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	/* load detection is cupported for CRT, TV and CV */
+	switch (display_signal) {
+	case SIGNAL_TYPE_RGB:
+		switch (dal_graphics_object_id_get_encoder_id(encoder)) {
+		case ENCODER_ID_INTERNAL_DAC1:
+		case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+			params.sDacload.usDeviceID =
+				cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
+			break;
+		case ENCODER_ID_INTERNAL_DAC2:
+		case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+			params.sDacload.usDeviceID =
+				cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
+			break;
+		default:
+			break;
+		}
+		break;
+		default:
+			return signal;
+	}
+
+	/* set the encoder to detect on */
+	switch (dal_graphics_object_id_get_encoder_id(encoder)) {
+	case ENCODER_ID_INTERNAL_DAC1:
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+		params.sDacload.ucDacType = ATOM_DAC_A;
+		break;
+	case ENCODER_ID_INTERNAL_DAC2:
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+		params.sDacload.ucDacType = ATOM_DAC_B;
+		break;
+	default:
+		return signal;
+	}
+
+	if (!EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params))
+		return signal;
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+	signal = bp->bios_helper->detect_sink(
+			bp->ctx,
+			encoder,
+			connector,
+			display_signal);
+#else
+	BREAK_TO_DEBUGGER(); /* VBios is needed */
+#endif
+
+	return signal;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                 BLANK CRTC
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result blank_crtc_v1(
+	struct bios_parser *bp,
+	struct bp_blank_crtc_parameters *bp_params,
+	bool blank);
+
+static void init_blank_crtc(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(BlankCRTC)) {
+	case 1:
+		bp->cmd_tbl.blank_crtc = blank_crtc_v1;
+		break;
+	default:
+		bp->cmd_tbl.blank_crtc = NULL;
+		break;
+	}
+}
+
+static enum bp_result blank_crtc_v1(
+	struct bios_parser *bp,
+	struct bp_blank_crtc_parameters *bp_params,
+	bool blank)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	BLANK_CRTC_PARAMETERS params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
+			&atom_controller_id)) {
+		params.ucCRTC = (uint8_t)atom_controller_id;
+
+		if (blank)
+			params.ucBlanking = ATOM_BLANKING;
+		else
+			params.ucBlanking = ATOM_BLANKING_OFF;
+		params.usBlackColorRCr =
+				cpu_to_le16((uint16_t)bp_params->black_color_rcr);
+		params.usBlackColorGY =
+				cpu_to_le16((uint16_t)bp_params->black_color_gy);
+		params.usBlackColorBCb =
+				cpu_to_le16((uint16_t)bp_params->black_color_bcb);
+
+		if (EXEC_BIOS_CMD_TABLE(BlankCRTC, params))
+			result = BP_RESULT_OK;
+	} else
+		/* Not support more than two CRTC as current ASIC, update this
+		 * if needed.
+		 */
+		result = BP_RESULT_BADINPUT;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET CRTC TIMING
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result set_crtc_using_dtd_timing_v3(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params);
+static enum bp_result set_crtc_timing_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params);
+
+static void init_set_crtc_timing(struct bios_parser *bp)
+{
+	uint32_t dtd_version =
+			BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
+	if (dtd_version > 2)
+		switch (dtd_version) {
+		case 3:
+			bp->cmd_tbl.set_crtc_timing =
+					set_crtc_using_dtd_timing_v3;
+			break;
+		default:
+			bp->cmd_tbl.set_crtc_timing = NULL;
+			break;
+		}
+	else
+		switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
+		case 1:
+			bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
+			break;
+		default:
+			bp->cmd_tbl.set_crtc_timing = NULL;
+			break;
+		}
+}
+
+static enum bp_result set_crtc_timing_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+
+	params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
+	params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
+	params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
+	params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
+	params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
+	params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
+	params.usV_SyncStart =
+			cpu_to_le16((uint16_t)(bp_params->v_sync_start));
+	params.usV_SyncWidth =
+			cpu_to_le16((uint16_t)(bp_params->v_sync_width));
+
+
+	/* VBIOS does not expect any value except zero into this call, for
+	 * underscan use another entry ProgramOverscan call but when mode
+	 * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
+	 * but when same ,but 60 Hz there is corruption
+	 * DAL1 does not allow the mode 1776x1000@60
+	 */
+	params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
+	params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
+	params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
+	params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
+
+	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
+
+	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
+
+	if (bp_params->flags.INTERLACE) {
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
+
+		/* original DAL code has this condition to apply tis for
+		 * non-TV/CV only due to complex MV testing for possible
+		 * impact
+		 * if (pACParameters->signal != SignalType_YPbPr &&
+		 *  pACParameters->signal != SignalType_Composite &&
+		 *  pACParameters->signal != SignalType_SVideo)
+		 */
+		/* HW will deduct 0.5 line from 2nd feild.
+		 * i.e. for 1080i, it is 2 lines for 1st field, 2.5
+		 * lines for the 2nd feild. we need input as 5 instead
+		 * of 4, but it is 4 either from Edid data
+		 * (spec CEA 861) or CEA timing table.
+		 */
+		params.usV_SyncStart =
+				cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
+	}
+
+	if (bp_params->flags.HORZ_COUNT_BY_TWO)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
+
+	if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result set_crtc_using_dtd_timing_v3(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_timing_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+
+	/* bios usH_Size wants h addressable size */
+	params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
+	/* bios usH_Blanking_Time wants borders included in blanking */
+	params.usH_Blanking_Time =
+			cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
+	/* bios usV_Size wants v addressable size */
+	params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
+	/* bios usV_Blanking_Time wants borders included in blanking */
+	params.usV_Blanking_Time =
+			cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
+	/* bios usHSyncOffset is the offset from the end of h addressable,
+	 * our horizontalSyncStart is the offset from the beginning
+	 * of h addressable */
+	params.usH_SyncOffset =
+			cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
+	params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
+	/* bios usHSyncOffset is the offset from the end of v addressable,
+	 * our verticalSyncStart is the offset from the beginning of
+	 * v addressable */
+	params.usV_SyncOffset =
+			cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
+	params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
+
+	/* we assume that overscan from original timing does not get bigger
+	 * than 255
+	 * we will program all the borders in the Set CRTC Overscan call below
+	 */
+
+	if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
+
+	if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
+
+
+	if (bp_params->flags.INTERLACE)	{
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
+
+		/* original DAL code has this condition to apply this
+		 * for non-TV/CV only
+		 * due to complex MV testing for possible impact
+		 * if ( pACParameters->signal != SignalType_YPbPr &&
+		 *  pACParameters->signal != SignalType_Composite &&
+		 *  pACParameters->signal != SignalType_SVideo)
+		 */
+		{
+			/* HW will deduct 0.5 line from 2nd feild.
+			 * i.e. for 1080i, it is 2 lines for 1st field,
+			 * 2.5 lines for the 2nd feild. we need input as 5
+			 * instead of 4.
+			 * but it is 4 either from Edid data (spec CEA 861)
+			 * or CEA timing table.
+			 */
+			params.usV_SyncOffset =
+					cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1);
+
+		}
+	}
+
+	if (bp_params->flags.HORZ_COUNT_BY_TWO)
+		params.susModeMiscInfo.usAccess =
+				cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
+
+	if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET CRTC OVERSCAN
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result set_crtc_overscan_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_overscan_parameters *bp_params);
+
+static void init_set_crtc_overscan(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_OverScan))	{
+	case 1:
+		bp->cmd_tbl.set_crtc_overscan = set_crtc_overscan_v1;
+		break;
+	default:
+		bp->cmd_tbl.set_crtc_overscan = NULL;
+		break;
+	}
+}
+
+static enum bp_result set_crtc_overscan_v1(
+	struct bios_parser *bp,
+	struct bp_hw_crtc_overscan_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SET_CRTC_OVERSCAN_PARAMETERS params = {0};
+	uint8_t atom_controller_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+	else
+		return BP_RESULT_BADINPUT;
+
+	params.usOverscanRight =
+			cpu_to_le16((uint16_t)bp_params->h_overscan_right);
+	params.usOverscanLeft =
+			cpu_to_le16((uint16_t)bp_params->h_overscan_left);
+	params.usOverscanBottom =
+			cpu_to_le16((uint16_t)bp_params->v_overscan_bottom);
+	params.usOverscanTop =
+			cpu_to_le16((uint16_t)bp_params->v_overscan_top);
+
+	if (EXEC_BIOS_CMD_TABLE(SetCRTC_OverScan, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SELECT CRTC SOURCE
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result select_crtc_source_v2(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params);
+static enum bp_result select_crtc_source_v3(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params);
+
+static void init_select_crtc_source(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) {
+	case 2:
+		bp->cmd_tbl.select_crtc_source = select_crtc_source_v2;
+		break;
+	case 3:
+		bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
+		break;
+	default:
+		bp->cmd_tbl.select_crtc_source = NULL;
+		break;
+	}
+}
+
+static enum bp_result select_crtc_source_v2(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	SELECT_CRTC_SOURCE_PARAMETERS_V2 params;
+	uint8_t atom_controller_id;
+	uint32_t atom_engine_id;
+	enum signal_type s = bp_params->signal;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	/* set controller id */
+	if (bp->cmd_helper->controller_id_to_atom(
+			bp_params->controller_id, &atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+	else
+		return BP_RESULT_FAILURE;
+
+	/* set encoder id */
+	if (bp->cmd_helper->engine_bp_to_atom(
+			bp_params->engine_id, &atom_engine_id))
+		params.ucEncoderID = (uint8_t)atom_engine_id;
+	else
+		return BP_RESULT_FAILURE;
+
+	if (SIGNAL_TYPE_EDP == s ||
+			(SIGNAL_TYPE_DISPLAY_PORT == s &&
+					SIGNAL_TYPE_LVDS == bp_params->sink_signal))
+		s = SIGNAL_TYPE_LVDS;
+
+	params.ucEncodeMode =
+			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+					s, bp_params->enable_dp_audio);
+
+	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result select_crtc_source_v3(
+	struct bios_parser *bp,
+	struct bp_crtc_source_select *bp_params)
+{
+	bool result = BP_RESULT_FAILURE;
+	SELECT_CRTC_SOURCE_PARAMETERS_V3 params;
+	uint8_t atom_controller_id;
+	uint32_t atom_engine_id;
+	enum signal_type s = bp_params->signal;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
+			&atom_controller_id))
+		params.ucCRTC = atom_controller_id;
+	else
+		return result;
+
+	if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
+			&atom_engine_id))
+		params.ucEncoderID = (uint8_t)atom_engine_id;
+	else
+		return result;
+
+	if (SIGNAL_TYPE_EDP == s ||
+			(SIGNAL_TYPE_DISPLAY_PORT == s &&
+					SIGNAL_TYPE_LVDS == bp_params->sink_signal))
+		s = SIGNAL_TYPE_LVDS;
+
+	params.ucEncodeMode =
+			bp->cmd_helper->encoder_mode_bp_to_atom(
+					s, bp_params->enable_dp_audio);
+	/* Needed for VBIOS Random Spatial Dithering feature */
+	params.ucDstBpc = (uint8_t)(bp_params->display_output_bit_depth);
+
+	if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE CRTC
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result enable_crtc_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable);
+
+static void init_enable_crtc(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
+	case 1:
+		bp->cmd_tbl.enable_crtc = enable_crtc_v1;
+		break;
+	default:
+		bp->cmd_tbl.enable_crtc = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_crtc_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable)
+{
+	bool result = BP_RESULT_FAILURE;
+	ENABLE_CRTC_PARAMETERS params = {0};
+	uint8_t id;
+
+	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
+		params.ucCRTC = id;
+	else
+		return BP_RESULT_BADINPUT;
+
+	if (enable)
+		params.ucEnable = ATOM_ENABLE;
+	else
+		params.ucEnable = ATOM_DISABLE;
+
+	if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE CRTC MEM REQ
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result enable_crtc_mem_req_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable);
+
+static void init_enable_crtc_mem_req(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
+	case 1:
+		bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
+		break;
+	default:
+		bp->cmd_tbl.enable_crtc_mem_req = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_crtc_mem_req_v1(
+	struct bios_parser *bp,
+	enum controller_id controller_id,
+	bool enable)
+{
+	bool result = BP_RESULT_BADINPUT;
+	ENABLE_CRTC_PARAMETERS params = {0};
+	uint8_t id;
+
+	if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
+		params.ucCRTC = id;
+
+		if (enable)
+			params.ucEnable = ATOM_ENABLE;
+		else
+			params.ucEnable = ATOM_DISABLE;
+
+		if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
+			result = BP_RESULT_OK;
+		else
+			result = BP_RESULT_FAILURE;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  DISPLAY PLL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result program_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+static enum bp_result program_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params);
+
+static void init_program_clock(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
+	case 5:
+		bp->cmd_tbl.program_clock = program_clock_v5;
+		break;
+	case 6:
+		bp->cmd_tbl.program_clock = program_clock_v6;
+		break;
+	default:
+		bp->cmd_tbl.program_clock = NULL;
+		break;
+	}
+}
+
+static enum bp_result program_clock_v5(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
+	uint32_t atom_pll_id;
+
+	dm_memset(&params, 0, sizeof(params));
+	if (!bp->cmd_helper->clock_source_id_to_atom(
+			bp_params->pll_id, &atom_pll_id)) {
+		BREAK_TO_DEBUGGER(); /* Invalid Inpute!! */
+		return BP_RESULT_BADINPUT;
+	}
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
+	params.sPCLKInput.usPixelClock =
+			cpu_to_le16((uint16_t) (bp_params->target_pixel_clock / 10));
+	params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
+
+	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
+
+	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+static enum bp_result program_clock_v6(
+	struct bios_parser *bp,
+	struct bp_pixel_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
+	uint32_t atom_pll_id;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (!bp->cmd_helper->clock_source_id_to_atom(
+			bp_params->pll_id, &atom_pll_id)) {
+		BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
+		return BP_RESULT_BADINPUT;
+	}
+
+	/* We need to convert from KHz units into 10KHz units */
+	params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
+	params.sPCLKInput.ulDispEngClkFreq =
+			cpu_to_le32(bp_params->target_pixel_clock / 10);
+
+	if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
+		params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
+
+	if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
+		/* True display clock is returned by VBIOS if DFS bypass
+		 * is enabled. */
+		bp_params->dfs_bypass_display_clock =
+				(uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                 COMPUTE MEMORY ENGINE PLL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result compute_memore_engine_pll_v4(
+	struct bios_parser *bp,
+	struct bp_display_clock_parameters *bp_params);
+
+static void init_compute_memore_engine_pll(struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(ComputeMemoryEnginePLL)) {
+	case 4:
+		bp->cmd_tbl.compute_memore_engine_pll =
+				compute_memore_engine_pll_v4;
+		break;
+	default:
+		bp->cmd_tbl.compute_memore_engine_pll = NULL;
+		break;
+	}
+}
+
+static enum bp_result compute_memore_engine_pll_v4(
+	struct bios_parser *bp,
+	struct bp_display_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+	COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 params;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	params.ulClock = cpu_to_le32(bp_params->target_display_clock / 10);
+
+	/* Initialize this to the target clock in case this call fails */
+	bp_params->actual_display_clock = bp_params->target_display_clock;
+
+	if (EXEC_BIOS_CMD_TABLE(ComputeMemoryEnginePLL, params)) {
+		/* Convert from 10KHz units back to KHz */
+		bp_params->actual_display_clock =
+				le32_to_cpu(params.ulClock) * 10;
+		bp_params->actual_post_divider_id = params.ucPostDiv;
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  EXTERNAL ENCODER CONTROL
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result external_encoder_control_v3(
+	struct bios_parser *bp,
+	struct bp_external_encoder_control *cntl);
+
+static void init_external_encoder_control(
+	struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
+	case 3:
+		bp->cmd_tbl.external_encoder_control =
+				external_encoder_control_v3;
+		break;
+	default:
+		bp->cmd_tbl.external_encoder_control = NULL;
+		break;
+	}
+}
+
+static enum bp_result external_encoder_control_v3(
+	struct bios_parser *bp,
+	struct bp_external_encoder_control *cntl)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	/* we need use _PS_Alloc struct */
+	EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
+	EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
+	struct graphics_object_id encoder;
+	bool is_input_signal_dp = false;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	cntl_params = &params.sExtEncoder;
+
+	encoder = cntl->encoder_id;
+
+	/* check if encoder supports external encoder control table */
+	switch (dal_graphics_object_id_get_encoder_id(encoder)) {
+	case ENCODER_ID_EXTERNAL_NUTMEG:
+	case ENCODER_ID_EXTERNAL_TRAVIS:
+		is_input_signal_dp = true;
+		break;
+
+	default:
+		BREAK_TO_DEBUGGER();
+		return BP_RESULT_BADINPUT;
+	}
+
+	/* Fill information based on the action
+	 *
+	 * Bit[6:4]: indicate external encoder, applied to all functions.
+	 * =0: external encoder1, mapped to external encoder enum id1
+	 * =1: external encoder2, mapped to external encoder enum id2
+	 *
+	 * enum ObjectEnumId
+	 * {
+	 *  EnumId_Unknown = 0,
+	 *  EnumId_1,
+	 *  EnumId_2,
+	 * };
+	 */
+	cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
+
+	switch (cntl->action) {
+	case EXTERNAL_ENCODER_CONTROL_INIT:
+		/* output display connector type. Only valid in encoder
+		 * initialization */
+		cntl_params->usConnectorId =
+				cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
+		break;
+	case EXTERNAL_ENCODER_CONTROL_SETUP:
+		/* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
+		 * 10KHz
+		 * output display device pixel clock frequency in unit of 10KHz.
+		 * Only valid in setup and enableoutput
+		 */
+		cntl_params->usPixelClock =
+				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+		/* Indicate display output signal type drive by external
+		 * encoder, only valid in setup and enableoutput */
+		cntl_params->ucEncoderMode =
+				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+						cntl->signal, false);
+
+		if (is_input_signal_dp) {
+			/* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
+			 * only valid in encoder setup with DP mode. */
+			if (LINK_RATE_HIGH == cntl->link_rate)
+				cntl_params->ucConfig |= 1;
+			/* output color depth Indicate encoder data bpc format
+			 * in DP mode, only valid in encoder setup in DP mode.
+			 */
+			cntl_params->ucBitPerColor =
+					(uint8_t)(cntl->color_depth);
+		}
+		/* Indicate how many lanes used by external encoder, only valid
+		 * in encoder setup and enableoutput. */
+		cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
+		break;
+	case EXTERNAL_ENCODER_CONTROL_ENABLE:
+		cntl_params->usPixelClock =
+				cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
+		cntl_params->ucEncoderMode =
+				(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
+						cntl->signal, false);
+		cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
+		break;
+	default:
+		break;
+	}
+
+	cntl_params->ucAction = (uint8_t)cntl->action;
+
+	if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
+		result = BP_RESULT_OK;
+
+	if (EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT == cntl->action) {
+#if defined(CONFIG_DRM_AMD_DAL_VBIOS_PRESENT)
+		if (BP_RESULT_OK == result)
+			/* get VBIOS result from scratch register.
+			 * ExternalEncoderControl runs detection and save result
+			 * in BIOS scratch registers. */
+			cntl->signal = bp->bios_helper->detect_sink(
+					bp->ctx,
+					encoder,
+					cntl->connector_obj_id,
+					cntl->signal);
+		else/* BIOS table does not work. */
+#endif
+		{
+			BREAK_TO_DEBUGGER(); /* VBios is needed */
+			cntl->signal = SIGNAL_TYPE_NONE;
+		}
+	}
+
+	return result;
+}
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  ENABLE DISPLAY POWER GATING
+ **
+ ********************************************************************************
+ *******************************************************************************/
+
+static enum bp_result enable_disp_power_gating_v2_1(
+	struct bios_parser *bp,
+	enum controller_id crtc_id,
+	enum bp_pipe_control_action action);
+
+static void init_enable_disp_power_gating(
+	struct bios_parser *bp)
+{
+	switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
+	case 1:
+		bp->cmd_tbl.enable_disp_power_gating =
+				enable_disp_power_gating_v2_1;
+		break;
+	default:
+		bp->cmd_tbl.enable_disp_power_gating = NULL;
+		break;
+	}
+}
+
+static enum bp_result enable_disp_power_gating_v2_1(
+	struct bios_parser *bp,
+	enum controller_id crtc_id,
+	enum bp_pipe_control_action action)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 params = {0};
+	uint8_t atom_crtc_id;
+
+	if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
+		params.ucDispPipeId = atom_crtc_id;
+	else
+		return BP_RESULT_BADINPUT;
+
+	params.ucEnable =
+			bp->cmd_helper->disp_power_gating_action_to_atom(action);
+
+	if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
+		result = BP_RESULT_OK;
+
+	return result;
+}
+
+
+/*******************************************************************************
+ ********************************************************************************
+ **
+ **                  SET DCE CLOCK
+ **
+ ********************************************************************************
+ *******************************************************************************/
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+static enum bp_result set_dce_clock_v2_1(
+	struct bios_parser *bp,
+	struct bp_set_dce_clock_parameters *bp_params);
+#endif
+
+static void init_set_dce_clock(struct bios_parser *bp)
+{
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+	switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
+	case 1:
+		bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
+		break;
+	default:
+		bp->cmd_tbl.set_dce_clock = NULL;
+		break;
+	}
+#endif
+}
+
+#ifdef LATEST_ATOM_BIOS_SUPPORT
+static enum bp_result set_dce_clock_v2_1(
+	struct bios_parser *bp,
+	struct bp_set_dce_clock_parameters *bp_params)
+{
+	enum bp_result result = BP_RESULT_FAILURE;
+
+	SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
+	uint32_t atom_pll_id;
+	uint32_t atom_clock_type;
+	const struct command_table_helper *cmd = bp->cmd_helper;
+
+	dm_memset(&params, 0, sizeof(params));
+
+	if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
+			!cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
+		return BP_RESULT_BADINPUT;
+
+	params.asParam.ucDCEClkSrc  = atom_pll_id;
+	params.asParam.ucDCEClkType = atom_clock_type;
+
+	if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
+		if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
+
+		if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
+
+		if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
+
+		if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
+			params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
+	}
+	else
+		/* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
+		/* We need to convert from KHz units into 10KHz units */
+		params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
+
+	if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
+		/* Convert from 10KHz units back to KHz */
+		bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
+		result = BP_RESULT_OK;
+	}
+
+	return result;
+}
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table.h b/drivers/gpu/drm/amd/dal/dc/bios/command_table.h
new file mode 100644
index 000000000000..3cb0c7f8c202
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_H__
+#define __DAL_COMMAND_TABLE_H__
+
+struct bios_parser;
+struct bp_encoder_control;
+
+struct cmd_tbl {
+	enum bp_result (*dig_encoder_control)(
+		struct bios_parser *bp,
+		struct bp_encoder_control *control);
+	enum bp_result (*encoder_control_dig1)(
+		struct bios_parser *bp,
+		struct bp_encoder_control *control);
+	enum bp_result (*encoder_control_dig2)(
+		struct bios_parser *bp,
+		struct bp_encoder_control *control);
+	enum bp_result (*transmitter_control)(
+		struct bios_parser *bp,
+		struct bp_transmitter_control *control);
+	enum bp_result (*set_pixel_clock)(
+		struct bios_parser *bp,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*enable_spread_spectrum_on_ppll)(
+		struct bios_parser *bp,
+		struct bp_spread_spectrum_parameters *bp_params,
+		bool enable);
+	enum bp_result (*adjust_display_pll)(
+		struct bios_parser *bp,
+		struct bp_adjust_pixel_clock_parameters *bp_params);
+	enum bp_result (*dac1_encoder_control)(
+		struct bios_parser *bp,
+		bool enable,
+		uint32_t pixel_clock,
+		uint8_t dac_standard);
+	enum bp_result (*dac2_encoder_control)(
+		struct bios_parser *bp,
+		bool enable,
+		uint32_t pixel_clock,
+		uint8_t dac_standard);
+	enum bp_result (*dac1_output_control)(
+		struct bios_parser *bp,
+		bool enable);
+	enum bp_result (*dac2_output_control)(
+		struct bios_parser *bp,
+		bool enable);
+	enum signal_type (*dac_load_detection)(
+		struct bios_parser *bp,
+		struct graphics_object_id encoder,
+		struct graphics_object_id connector,
+		enum signal_type display_signal);
+	enum bp_result (*blank_crtc)(
+		struct bios_parser *bp,
+		struct bp_blank_crtc_parameters *bp_params,
+		bool blank);
+	enum bp_result (*set_crtc_timing)(
+		struct bios_parser *bp,
+		struct bp_hw_crtc_timing_parameters *bp_params);
+	enum bp_result (*set_crtc_overscan)(
+		struct bios_parser *bp,
+		struct bp_hw_crtc_overscan_parameters *bp_params);
+	enum bp_result (*select_crtc_source)(
+		struct bios_parser *bp,
+		struct bp_crtc_source_select *bp_params);
+	enum bp_result (*enable_crtc)(
+		struct bios_parser *bp,
+		enum controller_id controller_id,
+		bool enable);
+	enum bp_result (*enable_crtc_mem_req)(
+		struct bios_parser *bp,
+		enum controller_id controller_id,
+		bool enable);
+	enum bp_result (*program_clock)(
+		struct bios_parser *bp,
+		struct bp_pixel_clock_parameters *bp_params);
+	enum bp_result (*compute_memore_engine_pll)(
+		struct bios_parser *bp,
+		struct bp_display_clock_parameters *bp_params);
+	enum bp_result (*external_encoder_control)(
+			struct bios_parser *bp,
+			struct bp_external_encoder_control *cntl);
+	enum bp_result (*enable_disp_power_gating)(
+		struct bios_parser *bp,
+		enum controller_id crtc_id,
+		enum bp_pipe_control_action action);
+	enum bp_result (*set_dce_clock)(
+		struct bios_parser *bp,
+		struct bp_set_dce_clock_parameters *bp_params);
+};
+
+void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
new file mode 100644
index 000000000000..566604ea877a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "include/adapter_service_types.h"
+
+#include "command_table_helper.h"
+
+bool dal_bios_parser_init_cmd_tbl_helper(
+	const struct command_table_helper **h,
+	enum dce_version dce)
+{
+	switch (dce) {
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		*h = dal_cmd_tbl_helper_dce110_get_table();
+		return true;
+#endif
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		*h = dal_cmd_tbl_helper_dce110_get_table();
+		return true;
+#endif
+
+	default:
+		/* Unsupported DCE */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+/* real implementations */
+
+bool dal_cmd_table_helper_controller_id_to_atom(
+	enum controller_id id,
+	uint8_t *atom_id)
+{
+	if (atom_id == NULL) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	switch (id) {
+	case CONTROLLER_ID_D0:
+		*atom_id = ATOM_CRTC1;
+		return true;
+	case CONTROLLER_ID_D1:
+		*atom_id = ATOM_CRTC2;
+		return true;
+	case CONTROLLER_ID_D2:
+		*atom_id = ATOM_CRTC3;
+		return true;
+	case CONTROLLER_ID_D3:
+		*atom_id = ATOM_CRTC4;
+		return true;
+	case CONTROLLER_ID_D4:
+		*atom_id = ATOM_CRTC5;
+		return true;
+	case CONTROLLER_ID_D5:
+		*atom_id = ATOM_CRTC6;
+		return true;
+	case CONTROLLER_ID_UNDERLAY0:
+		*atom_id = ATOM_UNDERLAY_PIPE0;
+		return true;
+	case CONTROLLER_ID_UNDEFINED:
+		*atom_id = ATOM_CRTC_INVALID;
+		return true;
+	default:
+		/* Wrong controller id */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+/**
+* translate_transmitter_bp_to_atom
+*
+* @brief
+*  Translate the Transmitter to the corresponding ATOM BIOS value
+*
+* @param
+*   input transmitter
+*   output digitalTransmitter
+*    // =00: Digital Transmitter1 ( UNIPHY linkAB )
+*    // =01: Digital Transmitter2 ( UNIPHY linkCD )
+*    // =02: Digital Transmitter3 ( UNIPHY linkEF )
+*/
+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom(
+	enum transmitter t)
+{
+	switch (t) {
+	case TRANSMITTER_UNIPHY_A:
+	case TRANSMITTER_UNIPHY_B:
+	case TRANSMITTER_TRAVIS_LCD:
+		return 0;
+	case TRANSMITTER_UNIPHY_C:
+	case TRANSMITTER_UNIPHY_D:
+		return 1;
+	case TRANSMITTER_UNIPHY_E:
+	case TRANSMITTER_UNIPHY_F:
+		return 2;
+	default:
+		/* Invalid Transmitter Type! */
+		BREAK_TO_DEBUGGER();
+		return 0;
+	}
+}
+
+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom(
+	enum signal_type s,
+	bool enable_dp_audio)
+{
+	switch (s) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		return ATOM_ENCODER_MODE_DVI;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		return ATOM_ENCODER_MODE_HDMI;
+	case SIGNAL_TYPE_LVDS:
+		return ATOM_ENCODER_MODE_LVDS;
+	case SIGNAL_TYPE_EDP:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+		if (enable_dp_audio)
+			return ATOM_ENCODER_MODE_DP_AUDIO;
+		else
+			return ATOM_ENCODER_MODE_DP;
+	case SIGNAL_TYPE_RGB:
+		return ATOM_ENCODER_MODE_CRT;
+	default:
+		return ATOM_ENCODER_MODE_CRT;
+	}
+}
+
+void dal_cmd_table_helper_assign_control_parameter(
+	const struct command_table_helper *h,
+	struct bp_encoder_control *control,
+	DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param)
+{
+	/* there are three transmitter blocks, each one has two links 4-lanes
+	 * each, A+B, C+D, E+F, Uniphy A, C and E are enumerated as link 0 in
+	 * each transmitter block B, D and F as link 1, third transmitter block
+	 * has non splitable links (UniphyE and UniphyF can not be configured
+	 * separately to drive two different streams)
+	 */
+	if ((control->transmitter == TRANSMITTER_UNIPHY_B) ||
+		(control->transmitter == TRANSMITTER_UNIPHY_D) ||
+		(control->transmitter == TRANSMITTER_UNIPHY_F)) {
+		/* Bit2: Link Select
+		 * =0: PHY linkA/C/E
+		 * =1: PHY linkB/D/F
+		 */
+		ctrl_param->acConfig.ucLinkSel = 1;
+	}
+
+	/* Bit[4:3]: Transmitter Selection
+	 * =00: Digital Transmitter1 ( UNIPHY linkAB )
+	 * =01: Digital Transmitter2 ( UNIPHY linkCD )
+	 * =02: Digital Transmitter3 ( UNIPHY linkEF )
+	 * =03: Reserved
+	 */
+	ctrl_param->acConfig.ucTransmitterSel =
+		(uint8_t)(h->transmitter_bp_to_atom(control->transmitter));
+
+	/* We need to convert from KHz units into 10KHz units */
+	ctrl_param->ucAction = h->encoder_action_to_atom(control->action);
+	ctrl_param->usPixelClock = cpu_to_le16((uint16_t)(control->pixel_clock / 10));
+	ctrl_param->ucEncoderMode =
+		(uint8_t)(h->encoder_mode_bp_to_atom(
+			control->signal, control->enable_dp_audio));
+	ctrl_param->ucLaneNum = (uint8_t)(control->lanes_number);
+}
+
+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src(
+	enum clock_source_id id,
+	uint32_t *ref_clk_src_id)
+{
+	if (ref_clk_src_id == NULL) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	switch (id) {
+	case CLOCK_SOURCE_ID_PLL1:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL;
+		return true;
+	case CLOCK_SOURCE_ID_PLL2:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL;
+		return true;
+	case CLOCK_SOURCE_ID_DCPLL:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL;
+		return true;
+	case CLOCK_SOURCE_ID_EXTERNAL:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK;
+		return true;
+	case CLOCK_SOURCE_ID_UNDEFINED:
+		*ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID;
+		return true;
+	default:
+		/* Unsupported clock source id */
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+}
+
+uint8_t dal_cmd_table_helper_encoder_id_to_atom(
+	enum encoder_id id)
+{
+	switch (id) {
+	case ENCODER_ID_INTERNAL_LVDS:
+		return ENCODER_OBJECT_ID_INTERNAL_LVDS;
+	case ENCODER_ID_INTERNAL_TMDS1:
+		return ENCODER_OBJECT_ID_INTERNAL_TMDS1;
+	case ENCODER_ID_INTERNAL_TMDS2:
+		return ENCODER_OBJECT_ID_INTERNAL_TMDS2;
+	case ENCODER_ID_INTERNAL_DAC1:
+		return ENCODER_OBJECT_ID_INTERNAL_DAC1;
+	case ENCODER_ID_INTERNAL_DAC2:
+		return ENCODER_OBJECT_ID_INTERNAL_DAC2;
+	case ENCODER_ID_INTERNAL_LVTM1:
+		return ENCODER_OBJECT_ID_INTERNAL_LVTM1;
+	case ENCODER_ID_INTERNAL_HDMI:
+		return ENCODER_OBJECT_ID_HDMI_INTERNAL;
+	case ENCODER_ID_EXTERNAL_TRAVIS:
+		return ENCODER_OBJECT_ID_TRAVIS;
+	case ENCODER_ID_EXTERNAL_NUTMEG:
+		return ENCODER_OBJECT_ID_NUTMEG;
+	case ENCODER_ID_INTERNAL_KLDSCP_TMDS1:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
+	case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
+	case ENCODER_ID_EXTERNAL_MVPU_FPGA:
+		return ENCODER_OBJECT_ID_MVPU_FPGA;
+	case ENCODER_ID_INTERNAL_DDI:
+		return ENCODER_OBJECT_ID_INTERNAL_DDI;
+	case ENCODER_ID_INTERNAL_UNIPHY:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY;
+	case ENCODER_ID_INTERNAL_KLDSCP_LVTMA:
+		return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA;
+	case ENCODER_ID_INTERNAL_UNIPHY1:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY1;
+	case ENCODER_ID_INTERNAL_UNIPHY2:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY2;
+	case ENCODER_ID_INTERNAL_UNIPHY3:
+		return ENCODER_OBJECT_ID_INTERNAL_UNIPHY3;
+	case ENCODER_ID_INTERNAL_WIRELESS:
+		return ENCODER_OBJECT_ID_INTERNAL_VCE;
+	case ENCODER_ID_UNKNOWN:
+		return ENCODER_OBJECT_ID_NONE;
+	default:
+		/* Invalid encoder id */
+		BREAK_TO_DEBUGGER();
+		return ENCODER_OBJECT_ID_NONE;
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
new file mode 100644
index 000000000000..4646cabd2b40
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/command_table_helper.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_HELPER_H__
+#define __DAL_COMMAND_TABLE_HELPER_H__
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0) || defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce110/command_table_helper_dce110.h"
+#endif
+
+struct command_table_helper {
+	bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id);
+	uint8_t (*encoder_action_to_atom)(
+			enum bp_encoder_control_action action);
+	uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s,
+			bool enable_dp_audio);
+	bool (*engine_bp_to_atom)(enum engine_id engine_id,
+			uint32_t *atom_engine_id);
+	void (*assign_control_parameter)(
+			const struct command_table_helper *h,
+			struct bp_encoder_control *control,
+			DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param);
+	bool (*clock_source_id_to_atom)(enum clock_source_id id,
+			uint32_t *atom_pll_id);
+	bool (*clock_source_id_to_ref_clk_src)(
+			enum clock_source_id id,
+			uint32_t *ref_clk_src_id);
+	uint8_t (*transmitter_bp_to_atom)(enum transmitter t);
+	uint8_t (*encoder_id_to_atom)(enum encoder_id id);
+	uint8_t (*clock_source_id_to_atom_phy_clk_src_id)(
+			enum clock_source_id id);
+	uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s);
+	uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id);
+	uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id);
+	uint8_t (*phy_id_to_atom)(enum transmitter t);
+	uint8_t (*disp_power_gating_action_to_atom)(
+			enum bp_pipe_control_action action);
+	bool (*dc_clock_type_to_atom)(enum bp_dce_clock_type id,
+			uint32_t *atom_clock_type);
+    uint8_t (*transmitter_color_depth_to_atom)(enum transmitter_color_depth id);
+};
+
+bool dal_bios_parser_init_cmd_tbl_helper(const struct command_table_helper **h,
+	enum dce_version dce);
+
+bool dal_cmd_table_helper_controller_id_to_atom(
+	enum controller_id id,
+	uint8_t *atom_id);
+
+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom(
+	enum signal_type s,
+	bool enable_dp_audio);
+
+void dal_cmd_table_helper_assign_control_parameter(
+	const struct command_table_helper *h,
+	struct bp_encoder_control *control,
+DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param);
+
+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src(
+	enum clock_source_id id,
+	uint32_t *ref_clk_src_id);
+
+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom(
+	enum transmitter t);
+
+uint8_t dal_cmd_table_helper_encoder_id_to_atom(
+	enum encoder_id id);
+#endif
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
new file mode 100644
index 000000000000..85d3103a1de7
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.c
@@ -0,0 +1,484 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "include/adapter_service_types.h"
+#include "include/logger_interface.h"
+
+#include "../bios_parser_helper.h"
+
+#include "dce/dce_11_0_d.h"
+#include "bif/bif_5_1_d.h"
+
+/**
+ * set_scratch_acc_mode_change
+ *
+ * @brief
+ *  set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when
+ *  VGA/non-Accelerated mode is set
+ *
+ * @param
+ *  struct dc_context *ctx - [in] DAL context
+ */
+static void set_scratch_acc_mode_change(
+	struct dc_context *ctx)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = 0;
+
+	value = dm_read_reg(ctx, addr);
+
+	value |= ATOM_S6_ACC_MODE;
+
+	dm_write_reg(ctx, addr, value);
+}
+
+/*
+ * set_scratch_active_and_requested
+ *
+ * @brief
+ * Set VBIOS scratch pad registers about active and requested displays
+ *
+ * @param
+ * struct dc_context *ctx - [in] DAL context for register accessing
+ * struct vbios_helper_data *d - [in] values to write
+ */
+static void set_scratch_active_and_requested(
+	struct dc_context *ctx,
+	struct vbios_helper_data *d)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+
+	/* mmBIOS_SCRATCH_3 = mmBIOS_SCRATCH_0 + ATOM_ACTIVE_INFO_DEF */
+	addr = mmBIOS_SCRATCH_3;
+
+	value = dm_read_reg(ctx, addr);
+
+	value &= ~ATOM_S3_DEVICE_ACTIVE_MASK;
+	value |= (d->active & ATOM_S3_DEVICE_ACTIVE_MASK);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* mmBIOS_SCRATCH_6 =  mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF */
+	addr = mmBIOS_SCRATCH_6;
+
+	value = dm_read_reg(ctx, addr);
+
+	value &= ~ATOM_S6_ACC_REQ_MASK;
+	value |= (d->requested & ATOM_S6_ACC_REQ_MASK);
+
+	dm_write_reg(ctx, addr, value);
+
+	/* mmBIOS_SCRATCH_5 =  mmBIOS_SCRATCH_0 + ATOM_DOS_REQ_INFO_DEF */
+	addr = mmBIOS_SCRATCH_5;
+
+	value = dm_read_reg(ctx, addr);
+
+	value &= ~ATOM_S5_DOS_REQ_DEVICEw0;
+	value |= (d->active & ATOM_S5_DOS_REQ_DEVICEw0);
+
+	dm_write_reg(ctx, addr, value);
+
+	d->active = 0;
+	d->requested = 0;
+}
+
+/**
+ * get LCD Scale Mode from VBIOS scratch register
+ */
+static enum lcd_scale get_scratch_lcd_scale(
+	struct dc_context *ctx)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = 0;
+
+	value = dm_read_reg(ctx, addr);
+
+	if (value & ATOM_S6_REQ_LCD_EXPANSION_FULL)
+		return LCD_SCALE_FULLPANEL;
+	else if (value & ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO)
+		return LCD_SCALE_ASPECTRATIO;
+	else
+		return LCD_SCALE_NONE;
+}
+
+/**
+ * prepare_scratch_active_and_requested
+ *
+ * @brief
+ *  prepare and update VBIOS scratch pad registers about active and requested
+ *  displays
+ *
+ * @param
+ * data - helper's shared data
+ * enum controller_ild - controller Id
+ * enum signal_type - signal type used on display
+ * const struct connector_device_tag_info* - pointer to display type and enum id
+ */
+static void prepare_scratch_active_and_requested(
+	struct dc_context *ctx,
+	struct vbios_helper_data *data,
+	enum controller_id id,
+	enum signal_type s,
+	const struct connector_device_tag_info *dev_tag)
+{
+	switch (s) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		if (dev_tag->dev_id.device_type == DEVICE_TYPE_DFP)
+			switch (dev_tag->dev_id.enum_id) {
+			case 1:
+				data->requested |= ATOM_S6_ACC_REQ_DFP1;
+				data->active |= ATOM_S3_DFP1_ACTIVE;
+				break;
+			case 2:
+				data->requested |= ATOM_S6_ACC_REQ_DFP2;
+				data->active |= ATOM_S3_DFP2_ACTIVE;
+				break;
+			case 3:
+				data->requested |= ATOM_S6_ACC_REQ_DFP3;
+				data->active |= ATOM_S3_DFP3_ACTIVE;
+				break;
+			case 4:
+				data->requested |= ATOM_S6_ACC_REQ_DFP4;
+				data->active |= ATOM_S3_DFP4_ACTIVE;
+				break;
+			case 5:
+				data->requested |= ATOM_S6_ACC_REQ_DFP5;
+				data->active |= ATOM_S3_DFP5_ACTIVE;
+				break;
+			case 6:
+				data->requested |= ATOM_S6_ACC_REQ_DFP6;
+				data->active |= ATOM_S3_DFP6_ACTIVE;
+				break;
+			default:
+				break;
+			}
+		break;
+	case SIGNAL_TYPE_LVDS:
+	case SIGNAL_TYPE_EDP:
+		data->requested |= ATOM_S6_ACC_REQ_LCD1;
+		data->active |= ATOM_S3_LCD1_ACTIVE;
+		break;
+	case SIGNAL_TYPE_RGB:
+		if (dev_tag->dev_id.device_type == DEVICE_TYPE_CRT)
+			switch (dev_tag->dev_id.enum_id) {
+			case 1:
+				data->requested |= ATOM_S6_ACC_REQ_CRT1;
+				data->active |= ATOM_S3_CRT1_ACTIVE;
+				break;
+			case 2:
+				dal_logger_write(ctx->logger,
+					LOG_MAJOR_BIOS,
+					LOG_MINOR_COMPONENT_BIOS,
+					"%s: DAL does not support DAC2!\n",
+					__func__);
+				break;
+			default:
+				break;
+			}
+		break;
+	default:
+		dal_logger_write(ctx->logger,
+				LOG_MAJOR_BIOS,
+				LOG_MINOR_COMPONENT_BIOS,
+				"%s: No such signal!\n",
+				__func__);
+		break;
+	}
+}
+
+/*
+ * is_accelerated_mode
+ *
+ * @brief
+ *  set Accelerated Mode in VBIOS scratch register, VBIOS will clean it when
+ *  VGA/non-Accelerated mode is set
+ *
+ * @param
+ * struct dc_context *ctx
+ *
+ * @return
+ * true if in acceleration mode, false otherwise.
+ */
+static bool is_accelerated_mode(
+	struct dc_context *ctx)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	return (value & ATOM_S6_ACC_MODE) ? true : false;
+}
+
+#define BIOS_SCRATCH0_DAC_B_SHIFT 8
+
+/**
+ * detect_sink
+ *
+ * @brief
+ *  read VBIOS scratch register to determine whether display for the specified
+ *  signal is present and return the actual sink signal type
+ *  For analog signals VBIOS load detection has to be called prior reading the
+ *  register
+ *
+ * @param
+ *  encoder - encoder id (to specify DAC)
+ *  connector - connector id (to check CV on DIN)
+ *  signal - signal (as display type) to check
+ *
+ * @return
+ *  signal_type - actual (on the sink) signal type detected
+ */
+static enum signal_type detect_sink(
+	struct dc_context *ctx,
+	struct graphics_object_id encoder,
+	struct graphics_object_id connector,
+	enum signal_type signal)
+{
+	uint32_t bios_scratch0;
+	uint32_t encoder_id = encoder.id;
+	/* after DCE 10.x does not support DAC2, so assert and return
+	 * SIGNAL_TYPE_NONE */
+	if (encoder_id == ENCODER_ID_INTERNAL_DAC2
+		|| encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC2) {
+		ASSERT(false);
+		return SIGNAL_TYPE_NONE;
+	}
+
+	bios_scratch0 = dm_read_reg(ctx,
+		mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF);
+
+	/* In further processing we use DACB masks. If we want detect load on
+	 * DACA, we need to shift the register so DACA bits will be in place of
+	 * DACB bits
+	 */
+	if (encoder_id == ENCODER_ID_INTERNAL_DAC1
+		|| encoder_id == ENCODER_ID_INTERNAL_KLDSCP_DAC1
+		|| encoder_id == ENCODER_ID_EXTERNAL_NUTMEG
+		|| encoder_id == ENCODER_ID_EXTERNAL_TRAVIS) {
+		bios_scratch0 <<= BIOS_SCRATCH0_DAC_B_SHIFT;
+	}
+
+	switch (signal) {
+	case SIGNAL_TYPE_RGB: {
+		if (bios_scratch0 & ATOM_S0_CRT2_MASK)
+			return SIGNAL_TYPE_RGB;
+		break;
+	}
+	case SIGNAL_TYPE_LVDS: {
+		if (bios_scratch0 & ATOM_S0_LCD1)
+			return SIGNAL_TYPE_LVDS;
+		break;
+	}
+	case SIGNAL_TYPE_EDP: {
+		if (bios_scratch0 & ATOM_S0_LCD1)
+			return SIGNAL_TYPE_EDP;
+		break;
+	}
+	default:
+		break;
+	}
+
+	return SIGNAL_TYPE_NONE;
+}
+
+/**
+ * set_scratch_connected
+ *
+ * @brief
+ *    update BIOS_SCRATCH_0 register about connected displays
+ *
+ * @param
+ * bool - update scratch register or just prepare info to be updated
+ * bool - connection state
+ * const struct connector_device_tag_info * - pointer to device type and enum ID
+ */
+static void set_scratch_connected(
+	struct dc_context *ctx,
+	struct graphics_object_id id,
+	bool connected,
+	const struct connector_device_tag_info *device_tag)
+{
+	uint32_t addr = 0;
+	uint32_t value = 0;
+	uint32_t update = 0;
+
+	switch (device_tag->dev_id.device_type) {
+	case DEVICE_TYPE_LCD:
+		/* For LCD VBIOS will update LCD Panel connected bit always and
+		 * Lid state bit based on SBIOS info do not do anything here
+		 * for LCD
+		 */
+		break;
+	case DEVICE_TYPE_CRT:
+		/*
+		 * CRT is not supported in DCE11
+		 */
+		break;
+	case DEVICE_TYPE_DFP:
+		switch (device_tag->dev_id.enum_id) {
+		case 1:
+			update |= ATOM_S0_DFP1;
+			break;
+		case 2:
+			update |= ATOM_S0_DFP2;
+			break;
+		case 3:
+			update |= ATOM_S0_DFP3;
+			break;
+		case 4:
+			update |= ATOM_S0_DFP4;
+			break;
+		case 5:
+			update |= ATOM_S0_DFP5;
+			break;
+		case 6:
+			update |= ATOM_S0_DFP6;
+			break;
+		default:
+			break;
+		}
+		break;
+	case DEVICE_TYPE_CV:
+		/* DCE 8.0 does not support CV,
+		 * so don't do anything */
+		break;
+
+	case DEVICE_TYPE_TV:
+		/* For TV VBIOS will update S-Video or
+		 * Composite scratch bits on DAL_LoadDetect
+		 * when called by driver, do not do anything
+		 * here for TV
+		 */
+		break;
+
+	default:
+		break;
+
+	}
+
+	/* update scratch register */
+	addr = mmBIOS_SCRATCH_0 + ATOM_DEVICE_CONNECT_INFO_DEF;
+
+	value = dm_read_reg(ctx, addr);
+
+	if (connected)
+		value |= update;
+	else
+		value &= ~update;
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_scratch_critical_state(
+	struct dc_context *ctx,
+	bool state)
+{
+	uint32_t addr = mmBIOS_SCRATCH_6;
+	uint32_t value = dm_read_reg(ctx, addr);
+
+	if (state)
+		value |= ATOM_S6_CRITICAL_STATE;
+	else
+		value &= ~ATOM_S6_CRITICAL_STATE;
+
+	dm_write_reg(ctx, addr, value);
+}
+
+static void set_scratch_lcd_scale(
+	struct dc_context *ctx,
+	enum lcd_scale lcd_scale_request)
+{
+	DAL_LOGGER_NOT_IMPL(
+		LOG_MINOR_COMPONENT_BIOS,
+		"Bios Parser:%s\n",
+		__func__);
+}
+
+static bool is_lid_open(struct dc_context *ctx)
+{
+	uint32_t bios_scratch6;
+
+	bios_scratch6 =
+		dm_read_reg(
+			ctx,
+			mmBIOS_SCRATCH_0 + ATOM_ACC_CHANGE_INFO_DEF);
+
+	/* lid is open if the bit is not set */
+	if (!(bios_scratch6 & ATOM_S6_LID_STATE))
+		return true;
+
+	return false;
+}
+
+/* function table */
+static const struct bios_parser_helper bios_parser_helper_funcs = {
+	.detect_sink = detect_sink,
+	.fmt_bit_depth_control = NULL,
+	.fmt_control = NULL,
+	.get_bios_event_info = NULL,
+	.get_embedded_display_controller_id = NULL,
+	.get_embedded_display_refresh_rate = NULL,
+	.get_requested_backlight_level = NULL,
+	.get_scratch_lcd_scale = get_scratch_lcd_scale,
+	.is_accelerated_mode = is_accelerated_mode,
+	.is_active_display = NULL,
+	.is_display_config_changed = NULL,
+	.is_lid_open = is_lid_open,
+	.is_lid_status_changed = NULL,
+	.prepare_scratch_active_and_requested =
+			prepare_scratch_active_and_requested,
+	.set_scratch_acc_mode_change = set_scratch_acc_mode_change,
+	.set_scratch_active_and_requested = set_scratch_active_and_requested,
+	.set_scratch_connected = set_scratch_connected,
+	.set_scratch_critical_state = set_scratch_critical_state,
+	.set_scratch_lcd_scale = set_scratch_lcd_scale,
+	.take_backlight_control = NULL,
+	.update_requested_backlight_level = NULL,
+};
+
+/*
+ * dal_bios_parser_dce110_init_bios_helper
+ *
+ * @brief
+ * Initialize BIOS helper functions
+ *
+ * @param
+ * const struct command_table_helper **h - [out] struct of functions
+ *
+ */
+
+const struct bios_parser_helper *dal_bios_parser_helper_dce110_get_table()
+{
+	return &bios_parser_helper_funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
new file mode 100644
index 000000000000..915f31ab9c1a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/bios_parser_helper_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_HELPER_DCE110_H__
+#define __DAL_BIOS_PARSER_HELPER_DCE110_H__
+
+struct bios_parser_helper;
+
+/* Initialize BIOS helper functions */
+const struct bios_parser_helper *dal_bios_parser_helper_dce110_get_table(void);
+
+#endif /* __DAL_BIOS_PARSER_HELPER_DCE110_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
new file mode 100644
index 000000000000..614ba94ac0c3
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+#include "include/adapter_service_types.h"
+
+#include "../command_table_helper.h"
+
+static uint8_t phy_id_to_atom(enum transmitter t)
+{
+	uint8_t atom_phy_id;
+
+	switch (t) {
+	case TRANSMITTER_UNIPHY_A:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYA;
+		break;
+	case TRANSMITTER_UNIPHY_B:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYB;
+		break;
+	case TRANSMITTER_UNIPHY_C:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYC;
+		break;
+	case TRANSMITTER_UNIPHY_D:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYD;
+		break;
+	case TRANSMITTER_UNIPHY_E:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYE;
+		break;
+	case TRANSMITTER_UNIPHY_F:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYF;
+		break;
+	case TRANSMITTER_UNIPHY_G:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYG;
+		break;
+	default:
+		atom_phy_id = ATOM_PHY_ID_UNIPHYA;
+		break;
+	}
+	return atom_phy_id;
+}
+
+
+static uint8_t signal_type_to_atom_dig_mode(enum signal_type s)
+{
+	uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
+
+	switch (s) {
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_EDP:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
+		break;
+	case SIGNAL_TYPE_LVDS:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS;
+		break;
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
+		break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI;
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST;
+		break;
+	default:
+		atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
+		break;
+	}
+
+	return atom_dig_mode;
+}
+
+static uint8_t clock_source_id_to_atom_phy_clk_src_id(
+		enum clock_source_id id)
+{
+	uint8_t atom_phy_clk_src_id = 0;
+
+	switch (id) {
+	case CLOCK_SOURCE_ID_PLL0:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL;
+		break;
+	case CLOCK_SOURCE_ID_PLL1:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
+		break;
+	case CLOCK_SOURCE_ID_PLL2:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL;
+		break;
+	case CLOCK_SOURCE_ID_EXTERNAL:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT;
+		break;
+	default:
+		atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
+		break;
+	}
+
+	return atom_phy_clk_src_id >> 2;
+}
+
+static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
+{
+	uint8_t atom_hpd_sel = 0;
+
+	switch (id) {
+	case HPD_SOURCEID1:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL;
+		break;
+	case HPD_SOURCEID2:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL;
+		break;
+	case HPD_SOURCEID3:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL;
+		break;
+	case HPD_SOURCEID4:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL;
+		break;
+	case HPD_SOURCEID5:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL;
+		break;
+	case HPD_SOURCEID6:
+		atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL;
+		break;
+	case HPD_SOURCEID_UNKNOWN:
+	default:
+		atom_hpd_sel = 0;
+		break;
+	}
+	return atom_hpd_sel >> 4;
+}
+
+static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
+{
+	uint8_t atom_dig_encoder_sel = 0;
+
+	switch (id) {
+	case ENGINE_ID_DIGA:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
+		break;
+	case ENGINE_ID_DIGB:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL;
+		break;
+	case ENGINE_ID_DIGC:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL;
+		break;
+	case ENGINE_ID_DIGD:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL;
+		break;
+	case ENGINE_ID_DIGE:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL;
+		break;
+	case ENGINE_ID_DIGF:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL;
+		break;
+	case ENGINE_ID_DIGG:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL;
+		break;
+	case ENGINE_ID_UNKNOWN:
+		 /* No DIG_FRONT is associated to DIG_BACKEND */
+		atom_dig_encoder_sel = 0;
+		break;
+	default:
+		atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
+		break;
+	}
+
+	return atom_dig_encoder_sel;
+}
+
+static bool clock_source_id_to_atom(
+	enum clock_source_id id,
+	uint32_t *atom_pll_id)
+{
+	bool result = true;
+
+	if (atom_pll_id != NULL)
+		switch (id) {
+		case CLOCK_SOURCE_ID_PLL0:
+			*atom_pll_id = ATOM_PPLL0;
+			break;
+		case CLOCK_SOURCE_ID_PLL1:
+			*atom_pll_id = ATOM_PPLL1;
+			break;
+		case CLOCK_SOURCE_ID_PLL2:
+			*atom_pll_id = ATOM_PPLL2;
+			break;
+		case CLOCK_SOURCE_ID_EXTERNAL:
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			break;
+		case CLOCK_SOURCE_ID_DFS:
+			*atom_pll_id = ATOM_EXT_PLL1;
+			break;
+		case CLOCK_SOURCE_ID_VCE:
+			/* for VCE encoding,
+			 * we need to pass in ATOM_PPLL_INVALID
+			 */
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			break;
+		case CLOCK_SOURCE_ID_DP_DTO:
+			/* When programming DP DTO PLL ID should be invalid */
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			break;
+		case CLOCK_SOURCE_ID_UNDEFINED:
+			/* Should not happen */
+			*atom_pll_id = ATOM_PPLL_INVALID;
+			result = false;
+			break;
+		default:
+			result = false;
+			break;
+		}
+
+	return result;
+}
+
+static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id)
+{
+	bool result = false;
+
+	if (atom_engine_id != NULL)
+		switch (id) {
+		case ENGINE_ID_DIGA:
+			*atom_engine_id = ASIC_INT_DIG1_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGB:
+			*atom_engine_id = ASIC_INT_DIG2_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGC:
+			*atom_engine_id = ASIC_INT_DIG3_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGD:
+			*atom_engine_id = ASIC_INT_DIG4_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGE:
+			*atom_engine_id = ASIC_INT_DIG5_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGF:
+			*atom_engine_id = ASIC_INT_DIG6_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DIGG:
+			*atom_engine_id = ASIC_INT_DIG7_ENCODER_ID;
+			result = true;
+			break;
+		case ENGINE_ID_DACA:
+			*atom_engine_id = ASIC_INT_DAC1_ENCODER_ID;
+			result = true;
+			break;
+		default:
+			break;
+		}
+
+	return result;
+}
+
+static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action)
+{
+	uint8_t atom_action = 0;
+
+	switch (action) {
+	case ENCODER_CONTROL_ENABLE:
+		atom_action = ATOM_ENABLE;
+		break;
+	case ENCODER_CONTROL_DISABLE:
+		atom_action = ATOM_DISABLE;
+		break;
+	case ENCODER_CONTROL_SETUP:
+		atom_action = ATOM_ENCODER_CMD_SETUP;
+		break;
+	case ENCODER_CONTROL_INIT:
+		atom_action = ATOM_ENCODER_INIT;
+		break;
+	default:
+		BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */
+		break;
+	}
+
+	return atom_action;
+}
+
+static uint8_t disp_power_gating_action_to_atom(
+	enum bp_pipe_control_action action)
+{
+	uint8_t atom_pipe_action = 0;
+
+	switch (action) {
+	case ASIC_PIPE_DISABLE:
+		atom_pipe_action = ATOM_DISABLE;
+		break;
+	case ASIC_PIPE_ENABLE:
+		atom_pipe_action = ATOM_ENABLE;
+		break;
+	case ASIC_PIPE_INIT:
+		atom_pipe_action = ATOM_INIT;
+		break;
+	default:
+		ASSERT_CRITICAL(false); /* Unhandle action in driver! */
+		break;
+	}
+
+	return atom_pipe_action;
+}
+
+/* function table */
+static const struct command_table_helper command_table_helper_funcs = {
+	.controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom,
+	.encoder_action_to_atom = encoder_action_to_atom,
+	.engine_bp_to_atom = engine_bp_to_atom,
+	.clock_source_id_to_atom = clock_source_id_to_atom,
+	.clock_source_id_to_atom_phy_clk_src_id =
+			clock_source_id_to_atom_phy_clk_src_id,
+	.signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode,
+	.hpd_sel_to_atom = hpd_sel_to_atom,
+	.dig_encoder_sel_to_atom = dig_encoder_sel_to_atom,
+	.phy_id_to_atom = phy_id_to_atom,
+	.disp_power_gating_action_to_atom = disp_power_gating_action_to_atom,
+	.assign_control_parameter = NULL,
+	.clock_source_id_to_ref_clk_src = NULL,
+	.transmitter_bp_to_atom = NULL,
+	.encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom,
+	.encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom,
+};
+
+/*
+ * dal_cmd_tbl_helper_dce110_get_table
+ *
+ * @brief
+ * Initialize command table helper functions
+ *
+ * @param
+ * const struct command_table_helper **h - [out] struct of functions
+ *
+ */
+const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table()
+{
+	return &command_table_helper_funcs;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
new file mode 100644
index 000000000000..eb60c2ead992
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/bios/dce110/command_table_helper_dce110.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_HELPER_DCE110_H__
+#define __DAL_COMMAND_TABLE_HELPER_DCE110_H__
+
+struct command_table_helper;
+
+/* Initialize command table helper functions */
+const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table(void);
+
+#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v3 24/26] drm/amd/dal: Add display core
  2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                     ` (2 preceding siblings ...)
  2016-02-29 21:56   ` [PATCH v3 07/26] drm/amd/dal: BIOS Parser Harry Wentland
@ 2016-02-29 21:56   ` Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
  5 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-29 21:56 UTC (permalink / raw)
  To: dri-devel

Adds a logical representation of our hardware. Provides ability to
- dc_validate_resources - validate a display configuration
- dc_commit_targets - commit a display configuration
- dc_commit_surfaces_to_target - update surfaces
- dc_link_detect - detect displays at link
- dc_resume - resume display HW
- dc_interrupt_set/ack - set and ack interrupts
- etc.

v3 changes:
- minor dm_helpers name cleanup
- expose I2C through i2c_adapter and route dal i2c calls through this

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/dc/Makefile               |   28 +
 drivers/gpu/drm/amd/dal/dc/core/dc.c              |  947 +++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c |   56 +
 drivers/gpu/drm/amd/dal/dc/core/dc_link.c         | 1645 ++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c     | 1121 +++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c      | 1728 +++++++++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c    |  201 +++
 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c     | 1243 +++++++++++++++
 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c         |  116 ++
 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c       |  188 +++
 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c      |  123 ++
 drivers/gpu/drm/amd/dal/dc/core/dc_target.c       |  548 +++++++
 12 files changed, 7944 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/dal/dc/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
 create mode 100644 drivers/gpu/drm/amd/dal/dc/core/dc_target.c

diff --git a/drivers/gpu/drm/amd/dal/dc/Makefile b/drivers/gpu/drm/amd/dal/dc/Makefile
new file mode 100644
index 000000000000..aed26eec81f9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/Makefile
@@ -0,0 +1,28 @@
+#
+# Makefile for Display Core (dc) component.
+#
+
+DC_LIBS = adapter asic_capability audio basics bios calcs \
+gpio gpu i2caux irq virtual
+
+ifdef CONFIG_DRM_AMD_DAL_DCE11_0
+DC_LIBS += dce110
+endif
+
+ifdef CONFIG_DRM_AMD_DAL_DCE10_0
+DC_LIBS += dce100
+endif
+
+AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DAL_PATH)/dc/,$(DC_LIBS)))
+
+include $(AMD_DC)
+
+DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_target.o dc_sink.o dc_stream.o \
+dc_hw_sequencer.o dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o
+
+AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE))
+
+AMD_DAL_FILES += $(AMD_DISPLAY_CORE)
+
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c
new file mode 100644
index 000000000000..3ba7af0390f5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c
@@ -0,0 +1,947 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ */
+
+#include "dm_services.h"
+
+#include "dc.h"
+
+#include "core_status.h"
+#include "core_types.h"
+#include "hw_sequencer.h"
+
+#include "resource.h"
+
+#include "adapter_service_interface.h"
+#include "clock_source.h"
+#include "dc_bios_types.h"
+
+#include "bandwidth_calcs.h"
+#include "include/irq_service_interface.h"
+#include "transform.h"
+#include "timing_generator.h"
+#include "virtual/virtual_link_encoder.h"
+
+#include "link_hwss.h"
+#include "link_encoder.h"
+
+#include "dc_link_ddc.h"
+
+/*******************************************************************************
+ * Private structures
+ ******************************************************************************/
+
+struct dc_target_sync_report {
+	uint32_t h_count;
+	uint32_t v_count;
+};
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static void destroy_links(struct dc *dc)
+{
+	uint32_t i;
+
+	for (i = 0; i < dc->link_count; i++) {
+		if (NULL != dc->links[i])
+			link_destroy(&dc->links[i]);
+	}
+}
+
+static bool create_links(struct dc *dc, const struct dc_init_data *init_params)
+{
+	int i;
+	int connectors_num;
+	struct dc_bios *dcb;
+
+	dc->link_count = 0;
+
+	dcb = dal_adapter_service_get_bios_parser(init_params->adapter_srv);
+
+	connectors_num = dcb->funcs->get_connectors_number(dcb);
+
+	if (connectors_num > ENUM_ID_COUNT) {
+		dm_error(
+			"DC: Number of connectors %d exceeds maximum of %d!\n",
+			connectors_num,
+			ENUM_ID_COUNT);
+		return false;
+	}
+
+	if (connectors_num == 0 && init_params->num_virtual_links == 0) {
+		dm_error("DC: Number of connectors can not be zero!\n");
+		return false;
+	}
+
+	dm_output_to_console(
+		"DC: %s: connectors_num: physical:%d, virtual:%d\n",
+		__func__,
+		connectors_num,
+		init_params->num_virtual_links);
+
+	for (i = 0; i < connectors_num; i++) {
+		struct link_init_data link_init_params = {0};
+		struct core_link *link;
+
+		link_init_params.ctx = init_params->ctx;
+		link_init_params.adapter_srv = init_params->adapter_srv;
+		link_init_params.connector_index = i;
+		link_init_params.link_index = dc->link_count;
+		link_init_params.dc = dc;
+		link = link_create(&link_init_params);
+
+		if (link) {
+			dc->links[dc->link_count] = link;
+			link->dc = dc;
+			++dc->link_count;
+		} else {
+			dm_error("DC: failed to create link!\n");
+		}
+	}
+
+	for (i = 0; i < init_params->num_virtual_links; i++) {
+		struct core_link *link = dm_alloc(
+			dc->ctx,
+			sizeof(*link));
+		struct encoder_init_data enc_init = {0};
+
+		if (link == NULL) {
+			BREAK_TO_DEBUGGER();
+			goto failed_alloc;
+		}
+
+		link->adapter_srv = init_params->adapter_srv;
+		link->ctx = init_params->ctx;
+		link->dc = dc;
+		link->public.connector_signal = SIGNAL_TYPE_VIRTUAL;
+		link->link_id.type = OBJECT_TYPE_CONNECTOR;
+		link->link_id.id = CONNECTOR_ID_VIRTUAL;
+		link->link_id.enum_id = ENUM_ID_1;
+		link->link_enc = dm_alloc(
+			dc->ctx,
+			sizeof(*link->link_enc));
+
+		enc_init.adapter_service = init_params->adapter_srv;
+		enc_init.ctx = init_params->ctx;
+		enc_init.channel = CHANNEL_ID_UNKNOWN;
+		enc_init.hpd_source = HPD_SOURCEID_UNKNOWN;
+		enc_init.transmitter = TRANSMITTER_UNKNOWN;
+		enc_init.connector = link->link_id;
+		enc_init.encoder.type = OBJECT_TYPE_ENCODER;
+		enc_init.encoder.id = ENCODER_ID_INTERNAL_VIRTUAL;
+		enc_init.encoder.enum_id = ENUM_ID_1;
+		virtual_link_encoder_construct(link->link_enc, &enc_init);
+
+		link->public.link_index = dc->link_count;
+		dc->links[dc->link_count] = link;
+		dc->link_count++;
+	}
+
+	return true;
+
+failed_alloc:
+	return false;
+}
+
+
+static void init_hw(struct dc *dc)
+{
+	int i;
+	struct dc_bios *bp;
+	struct transform *xfm;
+
+	bp = dal_adapter_service_get_bios_parser(dc->res_pool.adapter_srv);
+	for(i = 0; i < dc->res_pool.controller_count; i++) {
+		xfm = dc->res_pool.transforms[i];
+
+		dc->hwss.enable_display_power_gating(
+				dc->ctx, i, bp,
+				PIPE_GATING_CONTROL_INIT);
+		dc->hwss.enable_display_power_gating(
+				dc->ctx, i, bp,
+				PIPE_GATING_CONTROL_DISABLE);
+
+		xfm->funcs->transform_power_up(xfm);
+		dc->hwss.enable_display_pipe_clock_gating(
+			dc->ctx,
+			true);
+	}
+
+	dc->hwss.clock_gating_power_up(dc->ctx, false);
+	bp->funcs->power_up(bp);
+	/***************************************/
+
+	for (i = 0; i < dc->link_count; i++) {
+		/****************************************/
+		/* Power up AND update implementation according to the
+		 * required signal (which may be different from the
+		 * default signal on connector). */
+		struct core_link *link = dc->links[i];
+		link->link_enc->funcs->hw_init(link->link_enc);
+	}
+
+	for(i = 0; i < dc->res_pool.controller_count; i++) {
+		struct timing_generator *tg = dc->res_pool.timing_generators[i];
+
+		tg->funcs->disable_vga(tg);
+
+		/* Blank controller using driver code instead of
+		 * command table. */
+		tg->funcs->set_blank(tg, true);
+	}
+
+	for(i = 0; i < dc->res_pool.audio_count; i++) {
+		struct audio *audio = dc->res_pool.audios[i];
+
+		if (dal_audio_power_up(audio) != AUDIO_RESULT_OK)
+			dm_error("Failed audio power up!\n");
+	}
+
+}
+
+static struct adapter_service *create_as(
+		struct dc_init_data *dc_init_data,
+		const struct dal_init_data *init)
+{
+	struct adapter_service *as = NULL;
+	struct as_init_data init_data;
+
+	dm_memset(&init_data, 0, sizeof(init_data));
+
+	init_data.ctx = dc_init_data->ctx;
+
+	/* BIOS parser init data */
+	init_data.bp_init_data.ctx = dc_init_data->ctx;
+	init_data.bp_init_data.bios = init->asic_id.atombios_base_address;
+
+	/* HW init data */
+	init_data.hw_init_data.chip_id = init->asic_id.chip_id;
+	init_data.hw_init_data.chip_family = init->asic_id.chip_family;
+	init_data.hw_init_data.pci_revision_id = init->asic_id.pci_revision_id;
+	init_data.hw_init_data.fake_paths_num = init->asic_id.fake_paths_num;
+	init_data.hw_init_data.feature_flags = init->asic_id.feature_flags;
+	init_data.hw_init_data.hw_internal_rev = init->asic_id.hw_internal_rev;
+	init_data.hw_init_data.runtime_flags = init->asic_id.runtime_flags;
+	init_data.hw_init_data.vram_width = init->asic_id.vram_width;
+	init_data.hw_init_data.vram_type = init->asic_id.vram_type;
+
+	/* bdf is BUS,DEVICE,FUNCTION*/
+	init_data.bdf_info = init->bdf_info;
+
+	init_data.display_param = &init->display_param;
+	init_data.vbios_override = init->vbios_override;
+	init_data.dce_environment = init->dce_environment;
+
+	as = dal_adapter_service_create(&init_data);
+
+	return as;
+}
+
+static void bw_calcs_data_update_from_pplib(struct dc *dc)
+{
+	struct dc_pp_clock_levels clks = {0};
+
+	/*do system clock*/
+	dm_pp_get_clock_levels_by_type(
+			dc->ctx,
+			DC_PP_CLOCK_TYPE_ENGINE_CLK,
+			&clks);
+	/* convert all the clock fro kHz to fix point mHz */
+	dc->bw_vbios.high_sclk = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels-1], 1000);
+	dc->bw_vbios.mid_sclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels>>1], 1000);
+	dc->bw_vbios.low_sclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[0], 1000);
+
+	/*do display clock*/
+	dm_pp_get_clock_levels_by_type(
+			dc->ctx,
+			DC_PP_CLOCK_TYPE_DISPLAY_CLK,
+			&clks);
+
+	dc->bw_vbios.high_voltage_max_dispclk = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels-1], 1000);
+	dc->bw_vbios.mid_voltage_max_dispclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[clks.num_levels>>1], 1000);
+	dc->bw_vbios.low_voltage_max_dispclk  = bw_frc_to_fixed(
+			clks.clocks_in_khz[0], 1000);
+
+	/*do memory clock*/
+	dm_pp_get_clock_levels_by_type(
+			dc->ctx,
+			DC_PP_CLOCK_TYPE_MEMORY_CLK,
+			&clks);
+
+	dc->bw_vbios.low_yclk = bw_frc_to_fixed(
+		clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000);
+	dc->bw_vbios.mid_yclk = bw_frc_to_fixed(
+		clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER,
+		1000);
+	dc->bw_vbios.high_yclk = bw_frc_to_fixed(
+		clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER,
+		1000);
+}
+
+static bool construct(struct dc *dc, const struct dal_init_data *init_params)
+{
+	struct dal_logger *logger;
+	/* Tempory code
+	 * TODO: replace dal_init_data with dc_init_data when dal is removed
+	 */
+	struct dc_init_data dc_init_data = {0};
+
+	/* Create dc context */
+	/* A temp dc context is used only to allocate the memory for actual
+	 * dc context */
+	struct dc_context ctx = {0};
+	ctx.cgs_device = init_params->cgs_device;
+	ctx.dc = dc;
+
+	dc_init_data.ctx = dm_alloc(&ctx, sizeof(*dc_init_data.ctx));
+	if (!dc_init_data.ctx) {
+		dm_error("%s: failed to create ctx\n", __func__);
+		goto ctx_fail;
+	}
+	dc_init_data.ctx->driver_context = init_params->driver;
+	dc_init_data.ctx->cgs_device = init_params->cgs_device;
+	dc_init_data.num_virtual_links = init_params->num_virtual_links;
+	dc_init_data.ctx->dc = dc;
+
+	/* Create logger */
+	logger = dal_logger_create(dc_init_data.ctx);
+
+	if (!logger) {
+		/* can *not* call logger. call base driver 'print error' */
+		dm_error("%s: failed to create Logger!\n", __func__);
+		goto logger_fail;
+	}
+	dc_init_data.ctx->logger = logger;
+
+	/* Create adapter service */
+	dc_init_data.adapter_srv = create_as(&dc_init_data, init_params);
+
+	if (!dc_init_data.adapter_srv) {
+		dm_error("%s: create_as() failed!\n", __func__);
+		goto as_fail;
+	}
+
+	/* Initialize HW controlled by Adapter Service */
+	if (false == dal_adapter_service_initialize_hw_data(
+			dc_init_data.adapter_srv)) {
+		dm_error("%s: dal_adapter_service_initialize_hw_data()"\
+				"  failed!\n", __func__);
+		/* Note that AS exist, so have to destroy it.*/
+		goto as_fail;
+	}
+
+	dc->ctx = dc_init_data.ctx;
+
+	dc->ctx->dce_environment = dal_adapter_service_get_dce_environment(
+			dc_init_data.adapter_srv);
+
+	/* Create hardware sequencer */
+	if (!dc_construct_hw_sequencer(dc_init_data.adapter_srv, dc))
+		goto hwss_fail;
+
+	if (!dc_construct_resource_pool(
+		dc_init_data.adapter_srv, dc, dc_init_data.num_virtual_links))
+		goto construct_resource_fail;
+
+	if (!create_links(dc, &dc_init_data))
+		goto create_links_fail;
+
+	bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios);
+
+	bw_calcs_data_update_from_pplib(dc);
+
+	return true;
+
+	/**** error handling here ****/
+construct_resource_fail:
+create_links_fail:
+as_fail:
+	dal_logger_destroy(&dc_init_data.ctx->logger);
+logger_fail:
+hwss_fail:
+	dm_free(&ctx, dc_init_data.ctx);
+ctx_fail:
+	return false;
+}
+
+static void destruct(struct dc *dc)
+{
+	destroy_links(dc);
+	dc->res_pool.funcs->destruct(&dc->res_pool);
+	dal_logger_destroy(&dc->ctx->logger);
+	dm_free(dc->ctx, dc->ctx);
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+struct dc *dc_create(const struct dal_init_data *init_params)
+ {
+	struct dc_context ctx = {
+		.driver_context = init_params->driver,
+		.cgs_device = init_params->cgs_device
+	};
+	struct dc *dc = dm_alloc(&ctx, sizeof(*dc));
+
+	if (NULL == dc)
+		goto alloc_fail;
+
+	ctx.dc = dc;
+	if (false == construct(dc, init_params))
+		goto construct_fail;
+
+	/*TODO: separate HW and SW initialization*/
+	init_hw(dc);
+
+	return dc;
+
+construct_fail:
+	dm_free(&ctx, dc);
+
+alloc_fail:
+	return NULL;
+}
+
+void dc_destroy(struct dc **dc)
+{
+	struct dc_context ctx = *(*dc)->ctx;
+	destruct(*dc);
+	dm_free(&ctx, *dc);
+	*dc = NULL;
+}
+
+bool dc_validate_resources(
+		const struct dc *dc,
+		const struct dc_validation_set set[],
+		uint8_t set_count)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	struct validate_context *context;
+
+	context = dm_alloc(dc->ctx, sizeof(struct validate_context));
+	if(context == NULL)
+		goto context_alloc_fail;
+
+	result = dc->res_pool.funcs->validate_with_context(
+						dc, set, set_count, context);
+
+	dm_free(dc->ctx, context);
+context_alloc_fail:
+
+	return (result == DC_OK);
+
+}
+
+static void program_timing_sync(
+		struct dc_context *dc_ctx,
+		struct validate_context *ctx)
+{
+	uint8_t i;
+	uint8_t j;
+	uint8_t group_size = 0;
+	uint8_t tg_count = ctx->res_ctx.pool.controller_count;
+	struct timing_generator *tg_set[3];
+
+	for (i = 0; i < tg_count; i++) {
+		if (!ctx->res_ctx.controller_ctx[i].stream)
+			continue;
+
+		tg_set[0] = ctx->res_ctx.pool.timing_generators[i];
+		group_size = 1;
+
+		/* Add tg to the set, search rest of the tg's for ones with
+		 * same timing, add all tgs with same timing to the group
+		 */
+		for (j = i + 1; j < tg_count; j++) {
+			if (!ctx->res_ctx.controller_ctx[j].stream)
+				continue;
+
+			if (is_same_timing(
+				&ctx->res_ctx.controller_ctx[j].stream->public
+								.timing,
+				&ctx->res_ctx.controller_ctx[i].stream->public
+								.timing)) {
+				tg_set[group_size] =
+					ctx->res_ctx.pool.timing_generators[j];
+				group_size++;
+			}
+		}
+
+		/* Right now we limit to one timing sync group so if one is
+		 * found we break. A group has to be more than one tg.*/
+		if (group_size > 1)
+			break;
+	}
+
+	if(group_size > 1) {
+		dc_ctx->dc->hwss.enable_timing_synchronization(dc_ctx, group_size, tg_set);
+	}
+}
+
+static bool targets_changed(
+		struct dc *dc,
+		struct dc_target *targets[],
+		uint8_t target_count)
+{
+	uint8_t i;
+
+	if (target_count != dc->current_context.target_count)
+		return true;
+
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		if (&dc->current_context.targets[i]->public != targets[i])
+			return true;
+	}
+
+	return false;
+}
+
+bool dc_commit_targets(
+	struct dc *dc,
+	struct dc_target *targets[],
+	uint8_t target_count)
+{
+	enum dc_status result = DC_ERROR_UNEXPECTED;
+	struct validate_context *context;
+	struct dc_validation_set set[4];
+	uint8_t i;
+
+	if (false == targets_changed(dc, targets, target_count))
+		return DC_OK;
+
+	dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_INTERFACE_TRACE,
+				LOG_MINOR_COMPONENT_DC,
+				"%s: %d targets\n",
+				__func__,
+				target_count);
+
+	for (i = 0; i < target_count; i++) {
+		struct dc_target *target = targets[i];
+
+		dc_target_log(target,
+				dc->ctx->logger,
+				LOG_MAJOR_INTERFACE_TRACE,
+				LOG_MINOR_COMPONENT_DC);
+
+		set[i].target = targets[i];
+		set[i].surface_count = 0;
+
+	}
+
+	context = dm_alloc(dc->ctx, sizeof(struct validate_context));
+	if (context == NULL)
+		goto context_alloc_fail;
+
+	result = dc->res_pool.funcs->validate_with_context(dc, set, target_count, context);
+	if (result != DC_OK){
+		BREAK_TO_DEBUGGER();
+		goto fail;
+	}
+
+	pplib_apply_safe_state(dc);
+
+	if (!dal_adapter_service_is_in_accelerated_mode(
+						dc->res_pool.adapter_srv)) {
+		dc->hwss.enable_accelerated_mode(dc);
+	}
+
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		/*TODO: optimize this to happen only when necessary*/
+		dc_target_disable_memory_requests(
+				&dc->current_context.targets[i]->public);
+	}
+
+	if (result == DC_OK) {
+		dc->hwss.reset_hw_ctx(dc, context, target_count);
+
+		if (context->target_count > 0)
+			result = dc->hwss.apply_ctx_to_hw(dc, context);
+	}
+
+	for (i = 0; i < context->target_count; i++) {
+		struct dc_target *dc_target = &context->targets[i]->public;
+		if (context->targets[i]->status.surface_count > 0)
+			dc_target_enable_memory_requests(dc_target);
+	}
+
+	/* Release old targets */
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		dc_target_release(
+				&dc->current_context.targets[i]->public);
+		dc->current_context.targets[i] = NULL;
+	}
+	/* Retain new targets*/
+	for (i = 0; i < context->target_count; i++) {
+		dc_target_retain(&context->targets[i]->public);
+	}
+
+	dc->current_context = *context;
+
+	program_timing_sync(dc->ctx, context);
+
+	pplib_apply_display_requirements(dc, context);
+
+	/* TODO: disable unused plls*/
+fail:
+	dm_free(dc->ctx, context);
+
+context_alloc_fail:
+	return (result == DC_OK);
+}
+
+uint8_t dc_get_current_target_count(const struct dc *dc)
+{
+	return dc->current_context.target_count;
+}
+
+struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i)
+{
+	if (i < dc->current_context.target_count)
+		return &dc->current_context.targets[i]->public;
+	return NULL;
+}
+
+const struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index)
+{
+	return &dc->links[link_index]->public;
+}
+
+const struct graphics_object_id dc_get_link_id_at_index(
+	struct dc *dc, uint32_t link_index)
+{
+	return dc->links[link_index]->link_id;
+}
+
+const struct ddc_service *dc_get_ddc_at_index(
+	struct dc *dc, uint32_t link_index)
+{
+	return dc->links[link_index]->ddc;
+}
+
+const enum dc_irq_source dc_get_hpd_irq_source_at_index(
+	struct dc *dc, uint32_t link_index)
+{
+	return dc->links[link_index]->public.irq_source_hpd;
+}
+
+const struct audio **dc_get_audios(struct dc *dc)
+{
+	return (const struct audio **)dc->res_pool.audios;
+}
+
+void dc_get_caps(const struct dc *dc, struct dc_caps *caps)
+{
+	caps->max_targets = dc->res_pool.controller_count;
+	caps->max_links = dc->link_count;
+	caps->max_audios = dc->res_pool.audio_count;
+}
+
+void dc_flip_surface_addrs(struct dc* dc,
+		const struct dc_surface *const surfaces[],
+		struct dc_flip_addrs flip_addrs[],
+		uint32_t count)
+{
+	uint8_t i;
+	for (i = 0; i < count; i++) {
+		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
+		/*
+		 * TODO figure out a good way to keep track of address. Until
+		 * then we'll have to awkwardly bypass the "const" surface.
+		 */
+		surface->public.address = flip_addrs[i].address;
+		surface->public.flip_immediate = flip_addrs[i].flip_immediate;
+
+		dc->hwss.update_plane_address(
+			dc,
+			surface,
+			DC_TARGET_TO_CORE(surface->status.dc_target));
+	}
+}
+
+enum dc_irq_source dc_interrupt_to_irq_source(
+		struct dc *dc,
+		uint32_t src_id,
+		uint32_t ext_id)
+{
+	return dal_irq_service_to_irq_source(dc->res_pool.irqs, src_id, ext_id);
+}
+
+
+void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable)
+{
+	dal_irq_service_set(dc->res_pool.irqs, src, enable);
+}
+
+void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
+{
+	dal_irq_service_ack(dc->res_pool.irqs, src);
+}
+
+const struct dc_target *dc_get_target_on_irq_source(
+		const struct dc *dc,
+		enum dc_irq_source src)
+{
+	uint8_t i, j;
+	uint8_t crtc_idx;
+
+	switch (src) {
+	case DC_IRQ_SOURCE_VUPDATE1:
+	case DC_IRQ_SOURCE_VUPDATE2:
+	case DC_IRQ_SOURCE_VUPDATE3:
+	case DC_IRQ_SOURCE_VUPDATE4:
+	case DC_IRQ_SOURCE_VUPDATE5:
+	case DC_IRQ_SOURCE_VUPDATE6:
+		crtc_idx = src - DC_IRQ_SOURCE_VUPDATE1;
+		break;
+	case DC_IRQ_SOURCE_PFLIP1:
+	case DC_IRQ_SOURCE_PFLIP2:
+	case DC_IRQ_SOURCE_PFLIP3:
+	case DC_IRQ_SOURCE_PFLIP4:
+	case DC_IRQ_SOURCE_PFLIP5:
+	case DC_IRQ_SOURCE_PFLIP6:
+	case DC_IRQ_SOURCE_PFLIP_UNDERLAY0:
+		crtc_idx = src - DC_IRQ_SOURCE_PFLIP1;
+		break;
+	default:
+		dm_error("%s: invalid irq source: %d\n!" ,__func__, src);
+		return NULL;
+	}
+
+	for (i = 0; i < dc->current_context.target_count; i++) {
+		struct core_target *target = dc->current_context.targets[i];
+
+		struct dc_target *dc_target;
+
+		if (NULL == target) {
+			dm_error("%s: 'dc_target' is NULL for irq source: %d\n!",
+					__func__, src);
+			continue;
+		}
+
+		dc_target = &target->public;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			const struct core_stream *stream =
+				DC_STREAM_TO_CORE(dc_target->streams[j]);
+			const uint8_t controller_idx = stream->controller_idx;
+
+			if (controller_idx == crtc_idx)
+				return dc_target;
+		}
+	}
+
+	return NULL;
+}
+
+void dc_set_power_state(
+	struct dc *dc,
+	enum dc_acpi_cm_power_state power_state,
+	enum dc_video_power_state video_power_state)
+{
+	dc->previous_power_state = dc->current_power_state;
+	dc->current_power_state = video_power_state;
+
+	switch (power_state) {
+	case DC_ACPI_CM_POWER_STATE_D0:
+		init_hw(dc);
+		break;
+	default:
+		/* NULL means "reset/release all DC targets" */
+		dc_commit_targets(dc, NULL, 0);
+
+		dc->hwss.power_down(dc);
+		break;
+	}
+
+}
+
+void dc_resume(const struct dc *dc)
+{
+	uint32_t i;
+
+	for (i = 0; i < dc->link_count; i++)
+		core_link_resume(dc->links[i]);
+}
+
+bool dc_read_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size)
+{
+	struct core_link *link =
+			DC_LINK_TO_LINK(dc_get_link_at_index(dc, link_index));
+
+	enum ddc_result r = dal_ddc_service_read_dpcd_data(
+			link->ddc,
+			address,
+			data,
+			size);
+	return r == DDC_RESULT_SUCESSFULL;
+}
+
+bool dc_write_dpcd(
+		struct dc *dc,
+		uint32_t link_index,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t size)
+{
+	struct core_link *link =
+			DC_LINK_TO_LINK(dc_get_link_at_index(dc, link_index));
+
+	enum ddc_result r = dal_ddc_service_write_dpcd_data(
+			link->ddc,
+			address,
+			data,
+			size);
+	return r == DDC_RESULT_SUCESSFULL;
+}
+
+bool dc_submit_i2c(
+		struct dc *dc,
+		uint32_t link_index,
+		struct i2c_command *cmd)
+{
+	struct core_link *link =
+			DC_LINK_TO_LINK(dc_get_link_at_index(dc, link_index));
+	struct ddc_service *ddc = link->ddc;
+
+	return dal_i2caux_submit_i2c_command(
+		dal_adapter_service_get_i2caux(ddc->as),
+		ddc->ddc_pin,
+		cmd);
+}
+
+bool dc_link_add_remote_sink(const struct dc_link *link, struct dc_sink *sink)
+{
+	struct core_link *core_link = DC_LINK_TO_LINK(link);
+	struct dc_link *dc_link = &core_link->public;
+
+	if (dc_link->sink_count >= MAX_SINKS_PER_LINK) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	dc_link->remote_sinks[link->sink_count] = sink;
+	dc_link->sink_count++;
+
+	return true;
+}
+
+void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink)
+{
+	struct core_link *core_link = DC_LINK_TO_LINK(link);
+	struct dc_link *dc_link = &core_link->public;
+
+	dc_link->local_sink = sink;
+
+	if (sink == NULL) {
+		dc_link->sink_count = 0;
+		dc_link->type = dc_connection_none;
+	} else {
+		dc_link->sink_count = 1;
+		dc_link->type = dc_connection_single;
+	}
+}
+
+void dc_link_remove_remote_sink(const struct dc_link *link, const struct dc_sink *sink)
+{
+	int i;
+	struct core_link *core_link = DC_LINK_TO_LINK(link);
+	struct dc_link *dc_link = &core_link->public;
+
+	if (!link->sink_count) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+
+	for (i = 0; i < dc_link->sink_count; i++) {
+		if (dc_link->remote_sinks[i] == sink) {
+			dc_sink_release(sink);
+			dc_link->remote_sinks[i] = NULL;
+
+			/* shrink array to remove empty place */
+			while (i < dc_link->sink_count - 1) {
+				dc_link->remote_sinks[i] = dc_link->remote_sinks[i+1];
+				i++;
+			}
+
+			dc_link->sink_count--;
+			return;
+		}
+	}
+}
+
+uint8_t dc_get_dig_index(const struct dc_stream *stream)
+{
+
+	struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
+
+	switch (core_stream->stream_enc->id) {
+	case ENGINE_ID_DIGA:
+		return 0;
+	case ENGINE_ID_DIGB:
+		return 1;
+	case ENGINE_ID_DIGC:
+		return 2;
+	case ENGINE_ID_DIGD:
+		return 3;
+	case ENGINE_ID_DIGE:
+		return 4;
+	case ENGINE_ID_DIGF:
+		return 5;
+	case ENGINE_ID_DIGG:
+		return 6;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+enum gpio_ddc_line dc_get_ddc_line(
+		const struct dc_stream *stream)
+{
+
+	struct core_sink *core_sink = DC_SINK_TO_CORE(stream->sink);
+	struct ddc *ddc_line = dal_ddc_service_get_ddc_pin(
+			core_sink->link->ddc);
+
+	return dal_ddc_get_line(ddc_line);
+}
+
+enum signal_type dc_get_display_signal(
+		const struct dc_stream *stream)
+{
+	return stream->sink->sink_signal;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
new file mode 100644
index 000000000000..db4f1313e056
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_hw_sequencer.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+#include "core_types.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce100/dce100_hw_sequencer.h"
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/dce110_hw_sequencer.h"
+#endif
+
+bool dc_construct_hw_sequencer(
+				struct adapter_service *adapter_serv,
+				struct dc *dc)
+{
+	enum dce_version dce_ver = dal_adapter_service_get_dce_version(adapter_serv);
+
+	switch (dce_ver)
+	{
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dce100_hw_sequencer_construct(dc);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dce110_hw_sequencer_construct(dc);
+#endif
+	default:
+		break;
+	}
+
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
new file mode 100644
index 000000000000..091299336d0e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
@@ -0,0 +1,1645 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "dc.h"
+#include "core_dc.h"
+#include "adapter_service_interface.h"
+#include "grph_object_id.h"
+#include "gpio_service_interface.h"
+#include "core_status.h"
+#include "dc_link_dp.h"
+#include "dc_link_ddc.h"
+#include "link_hwss.h"
+#include "stream_encoder.h"
+#include "link_encoder.h"
+#include "hw_sequencer.h"
+#include "fixed31_32.h"
+
+
+#define LINK_INFO(...) \
+	dal_logger_write(dc_ctx->logger, \
+		LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_HOTPLUG, \
+		__VA_ARGS__)
+
+
+/*******************************************************************************
+ * Private structures
+ ******************************************************************************/
+
+enum {
+	LINK_RATE_REF_FREQ_IN_MHZ = 27,
+	PEAK_FACTOR_X1000 = 1006
+};
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static void destruct(struct core_link *link)
+{
+	if (link->ddc)
+		dal_ddc_service_destroy(&link->ddc);
+
+	if(link->link_enc)
+		link->ctx->dc->res_pool.funcs->link_enc_destroy(&link->link_enc);
+}
+
+/*
+ *  Function: program_hpd_filter
+ *
+ *  @brief
+ *     Programs HPD filter on associated HPD line
+ *
+ *  @param [in] delay_on_connect_in_ms: Connect filter timeout
+ *  @param [in] delay_on_disconnect_in_ms: Disconnect filter timeout
+ *
+ *  @return
+ *     true on success, false otherwise
+ */
+static bool program_hpd_filter(
+	const struct core_link *link)
+{
+	bool result = false;
+
+	struct irq *hpd;
+
+	int delay_on_connect_in_ms = 0;
+	int delay_on_disconnect_in_ms = 0;
+
+	/* Verify feature is supported */
+	switch (link->public.connector_signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		/* Program hpd filter */
+		delay_on_connect_in_ms = 500;
+		delay_on_disconnect_in_ms = 100;
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		/* Program hpd filter to allow DP signal to settle */
+		delay_on_connect_in_ms = 20;
+		delay_on_disconnect_in_ms = 0;
+		break;
+	case SIGNAL_TYPE_LVDS:
+	case SIGNAL_TYPE_EDP:
+	default:
+		/* Don't program hpd filter */
+		return false;
+	}
+
+	/* Obtain HPD handle */
+	hpd = dal_adapter_service_obtain_hpd_irq(
+		link->adapter_srv, link->link_id);
+
+	if (!hpd)
+		return result;
+
+	/* Setup HPD filtering */
+	if (dal_irq_open(hpd) == GPIO_RESULT_OK) {
+		struct gpio_hpd_config config;
+
+		config.delay_on_connect = delay_on_connect_in_ms;
+		config.delay_on_disconnect = delay_on_disconnect_in_ms;
+
+		dal_irq_setup_hpd_filter(hpd, &config);
+
+		dal_irq_close(hpd);
+
+		result = true;
+	} else {
+		ASSERT_CRITICAL(false);
+	}
+
+	/* Release HPD handle */
+	dal_adapter_service_release_irq(link->adapter_srv, hpd);
+
+	return result;
+}
+
+static bool detect_sink(struct core_link *link, enum dc_connection_type *type)
+{
+	uint32_t is_hpd_high = 0;
+	struct irq *hpd_pin;
+
+	/* todo: may need to lock gpio access */
+	hpd_pin = dal_adapter_service_obtain_hpd_irq(
+			link->adapter_srv,
+			link->link_id);
+	if (hpd_pin == NULL)
+		goto hpd_gpio_failure;
+
+	dal_irq_open(hpd_pin);
+	dal_irq_get_value(hpd_pin, &is_hpd_high);
+	dal_irq_close(hpd_pin);
+	dal_adapter_service_release_irq(
+		link->adapter_srv,
+		hpd_pin);
+
+	if (is_hpd_high) {
+		*type = dc_connection_single;
+		/* TODO: need to do the actual detection */
+	} else {
+		*type = dc_connection_none;
+	}
+
+	return true;
+
+hpd_gpio_failure:
+	return false;
+}
+
+
+enum ddc_transaction_type get_ddc_transaction_type(
+		enum signal_type sink_signal)
+{
+	enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE;
+
+
+	switch (sink_signal) {
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	case SIGNAL_TYPE_LVDS:
+	case SIGNAL_TYPE_RGB:
+		transaction_type = DDC_TRANSACTION_TYPE_I2C;
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_EDP:
+		transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+		break;
+
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		/* MST does not use I2COverAux, but there is the
+		 * SPECIAL use case for "immediate dwnstrm device
+		 * access" (EPR#370830). */
+		transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+		break;
+
+	default:
+		break;
+	}
+
+
+	return transaction_type;
+}
+
+static enum signal_type get_basic_signal_type(
+	struct graphics_object_id encoder,
+	struct graphics_object_id downstream)
+{
+	if (downstream.type == OBJECT_TYPE_CONNECTOR) {
+		switch (downstream.id) {
+		case CONNECTOR_ID_SINGLE_LINK_DVII:
+			switch (encoder.id) {
+			case ENCODER_ID_INTERNAL_DAC1:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+			case ENCODER_ID_INTERNAL_DAC2:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+				return SIGNAL_TYPE_RGB;
+			default:
+				return SIGNAL_TYPE_DVI_SINGLE_LINK;
+			}
+		break;
+		case CONNECTOR_ID_DUAL_LINK_DVII:
+		{
+			switch (encoder.id) {
+			case ENCODER_ID_INTERNAL_DAC1:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+			case ENCODER_ID_INTERNAL_DAC2:
+			case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+				return SIGNAL_TYPE_RGB;
+			default:
+				return SIGNAL_TYPE_DVI_DUAL_LINK;
+			}
+		}
+		break;
+		case CONNECTOR_ID_SINGLE_LINK_DVID:
+			return SIGNAL_TYPE_DVI_SINGLE_LINK;
+		case CONNECTOR_ID_DUAL_LINK_DVID:
+			return SIGNAL_TYPE_DVI_DUAL_LINK;
+		case CONNECTOR_ID_VGA:
+			return SIGNAL_TYPE_RGB;
+		case CONNECTOR_ID_HDMI_TYPE_A:
+			return SIGNAL_TYPE_HDMI_TYPE_A;
+		case CONNECTOR_ID_LVDS:
+			return SIGNAL_TYPE_LVDS;
+		case CONNECTOR_ID_DISPLAY_PORT:
+			return SIGNAL_TYPE_DISPLAY_PORT;
+		case CONNECTOR_ID_EDP:
+			return SIGNAL_TYPE_EDP;
+		default:
+			return SIGNAL_TYPE_NONE;
+		}
+	} else if (downstream.type == OBJECT_TYPE_ENCODER) {
+		switch (downstream.id) {
+		case ENCODER_ID_EXTERNAL_NUTMEG:
+		case ENCODER_ID_EXTERNAL_TRAVIS:
+			return SIGNAL_TYPE_DISPLAY_PORT;
+		default:
+			return SIGNAL_TYPE_NONE;
+		}
+	}
+
+	return SIGNAL_TYPE_NONE;
+}
+
+/*
+ * @brief
+ * Check whether there is a dongle on DP connector
+ */
+static bool is_dp_sink_present(struct core_link *link)
+{
+	enum gpio_result gpio_result;
+	uint32_t clock_pin = 0;
+	uint32_t data_pin = 0;
+
+	struct ddc *ddc;
+
+	enum connector_id connector_id =
+		dal_graphics_object_id_get_connector_id(link->link_id);
+
+	bool present =
+		((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
+		(connector_id == CONNECTOR_ID_EDP));
+
+	ddc = dal_adapter_service_obtain_ddc(link->adapter_srv, link->link_id);
+
+	if (!ddc)
+		return present;
+
+	/* Open GPIO and set it to I2C mode */
+	/* Note: this GpioMode_Input will be converted
+	 * to GpioConfigType_I2cAuxDualMode in GPIO component,
+	 * which indicates we need additional delay */
+
+	if (GPIO_RESULT_OK != dal_ddc_open(
+		ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
+		dal_adapter_service_release_ddc(link->adapter_srv, ddc);
+
+		return present;
+	}
+
+	/* Read GPIO: DP sink is present if both clock and data pins are zero */
+	/* [anaumov] in DAL2, there was no check for GPIO failure */
+
+	gpio_result = dal_ddc_get_clock(ddc, &clock_pin);
+	ASSERT(gpio_result == GPIO_RESULT_OK);
+
+	if (gpio_result == GPIO_RESULT_OK)
+		if (link->link_enc->features.flags.bits.
+						DP_SINK_DETECT_POLL_DATA_PIN)
+			gpio_result = dal_ddc_get_data(ddc, &data_pin);
+
+	present = (gpio_result == GPIO_RESULT_OK) && !(clock_pin || data_pin);
+
+	dal_ddc_close(ddc);
+
+	dal_adapter_service_release_ddc(link->adapter_srv, ddc);
+
+	return present;
+}
+
+/*
+ * @brief
+ * Detect output sink type
+ */
+static enum signal_type link_detect_sink(struct core_link *link)
+{
+	enum signal_type result = get_basic_signal_type(
+		link->link_enc->id, link->link_id);
+
+	/* Internal digital encoder will detect only dongles
+	 * that require digital signal */
+
+	/* Detection mechanism is different
+	 * for different native connectors.
+	 * LVDS connector supports only LVDS signal;
+	 * PCIE is a bus slot, the actual connector needs to be detected first;
+	 * eDP connector supports only eDP signal;
+	 * HDMI should check straps for audio */
+
+	/* PCIE detects the actual connector on add-on board */
+
+	if (link->link_id.id == CONNECTOR_ID_PCIE) {
+		/* ZAZTODO implement PCIE add-on card detection */
+	}
+
+	switch (link->link_id.id) {
+	case CONNECTOR_ID_HDMI_TYPE_A: {
+		/* check audio support:
+		 * if native HDMI is not supported, switch to DVI */
+		union audio_support audio_support =
+			dal_adapter_service_get_audio_support(
+				link->adapter_srv);
+
+		if (!audio_support.bits.HDMI_AUDIO_NATIVE)
+			if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A)
+				result = SIGNAL_TYPE_DVI_SINGLE_LINK;
+	}
+	break;
+	case CONNECTOR_ID_DISPLAY_PORT: {
+
+		/* Check whether DP signal detected: if not -
+		 * we assume signal is DVI; it could be corrected
+		 * to HDMI after dongle detection */
+		if (!is_dp_sink_present(link))
+			result = SIGNAL_TYPE_DVI_SINGLE_LINK;
+	}
+	break;
+	default:
+	break;
+	}
+
+	return result;
+}
+
+static enum signal_type decide_signal_from_strap_and_dongle_type(
+		enum display_dongle_type dongle_type,
+		union audio_support *audio_support)
+{
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+
+	switch (dongle_type) {
+	case DISPLAY_DONGLE_DP_HDMI_DONGLE:
+		if (audio_support->bits.HDMI_AUDIO_ON_DONGLE)
+			signal =  SIGNAL_TYPE_HDMI_TYPE_A;
+		else
+			signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	case DISPLAY_DONGLE_DP_DVI_DONGLE:
+		signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE:
+		if (audio_support->bits.HDMI_AUDIO_NATIVE)
+			signal =  SIGNAL_TYPE_HDMI_TYPE_A;
+		else
+			signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	default:
+		signal = SIGNAL_TYPE_NONE;
+		break;
+	}
+
+	return signal;
+}
+
+static enum signal_type dp_passive_dongle_detection(
+		struct ddc_service *ddc,
+		struct display_sink_capability *sink_cap,
+		union audio_support *audio_support)
+{
+	/* TODO:These 2 functions should be protected for upstreaming purposes
+	 * in case hackers want to save 10 cents hdmi license fee
+	 */
+	dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
+						ddc, sink_cap);
+	return decide_signal_from_strap_and_dongle_type(
+			sink_cap->dongle_type,
+			audio_support);
+}
+
+static void link_disconnect_sink(struct core_link *link)
+{
+	if (link->public.local_sink) {
+		dc_sink_release(link->public.local_sink);
+		link->public.local_sink = NULL;
+	}
+
+	link->dpcd_sink_count = 0;
+}
+
+static enum dc_edid_status read_edid(
+	struct core_link *link,
+	struct core_sink *sink)
+{
+	uint32_t edid_retry = 3;
+	enum dc_edid_status edid_status;
+
+	/* some dongles read edid incorrectly the first time,
+	 * do check sum and retry to make sure read correct edid.
+	 */
+	do {
+		sink->public.dc_edid.length =
+				dal_ddc_service_edid_query(link->ddc);
+
+		if (0 == sink->public.dc_edid.length)
+			return EDID_NO_RESPONSE;
+
+		dal_ddc_service_get_edid_buf(link->ddc,
+				sink->public.dc_edid.raw_edid);
+		edid_status = dm_helpers_parse_edid_caps(
+				sink->ctx,
+				&sink->public.dc_edid,
+				&sink->public.edid_caps);
+		--edid_retry;
+		if (edid_status == EDID_BAD_CHECKSUM)
+			dal_logger_write(link->ctx->logger,
+					LOG_MAJOR_WARNING,
+					LOG_MINOR_DETECTION_EDID_PARSER,
+					"Bad EDID checksum, retry remain: %d\n",
+					edid_retry);
+	} while (edid_status == EDID_BAD_CHECKSUM && edid_retry > 0);
+
+	return edid_status;
+}
+
+static void detect_dp(
+	struct core_link *link,
+	struct display_sink_capability *sink_caps,
+	bool *converter_disable_audio,
+	union audio_support *audio_support,
+	bool boot)
+{
+	sink_caps->signal = link_detect_sink(link);
+	sink_caps->transaction_type =
+		get_ddc_transaction_type(sink_caps->signal);
+
+	if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
+		sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
+		detect_dp_sink_caps(link);
+
+		/* DP active dongles */
+		if (is_dp_active_dongle(link)) {
+			if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
+				link->public.type = dc_connection_none;
+				/*
+				 * active dongle unplug processing for short irq
+				 */
+				link_disconnect_sink(link);
+				return;
+			}
+
+			if (link->dpcd_caps.dongle_type !=
+			DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
+				*converter_disable_audio = true;
+			}
+		}
+		if (is_mst_supported(link)) {
+			sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
+
+			/*
+			 * This call will initiate MST topology discovery. Which
+			 * will detect MST ports and add new DRM connector DRM
+			 * framework. Then read EDID via remote i2c over aux. In
+			 * the end, will notify DRM detect result and save EDID
+			 * into DRM framework.
+			 *
+			 * .detect is called by .fill_modes.
+			 * .fill_modes is called by user mode ioctl
+			 * DRM_IOCTL_MODE_GETCONNECTOR.
+			 *
+			 * .get_modes is called by .fill_modes.
+			 *
+			 * call .get_modes, AMDGPU DM implementation will create
+			 * new dc_sink and add to dc_link. For long HPD plug
+			 * in/out, MST has its own handle.
+			 *
+			 * Therefore, just after dc_create, link->sink is not
+			 * created for MST until user mode app calls
+			 * DRM_IOCTL_MODE_GETCONNECTOR.
+			 *
+			 * Need check ->sink usages in case ->sink = NULL
+			 * TODO: s3 resume check
+			 */
+
+			if (dm_helpers_dp_mst_start_top_mgr(
+				link->ctx,
+				&link->public, boot)) {
+				link->public.type = dc_connection_mst_branch;
+			} else {
+				/* MST not supported */
+				sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
+			}
+		}
+	} else {
+		/* DP passive dongles */
+		sink_caps->signal = dp_passive_dongle_detection(link->ddc,
+				sink_caps,
+				audio_support);
+	}
+}
+
+bool dc_link_detect(const struct dc_link *dc_link, bool boot)
+{
+	struct core_link *link = DC_LINK_TO_LINK(dc_link);
+	struct dc_sink_init_data sink_init_data = { 0 };
+	struct display_sink_capability sink_caps = { 0 };
+	uint8_t i;
+	bool converter_disable_audio = false;
+	union audio_support audio_support =
+		dal_adapter_service_get_audio_support(
+			link->adapter_srv);
+	enum dc_edid_status edid_status;
+	struct dc_context *dc_ctx = link->ctx;
+	struct dc_sink *dc_sink;
+	struct core_sink *sink = NULL;
+	enum dc_connection_type new_connection_type = dc_connection_none;
+
+	if (link->public.connector_signal == SIGNAL_TYPE_VIRTUAL)
+		return false;
+
+	if (false == detect_sink(link, &new_connection_type)) {
+		BREAK_TO_DEBUGGER();
+		return false;
+	}
+
+	link_disconnect_sink(link);
+
+	if (new_connection_type != dc_connection_none) {
+		link->public.type = new_connection_type;
+
+		/* From Disconnected-to-Connected. */
+		switch (link->public.connector_signal) {
+		case SIGNAL_TYPE_HDMI_TYPE_A: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			if (audio_support.bits.HDMI_AUDIO_NATIVE)
+				sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+			else
+				sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+			break;
+		}
+
+		case SIGNAL_TYPE_DVI_SINGLE_LINK: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+			break;
+		}
+
+		case SIGNAL_TYPE_DVI_DUAL_LINK: {
+			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+			sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+			break;
+		}
+
+		case SIGNAL_TYPE_EDP: {
+			detect_dp_sink_caps(link);
+			sink_caps.transaction_type =
+				DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+			sink_caps.signal = SIGNAL_TYPE_EDP;
+			break;
+		}
+
+		case SIGNAL_TYPE_DISPLAY_PORT: {
+			detect_dp(
+				link,
+				&sink_caps,
+				&converter_disable_audio,
+				&audio_support, boot);
+
+			/* Active dongle downstream unplug */
+			if (link->public.type == dc_connection_none)
+				return true;
+
+			if (link->public.type == dc_connection_mst_branch) {
+				LINK_INFO("link=%d, mst branch is now Connected\n",
+					link->public.link_index);
+				return false;
+			}
+
+			break;
+		}
+
+		default:
+			DC_ERROR("Invalid connector type! signal:%d\n",
+				link->public.connector_signal);
+			return false;
+		} /* switch() */
+
+		if (link->dpcd_caps.sink_count.bits.SINK_COUNT)
+			link->dpcd_sink_count = link->dpcd_caps.sink_count.
+					bits.SINK_COUNT;
+			else
+				link->dpcd_sink_count = 1;
+
+
+		dal_ddc_service_set_transaction_type(
+						link->ddc,
+						sink_caps.transaction_type);
+
+		sink_init_data.link = &link->public;
+		sink_init_data.sink_signal = sink_caps.signal;
+		sink_init_data.dongle_max_pix_clk =
+			sink_caps.max_hdmi_pixel_clock;
+		sink_init_data.converter_disable_audio =
+			converter_disable_audio;
+
+		dc_sink = dc_sink_create(&sink_init_data);
+		if (!dc_sink) {
+			DC_ERROR("Failed to create sink!\n");
+			return false;
+		}
+
+		sink = DC_SINK_TO_CORE(dc_sink);
+		link->public.local_sink = &sink->public;
+
+		edid_status = read_edid(link, sink);
+
+		switch (edid_status) {
+		case EDID_BAD_CHECKSUM:
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_DETECTION_EDID_PARSER,
+				"EDID checksum invalid.\n");
+			break;
+		case EDID_NO_RESPONSE:
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_DETECTION_EDID_PARSER,
+				"No EDID read.\n");
+			return false;
+
+		default:
+			break;
+		}
+
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_DETECTION,
+			LOG_MINOR_DETECTION_EDID_PARSER,
+			"%s: "
+			"manufacturer_id = %X, "
+			"product_id = %X, "
+			"serial_number = %X, "
+			"manufacture_week = %d, "
+			"manufacture_year = %d, "
+			"display_name = %s, "
+			"speaker_flag = %d, "
+			"audio_mode_count = %d\n",
+			__func__,
+			sink->public.edid_caps.manufacturer_id,
+			sink->public.edid_caps.product_id,
+			sink->public.edid_caps.serial_number,
+			sink->public.edid_caps.manufacture_week,
+			sink->public.edid_caps.manufacture_year,
+			sink->public.edid_caps.display_name,
+			sink->public.edid_caps.speaker_flags,
+			sink->public.edid_caps.audio_mode_count);
+
+		for (i = 0; i < sink->public.edid_caps.audio_mode_count; i++) {
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_DETECTION,
+				LOG_MINOR_DETECTION_EDID_PARSER,
+				"%s: mode number = %d, "
+				"format_code = %d, "
+				"channel_count = %d, "
+				"sample_rate = %d, "
+				"sample_size = %d\n",
+				__func__,
+				i,
+				sink->public.edid_caps.audio_modes[i].format_code,
+				sink->public.edid_caps.audio_modes[i].channel_count,
+				sink->public.edid_caps.audio_modes[i].sample_rate,
+				sink->public.edid_caps.audio_modes[i].sample_size);
+		}
+
+	} else {
+		/* From Connected-to-Disconnected. */
+		if (link->public.type == dc_connection_mst_branch) {
+			LINK_INFO("link=%d, mst branch is now Disconnected\n",
+				link->public.link_index);
+			dm_helpers_dp_mst_stop_top_mgr(link->ctx, &link->public);
+		}
+
+		link->public.type = dc_connection_none;
+		sink_caps.signal = SIGNAL_TYPE_NONE;
+	}
+
+	LINK_INFO("link=%d, dc_sink_in=%p is now %s\n",
+		link->public.link_index, &sink->public,
+		(sink_caps.signal == SIGNAL_TYPE_NONE ?
+			"Disconnected":"Connected"));
+
+	return true;
+}
+
+static enum hpd_source_id get_hpd_line(
+		struct core_link *link,
+		struct adapter_service *as)
+{
+	struct irq *hpd;
+	enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN;
+
+	hpd = dal_adapter_service_obtain_hpd_irq(as, link->link_id);
+
+	if (hpd) {
+		switch (dal_irq_get_source(hpd)) {
+		case DC_IRQ_SOURCE_HPD1:
+			hpd_id = HPD_SOURCEID1;
+		break;
+		case DC_IRQ_SOURCE_HPD2:
+			hpd_id = HPD_SOURCEID2;
+		break;
+		case DC_IRQ_SOURCE_HPD3:
+			hpd_id = HPD_SOURCEID3;
+		break;
+		case DC_IRQ_SOURCE_HPD4:
+			hpd_id = HPD_SOURCEID4;
+		break;
+		case DC_IRQ_SOURCE_HPD5:
+			hpd_id = HPD_SOURCEID5;
+		break;
+		case DC_IRQ_SOURCE_HPD6:
+			hpd_id = HPD_SOURCEID6;
+		break;
+		default:
+			BREAK_TO_DEBUGGER();
+		break;
+		}
+
+		dal_adapter_service_release_irq(as, hpd);
+	}
+
+	return hpd_id;
+}
+
+static enum channel_id get_ddc_line(struct core_link *link, struct adapter_service *as)
+{
+	struct ddc *ddc;
+	enum channel_id channel = CHANNEL_ID_UNKNOWN;
+
+	ddc = dal_adapter_service_obtain_ddc(as, link->link_id);
+
+	if (ddc) {
+		switch (dal_ddc_get_line(ddc)) {
+		case GPIO_DDC_LINE_DDC1:
+			channel = CHANNEL_ID_DDC1;
+			break;
+		case GPIO_DDC_LINE_DDC2:
+			channel = CHANNEL_ID_DDC2;
+			break;
+		case GPIO_DDC_LINE_DDC3:
+			channel = CHANNEL_ID_DDC3;
+			break;
+		case GPIO_DDC_LINE_DDC4:
+			channel = CHANNEL_ID_DDC4;
+			break;
+		case GPIO_DDC_LINE_DDC5:
+			channel = CHANNEL_ID_DDC5;
+			break;
+		case GPIO_DDC_LINE_DDC6:
+			channel = CHANNEL_ID_DDC6;
+			break;
+		case GPIO_DDC_LINE_DDC_VGA:
+			channel = CHANNEL_ID_DDC_VGA;
+			break;
+		case GPIO_DDC_LINE_I2C_PAD:
+			channel = CHANNEL_ID_I2C_PAD;
+			break;
+		default:
+			BREAK_TO_DEBUGGER();
+			break;
+		}
+
+		dal_adapter_service_release_ddc(as, ddc);
+	}
+
+	return channel;
+}
+
+static enum transmitter translate_encoder_to_transmitter(
+	struct graphics_object_id encoder)
+{
+	switch (encoder.id) {
+	case ENCODER_ID_INTERNAL_UNIPHY:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_A;
+		case ENUM_ID_2:
+			return TRANSMITTER_UNIPHY_B;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_INTERNAL_UNIPHY1:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_C;
+		case ENUM_ID_2:
+			return TRANSMITTER_UNIPHY_D;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_INTERNAL_UNIPHY2:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_E;
+		case ENUM_ID_2:
+			return TRANSMITTER_UNIPHY_F;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_INTERNAL_UNIPHY3:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_UNIPHY_G;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_EXTERNAL_NUTMEG:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_NUTMEG_CRT;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	case ENCODER_ID_EXTERNAL_TRAVIS:
+		switch (encoder.enum_id) {
+		case ENUM_ID_1:
+			return TRANSMITTER_TRAVIS_CRT;
+		case ENUM_ID_2:
+			return TRANSMITTER_TRAVIS_LCD;
+		default:
+			return TRANSMITTER_UNKNOWN;
+		}
+	break;
+	default:
+		return TRANSMITTER_UNKNOWN;
+	}
+}
+
+
+static bool construct(
+	struct core_link *link,
+	const struct link_init_data *init_params)
+{
+	uint8_t i;
+	struct adapter_service *as = init_params->adapter_srv;
+	struct irq *hpd_gpio = NULL;
+	struct ddc_service_init_data ddc_service_init_data = { 0 };
+	struct dc_context *dc_ctx = init_params->ctx;
+	struct encoder_init_data enc_init_data = { 0 };
+	struct integrated_info info = {{{ 0 }}};
+
+	link->dc = init_params->dc;
+	link->adapter_srv = as;
+	link->ctx = dc_ctx;
+	link->public.link_index = init_params->link_index;
+
+	link->link_id = dal_adapter_service_get_connector_obj_id(
+			as,
+			init_params->connector_index);
+
+	if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
+		dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d!\n",
+				__func__, init_params->connector_index);
+		goto create_fail;
+	}
+
+	switch (link->link_id.id) {
+	case CONNECTOR_ID_HDMI_TYPE_A:
+		link->public.connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
+		break;
+	case CONNECTOR_ID_SINGLE_LINK_DVID:
+	case CONNECTOR_ID_SINGLE_LINK_DVII:
+		link->public.connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+		break;
+	case CONNECTOR_ID_DUAL_LINK_DVID:
+	case CONNECTOR_ID_DUAL_LINK_DVII:
+		link->public.connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+		break;
+	case CONNECTOR_ID_DISPLAY_PORT:
+		link->public.connector_signal =	SIGNAL_TYPE_DISPLAY_PORT;
+		hpd_gpio = dal_adapter_service_obtain_hpd_irq(
+					as,
+					link->link_id);
+
+		if (hpd_gpio != NULL) {
+			link->public.irq_source_hpd_rx =
+					dal_irq_get_rx_source(hpd_gpio);
+			dal_adapter_service_release_irq(
+					as, hpd_gpio);
+		}
+
+		break;
+	case CONNECTOR_ID_EDP:
+		link->public.connector_signal = SIGNAL_TYPE_EDP;
+		hpd_gpio = dal_adapter_service_obtain_hpd_irq(
+					as,
+					link->link_id);
+
+		if (hpd_gpio != NULL) {
+			link->public.irq_source_hpd_rx =
+					dal_irq_get_rx_source(hpd_gpio);
+			dal_adapter_service_release_irq(
+					as, hpd_gpio);
+		}
+		break;
+	default:
+		dal_logger_write(dc_ctx->logger,
+			LOG_MAJOR_WARNING, LOG_MINOR_TM_LINK_SRV,
+			"Unsupported Connector type:%d!\n", link->link_id.id);
+		goto create_fail;
+	}
+
+	/* TODO: #DAL3 Implement id to str function.*/
+	LINK_INFO("Connector[%d] description:"
+			"signal %d\n",
+			init_params->connector_index,
+			link->public.connector_signal);
+
+	hpd_gpio = dal_adapter_service_obtain_hpd_irq(as, link->link_id);
+
+	if (hpd_gpio != NULL) {
+		link->public.irq_source_hpd = dal_irq_get_source(hpd_gpio);
+		dal_adapter_service_release_irq(as, hpd_gpio);
+	}
+
+	ddc_service_init_data.as = as;
+	ddc_service_init_data.ctx = link->ctx;
+	ddc_service_init_data.id = link->link_id;
+	ddc_service_init_data.link = link;
+	link->ddc = dal_ddc_service_create(&ddc_service_init_data);
+
+	if (NULL == link->ddc) {
+		DC_ERROR("Failed to create ddc_service!\n");
+		goto create_fail;
+	}
+
+	enc_init_data.adapter_service = as;
+	enc_init_data.ctx = dc_ctx;
+	enc_init_data.encoder = dal_adapter_service_get_src_obj(
+							as, link->link_id, 0);
+	enc_init_data.connector = link->link_id;
+	enc_init_data.channel = get_ddc_line(link, as);
+	enc_init_data.hpd_source = get_hpd_line(link, as);
+	enc_init_data.transmitter =
+			translate_encoder_to_transmitter(enc_init_data.encoder);
+	link->link_enc = dc_ctx->dc->res_pool.funcs->link_enc_create(
+								&enc_init_data);
+
+	if( link->link_enc == NULL) {
+		DC_ERROR("Failed to create link encoder!\n");
+		goto create_fail;
+	}
+
+	dal_adapter_service_get_integrated_info(as, &info);
+
+	for (i = 0; ; i++) {
+		if (!dal_adapter_service_get_device_tag(
+				as, link->link_id, i, &link->device_tag)) {
+			DC_ERROR("Failed to find device tag!\n");
+			goto create_fail;
+		}
+
+		/* Look for device tag that matches connector signal,
+		 * CRT for rgb, LCD for other supported signal tyes
+		 */
+		if (!dal_adapter_service_is_device_id_supported(
+						as, link->device_tag.dev_id))
+			continue;
+		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT
+			&& link->public.connector_signal != SIGNAL_TYPE_RGB)
+			continue;
+		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD
+			&& link->public.connector_signal == SIGNAL_TYPE_RGB)
+			continue;
+		if (link->device_tag.dev_id.device_type == DEVICE_TYPE_WIRELESS
+			&& link->public.connector_signal != SIGNAL_TYPE_WIRELESS)
+			continue;
+		break;
+	}
+
+	/* Look for channel mapping corresponding to connector and device tag */
+	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
+		struct external_display_path *path =
+			&info.ext_disp_conn_info.path[i];
+		if (path->device_connector_id.enum_id == link->link_id.enum_id
+			&& path->device_connector_id.id == link->link_id.id
+			&& path->device_connector_id.type == link->link_id.type
+			&& path->device_acpi_enum
+					== link->device_tag.acpi_device) {
+			link->ddi_channel_mapping = path->channel_mapping;
+			break;
+		}
+	}
+
+	/*
+	 * TODO check if GPIO programmed correctly
+	 *
+	 * If GPIO isn't programmed correctly HPD might not rise or drain
+	 * fast enough, leading to bounces.
+	 */
+	program_hpd_filter(link);
+
+	return true;
+
+create_fail:
+	return false;
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+struct core_link *link_create(const struct link_init_data *init_params)
+{
+	struct core_link *link =
+			dm_alloc(init_params->ctx, sizeof(*link));
+
+	if (NULL == link)
+		goto alloc_fail;
+
+	if (false == construct(link, init_params))
+		goto construct_fail;
+
+	return link;
+
+construct_fail:
+	dm_free(init_params->ctx, link);
+
+alloc_fail:
+	return NULL;
+}
+
+void link_destroy(struct core_link **link)
+{
+	destruct(*link);
+	dm_free((*link)->ctx, *link);
+	*link = NULL;
+}
+
+static void dpcd_configure_panel_mode(
+	struct core_link *link,
+	enum dp_panel_mode panel_mode)
+{
+	union dpcd_edp_config edp_config_set;
+	bool panel_mode_edp = false;
+
+	dm_memset(&edp_config_set, '\0', sizeof(union dpcd_edp_config));
+
+	if (DP_PANEL_MODE_DEFAULT != panel_mode) {
+
+		switch (panel_mode) {
+		case DP_PANEL_MODE_EDP:
+		case DP_PANEL_MODE_SPECIAL:
+			panel_mode_edp = true;
+			break;
+
+		default:
+			break;
+		}
+
+		/*set edp panel mode in receiver*/
+		core_link_read_dpcd(
+			link,
+			DPCD_ADDRESS_EDP_CONFIG_SET,
+			&edp_config_set.raw,
+			sizeof(edp_config_set.raw));
+
+		if (edp_config_set.bits.PANEL_MODE_EDP
+			!= panel_mode_edp) {
+			enum ddc_result result = DDC_RESULT_UNKNOWN;
+
+			edp_config_set.bits.PANEL_MODE_EDP =
+			panel_mode_edp;
+			result = core_link_write_dpcd(
+				link,
+				DPCD_ADDRESS_EDP_CONFIG_SET,
+				&edp_config_set.raw,
+				sizeof(edp_config_set.raw));
+
+			ASSERT(result == DDC_RESULT_SUCESSFULL);
+		}
+	}
+	dal_logger_write(link->ctx->logger, LOG_MAJOR_DETECTION,
+			LOG_MINOR_DETECTION_DP_CAPS,
+			"Link: %d eDP panel mode supported: %d "
+			"eDP panel mode enabled: %d \n",
+			link->public.link_index,
+			link->dpcd_caps.panel_mode_edp,
+			panel_mode_edp);
+}
+
+static enum dc_status enable_link_dp(struct core_stream *stream)
+{
+	enum dc_status status;
+	bool skip_video_pattern;
+	struct core_link *link = stream->sink->link;
+	struct link_settings link_settings = {0};
+	enum dp_panel_mode panel_mode;
+
+	/* get link settings for video mode timing */
+	decide_link_settings(stream, &link_settings);
+	dp_enable_link_phy(
+		stream->sink->link,
+		stream->signal,
+		&link_settings);
+
+	panel_mode = dp_get_panel_mode(link);
+	dpcd_configure_panel_mode(link, panel_mode);
+
+	skip_video_pattern = true;
+
+	if (link_settings.link_rate == LINK_RATE_LOW)
+			skip_video_pattern = false;
+
+	if (perform_link_training(link, &link_settings, skip_video_pattern)) {
+		link->cur_link_settings = link_settings;
+		status = DC_OK;
+	}
+	else
+		status = DC_ERROR_UNEXPECTED;
+
+	return status;
+}
+
+static enum dc_status enable_link_dp_mst(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+
+	/* sink signal type after MST branch is MST. Multiple MST sinks
+	 * share one link. Link DP PHY is enable or training only once.
+	 */
+	if (link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN)
+		return DC_OK;
+
+	return enable_link_dp(stream);
+}
+
+static void enable_link_hdmi(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+
+	/* enable video output */
+	/* here we need to specify that encoder output settings
+	 * need to be calculated as for the set mode,
+	 * it will lead to querying dynamic link capabilities
+	 * which should be done before enable output */
+	uint32_t normalized_pix_clk = stream->public.timing.pix_clk_khz;
+	switch (stream->public.timing.display_color_depth) {
+	case COLOR_DEPTH_888:
+		break;
+	case COLOR_DEPTH_101010:
+		normalized_pix_clk = (normalized_pix_clk * 30) / 24;
+		break;
+	case COLOR_DEPTH_121212:
+		normalized_pix_clk = (normalized_pix_clk * 36) / 24;
+		break;
+	case COLOR_DEPTH_161616:
+		normalized_pix_clk = (normalized_pix_clk * 48) / 24;
+		break;
+	default:
+		break;
+	}
+
+	if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		dal_ddc_service_write_scdc_data(
+			stream->sink->link->ddc,
+			normalized_pix_clk,
+			stream->public.timing.flags.LTE_340MCSC_SCRAMBLE);
+
+	dm_memset(&stream->sink->link->cur_link_settings, 0,
+			sizeof(struct link_settings));
+
+	link->link_enc->funcs->enable_tmds_output(
+			link->link_enc,
+			stream->clock_source->id,
+			stream->public.timing.display_color_depth,
+			stream->signal == SIGNAL_TYPE_HDMI_TYPE_A,
+			stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK,
+			stream->public.timing.pix_clk_khz);
+
+	if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+		dal_ddc_service_read_scdc_data(link->ddc);
+}
+
+/****************************enable_link***********************************/
+static enum dc_status enable_link(struct core_stream *stream)
+{
+	enum dc_status status = DC_ERROR_UNEXPECTED;
+	switch (stream->signal) {
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_EDP:
+		status = enable_link_dp(stream);
+		break;
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		status = enable_link_dp_mst(stream);
+		dm_sleep_in_milliseconds(stream->ctx, 200);
+		break;
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		enable_link_hdmi(stream);
+		status = DC_OK;
+		break;
+	case SIGNAL_TYPE_VIRTUAL:
+		status = DC_OK;
+		break;
+	default:
+		break;
+	}
+
+	if (stream->audio && status == DC_OK) {
+		/* notify audio driver for audio modes of monitor */
+		dal_audio_enable_azalia_audio_jack_presence(stream->audio,
+				stream->stream_enc->id);
+
+		/* un-mute audio */
+		dal_audio_unmute(stream->audio, stream->stream_enc->id,
+				stream->signal);
+	}
+
+	return status;
+}
+
+static void disable_link(struct core_stream *stream)
+{
+	/* TODO  dp_set_hw_test_pattern */
+
+	/* here we need to specify that encoder output settings
+	 * need to be calculated as for the set mode,
+	 * it will lead to querying dynamic link capabilities
+	 * which should be done before enable output */
+
+	if (dc_is_dp_signal(stream->signal)) {
+		/* SST DP, eDP */
+		if (dc_is_dp_sst_signal(stream->signal))
+			dp_disable_link_phy(
+					stream->sink->link, stream->signal);
+		else {
+			dp_disable_link_phy_mst(
+					stream->sink->link, stream);
+		}
+	} else {
+		struct link_encoder *encoder =
+				stream->sink->link->link_enc;
+
+		encoder->funcs->disable_output(encoder, stream->signal);
+	}
+}
+
+enum dc_status dc_link_validate_mode_timing(
+		const struct core_sink *sink,
+		struct core_link *link,
+		const struct dc_crtc_timing *timing)
+{
+	uint32_t max_pix_clk = sink->dongle_max_pix_clk;
+
+	if (0 != max_pix_clk && timing->pix_clk_khz > max_pix_clk)
+		return DC_EXCEED_DONGLE_MAX_CLK;
+
+	switch (sink->public.sink_signal) {
+		case SIGNAL_TYPE_DISPLAY_PORT:
+			if(!dp_validate_mode_timing(
+					link,
+					timing))
+				return DC_NO_DP_LINK_BANDWIDTH;
+			break;
+
+		default:
+			break;
+	}
+
+	return DC_OK;
+}
+
+bool dc_link_set_backlight_level(const struct dc_link *public, uint32_t level)
+{
+	struct core_link *link = DC_LINK_TO_CORE(public);
+	struct dc_context *ctx = link->ctx;
+
+	dal_logger_write(ctx->logger, LOG_MAJOR_BACKLIGHT,
+			LOG_MINOR_BACKLIGHT_INTERFACE,
+			"New Backlight level: %d (0x%X)\n", level, level);
+
+	link->link_enc->funcs->set_lcd_backlight_level(link->link_enc, level);
+
+	return true;
+}
+
+void core_link_resume(struct core_link *link)
+{
+	if (link->public.connector_signal != SIGNAL_TYPE_VIRTUAL)
+		program_hpd_filter(link);
+}
+
+static struct fixed31_32 get_pbn_per_slot(struct core_stream *stream)
+{
+	struct link_settings *link_settings =
+			&stream->sink->link->cur_link_settings;
+	uint32_t link_rate_in_mbps =
+			link_settings->link_rate * LINK_RATE_REF_FREQ_IN_MHZ;
+	struct fixed31_32 mbps = dal_fixed31_32_from_int(
+			link_rate_in_mbps * link_settings->lane_count);
+
+	return dal_fixed31_32_div_int(mbps, 54);
+}
+
+static int get_color_depth(struct core_stream *stream)
+{
+	switch (stream->pix_clk_params.color_depth) {
+	case COLOR_DEPTH_666: return 6;
+	case COLOR_DEPTH_888: return 8;
+	case COLOR_DEPTH_101010: return 10;
+	case COLOR_DEPTH_121212: return 12;
+	case COLOR_DEPTH_141414: return 14;
+	case COLOR_DEPTH_161616: return 16;
+	default: return 0;
+	}
+}
+
+static struct fixed31_32 get_pbn_from_timing(struct core_stream *stream)
+{
+	uint32_t bpc;
+	uint64_t kbps;
+	struct fixed31_32 peak_kbps;
+	uint32_t numerator;
+	uint32_t denominator;
+
+	bpc = get_color_depth(stream);
+	kbps = stream->pix_clk_params.requested_pix_clk * bpc * 3;
+
+	/*
+	 * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
+	 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
+	 * common multiplier to render an integer PBN for all link rate/lane
+	 * counts combinations
+	 * calculate
+	 * peak_kbps *= (1006/1000)
+	 * peak_kbps *= (64/54)
+	 * peak_kbps *= 8    convert to bytes
+	 */
+
+	numerator = 64 * PEAK_FACTOR_X1000;
+	denominator = 54 * 8 * 1000 * 1000;
+	kbps *= numerator;
+	peak_kbps = dal_fixed31_32_from_fraction(kbps, denominator);
+
+	return peak_kbps;
+}
+
+static void update_mst_stream_alloc_table(
+	struct core_link *link,
+	struct core_stream *stream,
+	const struct dp_mst_stream_allocation_table *proposed_table)
+{
+	struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = {
+			{ 0 } };
+	struct link_mst_stream_allocation *dc_alloc;
+
+	int i;
+	int j;
+
+	/* if DRM proposed_table has more than one new payload */
+	ASSERT(proposed_table->stream_count -
+			link->mst_stream_alloc_table.stream_count < 2);
+
+	/* copy proposed_table to core_link, add stream encoder */
+	for (i = 0; i < proposed_table->stream_count; i++) {
+
+		for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) {
+			dc_alloc =
+			&link->mst_stream_alloc_table.stream_allocations[j];
+
+			if (dc_alloc->vcp_id ==
+				proposed_table->stream_allocations[i].vcp_id) {
+
+				work_table[i] = *dc_alloc;
+				break; /* exit j loop */
+			}
+		}
+
+		/* new vcp_id */
+		if (j == link->mst_stream_alloc_table.stream_count) {
+			work_table[i].vcp_id =
+				proposed_table->stream_allocations[i].vcp_id;
+			work_table[i].slot_count =
+				proposed_table->stream_allocations[i].slot_count;
+			work_table[i].stream_enc = stream->stream_enc;
+		}
+	}
+
+	/* update link->mst_stream_alloc_table with work_table */
+	link->mst_stream_alloc_table.stream_count =
+			proposed_table->stream_count;
+	for (i = 0; i < MAX_CONTROLLER_NUM; i++)
+		link->mst_stream_alloc_table.stream_allocations[i] =
+				work_table[i];
+}
+
+/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table
+ * because stream_encoder is not exposed to dm
+ */
+static enum dc_status allocate_mst_payload(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+	struct link_encoder *link_encoder = link->link_enc;
+	struct stream_encoder *stream_encoder = stream->stream_enc;
+	struct dp_mst_stream_allocation_table proposed_table = {0};
+	struct fixed31_32 avg_time_slots_per_mtp;
+	struct fixed31_32 pbn;
+	struct fixed31_32 pbn_per_slot;
+	uint8_t i;
+
+	/* enable_link_dp_mst already check link->enabled_stream_count
+	 * and stream is in link->stream[]. This is called during set mode,
+	 * stream_enc is available.
+	 */
+
+	/* get calculate VC payload for stream: stream_alloc */
+	dm_helpers_dp_mst_write_payload_allocation_table(
+		stream->ctx,
+		&stream->public,
+		&proposed_table,
+		true);
+
+	update_mst_stream_alloc_table(link, stream, &proposed_table);
+
+	dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_MST,
+			LOG_MINOR_MST_PROGRAMMING,
+			"%s  "
+			"stream_count: %d: \n ",
+			__func__,
+			link->mst_stream_alloc_table.stream_count);
+
+	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
+		dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_MST,
+		LOG_MINOR_MST_PROGRAMMING,
+		"stream_enc[%d]: 0x%x      "
+		"stream[%d].vcp_id: %d      "
+		"stream[%d].slot_count: %d\n",
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
+	}
+
+	ASSERT(proposed_table.stream_count > 0);
+
+	/*
+	 * temporary fix. Unplug of MST chain happened (two displays),
+	 * table is empty on first reset mode, and cause 0 division in
+	 * avg_time_slots_per_mtp calculation
+	 */
+
+	/* to be removed or debugged */
+	if (proposed_table.stream_count == 0)
+		return DC_OK;
+
+	/* program DP source TX for payload */
+	link_encoder->funcs->update_mst_stream_allocation_table(
+		link_encoder,
+		&link->mst_stream_alloc_table);
+
+	/* send down message */
+	dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+			stream->ctx,
+			&stream->public);
+
+	dm_helpers_dp_mst_send_payload_allocation(
+			stream->ctx,
+			&stream->public,
+			true);
+
+	/* slot X.Y for only current stream */
+	pbn_per_slot = get_pbn_per_slot(stream);
+	pbn = get_pbn_from_timing(stream);
+	avg_time_slots_per_mtp = dal_fixed31_32_div(pbn, pbn_per_slot);
+
+
+
+	stream_encoder->funcs->set_mst_bandwidth(
+		stream_encoder,
+		avg_time_slots_per_mtp);
+
+	return DC_OK;
+
+}
+
+static enum dc_status deallocate_mst_payload(struct core_stream *stream)
+{
+	struct core_link *link = stream->sink->link;
+	struct link_encoder *link_encoder = link->link_enc;
+	struct stream_encoder *stream_encoder = stream->stream_enc;
+	struct dp_mst_stream_allocation_table proposed_table = {0};
+	struct fixed31_32 avg_time_slots_per_mtp = dal_fixed31_32_from_int(0);
+	uint8_t i;
+	bool mst_mode = (link->public.type == dc_connection_mst_branch);
+
+	/* deallocate_mst_payload is called before disable link. When mode or
+	 * disable/enable monitor, new stream is created which is not in link
+	 * stream[] yet. For this, payload is not allocated yet, so de-alloc
+	 * should not done. For new mode set, map_resources will get engine
+	 * for new stream, so stream_enc->id should be validated until here.
+	 */
+
+	/* slot X.Y */
+	stream_encoder->funcs->set_mst_bandwidth(
+		stream_encoder,
+		avg_time_slots_per_mtp);
+
+	/* TODO: which component is responsible for remove payload table? */
+	if (mst_mode)
+		dm_helpers_dp_mst_write_payload_allocation_table(
+				stream->ctx,
+				&stream->public,
+				&proposed_table,
+				false);
+
+	update_mst_stream_alloc_table(link, stream, &proposed_table);
+
+	dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_MST,
+			LOG_MINOR_MST_PROGRAMMING,
+			"%s"
+			"stream_count: %d: ",
+			__func__,
+			link->mst_stream_alloc_table.stream_count);
+
+	for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
+		dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_MST,
+		LOG_MINOR_MST_PROGRAMMING,
+		"stream_enc[%d]: 0x%x      "
+		"stream[%d].vcp_id: %d      "
+		"stream[%d].slot_count: %d\n",
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].stream_enc,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].vcp_id,
+		i,
+		link->mst_stream_alloc_table.stream_allocations[i].slot_count);
+	}
+
+	link_encoder->funcs->update_mst_stream_allocation_table(
+		link_encoder,
+		&link->mst_stream_alloc_table);
+
+	if (mst_mode) {
+		dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+			stream->ctx,
+			&stream->public);
+
+		dm_helpers_dp_mst_send_payload_allocation(
+			stream->ctx,
+			&stream->public,
+			false);
+	}
+
+	return DC_OK;
+}
+
+void core_link_enable_stream(
+		struct core_link *link,
+		struct core_stream *stream)
+{
+	struct dc *dc = stream->ctx->dc;
+
+	if (DC_OK != enable_link(stream)) {
+			BREAK_TO_DEBUGGER();
+			return;
+	}
+
+	dc->hwss.enable_stream(stream);
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+		allocate_mst_payload(stream);
+}
+
+void core_link_disable_stream(
+		struct core_link *link,
+		struct core_stream *stream)
+{
+	struct dc *dc = stream->ctx->dc;
+
+	if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+		deallocate_mst_payload(stream);
+
+	dc->hwss.disable_stream(stream);
+
+	disable_link(stream);
+
+}
+
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
new file mode 100644
index 000000000000..f725da7c0e43
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_ddc.c
@@ -0,0 +1,1121 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "include/adapter_service_interface.h"
+#include "include/ddc_service_types.h"
+#include "include/grph_object_id.h"
+#include "include/dpcd_defs.h"
+#include "include/logger_interface.h"
+#include "include/vector.h"
+#include "core_types.h"
+#include "dc_link_ddc.h"
+
+#define AUX_POWER_UP_WA_DELAY 500
+#define I2C_OVER_AUX_DEFER_WA_DELAY 70
+
+/* CV smart dongle slave address for retrieving supported HDTV modes*/
+#define CV_SMART_DONGLE_ADDRESS 0x20
+/* DVI-HDMI dongle slave address for retrieving dongle signature*/
+#define DVI_HDMI_DONGLE_ADDRESS 0x68
+static const int8_t dvi_hdmi_dongle_signature_str[] = "6140063500G";
+struct dvi_hdmi_dongle_signature_data {
+	int8_t vendor[3];/* "AMD" */
+	uint8_t version[2];
+	uint8_t size;
+	int8_t id[11];/* "6140063500G"*/
+};
+/* DP-HDMI dongle slave address for retrieving dongle signature*/
+#define DP_HDMI_DONGLE_ADDRESS 0x40
+static const uint8_t dp_hdmi_dongle_signature_str[] = "DP-HDMI ADAPTOR";
+#define DP_HDMI_DONGLE_SIGNATURE_EOT 0x04
+
+struct dp_hdmi_dongle_signature_data {
+	int8_t id[15];/* "DP-HDMI ADAPTOR"*/
+	uint8_t eot;/* end of transmition '\x4' */
+};
+
+/* Address range from 0x00 to 0x1F.*/
+#define DP_ADAPTOR_TYPE2_SIZE 0x20
+#define DP_ADAPTOR_TYPE2_REG_ID 0x10
+#define DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK 0x1D
+/* Identifies adaptor as Dual-mode adaptor */
+#define DP_ADAPTOR_TYPE2_ID 0xA0
+/* MHz*/
+#define DP_ADAPTOR_TYPE2_MAX_TMDS_CLK 600
+/* MHz*/
+#define DP_ADAPTOR_TYPE2_MIN_TMDS_CLK 25
+/* kHZ*/
+#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000
+/* kHZ*/
+#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000
+
+#define DDC_I2C_COMMAND_ENGINE I2C_COMMAND_ENGINE_SW
+
+enum edid_read_result {
+	EDID_READ_RESULT_EDID_MATCH = 0,
+	EDID_READ_RESULT_EDID_MISMATCH,
+	EDID_READ_RESULT_CHECKSUM_READ_ERR,
+	EDID_READ_RESULT_VENDOR_READ_ERR
+};
+
+/* SCDC Address defines (HDMI 2.0)*/
+#define HDMI_SCDC_WRITE_UPDATE_0_ARRAY 3
+#define HDMI_SCDC_ADDRESS  0x54
+#define HDMI_SCDC_SINK_VERSION 0x01
+#define HDMI_SCDC_SOURCE_VERSION 0x02
+#define HDMI_SCDC_UPDATE_0 0x10
+#define HDMI_SCDC_TMDS_CONFIG 0x20
+#define HDMI_SCDC_SCRAMBLER_STATUS 0x21
+#define HDMI_SCDC_CONFIG_0 0x30
+#define HDMI_SCDC_STATUS_FLAGS 0x40
+#define HDMI_SCDC_ERR_DETECT 0x50
+#define HDMI_SCDC_TEST_CONFIG 0xC0
+
+
+union hdmi_scdc_update_read_data {
+	uint8_t byte[2];
+	struct {
+		uint8_t STATUS_UPDATE:1;
+		uint8_t CED_UPDATE:1;
+		uint8_t RR_TEST:1;
+		uint8_t RESERVED:5;
+		uint8_t RESERVED2:8;
+	} fields;
+};
+
+union hdmi_scdc_status_flags_data {
+	uint8_t byte[2];
+	struct {
+		uint8_t CLOCK_DETECTED:1;
+		uint8_t CH0_LOCKED:1;
+		uint8_t CH1_LOCKED:1;
+		uint8_t CH2_LOCKED:1;
+		uint8_t RESERVED:4;
+		uint8_t RESERVED2:8;
+	} fields;
+};
+
+union hdmi_scdc_ced_data {
+	uint8_t byte[7];
+	struct {
+		uint8_t CH0_8LOW:8;
+		uint8_t CH0_7HIGH:7;
+		uint8_t CH0_VALID:1;
+		uint8_t CH1_8LOW:8;
+		uint8_t CH1_7HIGH:7;
+		uint8_t CH1_VALID:1;
+		uint8_t CH2_8LOW:8;
+		uint8_t CH2_7HIGH:7;
+		uint8_t CH2_VALID:1;
+		uint8_t CHECKSUM:8;
+	} fields;
+};
+
+union hdmi_scdc_test_config_Data {
+	uint8_t byte;
+	struct {
+		uint8_t TEST_READ_REQUEST_DELAY:7;
+		uint8_t TEST_READ_REQUEST: 1;
+	} fields;
+};
+
+
+
+struct i2c_payloads {
+	struct vector payloads;
+};
+
+struct aux_payloads {
+	struct vector payloads;
+};
+
+struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count)
+{
+	struct i2c_payloads *payloads;
+
+	payloads = dm_alloc(ctx, sizeof(struct i2c_payloads));
+
+	if (!payloads)
+		return NULL;
+
+	if (dal_vector_construct(
+		&payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
+		return payloads;
+
+	dm_free(ctx, payloads);
+	return NULL;
+
+}
+
+struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
+{
+	return (struct i2c_payload *)p->payloads.container;
+}
+
+uint32_t  dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p)
+{
+	return p->payloads.count;
+}
+
+void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p)
+{
+	if (!p || !*p)
+		return;
+	dal_vector_destruct(&(*p)->payloads);
+	dm_free((*p)->payloads.ctx, *p);
+	*p = NULL;
+
+}
+
+struct aux_payloads *dal_ddc_aux_payloads_create(struct dc_context *ctx, uint32_t count)
+{
+	struct aux_payloads *payloads;
+
+	payloads = dm_alloc(ctx, sizeof(struct aux_payloads));
+
+	if (!payloads)
+		return NULL;
+
+	if (dal_vector_construct(
+		&payloads->payloads, ctx, count, sizeof(struct aux_payloads)))
+		return payloads;
+
+	dm_free(ctx, payloads);
+	return NULL;
+}
+
+struct aux_payload *dal_ddc_aux_payloads_get(struct aux_payloads *p)
+{
+	return (struct aux_payload *)p->payloads.container;
+}
+
+uint32_t  dal_ddc_aux_payloads_get_count(struct aux_payloads *p)
+{
+	return p->payloads.count;
+}
+
+
+void dal_ddc_aux_payloads_destroy(struct aux_payloads **p)
+{
+	if (!p || !*p)
+		return;
+
+	dal_vector_destruct(&(*p)->payloads);
+	dm_free((*p)->payloads.ctx, *p);
+	*p = NULL;
+}
+
+#define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+void dal_ddc_i2c_payloads_add(
+	struct i2c_payloads *payloads,
+	uint32_t address,
+	uint32_t len,
+	uint8_t *data,
+	bool write)
+{
+	uint32_t payload_size = EDID_SEGMENT_SIZE;
+	uint32_t pos;
+
+	for (pos = 0; pos < len; pos += payload_size) {
+		struct i2c_payload payload = {
+			.write = write,
+			.address = address,
+			.length = DDC_MIN(payload_size, len - pos),
+			.data = data + pos };
+		dal_vector_append(&payloads->payloads, &payload);
+	}
+
+}
+
+void dal_ddc_aux_payloads_add(
+	struct aux_payloads *payloads,
+	uint32_t address,
+	uint32_t len,
+	uint8_t *data,
+	bool write)
+{
+	uint32_t payload_size = DEFAULT_AUX_MAX_DATA_SIZE;
+	uint32_t pos;
+
+	for (pos = 0; pos < len; pos += payload_size) {
+		struct aux_payload payload = {
+			.i2c_over_aux = true,
+			.write = write,
+			.address = address,
+			.length = DDC_MIN(payload_size, len - pos),
+			.data = data + pos };
+		dal_vector_append(&payloads->payloads, &payload);
+	}
+}
+
+
+static bool construct(
+	struct ddc_service *ddc_service,
+	struct ddc_service_init_data *init_data)
+{
+	enum connector_id connector_id =
+		dal_graphics_object_id_get_connector_id(init_data->id);
+
+	ddc_service->link = init_data->link;
+	ddc_service->ctx = init_data->ctx;
+	ddc_service->as = init_data->as;
+	ddc_service->ddc_pin = dal_adapter_service_obtain_ddc(
+			init_data->as, init_data->id);
+
+	ddc_service->flags.EDID_QUERY_DONE_ONCE = false;
+
+	ddc_service->flags.FORCE_READ_REPEATED_START =
+		dal_adapter_service_is_feature_supported(
+			FEATURE_DDC_READ_FORCE_REPEATED_START);
+
+	ddc_service->flags.EDID_STRESS_READ =
+			dal_adapter_service_is_feature_supported(
+				FEATURE_EDID_STRESS_READ);
+
+
+	ddc_service->flags.IS_INTERNAL_DISPLAY =
+		connector_id == CONNECTOR_ID_EDP ||
+		connector_id == CONNECTOR_ID_LVDS;
+
+	ddc_service->wa.raw = 0;
+	return true;
+}
+
+struct ddc_service *dal_ddc_service_create(
+	struct ddc_service_init_data *init_data)
+{
+	struct ddc_service *ddc_service;
+
+	ddc_service = dm_alloc(init_data->ctx, sizeof(struct ddc_service));
+
+	if (!ddc_service)
+		return NULL;
+
+	if (construct(ddc_service, init_data))
+		return ddc_service;
+
+	dm_free(init_data->ctx, ddc_service);
+	return NULL;
+}
+
+static void destruct(struct ddc_service *ddc)
+{
+	if (ddc->ddc_pin)
+		dal_adapter_service_release_ddc(ddc->as, ddc->ddc_pin);
+}
+
+void dal_ddc_service_destroy(struct ddc_service **ddc)
+{
+	if (!ddc || !*ddc) {
+		BREAK_TO_DEBUGGER();
+		return;
+	}
+	destruct(*ddc);
+	dm_free((*ddc)->ctx, *ddc);
+	*ddc = NULL;
+}
+
+enum ddc_service_type dal_ddc_service_get_type(struct ddc_service *ddc)
+{
+	return DDC_SERVICE_TYPE_CONNECTOR;
+}
+
+void dal_ddc_service_set_transaction_type(
+	struct ddc_service *ddc,
+	enum ddc_transaction_type type)
+{
+	ddc->transaction_type = type;
+}
+
+bool dal_ddc_service_is_in_aux_transaction_mode(struct ddc_service *ddc)
+{
+	switch (ddc->transaction_type) {
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+void ddc_service_set_dongle_type(struct ddc_service *ddc,
+		enum display_dongle_type dongle_type)
+{
+	ddc->dongle_type = dongle_type;
+}
+
+static uint32_t defer_delay_converter_wa(
+	struct ddc_service *ddc,
+	uint32_t defer_delay)
+{
+	struct dp_receiver_id_info dp_rec_info = {0};
+
+	if (dal_ddc_service_get_dp_receiver_id_info(ddc, &dp_rec_info) &&
+		(dp_rec_info.branch_id == DP_BRANCH_DEVICE_ID_4) &&
+		!dm_strncmp(dp_rec_info.branch_name,
+			DP_DVI_CONVERTER_ID_4,
+			sizeof(dp_rec_info.branch_name)))
+		return defer_delay > I2C_OVER_AUX_DEFER_WA_DELAY ?
+			defer_delay : I2C_OVER_AUX_DEFER_WA_DELAY;
+
+	return defer_delay;
+
+}
+
+#define DP_TRANSLATOR_DELAY 5
+
+static uint32_t get_defer_delay(struct ddc_service *ddc)
+{
+	uint32_t defer_delay = 0;
+
+	switch (ddc->transaction_type) {
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX:
+		if ((DISPLAY_DONGLE_DP_VGA_CONVERTER == ddc->dongle_type) ||
+			(DISPLAY_DONGLE_DP_DVI_CONVERTER == ddc->dongle_type) ||
+			(DISPLAY_DONGLE_DP_HDMI_CONVERTER ==
+				ddc->dongle_type)) {
+
+			defer_delay = DP_TRANSLATOR_DELAY;
+
+			defer_delay =
+				defer_delay_converter_wa(ddc, defer_delay);
+
+		} else /*sink has a delay different from an Active Converter*/
+			defer_delay = 0;
+		break;
+	case DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER:
+		defer_delay = DP_TRANSLATOR_DELAY;
+		break;
+	default:
+		break;
+	}
+	return defer_delay;
+}
+
+static bool i2c_read(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t *buffer,
+	uint32_t len)
+{
+	uint8_t offs_data = 0;
+	struct i2c_payload payloads[2] = {
+		{
+		.write = true,
+		.address = address,
+		.length = 1,
+		.data = &offs_data },
+		{
+		.write = false,
+		.address = address,
+		.length = len,
+		.data = buffer } };
+
+	struct i2c_command command = {
+		.payloads = payloads,
+		.number_of_payloads = 2,
+		.engine = DDC_I2C_COMMAND_ENGINE,
+		.speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) };
+
+	return dm_helpers_submit_i2c(
+			ddc->ctx,
+			&ddc->link->public,
+			&command);
+}
+
+static uint8_t aux_read_edid_block(
+	struct ddc_service *ddc,
+	uint8_t address,
+	uint8_t index,
+	uint8_t *buf)
+{
+	struct aux_command cmd = {
+		.payloads = NULL,
+		.number_of_payloads = 0,
+		.defer_delay = get_defer_delay(ddc),
+		.max_defer_write_retry = 0 };
+
+	uint8_t retrieved = 0;
+	uint8_t base_offset =
+		(index % DDC_EDID_BLOCKS_PER_SEGMENT) * DDC_EDID_BLOCK_SIZE;
+	uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT;
+
+	for (retrieved = 0; retrieved < DDC_EDID_BLOCK_SIZE;
+		retrieved += DEFAULT_AUX_MAX_DATA_SIZE) {
+
+		uint8_t offset = base_offset + retrieved;
+
+		struct aux_payload payloads[3] = {
+			{
+			.i2c_over_aux = true,
+			.write = true,
+			.address = DDC_EDID_SEGMENT_ADDRESS,
+			.length = 1,
+			.data = &segment },
+			{
+			.i2c_over_aux = true,
+			.write = true,
+			.address = address,
+			.length = 1,
+			.data = &offset },
+			{
+			.i2c_over_aux = true,
+			.write = false,
+			.address = address,
+			.length = DEFAULT_AUX_MAX_DATA_SIZE,
+			.data = &buf[retrieved] } };
+
+		if (segment == 0) {
+			cmd.payloads = &payloads[1];
+			cmd.number_of_payloads = 2;
+		} else {
+			cmd.payloads = payloads;
+			cmd.number_of_payloads = 3;
+		}
+
+		if (!dal_i2caux_submit_aux_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd))
+			/* cannot read, break*/
+			break;
+	}
+
+	/* Reset segment to 0. Needed by some panels */
+	if (0 != segment) {
+		struct aux_payload payloads[1] = { {
+			.i2c_over_aux = true,
+			.write = true,
+			.address = DDC_EDID_SEGMENT_ADDRESS,
+			.length = 1,
+			.data = &segment } };
+		bool result = false;
+
+		segment = 0;
+
+		cmd.number_of_payloads = ARRAY_SIZE(payloads);
+		cmd.payloads = payloads;
+
+		result = dal_i2caux_submit_aux_command(
+			dal_adapter_service_get_i2caux(ddc->as),
+			ddc->ddc_pin,
+			&cmd);
+
+		if (false == result)
+			dal_logger_write(
+				ddc->ctx->logger,
+				LOG_MAJOR_ERROR,
+				LOG_MINOR_COMPONENT_DISPLAY_CAPABILITY_SERVICE,
+				"%s: Writing of EDID Segment (0x30) failed!\n",
+				__func__);
+	}
+
+	return retrieved;
+}
+
+static uint8_t i2c_read_edid_block(
+	struct ddc_service *ddc,
+	uint8_t address,
+	uint8_t index,
+	uint8_t *buf)
+{
+	bool ret = false;
+	uint8_t offset = (index % DDC_EDID_BLOCKS_PER_SEGMENT) *
+		DDC_EDID_BLOCK_SIZE;
+	uint8_t segment = index / DDC_EDID_BLOCKS_PER_SEGMENT;
+
+	struct i2c_command cmd = {
+		.payloads = NULL,
+		.number_of_payloads = 0,
+		.engine = DDC_I2C_COMMAND_ENGINE,
+		.speed = dal_adapter_service_get_sw_i2c_speed(ddc->as) };
+
+	struct i2c_payload payloads[3] = {
+		{
+		.write = true,
+		.address = DDC_EDID_SEGMENT_ADDRESS,
+		.length = 1,
+		.data = &segment },
+		{
+		.write = true,
+		.address = address,
+		.length = 1,
+		.data = &offset },
+		{
+		.write = false,
+		.address = address,
+		.length = DDC_EDID_BLOCK_SIZE,
+		.data = buf } };
+/*
+ * Some I2C engines don't handle stop/start between write-offset and read-data
+ * commands properly. For those displays, we have to force the newer E-DDC
+ * behavior of repeated-start which can be enabled by runtime parameter. */
+/* Originally implemented for OnLive using NXP receiver chip */
+
+	if (index == 0 && !ddc->flags.FORCE_READ_REPEATED_START) {
+		/* base block, use use DDC2B, submit as 2 commands */
+		cmd.payloads = &payloads[1];
+		cmd.number_of_payloads = 1;
+
+		if (dm_helpers_submit_i2c(
+			ddc->ctx,
+			&ddc->link->public,
+			&cmd)) {
+
+			cmd.payloads = &payloads[2];
+			cmd.number_of_payloads = 1;
+
+			ret = dm_helpers_submit_i2c(
+					ddc->ctx,
+					&ddc->link->public,
+					&cmd);
+		}
+
+	} else {
+		/*
+		 * extension block use E-DDC, submit as 1 command
+		 * or if repeated-start is forced by runtime parameter
+		 */
+		if (segment != 0) {
+			/* include segment offset in command*/
+			cmd.payloads = payloads;
+			cmd.number_of_payloads = 3;
+		} else {
+			/* we are reading first segment,
+			 * segment offset is not required */
+			cmd.payloads = &payloads[1];
+			cmd.number_of_payloads = 2;
+		}
+
+		ret = dm_helpers_submit_i2c(
+				ddc->ctx,
+				&ddc->link->public,
+				&cmd);
+	}
+
+	return ret ? DDC_EDID_BLOCK_SIZE : 0;
+}
+
+static uint32_t query_edid_block(
+	struct ddc_service *ddc,
+	uint8_t address,
+	uint8_t index,
+	uint8_t *buf,
+	uint32_t size)
+{
+	uint32_t size_retrieved = 0;
+
+	if (size < DDC_EDID_BLOCK_SIZE)
+		return 0;
+
+	if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
+
+		ASSERT(index < 2);
+		size_retrieved =
+			aux_read_edid_block(ddc, address, index, buf);
+	} else {
+		size_retrieved =
+			i2c_read_edid_block(ddc, address, index, buf);
+	}
+
+	return size_retrieved;
+}
+
+#define DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS 0x261
+#define DDC_TEST_ACK_ADDRESS 0x260
+#define DDC_DPCD_EDID_TEST_ACK 0x04
+#define DDC_DPCD_EDID_TEST_MASK 0x04
+#define DDC_DPCD_TEST_REQUEST_ADDRESS 0x218
+
+/* AG TODO GO throug DM callback here like for DPCD */
+
+static void write_dp_edid_checksum(
+	struct ddc_service *ddc,
+	uint8_t checksum)
+{
+	uint8_t dpcd_data;
+
+	dal_ddc_service_read_dpcd_data(
+		ddc,
+		DDC_DPCD_TEST_REQUEST_ADDRESS,
+		&dpcd_data,
+		1);
+
+	if (dpcd_data & DDC_DPCD_EDID_TEST_MASK) {
+
+		dal_ddc_service_write_dpcd_data(
+			ddc,
+			DDC_DPCD_EDID_CHECKSUM_WRITE_ADDRESS,
+			&checksum,
+			1);
+
+		dpcd_data = DDC_DPCD_EDID_TEST_ACK;
+
+		dal_ddc_service_write_dpcd_data(
+			ddc,
+			DDC_TEST_ACK_ADDRESS,
+			&dpcd_data,
+			1);
+	}
+}
+
+uint32_t dal_ddc_service_edid_query(struct ddc_service *ddc)
+{
+	uint32_t bytes_read = 0;
+	uint32_t ext_cnt = 0;
+
+	uint8_t address;
+	uint32_t i;
+
+	for (address = DDC_EDID_ADDRESS_START;
+		address <= DDC_EDID_ADDRESS_END; ++address) {
+
+		bytes_read = query_edid_block(
+			ddc,
+			address,
+			0,
+			ddc->edid_buf,
+			sizeof(ddc->edid_buf) - bytes_read);
+
+		if (bytes_read != DDC_EDID_BLOCK_SIZE)
+			continue;
+
+		/* get the number of ext blocks*/
+		ext_cnt = ddc->edid_buf[DDC_EDID_EXT_COUNT_OFFSET];
+
+		/* EDID 2.0, need to read 1 more block because EDID2.0 is
+		 * 256 byte in size*/
+		if (ddc->edid_buf[DDC_EDID_20_SIGNATURE_OFFSET] ==
+			DDC_EDID_20_SIGNATURE)
+				ext_cnt = 1;
+
+		for (i = 0; i < ext_cnt; i++) {
+			/* read additional ext blocks accordingly */
+			bytes_read += query_edid_block(
+					ddc,
+					address,
+					i+1,
+					&ddc->edid_buf[bytes_read],
+					sizeof(ddc->edid_buf) - bytes_read);
+		}
+
+		/*this is special code path for DP compliance*/
+		if (DDC_TRANSACTION_TYPE_I2C_OVER_AUX == ddc->transaction_type)
+			write_dp_edid_checksum(
+				ddc,
+				ddc->edid_buf[(ext_cnt * DDC_EDID_BLOCK_SIZE) +
+				DDC_EDID1X_CHECKSUM_OFFSET]);
+
+		/*remembers the address where we fetch the EDID from
+		 * for later signature check use */
+		ddc->address = address;
+
+		break;/* already read edid, done*/
+	}
+
+	ddc->edid_buf_len = bytes_read;
+	return bytes_read;
+}
+
+uint32_t dal_ddc_service_get_edid_buf_len(struct ddc_service *ddc)
+{
+	return ddc->edid_buf_len;
+}
+
+void dal_ddc_service_get_edid_buf(struct ddc_service *ddc, uint8_t *edid_buf)
+{
+	dm_memmove(edid_buf,
+			ddc->edid_buf, ddc->edid_buf_len);
+}
+
+void dal_ddc_service_i2c_query_dp_dual_mode_adaptor(
+	struct ddc_service *ddc,
+	struct display_sink_capability *sink_cap)
+{
+	uint8_t i;
+	bool is_valid_hdmi_signature;
+	enum display_dongle_type *dongle = &sink_cap->dongle_type;
+	uint8_t type2_dongle_buf[DP_ADAPTOR_TYPE2_SIZE];
+	bool is_type2_dongle = false;
+	struct dp_hdmi_dongle_signature_data *dongle_signature;
+
+	/* Assume we have no valid DP passive dongle connected */
+	*dongle = DISPLAY_DONGLE_NONE;
+	sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
+
+	/* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
+	if (!i2c_read(
+		ddc,
+		DP_HDMI_DONGLE_ADDRESS,
+		type2_dongle_buf,
+		sizeof(type2_dongle_buf))) {
+		dal_logger_write(ddc->ctx->logger,
+			LOG_MAJOR_DCS,
+			LOG_MINOR_DCS_DONGLE_DETECTION,
+			"Detected DP-DVI dongle.\n");
+		*dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
+		sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
+		return;
+	}
+
+	/* Check if Type 2 dongle.*/
+	if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID)
+		is_type2_dongle = true;
+
+	dongle_signature =
+		(struct dp_hdmi_dongle_signature_data *)type2_dongle_buf;
+
+	is_valid_hdmi_signature = true;
+
+	/* Check EOT */
+	if (dongle_signature->eot != DP_HDMI_DONGLE_SIGNATURE_EOT) {
+		is_valid_hdmi_signature = false;
+	}
+
+	/* Check signature */
+	for (i = 0; i < sizeof(dongle_signature->id); ++i) {
+		/* If its not the right signature,
+		 * skip mismatch in subversion byte.*/
+		if (dongle_signature->id[i] !=
+			dp_hdmi_dongle_signature_str[i] && i != 3) {
+
+			if (is_type2_dongle) {
+				is_valid_hdmi_signature = false;
+				break;
+			}
+
+		}
+	}
+
+	if (is_type2_dongle) {
+		uint32_t max_tmds_clk =
+			type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_MAX_TMDS_CLK];
+
+		max_tmds_clk = max_tmds_clk * 2 + max_tmds_clk / 2;
+
+		if (0 == max_tmds_clk ||
+				max_tmds_clk < DP_ADAPTOR_TYPE2_MIN_TMDS_CLK ||
+				max_tmds_clk > DP_ADAPTOR_TYPE2_MAX_TMDS_CLK) {
+			dal_logger_write(ddc->ctx->logger,
+				LOG_MAJOR_DCS,
+				LOG_MINOR_DCS_DONGLE_DETECTION,
+				"Invalid Maximum TMDS clock");
+			*dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
+		} else {
+			if (is_valid_hdmi_signature == true) {
+				*dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
+				dal_logger_write(ddc->ctx->logger,
+					LOG_MAJOR_DCS,
+					LOG_MINOR_DCS_DONGLE_DETECTION,
+					"Detected Type 2 DP-HDMI Maximum TMDS "
+					"clock, max TMDS clock: %d MHz",
+					max_tmds_clk);
+			} else {
+				*dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
+				dal_logger_write(ddc->ctx->logger,
+					LOG_MAJOR_DCS,
+					LOG_MINOR_DCS_DONGLE_DETECTION,
+					"Detected Type 2 DP-HDMI (no valid HDMI"
+					" signature) Maximum TMDS clock, max "
+					"TMDS clock: %d MHz",
+					max_tmds_clk);
+			}
+
+			/* Multiply by 1000 to convert to kHz. */
+			sink_cap->max_hdmi_pixel_clock =
+				max_tmds_clk * 1000;
+		}
+
+	} else {
+		if (is_valid_hdmi_signature == true) {
+			dal_logger_write(ddc->ctx->logger,
+				LOG_MAJOR_DCS,
+				LOG_MINOR_DCS_DONGLE_DETECTION,
+				"Detected Type 1 DP-HDMI dongle.\n");
+			*dongle = DISPLAY_DONGLE_DP_HDMI_DONGLE;
+		} else {
+			dal_logger_write(ddc->ctx->logger,
+				LOG_MAJOR_DCS,
+				LOG_MINOR_DCS_DONGLE_DETECTION,
+				"Detected Type 1 DP-HDMI dongle (no valid HDMI "
+				"signature).\n");
+
+			*dongle = DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE;
+		}
+	}
+
+	return;
+}
+
+enum {
+	DP_SINK_CAP_SIZE =
+		DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV + 1
+};
+
+bool dal_ddc_service_query_ddc_data(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t *write_buf,
+	uint32_t write_size,
+	uint8_t *read_buf,
+	uint32_t read_size)
+{
+	bool ret;
+	uint32_t payload_size =
+		dal_ddc_service_is_in_aux_transaction_mode(ddc) ?
+			DEFAULT_AUX_MAX_DATA_SIZE : EDID_SEGMENT_SIZE;
+
+	uint32_t write_payloads =
+		(write_size + payload_size - 1) / payload_size;
+
+	uint32_t read_payloads =
+		(read_size + payload_size - 1) / payload_size;
+
+	uint32_t payloads_num = write_payloads + read_payloads;
+
+	if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE)
+		return false;
+
+	/*TODO: len of payload data for i2c and aux is uint8!!!!,
+	 *  but we want to read 256 over i2c!!!!*/
+	if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
+
+		struct aux_payloads *payloads =
+			dal_ddc_aux_payloads_create(ddc->ctx, payloads_num);
+
+		struct aux_command command = {
+			.payloads = dal_ddc_aux_payloads_get(payloads),
+			.number_of_payloads = 0,
+			.defer_delay = get_defer_delay(ddc),
+			.max_defer_write_retry = 0 };
+
+		dal_ddc_aux_payloads_add(
+			payloads, address, write_size, write_buf, true);
+
+		dal_ddc_aux_payloads_add(
+			payloads, address, read_size, read_buf, false);
+
+		command.number_of_payloads =
+			dal_ddc_aux_payloads_get_count(payloads);
+
+		ret = dal_i2caux_submit_aux_command(
+				dal_adapter_service_get_i2caux(ddc->as),
+				ddc->ddc_pin,
+				&command);
+
+		dal_ddc_aux_payloads_destroy(&payloads);
+
+	} else {
+		struct i2c_payloads *payloads =
+			dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
+
+		struct i2c_command command = {
+			.payloads = dal_ddc_i2c_payloads_get(payloads),
+			.number_of_payloads = 0,
+			.engine = DDC_I2C_COMMAND_ENGINE,
+			.speed =
+				dal_adapter_service_get_sw_i2c_speed(ddc->as) };
+
+		dal_ddc_i2c_payloads_add(
+			payloads, address, write_size, write_buf, true);
+
+		dal_ddc_i2c_payloads_add(
+			payloads, address, read_size, read_buf, false);
+
+		command.number_of_payloads =
+			dal_ddc_i2c_payloads_get_count(payloads);
+
+		ret = dm_helpers_submit_i2c(
+				ddc->ctx,
+				&ddc->link->public,
+				&command);
+
+		dal_ddc_i2c_payloads_destroy(&payloads);
+	}
+
+	return ret;
+}
+
+bool dal_ddc_service_get_dp_receiver_id_info(
+	struct ddc_service *ddc,
+	struct dp_receiver_id_info *info)
+{
+	if (!info)
+		return false;
+
+	*info = ddc->dp_receiver_id_info;
+	return true;
+}
+
+enum ddc_result dal_ddc_service_read_dpcd_data(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t len)
+{
+	struct aux_payload read_payload = {
+		.i2c_over_aux = false,
+		.write = false,
+		.address = address,
+		.length = len,
+		.data = data,
+	};
+	struct aux_command command = {
+		.payloads = &read_payload,
+		.number_of_payloads = 1,
+		.defer_delay = 0,
+		.max_defer_write_retry = 0,
+	};
+
+	if (len > DEFAULT_AUX_MAX_DATA_SIZE) {
+		BREAK_TO_DEBUGGER();
+		return DDC_RESULT_FAILED_INVALID_OPERATION;
+	}
+
+	if (dal_i2caux_submit_aux_command(
+		dal_adapter_service_get_i2caux(ddc->as),
+		ddc->ddc_pin,
+		&command))
+		return DDC_RESULT_SUCESSFULL;
+
+	return DDC_RESULT_FAILED_OPERATION;
+}
+
+enum ddc_result dal_ddc_service_write_dpcd_data(
+	struct ddc_service *ddc,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t len)
+{
+	struct aux_payload write_payload = {
+		.i2c_over_aux = false,
+		.write = true,
+		.address = address,
+		.length = len,
+		.data = (uint8_t *)data,
+	};
+	struct aux_command command = {
+		.payloads = &write_payload,
+		.number_of_payloads = 1,
+		.defer_delay = 0,
+		.max_defer_write_retry = 0,
+	};
+
+	if (len > DEFAULT_AUX_MAX_DATA_SIZE) {
+		BREAK_TO_DEBUGGER();
+		return DDC_RESULT_FAILED_INVALID_OPERATION;
+	}
+
+	if (dal_i2caux_submit_aux_command(
+		dal_adapter_service_get_i2caux(ddc->as),
+		ddc->ddc_pin,
+		&command))
+		return DDC_RESULT_SUCESSFULL;
+
+	return DDC_RESULT_FAILED_OPERATION;
+}
+
+/*test only function*/
+void dal_ddc_service_set_ddc_pin(
+	struct ddc_service *ddc_service,
+	struct ddc *ddc)
+{
+	ddc_service->ddc_pin = ddc;
+}
+
+struct ddc *dal_ddc_service_get_ddc_pin(struct ddc_service *ddc_service)
+{
+	return ddc_service->ddc_pin;
+}
+
+
+void dal_ddc_service_reset_dp_receiver_id_info(struct ddc_service *ddc_service)
+{
+	dm_memset(&ddc_service->dp_receiver_id_info,
+		0, sizeof(struct dp_receiver_id_info));
+}
+
+void dal_ddc_service_write_scdc_data(struct ddc_service *ddc_service,
+		uint32_t pix_clk,
+		bool lte_340_scramble)
+{
+	bool over_340_mhz = pix_clk > 340000 ? 1 : 0;
+	uint8_t slave_address = HDMI_SCDC_ADDRESS;
+	uint8_t offset = HDMI_SCDC_SINK_VERSION;
+	uint8_t sink_version = 0;
+	uint8_t write_buffer[2] = {0};
+	/*Lower than 340 Scramble bit from SCDC caps*/
+
+	dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
+			sizeof(offset), &sink_version, sizeof(sink_version));
+	if (sink_version == 1) {
+		/*Source Version = 1*/
+		write_buffer[0] = HDMI_SCDC_SOURCE_VERSION;
+		write_buffer[1] = 1;
+		dal_ddc_service_query_ddc_data(ddc_service, slave_address,
+				write_buffer, sizeof(write_buffer), NULL, 0);
+		/*Read Request from SCDC caps*/
+	}
+	write_buffer[0] = HDMI_SCDC_TMDS_CONFIG;
+
+	if (over_340_mhz) {
+		write_buffer[1] = 3;
+	} else if (lte_340_scramble) {
+		write_buffer[1] = 1;
+	} else {
+		write_buffer[1] = 0;
+	}
+	dal_ddc_service_query_ddc_data(ddc_service, slave_address, write_buffer,
+			sizeof(write_buffer), NULL, 0);
+}
+
+void dal_ddc_service_read_scdc_data(struct ddc_service *ddc_service)
+{
+	uint8_t slave_address = HDMI_SCDC_ADDRESS;
+	uint8_t offset = HDMI_SCDC_TMDS_CONFIG;
+	uint8_t tmds_config = 0;
+
+	dal_ddc_service_query_ddc_data(ddc_service, slave_address, &offset,
+			sizeof(offset), &tmds_config, sizeof(tmds_config));
+	if (tmds_config & 0x1) {
+		union hdmi_scdc_status_flags_data status_data = { {0} };
+		uint8_t scramble_status = 0;
+
+		offset = HDMI_SCDC_SCRAMBLER_STATUS;
+		dal_ddc_service_query_ddc_data(ddc_service, slave_address,
+				&offset, sizeof(offset), &scramble_status,
+				sizeof(scramble_status));
+		offset = HDMI_SCDC_STATUS_FLAGS;
+		dal_ddc_service_query_ddc_data(ddc_service, slave_address,
+				&offset, sizeof(offset), status_data.byte,
+				sizeof(status_data.byte));
+	}
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
new file mode 100644
index 000000000000..742ab756cb48
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_dp.c
@@ -0,0 +1,1728 @@
+/* Copyright 2015 Advanced Micro Devices, Inc. */
+#include "dm_services.h"
+#include "dc.h"
+#include "dc_link_dp.h"
+#include "dm_helpers.h"
+
+#include "inc/core_types.h"
+#include "link_hwss.h"
+#include "dc_link_ddc.h"
+#include "core_status.h"
+#include "dpcd_defs.h"
+
+/* maximum pre emphasis level allowed for each voltage swing level*/
+static const enum pre_emphasis voltage_swing_to_pre_emphasis[] = {
+		PRE_EMPHASIS_LEVEL3,
+		PRE_EMPHASIS_LEVEL2,
+		PRE_EMPHASIS_LEVEL1,
+		PRE_EMPHASIS_DISABLED };
+
+enum {
+	POST_LT_ADJ_REQ_LIMIT = 6,
+	POST_LT_ADJ_REQ_TIMEOUT = 200
+};
+
+enum {
+	LINK_TRAINING_MAX_RETRY_COUNT = 5,
+	/* to avoid infinite loop where-in the receiver
+	 * switches between different VS
+	 */
+	LINK_TRAINING_MAX_CR_RETRY = 100
+};
+
+static const struct link_settings link_training_fallback_table[] = {
+/* 2160 Mbytes/sec*/
+{ LANE_COUNT_FOUR, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED },
+/* 1080 Mbytes/sec*/
+{ LANE_COUNT_FOUR, LINK_RATE_HIGH, LINK_SPREAD_DISABLED },
+/* 648 Mbytes/sec*/
+{ LANE_COUNT_FOUR, LINK_RATE_LOW, LINK_SPREAD_DISABLED },
+/* 1080 Mbytes/sec*/
+{ LANE_COUNT_TWO, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED },
+/* 540 Mbytes/sec*/
+{ LANE_COUNT_TWO, LINK_RATE_HIGH, LINK_SPREAD_DISABLED },
+/* 324 Mbytes/sec*/
+{ LANE_COUNT_TWO, LINK_RATE_LOW, LINK_SPREAD_DISABLED },
+/* 540 Mbytes/sec*/
+{ LANE_COUNT_ONE, LINK_RATE_HIGH2, LINK_SPREAD_DISABLED },
+/* 270 Mbytes/sec*/
+{ LANE_COUNT_ONE, LINK_RATE_HIGH, LINK_SPREAD_DISABLED },
+/* 162 Mbytes/sec*/
+{ LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED } };
+
+static void wait_for_training_aux_rd_interval(
+	struct core_link* link,
+	uint32_t default_wait_in_micro_secs)
+{
+	uint8_t training_rd_interval;
+
+	/* overwrite the delay if rev > 1.1*/
+	if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
+		/* DP 1.2 or later - retrieve delay through
+		 * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */
+		core_link_read_dpcd(
+			link,
+			DPCD_ADDRESS_TRAINING_AUX_RD_INTERVAL,
+			&training_rd_interval,
+			sizeof(training_rd_interval));
+		default_wait_in_micro_secs = training_rd_interval ?
+			(training_rd_interval * 4000) :
+			default_wait_in_micro_secs;
+	}
+
+	dm_delay_in_microseconds(link->ctx, default_wait_in_micro_secs);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n wait = %d\n",
+		__func__,
+		default_wait_in_micro_secs);
+}
+
+static void dpcd_set_training_pattern(
+	struct core_link* link,
+	union dpcd_training_pattern dpcd_pattern)
+{
+	core_link_write_dpcd(
+		link,
+		DPCD_ADDRESS_TRAINING_PATTERN_SET,
+		&dpcd_pattern.raw,
+		1);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x pattern = %x\n",
+		__func__,
+		DPCD_ADDRESS_TRAINING_PATTERN_SET,
+		dpcd_pattern.bits.TRAINING_PATTERN_SET);
+}
+
+static void dpcd_set_link_settings(
+	struct core_link* link,
+	const struct link_training_settings *lt_settings)
+{
+	uint8_t rate = (uint8_t)
+	(lt_settings->link_settings.link_rate);
+
+	union down_spread_ctrl downspread = {{0}};
+	union lane_count_set lane_count_set = {{0}};
+	uint8_t link_set_buffer[2];
+
+
+	downspread.raw = (uint8_t)
+	(lt_settings->link_settings.link_spread);
+
+	lane_count_set.bits.LANE_COUNT_SET =
+	lt_settings->link_settings.lane_count;
+
+	lane_count_set.bits.ENHANCED_FRAMING = 1;
+
+	lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
+		link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
+
+	link_set_buffer[0] = rate;
+	link_set_buffer[1] = lane_count_set.raw;
+
+	core_link_write_dpcd(link, DPCD_ADDRESS_LINK_BW_SET,
+	link_set_buffer, 2);
+	core_link_write_dpcd(link, DPCD_ADDRESS_DOWNSPREAD_CNTL,
+	&downspread.raw, sizeof(downspread));
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
+		__func__,
+		DPCD_ADDRESS_LINK_BW_SET,
+		lt_settings->link_settings.link_rate,
+		DPCD_ADDRESS_LANE_COUNT_SET,
+		lt_settings->link_settings.lane_count,
+		DPCD_ADDRESS_DOWNSPREAD_CNTL,
+		lt_settings->link_settings.link_spread);
+
+}
+
+static enum dpcd_training_patterns
+	hw_training_pattern_to_dpcd_training_pattern(
+	struct core_link* link,
+	enum hw_dp_training_pattern pattern)
+{
+	enum dpcd_training_patterns dpcd_tr_pattern =
+	DPCD_TRAINING_PATTERN_VIDEOIDLE;
+
+	switch (pattern) {
+	case HW_DP_TRAINING_PATTERN_1:
+		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
+		break;
+	case HW_DP_TRAINING_PATTERN_2:
+		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
+		break;
+	case HW_DP_TRAINING_PATTERN_3:
+		dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
+		break;
+	default:
+		ASSERT(0);
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_LINK_TRAINING,
+			"%s: Invalid HW Training pattern: %d\n",
+			__func__, pattern);
+		break;
+	}
+
+	return dpcd_tr_pattern;
+
+}
+
+static void dpcd_set_lt_pattern_and_lane_settings(
+	struct core_link* link,
+	const struct link_training_settings *lt_settings,
+	enum hw_dp_training_pattern pattern)
+{
+	union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
+	const uint32_t dpcd_base_lt_offset =
+	DPCD_ADDRESS_TRAINING_PATTERN_SET;
+	uint8_t dpcd_lt_buffer[5] = {0};
+	union dpcd_training_pattern dpcd_pattern = {{0}};
+	uint32_t lane;
+	uint32_t size_in_bytes;
+	bool edp_workaround = false; /* TODO link_prop.INTERNAL */
+
+	/*****************************************************************
+	* DpcdAddress_TrainingPatternSet
+	*****************************************************************/
+	dpcd_pattern.bits.TRAINING_PATTERN_SET =
+		hw_training_pattern_to_dpcd_training_pattern(link, pattern);
+
+	dpcd_lt_buffer[DPCD_ADDRESS_TRAINING_PATTERN_SET - dpcd_base_lt_offset]
+		= dpcd_pattern.raw;
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x pattern = %x\n",
+		__func__,
+		DPCD_ADDRESS_TRAINING_PATTERN_SET,
+		dpcd_pattern.bits.TRAINING_PATTERN_SET);
+
+
+	/*****************************************************************
+	* DpcdAddress_Lane0Set -> DpcdAddress_Lane3Set
+	*****************************************************************/
+	for (lane = 0; lane <
+		(uint32_t)(lt_settings->link_settings.lane_count); lane++) {
+
+		dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
+		(uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING);
+		dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
+		(uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS);
+
+		dpcd_lane[lane].bits.MAX_SWING_REACHED =
+		(lt_settings->lane_settings[lane].VOLTAGE_SWING ==
+		VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
+		dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
+		(lt_settings->lane_settings[lane].PRE_EMPHASIS ==
+		PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
+	}
+
+	/* concatinate everything into one buffer*/
+
+	size_in_bytes = lt_settings->link_settings.lane_count * sizeof(dpcd_lane[0]);
+
+	 // 0x00103 - 0x00102
+	dm_memmove(
+		&dpcd_lt_buffer[DPCD_ADDRESS_LANE0_SET - dpcd_base_lt_offset],
+		dpcd_lane,
+		size_in_bytes);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n %x VS set = %x  PE set = %x \
+		max VS Reached = %x  max PE Reached = %x\n",
+		__func__,
+		DPCD_ADDRESS_LANE0_SET,
+		dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+		dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+		dpcd_lane[0].bits.MAX_SWING_REACHED,
+		dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+
+
+	if (edp_workaround) {
+		/* for eDP write in 2 parts because the 5-byte burst is
+		* causing issues on some eDP panels (EPR#366724)
+		*/
+		core_link_write_dpcd(
+			link,
+			DPCD_ADDRESS_TRAINING_PATTERN_SET,
+			&dpcd_pattern.raw,
+			sizeof(dpcd_pattern.raw) );
+
+		core_link_write_dpcd(
+			link,
+			DPCD_ADDRESS_LANE0_SET,
+			(uint8_t *)(dpcd_lane),
+			size_in_bytes);
+
+		} else
+		/* write it all in (1 + number-of-lanes)-byte burst*/
+			core_link_write_dpcd(
+				link,
+				dpcd_base_lt_offset,
+				dpcd_lt_buffer,
+				size_in_bytes + sizeof(dpcd_pattern.raw) );
+
+	link->ln_setting = lt_settings->lane_settings[0];
+}
+
+static bool is_cr_done(enum lane_count ln_count,
+	union lane_status *dpcd_lane_status)
+{
+	bool done = true;
+	uint32_t lane;
+	/*LANEx_CR_DONE bits All 1's?*/
+	for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
+		if (!dpcd_lane_status[lane].bits.CR_DONE_0)
+			done = false;
+	}
+	return done;
+
+}
+
+static bool is_ch_eq_done(enum lane_count ln_count,
+	union lane_status *dpcd_lane_status,
+	union lane_align_status_updated *lane_status_updated)
+{
+	bool done = true;
+	uint32_t lane;
+	if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE)
+		done = false;
+	else {
+		for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
+			if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 ||
+				!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
+				done = false;
+		}
+	}
+	return done;
+
+}
+
+static void update_drive_settings(
+		struct link_training_settings *dest,
+		struct link_training_settings src)
+{
+	uint32_t lane;
+	for (lane = 0; lane < src.link_settings.lane_count; lane++) {
+		dest->lane_settings[lane].VOLTAGE_SWING =
+			src.lane_settings[lane].VOLTAGE_SWING;
+		dest->lane_settings[lane].PRE_EMPHASIS =
+			src.lane_settings[lane].PRE_EMPHASIS;
+		dest->lane_settings[lane].POST_CURSOR2 =
+			src.lane_settings[lane].POST_CURSOR2;
+	}
+}
+
+static uint8_t get_nibble_at_index(const uint8_t *buf,
+	uint32_t index)
+{
+	uint8_t nibble;
+	nibble = buf[index / 2];
+
+	if (index % 2)
+		nibble >>= 4;
+	else
+		nibble &= 0x0F;
+
+	return nibble;
+}
+
+static enum pre_emphasis get_max_pre_emphasis_for_voltage_swing(
+	enum voltage_swing voltage)
+{
+	enum pre_emphasis pre_emphasis;
+	pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
+
+	if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
+		pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
+
+	return pre_emphasis;
+
+}
+
+static void find_max_drive_settings(
+	const struct link_training_settings *link_training_setting,
+	struct link_training_settings *max_lt_setting)
+{
+	uint32_t lane;
+	struct lane_settings max_requested;
+
+	max_requested.VOLTAGE_SWING =
+		link_training_setting->
+		lane_settings[0].VOLTAGE_SWING;
+	max_requested.PRE_EMPHASIS =
+		link_training_setting->
+		lane_settings[0].PRE_EMPHASIS;
+	/*max_requested.postCursor2 =
+	 * link_training_setting->laneSettings[0].postCursor2;*/
+
+	/* Determine what the maximum of the requested settings are*/
+	for (lane = 1; lane < link_training_setting->link_settings.lane_count;
+			lane++) {
+		if (link_training_setting->lane_settings[lane].VOLTAGE_SWING >
+			max_requested.VOLTAGE_SWING)
+
+			max_requested.VOLTAGE_SWING =
+			link_training_setting->
+			lane_settings[lane].VOLTAGE_SWING;
+
+
+		if (link_training_setting->lane_settings[lane].PRE_EMPHASIS >
+				max_requested.PRE_EMPHASIS)
+			max_requested.PRE_EMPHASIS =
+			link_training_setting->
+			lane_settings[lane].PRE_EMPHASIS;
+
+		/*
+		if (link_training_setting->laneSettings[lane].postCursor2 >
+		 max_requested.postCursor2)
+		{
+		max_requested.postCursor2 =
+		link_training_setting->laneSettings[lane].postCursor2;
+		}
+		*/
+	}
+
+	/* make sure the requested settings are
+	 * not higher than maximum settings*/
+	if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
+		max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
+
+	if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
+		max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
+	/*
+	if (max_requested.postCursor2 > PostCursor2_MaxLevel)
+	max_requested.postCursor2 = PostCursor2_MaxLevel;
+	*/
+
+	/* make sure the pre-emphasis matches the voltage swing*/
+	if (max_requested.PRE_EMPHASIS >
+		get_max_pre_emphasis_for_voltage_swing(
+			max_requested.VOLTAGE_SWING))
+		max_requested.PRE_EMPHASIS =
+		get_max_pre_emphasis_for_voltage_swing(
+			max_requested.VOLTAGE_SWING);
+
+	/*
+	 * Post Cursor2 levels are completely independent from
+	 * pre-emphasis (Post Cursor1) levels. But Post Cursor2 levels
+	 * can only be applied to each allowable combination of voltage
+	 * swing and pre-emphasis levels */
+	 /* if ( max_requested.postCursor2 >
+	  *  getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing))
+	  *  max_requested.postCursor2 =
+	  *  getMaxPostCursor2ForVoltageSwing(max_requested.voltageSwing);
+	  */
+
+	max_lt_setting->link_settings.link_rate =
+		link_training_setting->link_settings.link_rate;
+	max_lt_setting->link_settings.lane_count =
+	link_training_setting->link_settings.lane_count;
+	max_lt_setting->link_settings.link_spread =
+		link_training_setting->link_settings.link_spread;
+
+	for (lane = 0; lane <
+		link_training_setting->link_settings.lane_count;
+		lane++) {
+		max_lt_setting->lane_settings[lane].VOLTAGE_SWING =
+			max_requested.VOLTAGE_SWING;
+		max_lt_setting->lane_settings[lane].PRE_EMPHASIS =
+			max_requested.PRE_EMPHASIS;
+		/*max_lt_setting->laneSettings[lane].postCursor2 =
+		 * max_requested.postCursor2;
+		 */
+	}
+
+}
+
+static void get_lane_status_and_drive_settings(
+	struct core_link* link,
+	const struct link_training_settings *link_training_setting,
+	union lane_status *ln_status,
+	union lane_align_status_updated *ln_status_updated,
+	struct link_training_settings *req_settings)
+{
+	uint8_t dpcd_buf[6] = {0};
+	union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {{{0}}};
+	struct link_training_settings request_settings = {{0}};
+	uint32_t lane;
+
+	dm_memset(req_settings, '\0', sizeof(struct link_training_settings));
+
+	core_link_read_dpcd(
+		link,
+		DPCD_ADDRESS_LANE_01_STATUS,
+		(uint8_t *)(dpcd_buf),
+		sizeof(dpcd_buf));
+
+
+	for (lane = 0; lane <
+		(uint32_t)(link_training_setting->link_settings.lane_count);
+		lane++) {
+
+		ln_status[lane].raw =
+			get_nibble_at_index(&dpcd_buf[0], lane);
+		dpcd_lane_adjust[lane].raw =
+			get_nibble_at_index(&dpcd_buf[4], lane);
+	}
+
+	ln_status_updated->raw = dpcd_buf[2];
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n%x Lane01Status = %x\n %x Lane23Status = %x\n ",
+		__func__,
+		DPCD_ADDRESS_LANE_01_STATUS, dpcd_buf[0],
+		DPCD_ADDRESS_LANE_23_STATUS, dpcd_buf[1]);
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s:\n %x Lane01AdjustRequest = %x\n %x Lane23AdjustRequest = %x\n",
+		__func__,
+		DPCD_ADDRESS_ADJUST_REQUEST_LANE0_1,
+		dpcd_buf[4],
+		DPCD_ADDRESS_ADJUST_REQUEST_LANE2_3,
+		dpcd_buf[5]);
+
+	/*copy to req_settings*/
+	request_settings.link_settings.lane_count =
+		link_training_setting->link_settings.lane_count;
+	request_settings.link_settings.link_rate =
+		link_training_setting->link_settings.link_rate;
+	request_settings.link_settings.link_spread =
+		link_training_setting->link_settings.link_spread;
+
+	for (lane = 0; lane <
+		(uint32_t)(link_training_setting->link_settings.lane_count);
+		lane++) {
+
+		request_settings.lane_settings[lane].VOLTAGE_SWING =
+			(enum voltage_swing)(dpcd_lane_adjust[lane].bits.
+				VOLTAGE_SWING_LANE);
+		request_settings.lane_settings[lane].PRE_EMPHASIS =
+			(enum pre_emphasis)(dpcd_lane_adjust[lane].bits.
+				PRE_EMPHASIS_LANE);
+	}
+
+	/*Note: for postcursor2, read adjusted
+	 * postcursor2 settings from*/
+	/*DpcdAddress_AdjustRequestPostCursor2 =
+	 *0x020C (not implemented yet)*/
+
+	/* we find the maximum of the requested settings across all lanes*/
+	/* and set this maximum for all lanes*/
+	find_max_drive_settings(&request_settings, req_settings);
+
+	/* if post cursor 2 is needed in the future,
+	 * read DpcdAddress_AdjustRequestPostCursor2 = 0x020C
+	 */
+
+}
+
+static void dpcd_set_lane_settings(
+	struct core_link* link,
+	const struct link_training_settings *link_training_setting)
+{
+	union dpcd_training_lane dpcd_lane[LANE_COUNT_DP_MAX] = {{{0}}};
+	uint32_t lane;
+
+	for (lane = 0; lane <
+		(uint32_t)(link_training_setting->
+		link_settings.lane_count);
+		lane++) {
+		dpcd_lane[lane].bits.VOLTAGE_SWING_SET =
+			(uint8_t)(link_training_setting->
+			lane_settings[lane].VOLTAGE_SWING);
+		dpcd_lane[lane].bits.PRE_EMPHASIS_SET =
+			(uint8_t)(link_training_setting->
+			lane_settings[lane].PRE_EMPHASIS);
+		dpcd_lane[lane].bits.MAX_SWING_REACHED =
+			(link_training_setting->
+			lane_settings[lane].VOLTAGE_SWING ==
+			VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
+		dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED =
+			(link_training_setting->
+			lane_settings[lane].PRE_EMPHASIS ==
+			PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
+	}
+
+	core_link_write_dpcd(link,
+		DPCD_ADDRESS_LANE0_SET,
+		(uint8_t *)(dpcd_lane),
+		link_training_setting->link_settings.lane_count);
+
+	/*
+	if (LTSettings.link.rate == LinkRate_High2)
+	{
+		DpcdTrainingLaneSet2 dpcd_lane2[lane_count_DPMax] = {0};
+		for ( uint32_t lane = 0;
+		lane < lane_count_DPMax; lane++)
+		{
+			dpcd_lane2[lane].bits.post_cursor2_set =
+			static_cast<unsigned char>(
+			LTSettings.laneSettings[lane].postCursor2);
+			dpcd_lane2[lane].bits.max_post_cursor2_reached = 0;
+		}
+		m_pDpcdAccessSrv->WriteDpcdData(
+		DpcdAddress_Lane0Set2,
+		reinterpret_cast<unsigned char*>(dpcd_lane2),
+		LTSettings.link.lanes);
+	}
+	*/
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_LINK_TRAINING,
+		"%s\n %x VS set = %x  PE set = %x \
+		max VS Reached = %x  max PE Reached = %x\n",
+		__func__,
+		DPCD_ADDRESS_LANE0_SET,
+		dpcd_lane[0].bits.VOLTAGE_SWING_SET,
+		dpcd_lane[0].bits.PRE_EMPHASIS_SET,
+		dpcd_lane[0].bits.MAX_SWING_REACHED,
+		dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED);
+
+	link->ln_setting = link_training_setting->lane_settings[0];
+
+}
+
+static bool is_max_vs_reached(
+	const struct link_training_settings *lt_settings)
+{
+	uint32_t lane;
+	for (lane = 0; lane <
+		(uint32_t)(lt_settings->link_settings.lane_count);
+		lane++) {
+		if (lt_settings->lane_settings[lane].VOLTAGE_SWING
+			== VOLTAGE_SWING_MAX_LEVEL)
+			return true;
+	}
+	return false;
+
+}
+
+void set_drive_settings(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	/* program ASIC PHY settings*/
+	dp_set_hw_lane_settings(link, lt_settings);
+
+	/* Notify DP sink the PHY settings from source */
+	dpcd_set_lane_settings(link, lt_settings);
+}
+
+static bool perform_post_lt_adj_req_sequence(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	enum lane_count lane_count =
+	lt_settings->link_settings.lane_count;
+
+	uint32_t adj_req_count;
+	uint32_t adj_req_timer;
+	bool req_drv_setting_changed;
+	uint32_t lane;
+
+	req_drv_setting_changed = false;
+	for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
+	adj_req_count++) {
+
+		req_drv_setting_changed = false;
+
+		for (adj_req_timer = 0;
+			adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
+			adj_req_timer++) {
+
+			struct link_training_settings req_settings;
+			union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
+			union lane_align_status_updated
+				dpcd_lane_status_updated;
+
+			get_lane_status_and_drive_settings(
+			link,
+			lt_settings,
+			dpcd_lane_status,
+			&dpcd_lane_status_updated,
+			&req_settings);
+
+			if (dpcd_lane_status_updated.bits.
+					POST_LT_ADJ_REQ_IN_PROGRESS == 0)
+				return true;
+
+			if (!is_cr_done(lane_count, dpcd_lane_status))
+				return false;
+
+			if (!is_ch_eq_done(
+				lane_count,
+				dpcd_lane_status,
+				&dpcd_lane_status_updated))
+				return false;
+
+			for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
+
+				if (lt_settings->
+				lane_settings[lane].VOLTAGE_SWING !=
+				req_settings.lane_settings[lane].
+				VOLTAGE_SWING ||
+				lt_settings->lane_settings[lane].PRE_EMPHASIS !=
+				req_settings.lane_settings[lane].PRE_EMPHASIS) {
+
+					req_drv_setting_changed = true;
+					break;
+				}
+			}
+
+			if (req_drv_setting_changed) {
+				update_drive_settings(
+					lt_settings,req_settings);
+
+				set_drive_settings(link, lt_settings);
+				break;
+			}
+
+			dm_sleep_in_milliseconds(link->ctx, 1);
+		}
+
+		if (!req_drv_setting_changed) {
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_WARNING,
+				LOG_MINOR_COMPONENT_LINK_SERVICE,
+				"%s: Post Link Training Adjust Request Timed out\n",
+				__func__);
+
+			ASSERT(0);
+			return true;
+		}
+	}
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_WARNING,
+		LOG_MINOR_COMPONENT_LINK_SERVICE,
+		"%s: Post Link Training Adjust Request limit reached\n",
+		__func__);
+
+	ASSERT(0);
+	return true;
+
+}
+
+static bool perform_channel_equalization_sequence(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	struct link_training_settings req_settings;
+	enum hw_dp_training_pattern hw_tr_pattern;
+	uint32_t retries_ch_eq;
+	enum lane_count lane_count = lt_settings->link_settings.lane_count;
+	union lane_align_status_updated dpcd_lane_status_updated = {{0}};
+	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};;
+
+	/*TODO hw_tr_pattern = HW_DP_TRAINING_PATTERN_3;*/
+	hw_tr_pattern = HW_DP_TRAINING_PATTERN_2;
+
+	dp_set_hw_training_pattern(link, hw_tr_pattern);
+
+	for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
+		retries_ch_eq++) {
+
+		dp_set_hw_lane_settings(link, lt_settings);
+
+		/* 2. update DPCD*/
+		if (!retries_ch_eq)
+			/* EPR #361076 - write as a 5-byte burst,
+			 * but only for the 1-st iteration*/
+			dpcd_set_lt_pattern_and_lane_settings(
+				link,
+				lt_settings,
+				hw_tr_pattern);
+		else
+			dpcd_set_lane_settings(link, lt_settings);
+
+		/* 3. wait for receiver to lock-on*/
+		wait_for_training_aux_rd_interval(link, 400);
+
+		/* 4. Read lane status and requested
+		 * drive settings as set by the sink*/
+
+		get_lane_status_and_drive_settings(
+			link,
+			lt_settings,
+			dpcd_lane_status,
+			&dpcd_lane_status_updated,
+			&req_settings);
+
+		/* 5. check CR done*/
+		if (!is_cr_done(lane_count, dpcd_lane_status))
+			return false;
+
+		/* 6. check CHEQ done*/
+		if (is_ch_eq_done(lane_count,
+			dpcd_lane_status,
+			&dpcd_lane_status_updated))
+			return true;
+
+		/* 7. update VS/PE/PC2 in lt_settings*/
+		update_drive_settings(lt_settings, req_settings);
+	}
+
+	return false;
+
+}
+
+static bool perform_clock_recovery_sequence(
+	struct core_link *link,
+	struct link_training_settings *lt_settings)
+{
+	uint32_t retries_cr;
+	uint32_t retry_count;
+	uint32_t lane;
+	struct link_training_settings req_settings;
+	enum lane_count lane_count =
+	lt_settings->link_settings.lane_count;
+	enum hw_dp_training_pattern hw_tr_pattern = HW_DP_TRAINING_PATTERN_1;
+	union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
+	union lane_align_status_updated dpcd_lane_status_updated;
+
+	retries_cr = 0;
+	retry_count = 0;
+	/* initial drive setting (VS/PE/PC2)*/
+	for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
+		lt_settings->lane_settings[lane].VOLTAGE_SWING =
+		VOLTAGE_SWING_LEVEL0;
+		lt_settings->lane_settings[lane].PRE_EMPHASIS =
+		PRE_EMPHASIS_DISABLED;
+		lt_settings->lane_settings[lane].POST_CURSOR2 =
+		POST_CURSOR2_DISABLED;
+	}
+
+	dp_set_hw_training_pattern(link, hw_tr_pattern);
+
+	/* najeeb - The synaptics MST hub can put the LT in
+	* infinite loop by switching the VS
+	*/
+	/* between level 0 and level 1 continuously, here
+	* we try for CR lock for LinkTrainingMaxCRRetry count*/
+	while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
+	(retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
+
+		dm_memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status));
+		dm_memset(&dpcd_lane_status_updated, '\0',
+		sizeof(dpcd_lane_status_updated));
+
+		/* 1. call HWSS to set lane settings*/
+		dp_set_hw_lane_settings(
+				link,
+				lt_settings);
+
+		/* 2. update DPCD of the receiver*/
+		if (!retries_cr)
+			/* EPR #361076 - write as a 5-byte burst,
+			 * but only for the 1-st iteration.*/
+			dpcd_set_lt_pattern_and_lane_settings(
+					link,
+					lt_settings,
+					hw_tr_pattern);
+		else
+			dpcd_set_lane_settings(
+					link,
+					lt_settings);
+
+
+		/* 3. wait receiver to lock-on*/
+		wait_for_training_aux_rd_interval(
+				link,
+				100);
+
+		/* 4. Read lane status and requested drive
+		* settings as set by the sink
+		*/
+		get_lane_status_and_drive_settings(
+				link,
+				lt_settings,
+				dpcd_lane_status,
+				&dpcd_lane_status_updated,
+				&req_settings);
+
+
+		/* 5. check CR done*/
+		if (is_cr_done(lane_count, dpcd_lane_status))
+			return true;
+
+		/* 6. max VS reached*/
+		if (is_max_vs_reached(lt_settings))
+			return false;
+
+		/* 7. same voltage*/
+		/* Note: VS same for all lanes,
+		* so comparing first lane is sufficient*/
+		if (lt_settings->lane_settings[0].VOLTAGE_SWING ==
+			req_settings.lane_settings[0].VOLTAGE_SWING)
+			retries_cr++;
+		else
+			retries_cr = 0;
+
+
+			/* 8. update VS/PE/PC2 in lt_settings*/
+			update_drive_settings(lt_settings, req_settings);
+
+			retry_count++;
+	}
+
+	if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
+		ASSERT(0);
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_ERROR,
+			LOG_MINOR_COMPONENT_LINK_SERVICE,
+			"%s: Link Training Error, could not \
+			 get CR after %d tries. \
+			Possibly voltage swing issue", __func__,
+			LINK_TRAINING_MAX_CR_RETRY);
+
+	}
+
+	return false;
+}
+
+ bool perform_link_training(
+	struct core_link *link,
+	const struct link_settings *link_setting,
+	bool skip_video_pattern)
+{
+	bool status;
+	union dpcd_training_pattern dpcd_pattern = {{0}};
+	union lane_count_set lane_count_set = {{0}};
+	const int8_t *link_rate = "Unknown";
+	struct link_training_settings lt_settings;
+
+	status = false;
+	dm_memset(&lt_settings, '\0', sizeof(lt_settings));
+
+	lt_settings.link_settings.link_rate = link_setting->link_rate;
+	lt_settings.link_settings.lane_count = link_setting->lane_count;
+
+	/*@todo[vdevulap] move SS to LS, should not be handled by displaypath*/
+
+	/* TODO hard coded to SS for now
+	 * lt_settings.link_settings.link_spread =
+	 * dal_display_path_is_ss_supported(
+	 * path_mode->display_path) ?
+	 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
+	 * LINK_SPREAD_DISABLED;
+	 */
+	lt_settings.link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
+
+	/* 1. set link rate, lane count and spread*/
+	dpcd_set_link_settings(link, &lt_settings);
+
+	/* 2. perform link training (set link training done
+	 *  to false is done as well)*/
+	if (perform_clock_recovery_sequence(link, &lt_settings)) {
+
+		if (perform_channel_equalization_sequence(link, &lt_settings))
+			status = true;
+	}
+
+	if (status || !skip_video_pattern) {
+
+		/* 3. set training not in progress*/
+		dpcd_pattern.bits.TRAINING_PATTERN_SET =
+			DPCD_TRAINING_PATTERN_VIDEOIDLE;
+		dpcd_set_training_pattern(link, dpcd_pattern);
+
+		/* 4. mainlink output idle pattern*/
+		dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE);
+
+		/* 5. post training adjust if required*/
+		if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED
+			== 1) {
+			if (status == true) {
+				if (perform_post_lt_adj_req_sequence(
+					link, &lt_settings) == false)
+					status = false;
+			}
+
+			lane_count_set.bits.LANE_COUNT_SET =
+				lt_settings.link_settings.lane_count;
+			lane_count_set.bits.ENHANCED_FRAMING = 1;
+			lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
+
+			core_link_write_dpcd(
+				link,
+				DPCD_ADDRESS_LANE_COUNT_SET,
+				&lane_count_set.raw,
+				sizeof(lane_count_set));
+		}
+	}
+
+	/* 6. print status message*/
+	switch (lt_settings.link_settings.link_rate) {
+
+	case LINK_RATE_LOW:
+		link_rate = "Low";
+		break;
+	case LINK_RATE_HIGH:
+		link_rate = "High";
+		break;
+	case LINK_RATE_HIGH2:
+		link_rate = "High2";
+		break;
+	case LINK_RATE_RBR2:
+		link_rate = "RBR2";
+		break;
+	default:
+		break;
+	}
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_MST,
+		LOG_MINOR_MST_PROGRAMMING,
+		"Link training for %d lanes at %s rate %s with PE %d, VS %d\n",
+		lt_settings.link_settings.lane_count,
+		link_rate,
+		status ? "succeeded" : "failed",
+		lt_settings.lane_settings[0].PRE_EMPHASIS,
+		lt_settings.lane_settings[0].VOLTAGE_SWING);
+
+	return status;
+}
+
+/*TODO add more check to see if link support request link configuration */
+static bool is_link_setting_supported(
+	const struct link_settings *link_setting,
+	const struct link_settings *max_link_setting)
+{
+	if (link_setting->lane_count > max_link_setting->lane_count ||
+		link_setting->link_rate > max_link_setting->link_rate)
+		return false;
+	return true;
+}
+
+static const uint32_t get_link_training_fallback_table_len(
+	struct core_link *link)
+{
+	return ARRAY_SIZE(link_training_fallback_table);
+}
+
+static const struct link_settings *get_link_training_fallback_table(
+	struct core_link *link, uint32_t i)
+{
+	return &link_training_fallback_table[i];
+}
+
+static bool exceeded_limit_link_setting(const struct link_settings *link_setting,
+			const struct link_settings *limit_link_setting)
+{
+	return (link_setting->lane_count * link_setting->link_rate
+		 > limit_link_setting->lane_count * limit_link_setting->link_rate ?
+				 true : false);
+}
+
+
+bool dp_hbr_verify_link_cap(
+	struct core_link *link,
+	struct link_settings *known_limit_link_setting)
+{
+	struct link_settings max_link_cap = {0};
+	bool success;
+	bool skip_link_training;
+	const struct link_settings *cur;
+	bool skip_video_pattern;
+	uint32_t i;
+
+	success = false;
+	skip_link_training = false;
+
+	/* TODO confirm this is correct for cz */
+	max_link_cap.lane_count = LANE_COUNT_FOUR;
+	max_link_cap.link_rate = LINK_RATE_HIGH2;
+	max_link_cap.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ;
+
+	/* TODO implement override and monitor patch later */
+
+	/* try to train the link from high to low to
+	 * find the physical link capability
+	 */
+	/* disable PHY done possible by BIOS, will be done by driver itself */
+	dp_disable_link_phy(link, link->public.connector_signal);
+
+	for (i = 0; i < get_link_training_fallback_table_len(link) &&
+		!success; i++) {
+		cur = get_link_training_fallback_table(link, i);
+
+		if (known_limit_link_setting->lane_count != LANE_COUNT_UNKNOWN &&
+			exceeded_limit_link_setting(cur,
+					known_limit_link_setting))
+			continue;
+
+		if (!is_link_setting_supported(cur, &max_link_cap))
+			continue;
+
+		skip_video_pattern = true;
+		if (cur->link_rate == LINK_RATE_LOW)
+			skip_video_pattern = false;
+
+		dp_enable_link_phy(
+				link,
+				link->public.connector_signal,
+				cur);
+
+		if (skip_link_training)
+			success = true;
+		else {
+			uint8_t num_retries = 3;
+			uint8_t j;
+			uint8_t delay_between_retries = 10;
+
+			for (j = 0; j < num_retries; ++j) {
+				success = perform_link_training(
+					link,
+					cur,
+					skip_video_pattern);
+
+				if (success)
+					break;
+
+				dm_sleep_in_milliseconds(
+					link->ctx,
+					delay_between_retries);
+
+				delay_between_retries += 10;
+			}
+		}
+
+		if (success)
+			link->verified_link_cap = *cur;
+
+		/* always disable the link before trying another
+		 * setting or before returning we'll enable it later
+		 * based on the actual mode we're driving
+		 */
+		dp_disable_link_phy(link, link->public.connector_signal);
+	}
+
+	/* Link Training failed for all Link Settings
+	 *  (Lane Count is still unknown)
+	 */
+	if (!success) {
+		/* If all LT fails for all settings,
+		 * set verified = failed safe (1 lane low)
+		 */
+		link->verified_link_cap.lane_count = LANE_COUNT_ONE;
+		link->verified_link_cap.link_rate = LINK_RATE_LOW;
+
+		link->verified_link_cap.link_spread =
+		LINK_SPREAD_DISABLED;
+	}
+
+	link->max_link_setting = link->verified_link_cap;
+
+	return success;
+}
+
+static uint32_t bandwidth_in_kbps_from_timing(
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t bits_per_channel = 0;
+	uint32_t kbps;
+	switch (timing->display_color_depth) {
+
+	case COLOR_DEPTH_666:
+		bits_per_channel = 6;
+		break;
+	case COLOR_DEPTH_888:
+		bits_per_channel = 8;
+		break;
+	case COLOR_DEPTH_101010:
+		bits_per_channel = 10;
+		break;
+	case COLOR_DEPTH_121212:
+		bits_per_channel = 12;
+		break;
+	case COLOR_DEPTH_141414:
+		bits_per_channel = 14;
+		break;
+	case COLOR_DEPTH_161616:
+		bits_per_channel = 16;
+		break;
+	default:
+		break;
+	}
+	ASSERT(bits_per_channel != 0);
+
+	kbps = timing->pix_clk_khz;
+	kbps *= bits_per_channel;
+
+	if (timing->flags.Y_ONLY != 1)
+		/*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
+		kbps *= 3;
+
+	return kbps;
+
+}
+
+static uint32_t bandwidth_in_kbps_from_link_settings(
+	const struct link_settings *link_setting)
+{
+	uint32_t link_rate_in_kbps = link_setting->link_rate *
+		LINK_RATE_REF_FREQ_IN_KHZ;
+
+	uint32_t lane_count  = link_setting->lane_count;
+	uint32_t kbps = link_rate_in_kbps;
+	kbps *= lane_count;
+	kbps *= 8;   /* 8 bits per byte*/
+
+	return kbps;
+
+}
+
+bool dp_validate_mode_timing(
+	struct core_link *link,
+	const struct dc_crtc_timing *timing)
+{
+	uint32_t req_bw;
+	uint32_t max_bw;
+
+	const struct link_settings *link_setting;
+
+	/*always DP fail safe mode*/
+	if (timing->pix_clk_khz == (uint32_t)25175 &&
+		timing->h_addressable == (uint32_t)640 &&
+		timing->v_addressable == (uint32_t)480)
+		return true;
+
+	/* For static validation we always use reported
+	 * link settings for other cases, when no modelist
+	 * changed we can use verified link setting*/
+	link_setting = &link->reported_link_cap;
+
+	/* TODO: DYNAMIC_VALIDATION needs to be implemented */
+	/*if (flags.DYNAMIC_VALIDATION == 1 &&
+		link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
+		link_setting = &link->verified_link_cap;
+	*/
+
+	req_bw = bandwidth_in_kbps_from_timing(timing);
+	max_bw = bandwidth_in_kbps_from_link_settings(link_setting);
+
+	if (req_bw < max_bw) {
+		/* remember the biggest mode here, during
+		 * initial link training (to get
+		 * verified_link_cap), LS sends event about
+		 * cannot train at reported cap to upper
+		 * layer and upper layer will re-enumerate modes.
+		 * this is not necessary if the lower
+		 * verified_link_cap is enough to drive
+		 * all the modes */
+
+		/* TODO: DYNAMIC_VALIDATION needs to be implemented */
+		/* if (flags.DYNAMIC_VALIDATION == 1)
+			dpsst->max_req_bw_for_verified_linkcap = dal_max(
+				dpsst->max_req_bw_for_verified_linkcap, req_bw); */
+		return true;
+	} else
+		return false;
+}
+
+void decide_link_settings(struct core_stream *stream,
+	struct link_settings *link_setting)
+{
+
+	const struct link_settings *cur_ls;
+	struct core_link* link;
+	uint32_t req_bw;
+	uint32_t link_bw;
+	uint32_t i;
+
+	req_bw = bandwidth_in_kbps_from_timing(
+			&stream->public.timing);
+
+	/* if preferred is specified through AMDDP, use it, if it's enough
+	 * to drive the mode
+	 */
+	link = stream->sink->link;
+
+	if ((link->reported_link_cap.lane_count != LANE_COUNT_UNKNOWN) &&
+		(link->reported_link_cap.link_rate <=
+				link->verified_link_cap.link_rate)) {
+
+		link_bw = bandwidth_in_kbps_from_link_settings(
+				&link->reported_link_cap);
+
+		if (req_bw < link_bw) {
+			*link_setting = link->reported_link_cap;
+			return;
+		}
+	}
+
+	/* search for first suitable setting for the requested
+	 * bandwidth
+	 */
+	for (i = 0; i < get_link_training_fallback_table_len(link); i++) {
+
+		cur_ls = get_link_training_fallback_table(link, i);
+
+		link_bw =
+				bandwidth_in_kbps_from_link_settings(
+				cur_ls);
+
+		if (req_bw < link_bw) {
+			if (is_link_setting_supported(
+				cur_ls,
+				&link->max_link_setting)) {
+				*link_setting = *cur_ls;
+				return;
+			}
+		}
+	}
+
+	BREAK_TO_DEBUGGER();
+	ASSERT(link->verified_link_cap.lane_count !=
+		LANE_COUNT_UNKNOWN);
+
+	*link_setting = link->verified_link_cap;
+}
+
+/*************************Short Pulse IRQ***************************/
+
+static bool hpd_rx_irq_check_link_loss_status(
+	struct core_link *link,
+	union hpd_irq_data *hpd_irq_dpcd_data)
+{
+	uint8_t irq_reg_rx_power_state;
+	enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
+	union lane_status lane_status;
+	uint32_t lane;
+	bool sink_status_changed;
+	bool return_code;
+
+	sink_status_changed = false;
+	return_code = false;
+
+	if (link->cur_link_settings.lane_count == 0)
+		return return_code;
+	/*1. Check that we can handle interrupt: Not in FS DOS,
+	 *  Not in "Display Timeout" state, Link is trained.
+	 */
+
+	dpcd_result = core_link_read_dpcd(link,
+		DPCD_ADDRESS_POWER_STATE,
+		&irq_reg_rx_power_state,
+		sizeof(irq_reg_rx_power_state));
+
+	if (dpcd_result != DC_OK) {
+		irq_reg_rx_power_state = DP_PWR_STATE_D0;
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_HPD_IRQ,
+			"%s: DPCD read failed to obtain power state.\n",
+			__func__);
+	}
+
+	if (irq_reg_rx_power_state == DP_PWR_STATE_D0) {
+
+		/*2. Check that Link Status changed, before re-training.*/
+
+		/*parse lane status*/
+		for (lane = 0;
+			lane < link->cur_link_settings.lane_count;
+			lane++) {
+
+			/* check status of lanes 0,1
+			 * changed DpcdAddress_Lane01Status (0x202)*/
+			lane_status.raw = get_nibble_at_index(
+				&hpd_irq_dpcd_data->bytes.lane01_status.raw,
+				lane);
+
+			if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
+				!lane_status.bits.CR_DONE_0 ||
+				!lane_status.bits.SYMBOL_LOCKED_0) {
+				/* if one of the channel equalization, clock
+				 * recovery or symbol lock is dropped
+				 * consider it as (link has been
+				 * dropped) dp sink status has changed*/
+				sink_status_changed = true;
+				break;
+			}
+
+		}
+
+		/* Check interlane align.*/
+		if (sink_status_changed ||
+			!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.
+			INTERLANE_ALIGN_DONE) {
+
+			dal_logger_write(link->ctx->logger,
+				LOG_MAJOR_HW_TRACE,
+				LOG_MINOR_HW_TRACE_HPD_IRQ,
+				"%s: Link Status changed.\n",
+				__func__);
+
+			return_code = true;
+		}
+	}
+
+	return return_code;
+}
+
+static enum dc_status read_hpd_rx_irq_data(
+	struct core_link *link,
+	union hpd_irq_data *irq_data)
+{
+	/* The HW reads 16 bytes from 200h on HPD,
+	 * but if we get an AUX_DEFER, the HW cannot retry
+	 * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
+	 * fail, so we now explicitly read 6 bytes which is
+	 * the req from the above mentioned test cases.
+	 */
+	return core_link_read_dpcd(
+	link,
+	DPCD_ADDRESS_SINK_COUNT,
+	irq_data->raw,
+	sizeof(union hpd_irq_data));
+}
+
+static bool allow_hpd_rx_irq(const struct core_link *link)
+{
+	/*
+	 * Don't handle RX IRQ unless one of following is met:
+	 * 1) The link is established (cur_link_settings != unknown)
+	 * 2) We kicked off MST detection
+	 * 3) We know we're dealing with an active dongle
+	 */
+
+	if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
+		(link->public.type == dc_connection_mst_branch) ||
+		is_dp_active_dongle(link))
+		return true;
+
+	return false;
+}
+
+bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link)
+{
+	struct core_link *link = DC_LINK_TO_LINK(dc_link);
+	union hpd_irq_data hpd_irq_dpcd_data = {{{{0}}}};
+	enum dc_status result = DDC_RESULT_UNKNOWN;
+	bool status = false;
+	/* For use cases related to down stream connection status change,
+	 * PSR and device auto test, refer to function handle_sst_hpd_irq
+	 * in DAL2.1*/
+
+	dal_logger_write(link->ctx->logger,
+		LOG_MAJOR_HW_TRACE,
+		LOG_MINOR_HW_TRACE_HPD_IRQ,
+		"%s: Got short pulse HPD on link %d\n",
+		__func__, link->public.link_index);
+
+	if (!allow_hpd_rx_irq(link)) {
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_HPD_IRQ,
+			"%s: skipping HPD handling on %d\n",
+			__func__, link->public.link_index);
+		return false;
+	}
+
+	 /* All the "handle_hpd_irq_xxx()" methods
+	 * should be called only after
+	 * dal_dpsst_ls_read_hpd_irq_data
+	 * Order of calls is important too
+	 */
+	result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
+
+	if (result != DC_OK) {
+		dal_logger_write(link->ctx->logger,
+			LOG_MAJOR_HW_TRACE,
+			LOG_MINOR_HW_TRACE_HPD_IRQ,
+			"%s: DPCD read failed to obtain irq data\n",
+			__func__);
+		return false;
+	}
+
+	/* check if we have MST msg and return since we poll for it */
+	if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY ||
+		hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY)
+		return false;
+
+
+	/* For now we only handle 'Downstream port status' case. */
+	/* If we got sink count changed it means Downstream port status changed,
+	 * then DM should call DC to do the detection. */
+	if (hpd_rx_irq_check_link_loss_status(
+		link,
+		&hpd_irq_dpcd_data)) {
+		perform_link_training(link, &link->cur_link_settings, true);
+		status = false;
+	}
+
+	if (hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
+				!= link->dpcd_sink_count)
+		status = true;
+
+	/* reasons for HPD RX:
+	 * 1. Link Loss - ie Re-train the Link
+	 * 2. MST sideband message
+	 * 3. Automated Test - ie. Internal Commit
+	 * 4. CP (copy protection) - (not interesting for DM???)
+	 * 5. DRR
+	 * 6. Downstream Port status changed -ie. Detect - this the only one
+	 * which is interesting for DM because it must call dc_link_detect.
+	 */
+	return status;
+}
+
+/*query dpcd for version and mst cap addresses*/
+bool is_mst_supported(struct core_link *link)
+{
+	bool mst          = false;
+	enum dc_status st = DC_OK;
+	union dpcd_rev rev;
+	union mstm_cap cap;
+
+	rev.raw  = 0;
+	cap.raw  = 0;
+
+	st = core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV, &rev.raw,
+			sizeof(rev));
+
+	if (st == DC_OK && rev.raw >= DPCD_REV_12) {
+
+		st = core_link_read_dpcd(link, DPCD_ADDRESS_MSTM_CAP,
+				&cap.raw, sizeof(cap));
+		if (st == DC_OK && cap.bits.MST_CAP == 1)
+			mst = true;
+	}
+	return mst;
+
+}
+
+bool is_dp_active_dongle(const struct core_link *link)
+{
+	enum display_dongle_type dongle_type = link->dpcd_caps.dongle_type;
+
+	return (dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) ||
+			(dongle_type == DISPLAY_DONGLE_DP_DVI_CONVERTER) ||
+			(dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER);
+}
+
+static void get_active_converter_info(
+	uint8_t data, struct core_link *link)
+{
+	union dp_downstream_port_present ds_port = { .byte = data };
+
+	/* decode converter info*/
+	if (!ds_port.fields.PORT_PRESENT) {
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
+		ddc_service_set_dongle_type(link->ddc,
+				link->dpcd_caps.dongle_type);
+		return;
+	}
+
+	switch (ds_port.fields.PORT_TYPE) {
+	case DOWNSTREAM_VGA:
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
+		break;
+	case DOWNSTREAM_DVI_HDMI:
+		/* At this point we don't know is it DVI or HDMI,
+		 * assume DVI.*/
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
+		break;
+	default:
+		link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
+		break;
+	}
+
+	if (link->dpcd_caps.dpcd_rev.raw >= DCS_DPCD_REV_11) {
+		uint8_t det_caps[4];
+		union dwnstream_port_caps_byte0 *port_caps =
+			(union dwnstream_port_caps_byte0 *)det_caps;
+		core_link_read_dpcd(link, DPCD_ADDRESS_DWN_STRM_PORT0_CAPS,
+				det_caps, sizeof(det_caps));
+
+		switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
+		case DOWN_STREAM_DETAILED_VGA:
+			link->dpcd_caps.dongle_type =
+				DISPLAY_DONGLE_DP_VGA_CONVERTER;
+			break;
+		case DOWN_STREAM_DETAILED_DVI:
+			link->dpcd_caps.dongle_type =
+				DISPLAY_DONGLE_DP_DVI_CONVERTER;
+			break;
+		case DOWN_STREAM_DETAILED_HDMI:
+			link->dpcd_caps.dongle_type =
+				DISPLAY_DONGLE_DP_HDMI_CONVERTER;
+
+			if (ds_port.fields.DETAILED_CAPS) {
+
+				union dwnstream_port_caps_byte3_hdmi
+					hdmi_caps = {.raw = det_caps[3] };
+
+				link->dpcd_caps.is_dp_hdmi_s3d_converter =
+					hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
+			}
+			break;
+		}
+	}
+	ddc_service_set_dongle_type(link->ddc,
+			link->dpcd_caps.dongle_type);
+}
+
+static void dp_wa_power_up_0010FA(struct core_link *link, uint8_t *dpcd_data,
+		int length)
+{
+	int retry = 0;
+	struct dp_device_vendor_id dp_id;
+	union dp_downstream_port_present ds_port = { 0 };
+
+	if (!link->dpcd_caps.dpcd_rev.raw) {
+		do {
+			dp_receiver_power_ctrl(link, true);
+			core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV,
+							dpcd_data, length);
+			link->dpcd_caps.dpcd_rev.raw = dpcd_data[
+				DPCD_ADDRESS_DPCD_REV -
+				DPCD_ADDRESS_DPCD_REV];
+		} while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
+	}
+
+	ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT -
+				 DPCD_ADDRESS_DPCD_REV];
+
+	get_active_converter_info(ds_port.byte, link);
+
+	/* read IEEE branch device id */
+	core_link_read_dpcd(link, DPCD_ADDRESS_BRANCH_DEVICE_ID_START,
+			(uint8_t *)&dp_id, sizeof(dp_id));
+	link->dpcd_caps.branch_dev_id =
+			(dp_id.ieee_oui[0] << 16) +
+			(dp_id.ieee_oui[1] << 8) +
+			dp_id.ieee_oui[2];
+
+	if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
+		switch (link->dpcd_caps.branch_dev_id) {
+		/* Some active dongles (DP-VGA, DP-DLDVI converters) power down
+		 * all internal circuits including AUX communication preventing
+		 * reading DPCD table and EDID (spec violation).
+		 * Encoder will skip DP RX power down on disable_output to
+		 * keep receiver powered all the time.*/
+		case DP_BRANCH_DEVICE_ID_1:
+		case DP_BRANCH_DEVICE_ID_4:
+			link->wa_flags.dp_keep_receiver_powered = true;
+			break;
+
+		/* TODO: May need work around for other dongles. */
+		default:
+			link->wa_flags.dp_keep_receiver_powered = false;
+			break;
+		}
+	} else
+		link->wa_flags.dp_keep_receiver_powered = false;
+}
+
+static void retrieve_link_cap(struct core_link *link)
+{
+	uint8_t dpcd_data[
+			DPCD_ADDRESS_EDP_CONFIG_CAP -
+			DPCD_ADDRESS_DPCD_REV + 1];
+
+	union down_stream_port_count down_strm_port_count;
+	union edp_configuration_cap edp_config_cap;
+	union max_down_spread max_down_spread;
+	union dp_downstream_port_present ds_port = { 0 };
+
+	dm_memset(dpcd_data, '\0', sizeof(dpcd_data));
+	dm_memset(&down_strm_port_count,
+		'\0', sizeof(union down_stream_port_count));
+	dm_memset(&edp_config_cap, '\0',
+		sizeof(union edp_configuration_cap));
+	dm_memset(&max_down_spread, '\0',
+		sizeof(union max_down_spread));
+
+	core_link_read_dpcd(link, DPCD_ADDRESS_DPCD_REV,
+			dpcd_data, sizeof(dpcd_data));
+	link->dpcd_caps.dpcd_rev.raw = dpcd_data[
+		DPCD_ADDRESS_DPCD_REV -
+		DPCD_ADDRESS_DPCD_REV];
+
+	ds_port.byte = dpcd_data[DPCD_ADDRESS_DOWNSTREAM_PORT_PRESENT -
+				 DPCD_ADDRESS_DPCD_REV];
+
+	get_active_converter_info(ds_port.byte, link);
+
+	dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
+
+	link->dpcd_caps.allow_invalid_MSA_timing_param =
+		down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
+
+	link->dpcd_caps.max_ln_count.raw = dpcd_data[
+		DPCD_ADDRESS_MAX_LANE_COUNT - DPCD_ADDRESS_DPCD_REV];
+
+	max_down_spread.raw = dpcd_data[
+		DPCD_ADDRESS_MAX_DOWNSPREAD - DPCD_ADDRESS_DPCD_REV];
+
+	link->reported_link_cap.lane_count =
+		link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
+	link->reported_link_cap.link_rate = dpcd_data[
+		DPCD_ADDRESS_MAX_LINK_RATE - DPCD_ADDRESS_DPCD_REV];
+	link->reported_link_cap.link_spread =
+		max_down_spread.bits.MAX_DOWN_SPREAD ?
+		LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
+
+	edp_config_cap.raw = dpcd_data[
+		DPCD_ADDRESS_EDP_CONFIG_CAP - DPCD_ADDRESS_DPCD_REV];
+	link->dpcd_caps.panel_mode_edp =
+		edp_config_cap.bits.ALT_SCRAMBLER_RESET;
+
+	link->edp_revision = DPCD_EDP_REVISION_EDP_UNKNOWN;
+
+	/* read sink count */
+	core_link_read_dpcd(link,
+			DPCD_ADDRESS_SINK_COUNT,
+			&link->dpcd_caps.sink_count.raw,
+			sizeof(link->dpcd_caps.sink_count.raw));
+
+	/* Display control registers starting at DPCD 700h are only valid and
+	 * enabled if this eDP config cap bit is set. */
+	if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) {
+		/* Read the Panel's eDP revision at DPCD 700h. */
+		core_link_read_dpcd(link,
+			DPCD_ADDRESS_EDP_REV,
+			(uint8_t *)(&link->edp_revision),
+			sizeof(link->edp_revision));
+	}
+	/* TODO: Confirm if need retrieve_psr_link_cap */
+}
+
+void detect_dp_sink_caps(struct core_link *link)
+{
+	retrieve_link_cap(link);
+
+	/* dc init_hw has power encoder using default
+	 * signal for connector. For native DP, no
+	 * need to power up encoder again. If not native
+	 * DP, hw_init may need check signal or power up
+	 * encoder here.
+	 */
+
+	if (is_mst_supported(link)) {
+		link->verified_link_cap = link->reported_link_cap;
+	} else {
+		dp_hbr_verify_link_cap(link,
+			&link->reported_link_cap);
+	}
+	/* TODO save sink caps in link->sink */
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
new file mode 100644
index 000000000000..d0f3999e54f5
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link_hwss.c
@@ -0,0 +1,201 @@
+/* Copyright 2015 Advanced Micro Devices, Inc. */
+
+#include "dm_services.h"
+#include "dc.h"
+#include "inc/core_dc.h"
+#include "include/ddc_service_types.h"
+#include "include/i2caux_interface.h"
+#include "link_hwss.h"
+#include "hw_sequencer.h"
+#include "dc_link_ddc.h"
+#include "dm_helpers.h"
+#include "dce110/dce110_link_encoder.h"
+#include "dce110/dce110_stream_encoder.h"
+
+
+enum dc_status core_link_read_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	uint8_t *data,
+	uint32_t size)
+{
+	if (!dm_helpers_dp_read_dpcd(link->ctx,
+			&link->public,
+			address, data, size))
+			return DC_ERROR_UNEXPECTED;
+
+	return DC_OK;
+}
+
+enum dc_status core_link_write_dpcd(
+	struct core_link* link,
+	uint32_t address,
+	const uint8_t *data,
+	uint32_t size)
+{
+	if (!dm_helpers_dp_write_dpcd(link->ctx,
+			&link->public,
+			address, data, size))
+				return DC_ERROR_UNEXPECTED;
+
+	return DC_OK;
+}
+
+void dp_receiver_power_ctrl(struct core_link *link, bool on)
+{
+	uint8_t state;
+
+	state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
+
+	core_link_write_dpcd(link, DPCD_ADDRESS_POWER_STATE, &state,
+			sizeof(state));
+}
+
+void dp_enable_link_phy(
+	struct core_link *link,
+	enum signal_type signal,
+	const struct link_settings *link_settings)
+{
+	struct link_encoder *link_enc = link->link_enc;
+
+	if (dc_is_dp_sst_signal(signal)) {
+		if (signal == SIGNAL_TYPE_EDP) {
+			link_enc->funcs->power_control(link_enc, true);
+			link_enc->funcs->backlight_control(link_enc, true);
+		}
+
+		link_enc->funcs->enable_dp_output(
+						link_enc,
+						link_settings,
+						CLOCK_SOURCE_ID_EXTERNAL);
+	} else {
+		link_enc->funcs->enable_dp_mst_output(
+						link_enc,
+						link_settings,
+						CLOCK_SOURCE_ID_EXTERNAL);
+	}
+
+	dp_receiver_power_ctrl(link, true);
+}
+
+void dp_disable_link_phy(struct core_link *link, enum signal_type signal)
+{
+	if (!link->wa_flags.dp_keep_receiver_powered)
+		dp_receiver_power_ctrl(link, false);
+
+	if (signal == SIGNAL_TYPE_EDP)
+		link->link_enc->funcs->backlight_control(link->link_enc, false);
+
+	link->link_enc->funcs->disable_output(link->link_enc, signal);
+
+	/* Clear current link setting.*/
+	dm_memset(&link->cur_link_settings, 0,
+			sizeof(link->cur_link_settings));
+}
+
+void dp_disable_link_phy_mst(struct core_link *link, struct core_stream *stream)
+{
+	/* MST disable link only when no stream use the link */
+	if (link->mst_stream_alloc_table.stream_count > 0)
+		return;
+
+	dp_disable_link_phy(link, stream->signal);
+}
+
+bool dp_set_hw_training_pattern(
+	struct core_link *link,
+	enum hw_dp_training_pattern pattern)
+{
+	enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
+	struct encoder_set_dp_phy_pattern_param pattern_param = {0};
+	struct link_encoder *encoder = link->link_enc;
+
+	switch (pattern) {
+	case HW_DP_TRAINING_PATTERN_1:
+		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
+		break;
+	case HW_DP_TRAINING_PATTERN_2:
+		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
+		break;
+	case HW_DP_TRAINING_PATTERN_3:
+		test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
+		break;
+	default:
+		break;
+	}
+
+	pattern_param.dp_phy_pattern = test_pattern;
+	pattern_param.custom_pattern = NULL;
+	pattern_param.custom_pattern_size = 0;
+	pattern_param.dp_panel_mode = dp_get_panel_mode(link);
+
+	encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
+
+	return true;
+}
+
+
+void dp_set_hw_lane_settings(
+	struct core_link *link,
+	const struct link_training_settings *link_settings)
+{
+	struct link_encoder *encoder = link->link_enc;
+
+	/* call Encoder to set lane settings */
+	encoder->funcs->dp_set_lane_settings(encoder, link_settings);
+}
+
+enum dp_panel_mode dp_get_panel_mode(struct core_link *link)
+{
+	/* We need to explicitly check that connector
+	 * is not DP. Some Travis_VGA get reported
+	 * by video bios as DP.
+	 */
+	if (link->public.connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
+
+		switch (link->dpcd_caps.branch_dev_id) {
+		case DP_BRANCH_DEVICE_ID_2:
+			if (strncmp(
+				link->dpcd_caps.branch_dev_name,
+				DP_VGA_LVDS_CONVERTER_ID_2,
+				sizeof(
+				link->dpcd_caps.
+				branch_dev_name)) == 0) {
+				return DP_PANEL_MODE_SPECIAL;
+			}
+			break;
+		case DP_BRANCH_DEVICE_ID_3:
+			if (strncmp(link->dpcd_caps.branch_dev_name,
+				DP_VGA_LVDS_CONVERTER_ID_3,
+				sizeof(
+				link->dpcd_caps.
+				branch_dev_name)) == 0) {
+				return DP_PANEL_MODE_SPECIAL;
+			}
+			break;
+		default:
+			break;
+		}
+
+		if (link->dpcd_caps.panel_mode_edp) {
+			return DP_PANEL_MODE_EDP;
+		}
+	}
+
+	return DP_PANEL_MODE_DEFAULT;
+}
+
+void dp_set_hw_test_pattern(
+	struct core_link *link,
+	enum dp_test_pattern test_pattern)
+{
+	struct encoder_set_dp_phy_pattern_param pattern_param = {0};
+	struct link_encoder *encoder = link->link_enc;
+
+	pattern_param.dp_phy_pattern = test_pattern;
+	pattern_param.custom_pattern = NULL;
+	pattern_param.custom_pattern_size = 0;
+	pattern_param.dp_panel_mode = dp_get_panel_mode(link);
+
+	encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
new file mode 100644
index 000000000000..8cb756e99bfd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c
@@ -0,0 +1,1243 @@
+/*
+* Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+#include "dm_services.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+#include "link_encoder.h"
+#include "stream_encoder.h"
+#include "opp.h"
+#include "transform.h"
+
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+#include "dce100/dce100_resource.h"
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+#include "dce110/dce110_resource.h"
+#endif
+
+bool dc_construct_resource_pool(struct adapter_service *adapter_serv,
+				struct dc *dc,
+				uint8_t num_virtual_links)
+{
+	enum dce_version dce_ver = dal_adapter_service_get_dce_version(adapter_serv);
+
+	switch (dce_ver) {
+#if defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case DCE_VERSION_10_0:
+		return dce100_construct_resource_pool(
+			adapter_serv, num_virtual_links, dc, &dc->res_pool);
+#endif
+#if defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case DCE_VERSION_11_0:
+		return dce110_construct_resource_pool(
+			adapter_serv, num_virtual_links, dc, &dc->res_pool);
+#endif
+	default:
+		break;
+	}
+
+	return false;
+}
+
+void unreference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.clk_src_count; i++) {
+		if (res_ctx->pool.clock_sources[i] == clock_source) {
+			res_ctx->clock_source_ref_count[i]--;
+
+		if (res_ctx->clock_source_ref_count[i] == 0)
+			clock_source->funcs->cs_power_down(clock_source);
+		}
+	}
+
+
+}
+
+void reference_clock_source(
+		struct resource_context *res_ctx,
+		struct clock_source *clock_source)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.clk_src_count; i++) {
+		if (res_ctx->pool.clock_sources[i] == clock_source) {
+			res_ctx->clock_source_ref_count[i]++;
+		}
+	}
+}
+
+bool is_same_timing(
+	const struct dc_crtc_timing *timing1,
+	const struct dc_crtc_timing *timing2)
+{
+	return dm_memcmp(timing1, timing2, sizeof(struct dc_crtc_timing)) == 0;
+}
+
+static bool is_sharable_clk_src(
+	const struct core_stream *stream_with_clk_src,
+	const struct core_stream *stream)
+{
+	enum clock_source_id id = stream_with_clk_src->clock_source->id;
+
+	if (stream_with_clk_src->clock_source == NULL)
+		return false;
+
+	if (id == CLOCK_SOURCE_ID_EXTERNAL)
+		return false;
+
+	/* Sharing dual link is not working */
+	if (stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK ||
+			stream_with_clk_src->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
+			return false;
+
+	if(!is_same_timing(
+		&stream_with_clk_src->public.timing, &stream->public.timing))
+		return false;
+
+	return true;
+}
+
+struct clock_source *find_used_clk_src_for_sharing(
+					struct validate_context *context,
+					struct core_stream *stream)
+{
+	uint8_t i, j;
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *clock_source_stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			if (clock_source_stream->clock_source == NULL)
+				continue;
+
+			if (is_sharable_clk_src(clock_source_stream, stream))
+				return clock_source_stream->clock_source;
+		}
+	}
+
+	return NULL;
+}
+
+static enum pixel_format convert_pixel_format_to_dalsurface(
+		enum surface_pixel_format surface_pixel_format)
+{
+	enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+
+	switch (surface_pixel_format) {
+	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
+		dal_pixel_format = PIXEL_FORMAT_INDEX8;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+		dal_pixel_format = PIXEL_FORMAT_RGB565;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+		dal_pixel_format = PIXEL_FORMAT_RGB565;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
+		dal_pixel_format = PIXEL_FORMAT_ARGB8888;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+		dal_pixel_format = PIXEL_FORMAT_ARGB2101010;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+		dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+		dal_pixel_format = PIXEL_FORMAT_FP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+		dal_pixel_format = PIXEL_FORMAT_FP16;
+		break;
+
+
+	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+		dal_pixel_format = PIXEL_FORMAT_420BPP12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+		dal_pixel_format = PIXEL_FORMAT_420BPP12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCb:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCr:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb1555:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_CrYCb565:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb4444:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA5551:
+		dal_pixel_format = PIXEL_FORMAT_444BPP16;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb8888:
+		dal_pixel_format = PIXEL_FORMAT_444BPP32;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_ACrYCb2101010:
+		dal_pixel_format = PIXEL_FORMAT_444BPP32;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_444_CbYCrA1010102:
+		dal_pixel_format = PIXEL_FORMAT_444BPP32;
+		break;
+	default:
+		dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+		break;
+	}
+	return dal_pixel_format;
+}
+
+static void calculate_viewport(
+		const struct dc_surface *surface,
+		struct core_stream *stream)
+{
+	const struct rect src = surface->src_rect;
+	const struct rect clip = surface->clip_rect;
+	const struct rect dst = surface->dst_rect;
+
+	/* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio
+	 * num_pixels = clip.num_pix * scl_ratio
+	 */
+	stream->viewport.x = src.x + (clip.x - dst.x) * src.width / dst.width;
+	stream->viewport.width = clip.width * src.width / dst.width;
+
+	stream->viewport.y = src.y + (clip.y - dst.y) * src.height / dst.height;
+	stream->viewport.height = clip.height * src.height / dst.height;
+
+	/* Minimum viewport such that 420/422 chroma vp is non 0 */
+	if (stream->viewport.width < 2)
+	{
+		stream->viewport.width = 2;
+	}
+	if (stream->viewport.height < 2)
+	{
+		stream->viewport.height = 2;
+	}
+}
+
+static void calculate_overscan(
+		const struct dc_surface *surface,
+		struct core_stream *stream)
+{
+	stream->overscan.left = stream->public.dst.x;
+	if (stream->public.src.x < surface->clip_rect.x)
+		stream->overscan.left += (surface->clip_rect.x
+			- stream->public.src.x) * stream->public.dst.width
+			/ stream->public.src.width;
+
+	stream->overscan.right = stream->public.timing.h_addressable
+		- stream->public.dst.x - stream->public.dst.width;
+	if (stream->public.src.x + stream->public.src.width
+		> surface->clip_rect.x + surface->clip_rect.width)
+		stream->overscan.right = stream->public.timing.h_addressable -
+			dal_fixed31_32_floor(dal_fixed31_32_div(
+				dal_fixed31_32_from_int(
+						stream->viewport.width),
+						stream->ratios.horz)) -
+						stream->overscan.left;
+
+
+	stream->overscan.top = stream->public.dst.y;
+	if (stream->public.src.y < surface->clip_rect.y)
+		stream->overscan.top += (surface->clip_rect.y
+			- stream->public.src.y) * stream->public.dst.height
+			/ stream->public.src.height;
+
+	stream->overscan.bottom = stream->public.timing.v_addressable
+		- stream->public.dst.y - stream->public.dst.height;
+	if (stream->public.src.y + stream->public.src.height
+		> surface->clip_rect.y + surface->clip_rect.height)
+		stream->overscan.bottom = stream->public.timing.v_addressable -
+			dal_fixed31_32_floor(dal_fixed31_32_div(
+				dal_fixed31_32_from_int(
+						stream->viewport.height),
+						stream->ratios.vert)) -
+						stream->overscan.top;
+
+
+	/* TODO: Add timing overscan to finalize overscan calculation*/
+}
+
+static void calculate_scaling_ratios(
+		const struct dc_surface *surface,
+		struct core_stream *stream)
+{
+	const uint32_t in_w = stream->public.src.width;
+	const uint32_t in_h = stream->public.src.height;
+	const uint32_t out_w = stream->public.dst.width;
+	const uint32_t out_h = stream->public.dst.height;
+
+	stream->ratios.horz = dal_fixed31_32_from_fraction(
+					surface->src_rect.width,
+					surface->dst_rect.width);
+	stream->ratios.vert = dal_fixed31_32_from_fraction(
+					surface->src_rect.height,
+					surface->dst_rect.height);
+
+	if (surface->stereo_format == PLANE_STEREO_FORMAT_SIDE_BY_SIDE)
+		stream->ratios.horz.value *= 2;
+	else if (surface->stereo_format
+					== PLANE_STEREO_FORMAT_TOP_AND_BOTTOM)
+		stream->ratios.vert.value *= 2;
+
+	stream->ratios.vert.value = div64_s64(stream->ratios.vert.value * in_h,
+			out_h);
+	stream->ratios.horz.value = div64_s64(stream->ratios.horz.value * in_w ,
+			out_w);
+
+	stream->ratios.horz_c = stream->ratios.horz;
+	stream->ratios.vert_c = stream->ratios.vert;
+
+	if (stream->format == PIXEL_FORMAT_420BPP12) {
+		stream->ratios.horz_c.value /= 2;
+		stream->ratios.vert_c.value /= 2;
+	} else if (stream->format == PIXEL_FORMAT_422BPP16) {
+		stream->ratios.horz_c.value /= 2;
+	}
+}
+
+/*TODO: per pipe not per stream*/
+void build_scaling_params(
+	const struct dc_surface *surface,
+	struct core_stream *stream)
+{
+	/* Important: scaling ratio calculation requires pixel format,
+	 * overscan calculation requires scaling ratios and viewport
+	 * and lb depth/taps calculation requires overscan. Call sequence
+	 * is therefore important */
+	stream->format = convert_pixel_format_to_dalsurface(surface->format);
+
+	calculate_viewport(surface, stream);
+
+	calculate_scaling_ratios(surface, stream);
+
+	calculate_overscan(surface, stream);
+
+	/* Check if scaling is required update taps if not */
+	if (dal_fixed31_32_u2d19(stream->ratios.horz) == 1 << 19)
+		stream->taps.h_taps = 1;
+	else
+		stream->taps.h_taps = surface->scaling_quality.h_taps;
+
+	if (dal_fixed31_32_u2d19(stream->ratios.horz_c) == 1 << 19)
+		stream->taps.h_taps_c = 1;
+	else
+		stream->taps.h_taps_c = surface->scaling_quality.h_taps_c;
+
+	if (dal_fixed31_32_u2d19(stream->ratios.vert) == 1 << 19)
+		stream->taps.v_taps = 1;
+	else
+		stream->taps.v_taps = surface->scaling_quality.v_taps;
+
+	if (dal_fixed31_32_u2d19(stream->ratios.vert_c) == 1 << 19)
+		stream->taps.v_taps_c = 1;
+	else
+		stream->taps.v_taps_c = surface->scaling_quality.v_taps_c;
+
+	dal_logger_write(stream->ctx->logger,
+				LOG_MAJOR_DCP,
+				LOG_MINOR_DCP_SCALER,
+				"%s: Overscan:\n bot:%d left:%d right:%d "
+				"top:%d\nViewport:\nheight:%d width:%d x:%d "
+				"y:%d\n dst_rect:\nheight:%d width:%d x:%d "
+				"y:%d\n",
+				__func__,
+				stream->overscan.bottom,
+				stream->overscan.left,
+				stream->overscan.right,
+				stream->overscan.top,
+				stream->viewport.height,
+				stream->viewport.width,
+				stream->viewport.x,
+				stream->viewport.y,
+				surface->dst_rect.height,
+				surface->dst_rect.width,
+				surface->dst_rect.x,
+				surface->dst_rect.y);
+}
+
+void build_scaling_params_for_context(
+	const struct dc *dc,
+	struct validate_context *context)
+{
+	uint8_t i, j, k;
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+		if (context->target_flags[i].unchanged)
+			continue;
+		for (j = 0; j < target->status.surface_count; j++) {
+			const struct dc_surface *surface =
+				target->status.surfaces[j];
+			for (k = 0; k < target->public.stream_count; k++) {
+				struct core_stream *stream =
+					DC_STREAM_TO_CORE(
+						target->public.streams[k]);
+
+				build_scaling_params(surface, stream);
+			}
+		}
+	}
+}
+
+bool logical_attach_surfaces_to_target(
+		struct dc_surface *surfaces[],
+		uint8_t surface_count,
+		struct dc_target *dc_target)
+{
+	uint8_t i;
+	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+
+	if (surface_count > MAX_SURFACE_NUM) {
+		dm_error("Surface: can not attach %d surfaces! Maximum is: %d\n",
+			surface_count, MAX_SURFACE_NUM);
+		return false;
+	}
+
+	for (i = 0; i < target->status.surface_count; i++)
+		dc_surface_release(target->status.surfaces[i]);
+
+	for (i = 0; i < surface_count; i++) {
+		struct core_surface *surface = DC_SURFACE_TO_CORE(surfaces[i]);
+		surface->status.dc_target = &target->public;
+		target->status.surfaces[i] = surfaces[i];
+		dc_surface_retain(target->status.surfaces[i]);
+	}
+	target->status.surface_count = surface_count;
+
+	return true;
+}
+
+static uint32_t get_min_vblank_time_us(const struct validate_context *context)
+{
+	uint8_t i, j;
+	uint32_t min_vertical_blank_time = -1;
+
+	for (i = 0; i < context->target_count; i++) {
+		const struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			const struct dc_stream *stream =
+						target->public.streams[j];
+			uint32_t vertical_blank_in_pixels = 0;
+			uint32_t vertical_blank_time = 0;
+
+			vertical_blank_in_pixels = stream->timing.h_total *
+				(stream->timing.v_total
+					- stream->timing.v_addressable);
+			vertical_blank_time = vertical_blank_in_pixels
+				* 1000 / stream->timing.pix_clk_khz;
+			if (min_vertical_blank_time > vertical_blank_time)
+				min_vertical_blank_time = vertical_blank_time;
+		}
+	}
+	return min_vertical_blank_time;
+}
+
+static void fill_display_configs(
+	const struct validate_context *context,
+	struct dc_pp_display_configuration *pp_display_cfg)
+{
+	uint8_t i, j;
+	uint8_t num_cfgs = 0;
+
+	for (i = 0; i < context->target_count; i++) {
+		const struct core_target *target = context->targets[i];
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			const struct core_stream *stream =
+			DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct dc_pp_single_disp_config *cfg =
+					&pp_display_cfg->disp_configs[num_cfgs];
+
+			num_cfgs++;
+			cfg->signal = stream->signal;
+			cfg->pipe_idx = stream->opp->inst;
+			cfg->src_height = stream->public.src.height;
+			cfg->src_width = stream->public.src.width;
+			cfg->ddi_channel_mapping =
+				stream->sink->link->ddi_channel_mapping.raw;
+			cfg->transmitter =
+				stream->sink->link->link_enc->transmitter;
+			cfg->link_settings =
+					stream->sink->link->cur_link_settings;
+			cfg->sym_clock = stream->public.timing.pix_clk_khz;
+			switch (stream->public.timing.display_color_depth) {
+			case COLOR_DEPTH_101010:
+				cfg->sym_clock = (cfg->sym_clock * 30) / 24;
+				break;
+			case COLOR_DEPTH_121212:
+				cfg->sym_clock = (cfg->sym_clock * 36) / 24;
+				break;
+			case COLOR_DEPTH_161616:
+				cfg->sym_clock = (cfg->sym_clock * 48) / 24;
+				break;
+			default:
+				break;
+			}
+			/* TODO: unhardcode*/
+			cfg->v_refresh = 60;
+		}
+	}
+	pp_display_cfg->display_count = num_cfgs;
+}
+
+void pplib_apply_safe_state(
+	const struct dc *dc)
+{
+	dm_pp_apply_safe_state(dc->ctx);
+}
+
+void pplib_apply_display_requirements(
+	const struct dc *dc,
+	const struct validate_context *context)
+{
+	struct dc_pp_display_configuration pp_display_cfg = { 0 };
+
+	pp_display_cfg.all_displays_in_sync =
+		context->bw_results.all_displays_in_sync;
+	pp_display_cfg.nb_pstate_switch_disable =
+			context->bw_results.nbp_state_change_enable == false;
+	pp_display_cfg.cpu_cc6_disable =
+			context->bw_results.cpuc_state_change_enable == false;
+	pp_display_cfg.cpu_pstate_disable =
+			context->bw_results.cpup_state_change_enable == false;
+	pp_display_cfg.cpu_pstate_separation_time =
+			context->bw_results.required_blackout_duration_us;
+
+	pp_display_cfg.min_memory_clock_khz = context->bw_results.required_yclk
+		/ MEMORY_TYPE_MULTIPLIER;
+	pp_display_cfg.min_engine_clock_khz = context->bw_results.required_sclk;
+	pp_display_cfg.min_engine_clock_deep_sleep_khz
+			= context->bw_results.required_sclk_deep_sleep;
+
+	pp_display_cfg.avail_mclk_switch_time_us =
+						get_min_vblank_time_us(context);
+	pp_display_cfg.avail_mclk_switch_time_in_disp_active_us = 0;
+
+	pp_display_cfg.disp_clk_khz = context->bw_results.dispclk_khz;
+
+	fill_display_configs(context, &pp_display_cfg);
+
+	/* TODO: is this still applicable?*/
+	if (pp_display_cfg.display_count == 1) {
+		const struct dc_crtc_timing *timing =
+			&context->targets[0]->public.streams[0]->timing;
+
+		pp_display_cfg.crtc_index =
+			pp_display_cfg.disp_configs[0].pipe_idx;
+		pp_display_cfg.line_time_in_us = timing->h_total * 1000
+							/ timing->pix_clk_khz;
+	}
+
+	dm_pp_apply_display_requirements(dc->ctx, &pp_display_cfg);
+}
+
+/* Maximum TMDS single link pixel clock 165MHz */
+#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
+
+static void attach_stream_to_controller(
+		struct resource_context *res_ctx,
+		struct core_stream *stream)
+{
+	res_ctx->controller_ctx[stream->controller_idx].stream = stream;
+}
+
+static void set_stream_engine_in_use(
+		struct resource_context *res_ctx,
+		struct stream_encoder *stream_enc)
+{
+	int i;
+
+	for (i = 0; i < res_ctx->pool.stream_enc_count; i++) {
+		if (res_ctx->pool.stream_enc[i] == stream_enc)
+			res_ctx->is_stream_enc_acquired[i] = true;
+	}
+}
+
+/* TODO: release audio object */
+static void set_audio_in_use(
+		struct resource_context *res_ctx,
+		struct audio *audio)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.audio_count; i++) {
+		if (res_ctx->pool.audios[i] == audio) {
+			res_ctx->is_audio_acquired[i] = true;
+		}
+	}
+}
+
+static bool assign_first_free_controller(
+		struct resource_context *res_ctx,
+		struct core_stream *stream)
+{
+	uint8_t i;
+	for (i = 0; i < res_ctx->pool.controller_count; i++) {
+		if (!res_ctx->controller_ctx[i].stream) {
+			stream->tg = res_ctx->pool.timing_generators[i];
+			stream->mi = res_ctx->pool.mis[i];
+			stream->ipp = res_ctx->pool.ipps[i];
+			stream->xfm = res_ctx->pool.transforms[i];
+			stream->opp = res_ctx->pool.opps[i];
+			stream->controller_idx = i;
+			stream->dis_clk = res_ctx->pool.display_clock;
+			return true;
+		}
+	}
+	return false;
+}
+
+static struct stream_encoder *find_first_free_match_stream_enc_for_link(
+		struct resource_context *res_ctx,
+		struct core_link *link)
+{
+	uint8_t i;
+	int8_t j = -1;
+	const struct dc_sink *sink = NULL;
+
+	for (i = 0; i < res_ctx->pool.stream_enc_count; i++) {
+		if (!res_ctx->is_stream_enc_acquired[i] &&
+					res_ctx->pool.stream_enc[i]) {
+			/* Store first available for MST second display
+			 * in daisy chain use case */
+			j = i;
+			if (res_ctx->pool.stream_enc[i]->id ==
+					link->link_enc->preferred_engine)
+				return res_ctx->pool.stream_enc[i];
+		}
+	}
+
+	/*
+	 * below can happen in cases when stream encoder is acquired:
+	 * 1) for second MST display in chain, so preferred engine already
+	 * acquired;
+	 * 2) for another link, which preferred engine already acquired by any
+	 * MST configuration.
+	 *
+	 * If signal is of DP type and preferred engine not found, return last available
+	 *
+	 * TODO - This is just a patch up and a generic solution is
+	 * required for non DP connectors.
+	 */
+
+	sink = link->public.local_sink ? link->public.local_sink : link->public.remote_sinks[0];
+
+	if (sink && j >= 0 &&  dc_is_dp_signal(sink->sink_signal))
+		return res_ctx->pool.stream_enc[j];
+
+	return NULL;
+}
+
+static struct audio *find_first_free_audio(struct resource_context *res_ctx)
+{
+	int i;
+	for (i = 0; i < res_ctx->pool.audio_count; i++) {
+		if (res_ctx->is_audio_acquired[i] == false) {
+			return res_ctx->pool.audios[i];
+		}
+	}
+
+	return 0;
+}
+
+static bool check_timing_change(struct core_stream *cur_stream,
+		struct core_stream *new_stream)
+{
+	if (cur_stream == NULL)
+		return true;
+
+	/* If sink pointer changed, it means this is a hotplug, we should do
+	 * full hw setting.
+	 */
+	if (cur_stream->sink != new_stream->sink)
+		return true;
+
+	return !is_same_timing(
+					&cur_stream->public.timing,
+					&new_stream->public.timing);
+}
+
+static void set_stream_signal(struct core_stream *stream)
+{
+	struct dc_sink *dc_sink = (struct dc_sink *)stream->public.sink;
+
+	/* For asic supports dual link DVI, we should adjust signal type
+	 * based on timing pixel clock. If pixel clock more than 165Mhz,
+	 * signal is dual link, otherwise, single link.
+	 */
+	if (dc_sink->sink_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
+			dc_sink->sink_signal == SIGNAL_TYPE_DVI_DUAL_LINK) {
+		if (stream->public.timing.pix_clk_khz >
+			TMDS_MAX_PIXEL_CLOCK_IN_KHZ)
+			dc_sink->sink_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+		else
+			dc_sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+	}
+
+	stream->signal = dc_sink->sink_signal;
+}
+
+enum dc_status map_resources(
+		const struct dc *dc,
+		struct validate_context *context)
+{
+	uint8_t i, j;
+
+	/* mark resources used for targets that are already active */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (!context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+
+			attach_stream_to_controller(
+				&context->res_ctx,
+				stream);
+
+			set_stream_engine_in_use(
+				&context->res_ctx,
+				stream->stream_enc);
+
+			reference_clock_source(
+				&context->res_ctx,
+				stream->clock_source);
+
+			if (stream->audio) {
+				set_audio_in_use(&context->res_ctx,
+					stream->audio);
+			}
+		}
+	}
+
+	/* acquire new resources */
+	for (i = 0; i < context->target_count; i++) {
+		struct core_target *target = context->targets[i];
+
+		if (context->target_flags[i].unchanged)
+			continue;
+
+		for (j = 0; j < target->public.stream_count; j++) {
+			struct core_stream *stream =
+				DC_STREAM_TO_CORE(target->public.streams[j]);
+			struct core_stream *curr_stream;
+
+			if (!assign_first_free_controller(
+					&context->res_ctx, stream))
+				return DC_NO_CONTROLLER_RESOURCE;
+
+			attach_stream_to_controller(&context->res_ctx, stream);
+
+			set_stream_signal(stream);
+
+			curr_stream =
+				dc->current_context.res_ctx.controller_ctx
+				[stream->controller_idx].stream;
+			context->res_ctx.controller_ctx[stream->controller_idx]
+			.flags.timing_changed =
+				check_timing_change(curr_stream, stream);
+
+			stream->stream_enc =
+				find_first_free_match_stream_enc_for_link(
+					&context->res_ctx,
+					stream->sink->link);
+
+			if (!stream->stream_enc)
+				return DC_NO_STREAM_ENG_RESOURCE;
+
+			set_stream_engine_in_use(
+					&context->res_ctx,
+					stream->stream_enc);
+
+			/* TODO: Add check if ASIC support and EDID audio */
+			if (!stream->sink->converter_disable_audio &&
+						dc_is_audio_capable_signal(
+						stream->signal)) {
+				stream->audio = find_first_free_audio(
+						&context->res_ctx);
+
+				if (!stream->audio)
+					return DC_NO_STREAM_AUDIO_RESOURCE;
+
+				set_audio_in_use(&context->res_ctx,
+						stream->audio);
+			}
+		}
+	}
+
+	return DC_OK;
+}
+
+static enum ds_color_space build_default_color_space(
+		struct core_stream *stream)
+{
+	enum ds_color_space color_space =
+			DS_COLOR_SPACE_SRGB_FULLRANGE;
+	struct dc_crtc_timing *timing = &stream->public.timing;
+
+	switch (stream->signal) {
+	/* TODO: implement other signal color space setting */
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+	case SIGNAL_TYPE_EDP:
+		break;
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+	{
+		uint32_t pix_clk_khz;
+
+		if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422 &&
+			timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) {
+			if (timing->timing_standard ==
+					TIMING_STANDARD_CEA770 &&
+				timing->timing_standard ==
+						TIMING_STANDARD_CEA861)
+				color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+
+			pix_clk_khz = timing->pix_clk_khz / 10;
+			if (timing->h_addressable == 640 &&
+				timing->v_addressable == 480 &&
+				(pix_clk_khz == 2520 || pix_clk_khz == 2517))
+				color_space = DS_COLOR_SPACE_SRGB_FULLRANGE;
+		} else {
+			if (timing->timing_standard ==
+					TIMING_STANDARD_CEA770 ||
+					timing->timing_standard ==
+					TIMING_STANDARD_CEA861) {
+
+				color_space =
+					(timing->pix_clk_khz > PIXEL_CLOCK) ?
+						DS_COLOR_SPACE_YCBCR709 :
+						DS_COLOR_SPACE_YCBCR601;
+			}
+		}
+		break;
+	}
+	default:
+		switch (timing->pixel_encoding) {
+		case PIXEL_ENCODING_YCBCR422:
+		case PIXEL_ENCODING_YCBCR444:
+			if (timing->pix_clk_khz > PIXEL_CLOCK)
+				color_space = DS_COLOR_SPACE_YCBCR709;
+			else
+				color_space = DS_COLOR_SPACE_YCBCR601;
+			break;
+		default:
+			break;
+		}
+		break;
+	}
+	return color_space;
+}
+
+static void translate_info_frame(const struct hw_info_frame *hw_info_frame,
+	struct encoder_info_frame *encoder_info_frame)
+{
+	dm_memset(
+		encoder_info_frame, 0, sizeof(struct encoder_info_frame));
+
+	/* For gamut we recalc checksum */
+	if (hw_info_frame->gamut_packet.valid) {
+		uint8_t chk_sum = 0;
+		uint8_t *ptr;
+		uint8_t i;
+
+		dm_memmove(
+						&encoder_info_frame->gamut,
+						&hw_info_frame->gamut_packet,
+						sizeof(struct hw_info_packet));
+
+		/*start of the Gamut data. */
+		ptr = &encoder_info_frame->gamut.sb[3];
+
+		for (i = 0; i <= encoder_info_frame->gamut.sb[1]; i++)
+			chk_sum += ptr[i];
+
+		encoder_info_frame->gamut.sb[2] = (uint8_t) (0x100 - chk_sum);
+	}
+
+	if (hw_info_frame->avi_info_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->avi,
+						&hw_info_frame->avi_info_packet,
+						sizeof(struct hw_info_packet));
+	}
+
+	if (hw_info_frame->vendor_info_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->vendor,
+						&hw_info_frame->vendor_info_packet,
+						sizeof(struct hw_info_packet));
+	}
+
+	if (hw_info_frame->spd_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->spd,
+						&hw_info_frame->spd_packet,
+						sizeof(struct hw_info_packet));
+	}
+
+	if (hw_info_frame->vsc_packet.valid) {
+		dm_memmove(
+						&encoder_info_frame->vsc,
+						&hw_info_frame->vsc_packet,
+						sizeof(struct hw_info_packet));
+	}
+}
+
+static void set_avi_info_frame(struct hw_info_packet *info_packet,
+		struct core_stream *stream)
+{
+	enum ds_color_space color_space = DS_COLOR_SPACE_UNKNOWN;
+	struct info_frame info_frame = { {0} };
+	uint32_t pixel_encoding = 0;
+	enum scanning_type scan_type = SCANNING_TYPE_NODATA;
+	enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA;
+	bool itc = false;
+	uint8_t cn0_cn1 = 0;
+	uint8_t *check_sum = NULL;
+	uint8_t byte_index = 0;
+
+	if (info_packet == NULL)
+		return;
+
+	color_space = build_default_color_space(stream);
+
+	/* Initialize header */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.header.
+			info_frame_type = INFO_FRAME_AVI;
+	/* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall
+	* not be used in HDMI 2.0 (Section 10.1) */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.header.version =
+			INFO_FRAME_VERSION_2;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.header.length =
+			INFO_FRAME_SIZE_AVI;
+
+	/* IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built
+	* according to HDMI 2.0 spec (Section 10.1)
+	* Add "case PixelEncoding_YCbCr420:    pixelEncoding = 3; break;"
+	* when YCbCr 4:2:0 is supported by DAL hardware. */
+
+	switch (stream->public.timing.pixel_encoding) {
+	case PIXEL_ENCODING_YCBCR422:
+		pixel_encoding = 1;
+		break;
+
+	case PIXEL_ENCODING_YCBCR444:
+		pixel_encoding = 2;
+		break;
+
+	case PIXEL_ENCODING_RGB:
+	default:
+		pixel_encoding = 0;
+	}
+
+	/* Y0_Y1_Y2 : The pixel encoding */
+	/* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.Y0_Y1_Y2 =
+		pixel_encoding;
+
+
+	/* A0 = 1 Active Format Information valid */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.A0 =
+		ACTIVE_FORMAT_VALID;
+
+	/* B0, B1 = 3; Bar info data is valid */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.B0_B1 =
+		BAR_INFO_BOTH_VALID;
+
+	info_frame.avi_info_packet.info_packet_hdmi.bits.SC0_SC1 =
+			PICTURE_SCALING_UNIFORM;
+
+	/* S0, S1 : Underscan / Overscan */
+	/* TODO: un-hardcode scan type */
+	scan_type = SCANNING_TYPE_UNDERSCAN;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.S0_S1 = scan_type;
+
+	/* C0, C1 : Colorimetry */
+	if (color_space == DS_COLOR_SPACE_YCBCR709)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_ITU709;
+	else if (color_space == DS_COLOR_SPACE_YCBCR601)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_ITU601;
+	else
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_NO_DATA;
+
+
+	/* TODO: un-hardcode aspect ratio */
+	aspect = stream->public.timing.aspect_ratio;
+
+	switch (aspect) {
+	case ASPECT_RATIO_4_3:
+	case ASPECT_RATIO_16_9:
+		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = aspect;
+		break;
+
+	case ASPECT_RATIO_NO_DATA:
+	case ASPECT_RATIO_64_27:
+	case ASPECT_RATIO_256_135:
+	default:
+		info_frame.avi_info_packet.info_packet_hdmi.bits.M0_M1 = 0;
+	}
+
+	/* Active Format Aspect ratio - same as Picture Aspect Ratio. */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.R0_R3 =
+			ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE;
+
+	/* TODO: un-hardcode cn0_cn1 and itc */
+	cn0_cn1 = 0;
+	itc = false;
+
+	if (itc) {
+		info_frame.avi_info_packet.info_packet_hdmi.bits.ITC = 1;
+		info_frame.avi_info_packet.info_packet_hdmi.bits.CN0_CN1 =
+			cn0_cn1;
+	}
+
+	/* TODO: un-hardcode q0_q1 */
+	if (color_space == DS_COLOR_SPACE_SRGB_FULLRANGE)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
+						RGB_QUANTIZATION_FULL_RANGE;
+	else if (color_space == DS_COLOR_SPACE_SRGB_LIMITEDRANGE)
+		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
+						RGB_QUANTIZATION_LIMITED_RANGE;
+	else
+		info_frame.avi_info_packet.info_packet_hdmi.bits.Q0_Q1 =
+						RGB_QUANTIZATION_DEFAULT_RANGE;
+
+	/* TODO : We should handle YCC quantization,
+	 * but we do not have matrix calculation */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.YQ0_YQ1 =
+					YYC_QUANTIZATION_LIMITED_RANGE;
+
+	info_frame.avi_info_packet.info_packet_hdmi.bits.VIC0_VIC7 =
+					stream->public.timing.vic;
+
+	/* pixel repetition
+	 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel
+	 * repetition start from 1 */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.PR0_PR3 = 0;
+
+	/* Bar Info
+	 * barTop:    Line Number of End of Top Bar.
+	 * barBottom: Line Number of Start of Bottom Bar.
+	 * barLeft:   Pixel Number of End of Left Bar.
+	 * barRight:  Pixel Number of Start of Right Bar. */
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_top =
+			stream->public.timing.v_border_top;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_bottom =
+		(stream->public.timing.v_border_top
+			- stream->public.timing.v_border_bottom + 1);
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_left =
+			stream->public.timing.h_border_left;
+	info_frame.avi_info_packet.info_packet_hdmi.bits.bar_right =
+		(stream->public.timing.h_total
+			- stream->public.timing.h_border_right + 1);
+
+	/* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */
+	check_sum =
+		&info_frame.
+		avi_info_packet.info_packet_hdmi.packet_raw_data.sb[0];
+	*check_sum = INFO_FRAME_AVI + INFO_FRAME_SIZE_AVI
+			+ INFO_FRAME_VERSION_2;
+
+	for (byte_index = 1; byte_index <= INFO_FRAME_SIZE_AVI; byte_index++)
+		*check_sum += info_frame.avi_info_packet.info_packet_hdmi.
+				packet_raw_data.sb[byte_index];
+
+	/* one byte complement */
+	*check_sum = (uint8_t) (0x100 - *check_sum);
+
+	/* Store in hw_path_mode */
+	info_packet->hb0 =
+		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb0;
+	info_packet->hb1 =
+		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb1;
+	info_packet->hb2 =
+		info_frame.avi_info_packet.info_packet_hdmi.packet_raw_data.hb2;
+
+	for (byte_index = 0; byte_index < sizeof(info_packet->sb); byte_index++)
+		info_packet->sb[byte_index] = info_frame.avi_info_packet.
+		info_packet_hdmi.packet_raw_data.sb[byte_index];
+
+	info_packet->valid = true;
+}
+
+static void set_vendor_info_packet(struct core_stream *stream,
+		struct hw_info_packet *info_packet)
+{
+	uint32_t length = 0;
+	bool hdmi_vic_mode = false;
+	uint8_t checksum = 0;
+	uint32_t i = 0;
+	enum dc_timing_3d_format format;
+
+	ASSERT_CRITICAL(stream != NULL);
+	ASSERT_CRITICAL(info_packet != NULL);
+
+	format = stream->public.timing.timing_3d_format;
+
+	/* Can be different depending on packet content */
+	length = 5;
+
+	if (stream->public.timing.hdmi_vic != 0
+			&& stream->public.timing.h_total >= 3840
+			&& stream->public.timing.v_total >= 2160)
+		hdmi_vic_mode = true;
+
+	/* According to HDMI 1.4a CTS, VSIF should be sent
+	 * for both 3D stereo and HDMI VIC modes.
+	 * For all other modes, there is no VSIF sent.  */
+
+	if (format == TIMING_3D_FORMAT_NONE && !hdmi_vic_mode)
+		return;
+
+	/* 24bit IEEE Registration identifier (0x000c03). LSB first. */
+	info_packet->sb[1] = 0x03;
+	info_packet->sb[2] = 0x0C;
+	info_packet->sb[3] = 0x00;
+
+	/*PB4: 5 lower bytes = 0 (reserved). 3 higher bits = HDMI_Video_Format.
+	 * The value for HDMI_Video_Format are:
+	 * 0x0 (0b000) - No additional HDMI video format is presented in this
+	 * packet
+	 * 0x1 (0b001) - Extended resolution format present. 1 byte of HDMI_VIC
+	 * parameter follows
+	 * 0x2 (0b010) - 3D format indication present. 3D_Structure and
+	 * potentially 3D_Ext_Data follows
+	 * 0x3..0x7 (0b011..0b111) - reserved for future use */
+	if (format != TIMING_3D_FORMAT_NONE)
+		info_packet->sb[4] = (2 << 5);
+	else if (hdmi_vic_mode)
+		info_packet->sb[4] = (1 << 5);
+
+	/* PB5: If PB4 claims 3D timing (HDMI_Video_Format = 0x2):
+	 * 4 lower bites = 0 (reserved). 4 higher bits = 3D_Structure.
+	 * The value for 3D_Structure are:
+	 * 0x0 - Frame Packing
+	 * 0x1 - Field Alternative
+	 * 0x2 - Line Alternative
+	 * 0x3 - Side-by-Side (full)
+	 * 0x4 - L + depth
+	 * 0x5 - L + depth + graphics + graphics-depth
+	 * 0x6 - Top-and-Bottom
+	 * 0x7 - Reserved for future use
+	 * 0x8 - Side-by-Side (Half)
+	 * 0x9..0xE - Reserved for future use
+	 * 0xF - Not used */
+	switch (format) {
+	case TIMING_3D_FORMAT_HW_FRAME_PACKING:
+	case TIMING_3D_FORMAT_SW_FRAME_PACKING:
+		info_packet->sb[5] = (0x0 << 4);
+		break;
+
+	case TIMING_3D_FORMAT_SIDE_BY_SIDE:
+	case TIMING_3D_FORMAT_SBS_SW_PACKED:
+		info_packet->sb[5] = (0x8 << 4);
+		length = 6;
+		break;
+
+	case TIMING_3D_FORMAT_TOP_AND_BOTTOM:
+	case TIMING_3D_FORMAT_TB_SW_PACKED:
+		info_packet->sb[5] = (0x6 << 4);
+		break;
+
+	default:
+		break;
+	}
+
+	/*PB5: If PB4 is set to 0x1 (extended resolution format)
+	 * fill PB5 with the correct HDMI VIC code */
+	if (hdmi_vic_mode)
+		info_packet->sb[5] = stream->public.timing.hdmi_vic;
+
+	/* Header */
+	info_packet->hb0 = 0x81; /* VSIF packet type. */
+	info_packet->hb1 = 0x01; /* Version */
+
+	/* 4 lower bits = Length, 4 higher bits = 0 (reserved) */
+	info_packet->hb2 = (uint8_t) (length);
+
+	/* Calculate checksum */
+	checksum = 0;
+	checksum += info_packet->hb0;
+	checksum += info_packet->hb1;
+	checksum += info_packet->hb2;
+
+	for (i = 1; i <= length; i++)
+		checksum += info_packet->sb[i];
+
+	info_packet->sb[0] = (uint8_t) (0x100 - checksum);
+
+	info_packet->valid = true;
+}
+
+void build_info_frame(struct core_stream *stream)
+{
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+	struct hw_info_frame info_frame = { { 0 } };
+
+	/* default all packets to invalid */
+	info_frame.avi_info_packet.valid = false;
+	info_frame.gamut_packet.valid = false;
+	info_frame.vendor_info_packet.valid = false;
+	info_frame.spd_packet.valid = false;
+	info_frame.vsc_packet.valid = false;
+
+	signal = stream->sink->public.sink_signal;
+
+	/* HDMi and DP have different info packets*/
+	if (signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+		set_avi_info_frame(&info_frame.avi_info_packet,
+				stream);
+		set_vendor_info_packet(stream, &info_frame.vendor_info_packet);
+	}
+
+	translate_info_frame(&info_frame,
+			&stream->encoder_info_frame);
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c b/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
new file mode 100644
index 000000000000..c5a770e61812
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_sink.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "core_types.h"
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+
+struct sink {
+	struct core_sink protected;
+	int ref_count;
+};
+
+#define DC_SINK_TO_SINK(dc_sink) \
+			container_of(dc_sink, struct sink, protected.public)
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+
+static void destruct(struct sink *sink)
+{
+
+}
+
+static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params)
+{
+
+	struct core_link *core_link = DC_LINK_TO_LINK(init_params->link);
+
+	sink->protected.public.sink_signal = init_params->sink_signal;
+	sink->protected.link = core_link;
+	sink->protected.ctx = core_link->ctx;
+	sink->protected.dongle_max_pix_clk = init_params->dongle_max_pix_clk;
+	sink->protected.converter_disable_audio =
+			init_params->converter_disable_audio;
+
+	return true;
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+
+void dc_sink_retain(const struct dc_sink *dc_sink)
+{
+	struct sink *sink = DC_SINK_TO_SINK(dc_sink);
+
+	++sink->ref_count;
+}
+
+void dc_sink_release(const struct dc_sink *dc_sink)
+{
+	struct core_sink *core_sink = DC_SINK_TO_CORE(dc_sink);
+	struct sink *sink = DC_SINK_TO_SINK(dc_sink);
+
+	--sink->ref_count;
+
+	if (sink->ref_count == 0) {
+		destruct(sink);
+		dm_free(core_sink->ctx, sink);
+	}
+}
+
+struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params)
+{
+	struct core_link *core_link = DC_LINK_TO_LINK(init_params->link);
+
+	struct sink *sink = dm_alloc(core_link->ctx, sizeof(*sink));
+
+	if (NULL == sink)
+		goto alloc_fail;
+
+	if (false == construct(sink, init_params))
+		goto construct_fail;
+
+	/* TODO should we move this outside to where the assignment actually happens? */
+	dc_sink_retain(&sink->protected.public);
+
+	return &sink->protected.public;
+
+construct_fail:
+	dm_free(core_link->ctx, sink);
+
+alloc_fail:
+	return NULL;
+}
+
+/*******************************************************************************
+ * Protected functions - visible only inside of DC (not visible in DM)
+ ******************************************************************************/
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c b/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
new file mode 100644
index 000000000000..d7012bcda10a
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_stream.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "dc.h"
+#include "core_types.h"
+#include "resource.h"
+
+/*******************************************************************************
+ * Private definitions
+ ******************************************************************************/
+
+struct stream {
+	struct core_stream protected;
+	int ref_count;
+};
+
+#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected.public)
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static void build_bit_depth_reduction_params(
+		const struct core_stream *stream,
+		struct bit_depth_reduction_params *fmt_bit_depth)
+{
+	dm_memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth));
+
+	/*TODO: Need to un-hardcode, refer to function with same name
+	 * in dal2 hw_sequencer*/
+
+	fmt_bit_depth->flags.TRUNCATE_ENABLED = 0;
+	fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 0;
+	fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 0;
+
+	/* Diagnostics need consistent CRC of the image, that means
+	 * dithering should not be enabled for Diagnostics. */
+	if (IS_DIAG_DC(stream->ctx->dce_environment) == false) {
+
+		fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1;
+		fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1;
+
+		/* frame random is on by default */
+		fmt_bit_depth->flags.FRAME_RANDOM = 1;
+		/* apply RGB dithering */
+		fmt_bit_depth->flags.RGB_RANDOM = true;
+	}
+
+	return;
+}
+
+static void setup_pixel_encoding(
+	struct clamping_and_pixel_encoding_params *clamping)
+{
+	/*TODO: Need to un-hardcode, refer to function with same name
+		 * in dal2 hw_sequencer*/
+
+	clamping->pixel_encoding = PIXEL_ENCODING_RGB;
+
+	return;
+}
+
+static bool construct(struct core_stream *stream,
+	const struct dc_sink *dc_sink_data)
+{
+	uint32_t i = 0;
+
+	stream->sink = DC_SINK_TO_CORE(dc_sink_data);
+	stream->ctx = stream->sink->ctx;
+	stream->public.sink = dc_sink_data;
+
+	dc_sink_retain(dc_sink_data);
+
+	build_bit_depth_reduction_params(stream, &stream->bit_depth_params);
+	setup_pixel_encoding(&stream->clamping);
+
+	/* Copy audio modes */
+	/* TODO - Remove this translation */
+	for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++)
+	{
+		stream->public.audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count;
+		stream->public.audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code;
+		stream->public.audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate;
+		stream->public.audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size;
+	}
+	stream->public.audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count;
+	stream->public.audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency;
+	stream->public.audio_info.video_latency = dc_sink_data->edid_caps.video_latency;
+	dm_memmove(
+		stream->public.audio_info.display_name,
+		dc_sink_data->edid_caps.display_name,
+		AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
+	stream->public.audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id;
+	stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id;
+	stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags;
+
+	/* TODO - Unhardcode port_id */
+	stream->public.audio_info.port_id[0] = 0x5558859e;
+	stream->public.audio_info.port_id[1] = 0xd989449;
+
+	/* EDID CAP translation for HDMI 2.0 */
+	stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
+	return true;
+}
+
+static void destruct(struct core_stream *stream)
+{
+	dc_sink_release(&stream->sink->public);
+}
+
+void dc_stream_retain(struct dc_stream *dc_stream)
+{
+	struct stream *stream = DC_STREAM_TO_STREAM(dc_stream);
+	stream->ref_count++;
+}
+
+void dc_stream_release(struct dc_stream *public)
+{
+	struct stream *stream = DC_STREAM_TO_STREAM(public);
+	struct core_stream *protected = DC_STREAM_TO_CORE(public);
+	struct dc_context *ctx = protected->ctx;
+	stream->ref_count--;
+
+	if (stream->ref_count == 0) {
+		destruct(protected);
+		dm_free(ctx, stream);
+	}
+}
+
+struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink)
+{
+	struct core_sink *sink = DC_SINK_TO_CORE(dc_sink);
+	struct stream *stream;
+
+	if (sink == NULL)
+		goto alloc_fail;
+
+	stream = dm_alloc(sink->ctx, sizeof(struct stream));
+
+	if (NULL == stream)
+		goto alloc_fail;
+
+	if (false == construct(&stream->protected, dc_sink))
+			goto construct_fail;
+
+	dc_stream_retain(&stream->protected.public);
+
+	return &stream->protected.public;
+
+construct_fail:
+	dm_free(sink->ctx, stream);
+
+alloc_fail:
+	return NULL;
+}
+
+void dc_update_stream(const struct dc_stream *dc_stream,
+		struct rect *src,
+		struct rect *dst)
+{
+	struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
+
+	stream->public.src = *src;
+	stream->public.dst = *dst;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
new file mode 100644
index 000000000000..1a9ee8f97757
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_surface.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+/* DC interface (public) */
+#include "dm_services.h"
+#include "dc.h"
+
+/* DC core (private) */
+#include "core_dc.h"
+#include "inc/transform.h"
+
+/*******************************************************************************
+ * Private structures
+ ******************************************************************************/
+struct surface {
+	struct core_surface protected;
+	enum dc_irq_source irq_source;
+	int ref_count;
+};
+
+#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public)
+#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected)
+
+/*******************************************************************************
+ * Private functions
+ ******************************************************************************/
+static bool construct(struct dc_context *ctx, struct surface *surface)
+{
+	uint32_t i;
+	struct gamma_ramp *gamma =
+			&surface->protected.public.gamma_correction;
+
+	/* construct gamma default value. */
+	for (i = 0; i < NUM_OF_RAW_GAMMA_RAMP_RGB_256; i++) {
+		gamma->gamma_ramp_rgb256x3x16.red[i] =
+				(unsigned short) (i << 8);
+		gamma->gamma_ramp_rgb256x3x16.green[i] =
+				(unsigned short) (i << 8);
+		gamma->gamma_ramp_rgb256x3x16.blue[i] =
+				(unsigned short) (i << 8);
+	}
+	gamma->type = GAMMA_RAMP_TYPE_RGB256;
+	gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
+
+	surface->protected.ctx = ctx;
+	return true;
+}
+
+static void destruct(struct surface *surface)
+{
+}
+
+/*******************************************************************************
+ * Public functions
+ ******************************************************************************/
+void enable_surface_flip_reporting(struct dc_surface *dc_surface,
+		uint32_t controller_id)
+{
+	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
+	surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1;
+	/*register_flip_interrupt(surface);*/
+}
+
+struct dc_surface *dc_create_surface(const struct dc *dc)
+{
+	struct surface *surface = dm_alloc(dc->ctx, sizeof(*surface));
+
+	if (NULL == surface)
+		goto alloc_fail;
+
+	if (false == construct(dc->ctx, surface))
+		goto construct_fail;
+
+	dc_surface_retain(&surface->protected.public);
+
+	return &surface->protected.public;
+
+construct_fail:
+	dm_free(dc->ctx, surface);
+
+alloc_fail:
+	return NULL;
+}
+
+void dc_surface_retain(const struct dc_surface *dc_surface)
+{
+	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
+
+	++surface->ref_count;
+}
+
+void dc_surface_release(const struct dc_surface *dc_surface)
+{
+	struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
+	--surface->ref_count;
+
+	if (surface->ref_count == 0) {
+		destruct(surface);
+		dm_free(surface->protected.ctx, surface);
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_target.c b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
new file mode 100644
index 000000000000..e93e73d13448
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/dc/core/dc_target.c
@@ -0,0 +1,548 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+#include "core_types.h"
+#include "hw_sequencer.h"
+#include "resource.h"
+#include "ipp.h"
+#include "timing_generator.h"
+
+#define COEFF_RANGE	3
+#define REGAMMA_COEFF_A0	31308
+#define REGAMMA_COEFF_A1	12920
+#define REGAMMA_COEFF_A2	55
+#define REGAMMA_COEFF_A3	55
+#define REGAMMA_COEFF_GAMMA	2400
+
+struct target {
+	struct core_target protected;
+	int ref_count;
+};
+
+#define DC_TARGET_TO_TARGET(dc_target) \
+	container_of(dc_target, struct target, protected.public)
+#define CORE_TARGET_TO_TARGET(core_target) \
+	container_of(core_target, struct target, protected)
+
+static void construct(
+	struct core_target *target,
+	struct dc_context *ctx,
+	struct dc_stream *dc_streams[],
+	uint8_t stream_count)
+{
+	uint8_t i;
+	for (i = 0; i < stream_count; i++) {
+		target->public.streams[i] = dc_streams[i];
+		dc_stream_retain(dc_streams[i]);
+	}
+
+	target->ctx = ctx;
+	target->public.stream_count = stream_count;
+}
+
+static void destruct(struct core_target *core_target)
+{
+	int i;
+
+	for (i = 0; i < core_target->status.surface_count; i++) {
+		dc_surface_release(core_target->status.surfaces[i]);
+		core_target->status.surfaces[i] = NULL;
+	}
+	for (i = 0; i < core_target->public.stream_count; i++) {
+		dc_stream_release(
+			(struct dc_stream *)core_target->public.streams[i]);
+		core_target->public.streams[i] = NULL;
+	}
+}
+
+void dc_target_retain(struct dc_target *dc_target)
+{
+	struct target *target = DC_TARGET_TO_TARGET(dc_target);
+
+	target->ref_count++;
+}
+
+void dc_target_release(struct dc_target *dc_target)
+{
+	struct target *target = DC_TARGET_TO_TARGET(dc_target);
+	struct core_target *protected = DC_TARGET_TO_CORE(dc_target);
+
+	ASSERT(target->ref_count > 0);
+	target->ref_count--;
+	if (target->ref_count == 0) {
+		destruct(protected);
+		dm_free(protected->ctx, target);
+	}
+}
+
+const struct dc_target_status *dc_target_get_status(
+					const struct dc_target* dc_target)
+{
+	struct core_target* target = DC_TARGET_TO_CORE(dc_target);
+	return &target->status;
+}
+
+struct dc_target *dc_create_target_for_streams(
+		struct dc_stream *dc_streams[],
+		uint8_t stream_count)
+{
+	struct core_stream *stream;
+	struct target *target;
+
+	if (0 == stream_count)
+		goto target_alloc_fail;
+
+	stream = DC_STREAM_TO_CORE(dc_streams[0]);
+
+	target = dm_alloc(stream->ctx, sizeof(struct target));
+
+	if (NULL == target)
+		goto target_alloc_fail;
+
+	construct(&target->protected, stream->ctx, dc_streams, stream_count);
+
+	dc_target_retain(&target->protected.public);
+
+	return &target->protected.public;
+
+
+target_alloc_fail:
+	return NULL;
+}
+
+static void build_gamma_params(
+		enum pixel_format pixel_format,
+		struct gamma_parameters *gamma_param)
+{
+	uint32_t i;
+
+	/* translate parameters */
+	gamma_param->surface_pixel_format = pixel_format;
+
+	gamma_param->regamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW;
+	gamma_param->degamma_adjust_type = GRAPHICS_REGAMMA_ADJUST_SW;
+
+	gamma_param->selected_gamma_lut = GRAPHICS_GAMMA_LUT_REGAMMA;
+
+	/* TODO support non-legacy gamma */
+	gamma_param->disable_adjustments = false;
+	gamma_param->flag.bits.config_is_changed = 0;
+	gamma_param->flag.bits.regamma_update = 1;
+	gamma_param->flag.bits.gamma_update = 1;
+
+	/* Set regamma */
+	gamma_param->regamma.features.bits.GRAPHICS_DEGAMMA_SRGB = 1;
+	gamma_param->regamma.features.bits.OVERLAY_DEGAMMA_SRGB = 1;
+	gamma_param->regamma.features.bits.GAMMA_RAMP_ARRAY = 0;
+	gamma_param->regamma.features.bits.APPLY_DEGAMMA = 0;
+
+	for (i = 0; i < COEFF_RANGE; i++) {
+		gamma_param->regamma.gamma_coeff.a0[i] = REGAMMA_COEFF_A0;
+		gamma_param->regamma.gamma_coeff.a1[i] = REGAMMA_COEFF_A1;
+		gamma_param->regamma.gamma_coeff.a2[i] = REGAMMA_COEFF_A2;
+		gamma_param->regamma.gamma_coeff.a3[i] = REGAMMA_COEFF_A3;
+		gamma_param->regamma.gamma_coeff.gamma[i] = REGAMMA_COEFF_GAMMA;
+	}
+}
+
+
+static bool program_gamma(
+		struct dc_context *ctx,
+		struct dc_surface *surface,
+		struct input_pixel_processor *ipp,
+		struct output_pixel_processor *opp)
+{
+	struct gamma_parameters *gamma_param;
+	bool result= false;
+
+	gamma_param = dm_alloc(ctx, sizeof(struct gamma_parameters));
+
+	if (!gamma_param)
+		goto gamma_param_fail;
+
+	build_gamma_params(surface->format, gamma_param);
+
+	result = ctx->dc->hwss.set_gamma_ramp(ipp, opp,
+			&surface->gamma_correction,
+			gamma_param);
+
+	dm_free(ctx, gamma_param);
+
+gamma_param_fail:
+	return result;
+}
+
+static bool validate_surface_address(
+		struct dc_plane_address address)
+{
+	bool is_valid_address = false;
+
+	switch (address.type) {
+	case PLN_ADDR_TYPE_GRAPHICS:
+		if (address.grph.addr.quad_part != 0)
+			is_valid_address = true;
+		break;
+	case PLN_ADDR_TYPE_GRPH_STEREO:
+		if ((address.grph_stereo.left_addr.quad_part != 0) &&
+			(address.grph_stereo.right_addr.quad_part != 0)) {
+			is_valid_address = true;
+		}
+		break;
+	case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
+	default:
+		/* not supported */
+		BREAK_TO_DEBUGGER();
+		break;
+	}
+
+	return is_valid_address;
+}
+
+bool dc_commit_surfaces_to_target(
+		struct dc *dc,
+		struct dc_surface *new_surfaces[],
+		uint8_t new_surface_count,
+		struct dc_target *dc_target)
+
+{
+	int i, j;
+	uint32_t prev_disp_clk = dc->current_context.bw_results.dispclk_khz;
+	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+
+	int current_enabled_surface_count = 0;
+	int new_enabled_surface_count = 0;
+
+	if (!dal_adapter_service_is_in_accelerated_mode(
+						dc->res_pool.adapter_srv) ||
+			dc->current_context.target_count == 0) {
+		return false;
+	}
+
+	for (i = 0; i < dc->current_context.target_count; i++)
+		if (target == dc->current_context.targets[i])
+			break;
+
+	/* Cannot commit surface to a target that is not commited */
+	if (i == dc->current_context.target_count)
+		return false;
+
+	for (i = 0; i < target->status.surface_count; i++)
+		if (target->status.surfaces[i]->visible)
+			current_enabled_surface_count++;
+
+	for (i = 0; i < new_surface_count; i++)
+		if (new_surfaces[i]->visible)
+			new_enabled_surface_count++;
+
+	dal_logger_write(dc->ctx->logger,
+				LOG_MAJOR_INTERFACE_TRACE,
+				LOG_MINOR_COMPONENT_DC,
+				"%s: commit %d surfaces to target 0x%x\n",
+				__func__,
+				new_surface_count,
+				dc_target);
+
+
+	if (!logical_attach_surfaces_to_target(
+						new_surfaces,
+						new_surface_count,
+						dc_target)) {
+		BREAK_TO_DEBUGGER();
+		goto unexpected_fail;
+	}
+
+	for (i = 0; i < new_surface_count; i++)
+		for (j = 0; j < target->public.stream_count; j++)
+			build_scaling_params(
+				new_surfaces[i],
+				DC_STREAM_TO_CORE(target->public.streams[j]));
+
+	if (dc->res_pool.funcs->validate_bandwidth(dc, &dc->current_context)
+								!= DC_OK) {
+		BREAK_TO_DEBUGGER();
+		goto unexpected_fail;
+	}
+
+	if (prev_disp_clk < dc->current_context.bw_results.dispclk_khz) {
+		dc->hwss.program_bw(dc, &dc->current_context);
+		pplib_apply_display_requirements(dc, &dc->current_context);
+	}
+
+	if (current_enabled_surface_count > 0 && new_enabled_surface_count == 0)
+		dc_target_disable_memory_requests(dc_target);
+
+	for (i = 0; i < new_surface_count; i++) {
+		struct dc_surface *surface = new_surfaces[i];
+		struct core_surface *core_surface = DC_SURFACE_TO_CORE(surface);
+		bool is_valid_address =
+				validate_surface_address(surface->address);
+
+		dal_logger_write(dc->ctx->logger,
+					LOG_MAJOR_INTERFACE_TRACE,
+					LOG_MINOR_COMPONENT_DC,
+					"0x%x:",
+					surface);
+
+		program_gamma(dc->ctx, surface,
+			DC_STREAM_TO_CORE(target->public.streams[0])->ipp,
+			DC_STREAM_TO_CORE(target->public.streams[0])->opp);
+
+		dc->hwss.set_plane_config(dc, core_surface, target);
+
+		if (is_valid_address)
+			dc->hwss.update_plane_address(dc, core_surface, target);
+	}
+
+	if (current_enabled_surface_count == 0 && new_enabled_surface_count > 0)
+		dc_target_enable_memory_requests(dc_target);
+
+	/* Lower display clock if necessary */
+	if (prev_disp_clk > dc->current_context.bw_results.dispclk_khz) {
+		dc->hwss.program_bw(dc, &dc->current_context);
+		pplib_apply_display_requirements(dc, &dc->current_context);
+	}
+
+	return true;
+
+unexpected_fail:
+	for (i = 0; i < new_surface_count; i++) {
+		target->status.surfaces[i] = NULL;
+	}
+	target->status.surface_count = 0;
+
+	return false;
+}
+
+bool dc_target_is_connected_to_sink(
+		const struct dc_target * dc_target,
+		const struct dc_sink *dc_sink)
+{
+	struct core_target *target = DC_TARGET_TO_CORE(dc_target);
+	uint8_t i;
+	for (i = 0; i < target->public.stream_count; i++) {
+		if (target->public.streams[i]->sink == dc_sink)
+			return true;
+	}
+	return false;
+}
+
+void dc_target_enable_memory_requests(struct dc_target *target)
+{
+	uint8_t i;
+	struct core_target *core_target = DC_TARGET_TO_CORE(target);
+	for (i = 0; i < core_target->public.stream_count; i++) {
+		struct timing_generator *tg =
+			DC_STREAM_TO_CORE(core_target->public.streams[i])->tg;
+
+		if (!tg->funcs->set_blank(tg, false)) {
+			dm_error("DC: failed to unblank crtc!\n");
+			BREAK_TO_DEBUGGER();
+		}
+	}
+}
+
+void dc_target_disable_memory_requests(struct dc_target *target)
+{
+	uint8_t i;
+	struct core_target *core_target = DC_TARGET_TO_CORE(target);
+	for (i = 0; i < core_target->public.stream_count; i++) {
+	struct timing_generator *tg =
+		DC_STREAM_TO_CORE(core_target->public.streams[i])->tg;
+
+		if (NULL == tg) {
+			dm_error("DC: timing generator is NULL!\n");
+			BREAK_TO_DEBUGGER();
+			continue;
+		}
+
+		if (false == tg->funcs->set_blank(tg, true)) {
+			dm_error("DC: failed to blank crtc!\n");
+			BREAK_TO_DEBUGGER();
+		}
+	}
+}
+
+/**
+ * Update the cursor attributes and set cursor surface address
+ */
+bool dc_target_set_cursor_attributes(
+	struct dc_target *dc_target,
+	const struct dc_cursor_attributes *attributes)
+{
+	struct core_target *core_target;
+	struct input_pixel_processor *ipp;
+
+	if (NULL == dc_target) {
+		dm_error("DC: dc_target is NULL!\n");
+			return false;
+
+	}
+
+	core_target = DC_TARGET_TO_CORE(dc_target);
+	ipp = DC_STREAM_TO_CORE(core_target->public.streams[0])->ipp;
+
+	if (NULL == ipp) {
+		dm_error("DC: input pixel processor is NULL!\n");
+		return false;
+	}
+
+	if (true == ipp->funcs->ipp_cursor_set_attributes(ipp, attributes))
+		return true;
+
+	return false;
+}
+
+bool dc_target_set_cursor_position(
+	struct dc_target *dc_target,
+	const struct dc_cursor_position *position)
+{
+	struct core_target *core_target;
+	struct input_pixel_processor *ipp;
+
+	if (NULL == dc_target) {
+		dm_error("DC: dc_target is NULL!\n");
+		return false;
+	}
+
+	if (NULL == position) {
+		dm_error("DC: cursor position is NULL!\n");
+		return false;
+	}
+
+	core_target = DC_TARGET_TO_CORE(dc_target);
+	ipp = DC_STREAM_TO_CORE(core_target->public.streams[0])->ipp;
+
+	if (NULL == ipp) {
+		dm_error("DC: input pixel processor is NULL!\n");
+		return false;
+	}
+
+
+	if (true == ipp->funcs->ipp_cursor_set_position(ipp, position))
+		return true;
+
+	return false;
+}
+
+/* TODO: #flip temporary to make flip work */
+uint8_t dc_target_get_link_index(const struct dc_target *dc_target)
+{
+	const struct core_target *target = CONST_DC_TARGET_TO_CORE(dc_target);
+	const struct core_sink *sink =
+		DC_SINK_TO_CORE(target->public.streams[0]->sink);
+
+	return sink->link->public.link_index;
+}
+
+uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target)
+{
+	struct core_target *core_target = DC_TARGET_TO_CORE(dc_target);
+	struct timing_generator *tg =
+		DC_STREAM_TO_CORE(core_target->public.streams[0])->tg;
+
+	return tg->funcs->get_frame_count(tg);
+}
+
+enum dc_irq_source dc_target_get_irq_src(
+	const struct dc_target *dc_target, const enum irq_type irq_type)
+{
+	struct core_target *core_target = DC_TARGET_TO_CORE(dc_target);
+
+	/* #TODO - Remove the assumption that the controller is always in the
+	 * first stream of a core target */
+	struct core_stream *stream =
+		DC_STREAM_TO_CORE(core_target->public.streams[0]);
+	uint8_t controller_idx = stream->controller_idx;
+
+	/* Get controller id */
+	enum controller_id crtc_id = controller_idx + 1;
+
+	/* Calculate controller offset */
+	unsigned int offset = crtc_id - CONTROLLER_ID_D0;
+	unsigned int base = irq_type;
+
+	/* Calculate irq source */
+	enum dc_irq_source src = base + offset;
+
+	return src;
+}
+
+void dc_target_log(
+	const struct dc_target *dc_target,
+	struct dal_logger *dal_logger,
+	enum log_major log_major,
+	enum log_minor log_minor)
+{
+	int i;
+
+	const struct core_target *core_target =
+			CONST_DC_TARGET_TO_CORE(dc_target);
+
+	dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"core_target 0x%x: surface_count=%d, stream_count=%d\n",
+			core_target,
+			core_target->status.surface_count,
+			core_target->public.stream_count);
+
+	for (i = 0; i < core_target->public.stream_count; i++) {
+		const struct core_stream *core_stream =
+			DC_STREAM_TO_CORE(core_target->public.streams[i]);
+
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n",
+			core_stream,
+			core_stream->public.src.x,
+			core_stream->public.src.y,
+			core_stream->public.src.width,
+			core_stream->public.src.height,
+			core_stream->public.dst.x,
+			core_stream->public.dst.y,
+			core_stream->public.dst.width,
+			core_stream->public.dst.height);
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"\tpix_clk_khz: %d, h_total: %d, v_total: %d\n",
+			core_stream->public.timing.pix_clk_khz,
+			core_stream->public.timing.h_total,
+			core_stream->public.timing.v_total);
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"\tsink name: %s, serial: %d\n",
+			core_stream->sink->public.edid_caps.display_name,
+			core_stream->sink->public.edid_caps.serial_number);
+		dal_logger_write(dal_logger,
+			log_major,
+			log_minor,
+			"\tlink: %d\n",
+			core_stream->sink->link->public.link_index);
+	}
+}
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v3 25/26] drm/amd/dal: Adding amdgpu_dm for dal
  2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                     ` (3 preceding siblings ...)
  2016-02-29 21:56   ` [PATCH v3 24/26] drm/amd/dal: Add display core Harry Wentland
@ 2016-02-29 21:56   ` Harry Wentland
  2016-02-29 21:56   ` [PATCH v3 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
  5 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-29 21:56 UTC (permalink / raw)
  To: dri-devel

Implements DRM's atomic KMS interfaces using DC.

v3 changes:
- use amdgpu's existing dce functions for some things, such as mc_access
- add stoney to dal check
- add missing hawaii and stoney case statements
- remove page work flip queue and use system queue instead
- minor dm_helpers function name cleanup
- expose I2C through i2c_adapter and route dal i2c calls through this

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile         |   17 +
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c      | 1271 ++++++++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h      |  168 ++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c  |  517 ++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c  |  820 ++++++
 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h  |  122 +
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c    |  480 ++++
 .../drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h    |   36 +
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c |  457 ++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c    | 2649 ++++++++++++++++++++
 .../gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h    |  100 +
 drivers/gpu/drm/amd/dal/dc/dm_services.h           |   17 -
 12 files changed, 6637 insertions(+), 17 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
 create mode 100644 drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h

diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
new file mode 100644
index 000000000000..0f365c65342e
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the 'dm' sub-component of DAL.
+# It provides the control and status of dm blocks.
+
+
+
+AMDGPUDM = amdgpu_dm_types.o amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o
+
+ifneq ($(CONFIG_DRM_AMD_DAL),)
+AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o
+endif
+
+subdir-ccflags-y += -I$(FULL_AMD_DAL_PATH)/dc
+
+AMDGPU_DM = $(addprefix $(AMDDALPATH)/amdgpu_dm/,$(AMDGPUDM))
+
+AMD_DAL_FILES += $(AMDGPU_DM)
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
new file mode 100644
index 000000000000..e3475b767e0f
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.c
@@ -0,0 +1,1271 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services_types.h"
+#include "dc.h"
+
+#include "vid.h"
+#include "amdgpu.h"
+#include "atom.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_types.h"
+
+#include "amd_shared.h"
+#include "amdgpu_dm_irq.h"
+#include "dm_helpers.h"
+
+#include "dce_v8_0.h"
+#include "dce_v10_0.h"
+#include "dce_v11_0.h"
+
+#include "ivsrcid/ivsrcid_vislands30.h"
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_dp_mst_helper.h>
+
+/* Define variables here
+ * These values will be passed to DAL for feature enable purpose
+ * Disable ALL for HDMI light up
+ * TODO: follow up if need this mechanism*/
+struct dal_override_parameters display_param = {
+	.bool_param_enable_mask = 0,
+	.bool_param_values = 0,
+	.int_param_values[DAL_PARAM_MAX_COFUNC_NON_DP_DISPLAYS] = DAL_PARAM_INVALID_INT,
+	.int_param_values[DAL_PARAM_DRR_SUPPORT] = DAL_PARAM_INVALID_INT,
+};
+
+/* Debug facilities */
+#define AMDGPU_DM_NOT_IMPL(fmt, ...) \
+	DRM_INFO("DM_NOT_IMPL: " fmt, ##__VA_ARGS__)
+
+/*
+ * dm_vblank_get_counter
+ *
+ * @brief
+ * Get counter for number of vertical blanks
+ *
+ * @param
+ * struct amdgpu_device *adev - [in] desired amdgpu device
+ * int disp_idx - [in] which CRTC to get the counter from
+ *
+ * @return
+ * Counter for vertical blanks
+ */
+static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
+{
+	if (crtc >= adev->mode_info.num_crtc)
+		return 0;
+	else {
+		struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
+
+		if (NULL == acrtc->target) {
+			DRM_ERROR("dc_target is NULL for crtc '%d'!\n", crtc);
+			return 0;
+		}
+
+		return dc_target_get_vblank_counter(acrtc->target);
+	}
+}
+
+static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
+					u32 *vbl, u32 *position)
+{
+	if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
+		return -EINVAL;
+
+/* TODO: #DAL3 Implement scanoutpos
+	dal_get_crtc_scanoutpos(adev->dm.dal, crtc, vbl, position);
+*/
+	return 0;
+}
+
+static bool dm_is_idle(void *handle)
+{
+	/* XXX todo */
+	return true;
+}
+
+static int dm_wait_for_idle(void *handle)
+{
+	/* XXX todo */
+	return 0;
+}
+
+static void dm_print_status(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	dev_info(adev->dev, "DCE registers\n");
+	/* XXX todo */
+}
+
+static int dm_soft_reset(void *handle)
+{
+	/* XXX todo */
+	return 0;
+}
+
+static struct amdgpu_crtc *get_crtc_by_target(
+	struct amdgpu_device *adev,
+	const struct dc_target *dc_target)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_crtc *crtc;
+	struct amdgpu_crtc *amdgpu_crtc;
+
+	/*
+	 * following if is check inherited from both functions where this one is
+	 * used now. Need to be checked why it could happen.
+	 */
+	if (dc_target == NULL)
+		return adev->mode_info.crtcs[0];
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+		if (amdgpu_crtc->target == dc_target)
+			return amdgpu_crtc;
+	}
+
+	return NULL;
+}
+
+static void dm_pflip_high_irq(void *interrupt_params)
+{
+	struct amdgpu_flip_work *works;
+	struct amdgpu_crtc *amdgpu_crtc;
+	struct common_irq_params *irq_params = interrupt_params;
+	struct amdgpu_device *adev = irq_params->adev;
+	unsigned long flags;
+	const struct dc *dc = irq_params->adev->dm.dc;
+	const struct dc_target *dc_target =
+			dc_get_target_on_irq_source(dc, irq_params->irq_src);
+
+	amdgpu_crtc = get_crtc_by_target(adev, dc_target);
+
+	/* IRQ could occur when in initial stage */
+	if(amdgpu_crtc == NULL)
+		return;
+
+	spin_lock_irqsave(&adev->ddev->event_lock, flags);
+	works = amdgpu_crtc->pflip_works;
+	if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
+		DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
+						 "AMDGPU_FLIP_SUBMITTED(%d)\n",
+						 amdgpu_crtc->pflip_status,
+						 AMDGPU_FLIP_SUBMITTED);
+		spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+		return;
+	}
+
+	/* page flip completed. clean up */
+	amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
+	amdgpu_crtc->pflip_works = NULL;
+
+	/* wakeup usersapce */
+	if(works->event)
+		drm_send_vblank_event(
+			adev->ddev,
+			amdgpu_crtc->crtc_id,
+			works->event);
+
+	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+
+	drm_crtc_vblank_put(&amdgpu_crtc->base);
+	schedule_work(&works->unpin_work);
+}
+
+static void dm_crtc_high_irq(void *interrupt_params)
+{
+	struct common_irq_params *irq_params = interrupt_params;
+	struct amdgpu_device *adev = irq_params->adev;
+	const struct dc *dc = irq_params->adev->dm.dc;
+	const struct dc_target *dc_target =
+			dc_get_target_on_irq_source(dc, irq_params->irq_src);
+	uint8_t crtc_index = 0;
+	struct amdgpu_crtc *acrtc = get_crtc_by_target(adev, dc_target);
+
+	if (acrtc)
+		crtc_index = acrtc->crtc_id;
+
+	drm_handle_vblank(adev->ddev, crtc_index);
+
+}
+
+static int dm_set_clockgating_state(void *handle,
+		  enum amd_clockgating_state state)
+{
+	return 0;
+}
+
+static int dm_set_powergating_state(void *handle,
+		  enum amd_powergating_state state)
+{
+	return 0;
+}
+
+/* Prototypes of private functions */
+static int dm_early_init(void* handle);
+
+static void hotplug_notify_work_func(struct work_struct *work)
+{
+	struct amdgpu_display_manager *dm = container_of(work, struct amdgpu_display_manager, mst_hotplug_work);
+	struct drm_device *dev = dm->ddev;
+
+	drm_kms_helper_hotplug_event(dev);
+}
+
+/* Init display KMS
+ *
+ * Returns 0 on success
+ */
+int amdgpu_dm_init(struct amdgpu_device *adev)
+{
+	struct dal_init_data init_data;
+	struct drm_device *ddev = adev->ddev;
+	adev->dm.ddev = adev->ddev;
+	adev->dm.adev = adev;
+
+	/* Zero all the fields */
+	memset(&init_data, 0, sizeof(init_data));
+
+	/* initialize DAL's lock (for SYNC context use) */
+	spin_lock_init(&adev->dm.dal_lock);
+
+	/* initialize DAL's mutex */
+	mutex_init(&adev->dm.dal_mutex);
+
+	if(amdgpu_dm_irq_init(adev)) {
+		DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
+		goto error;
+	}
+
+	if (ddev->pdev) {
+		init_data.bdf_info.DEVICE_NUMBER = PCI_SLOT(ddev->pdev->devfn);
+		init_data.bdf_info.FUNCTION_NUMBER =
+			PCI_FUNC(ddev->pdev->devfn);
+		if (ddev->pdev->bus)
+			init_data.bdf_info.BUS_NUMBER = ddev->pdev->bus->number;
+	}
+
+	init_data.display_param = display_param;
+
+	init_data.asic_id.chip_family = adev->family;
+
+	init_data.asic_id.pci_revision_id = adev->rev_id;
+	init_data.asic_id.hw_internal_rev = adev->external_rev_id;
+
+	init_data.asic_id.vram_width = adev->mc.vram_width;
+	/* TODO: initialize init_data.asic_id.vram_type here!!!! */
+	init_data.asic_id.atombios_base_address =
+		adev->mode_info.atom_context->bios;
+	init_data.asic_id.runtime_flags.flags.bits.SKIP_POWER_DOWN_ON_RESUME = 1;
+
+	if ((adev->asic_type == CHIP_CARRIZO) ||
+	    (adev->asic_type == CHIP_STONEY))
+		init_data.asic_id.runtime_flags.flags.bits.GNB_WAKEUP_SUPPORTED = 1;
+
+	init_data.driver = adev;
+
+	adev->dm.cgs_device = amdgpu_cgs_create_device(adev);
+
+	if (!adev->dm.cgs_device) {
+		DRM_ERROR("amdgpu: failed to create cgs device.\n");
+		goto error;
+	}
+
+	init_data.cgs_device = adev->dm.cgs_device;
+
+	adev->dm.dal = NULL;
+
+	/* enable gpu scaling in DAL */
+	init_data.display_param.bool_param_enable_mask |=
+		1 << DAL_PARAM_ENABLE_GPU_SCALING;
+	init_data.display_param.bool_param_values |=
+		1 << DAL_PARAM_ENABLE_GPU_SCALING;
+
+	init_data.dce_environment = DCE_ENV_PRODUCTION_DRV;
+
+	/* Display Core create. */
+	adev->dm.dc = dc_create(&init_data);
+
+	INIT_WORK(&adev->dm.mst_hotplug_work, hotplug_notify_work_func);
+
+	if (amdgpu_dm_initialize_drm_device(adev)) {
+		DRM_ERROR(
+		"amdgpu: failed to initialize sw for display support.\n");
+		goto error;
+	}
+
+	/* Update the actual used number of crtc */
+	adev->mode_info.num_crtc = adev->dm.display_indexes_num;
+
+	/* TODO: Add_display_info? */
+
+	/* TODO use dynamic cursor width */
+	adev->ddev->mode_config.cursor_width = 128;
+	adev->ddev->mode_config.cursor_height = 128;
+
+	if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) {
+		DRM_ERROR(
+		"amdgpu: failed to initialize sw for display support.\n");
+		goto error;
+	}
+
+	DRM_INFO("KMS initialized.\n");
+
+	return 0;
+error:
+	amdgpu_dm_fini(adev);
+
+	return -1;
+}
+
+void amdgpu_dm_fini(struct amdgpu_device *adev)
+{
+	amdgpu_dm_destroy_drm_device(&adev->dm);
+	/*
+	 * TODO: pageflip, vlank interrupt
+	 *
+	 * amdgpu_dm_irq_fini(adev);
+	 */
+
+	if (adev->dm.cgs_device) {
+		amdgpu_cgs_destroy_device(adev->dm.cgs_device);
+		adev->dm.cgs_device = NULL;
+	}
+
+	/* DC Destroy TODO: Replace destroy DAL */
+	{
+		dc_destroy(&adev->dm.dc);
+	}
+	return;
+}
+
+/* moved from amdgpu_dm_kms.c */
+void amdgpu_dm_destroy()
+{
+}
+
+static int dm_sw_init(void *handle)
+{
+	return 0;
+}
+
+static int dm_sw_fini(void *handle)
+{
+	return 0;
+}
+
+
+static void detect_link_for_all_connectors(struct drm_device *dev)
+{
+	struct amdgpu_connector *aconnector;
+	struct drm_connector *connector;
+
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		   aconnector = to_amdgpu_connector(connector);
+		   if (aconnector->dc_link->type == dc_connection_mst_branch) {
+			   DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n",
+						aconnector, aconnector->base.base.id);
+
+				if (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) < 0) {
+					DRM_ERROR("DM_MST: Failed to start MST\n");
+					((struct dc_link *)aconnector->dc_link)->type = dc_connection_single;
+				}
+		   }
+	}
+
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+}
+
+
+static int dm_hw_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	/* Create DAL display manager */
+	amdgpu_dm_init(adev);
+
+	amdgpu_dm_hpd_init(adev);
+
+	detect_link_for_all_connectors(adev->ddev);
+
+
+
+	return 0;
+}
+
+static int dm_hw_fini(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	amdgpu_dm_hpd_fini(adev);
+
+	amdgpu_dm_irq_fini(adev);
+
+	return 0;
+}
+
+static int dm_display_suspend(struct drm_device *ddev)
+{
+	struct drm_mode_config *config = &ddev->mode_config;
+	struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
+	struct drm_atomic_state *state;
+	struct drm_crtc *crtc;
+	unsigned crtc_mask = 0;
+	int ret = 0;
+
+	if (WARN_ON(!ctx))
+		return 0;
+
+	lockdep_assert_held(&ctx->ww_ctx);
+
+	state = drm_atomic_state_alloc(ddev);
+	if (WARN_ON(!state))
+		return -ENOMEM;
+
+	state->acquire_ctx = ctx;
+	state->allow_modeset = true;
+
+	/* Set all active crtcs to inactive, to turn off displays*/
+	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
+		struct drm_crtc_state *crtc_state =
+			drm_atomic_get_crtc_state(state, crtc);
+
+		ret = PTR_ERR_OR_ZERO(crtc_state);
+		if (ret)
+			goto free;
+
+		if (!crtc_state->active)
+			continue;
+
+		crtc_state->active = false;
+		crtc_mask |= (1 << drm_crtc_index(crtc));
+	}
+
+	if (crtc_mask) {
+		ret = drm_atomic_commit(state);
+
+		/* In case of failure, revert everything we did*/
+		if (!ret) {
+			list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head)
+				if (crtc_mask & (1 << drm_crtc_index(crtc)))
+					crtc->state->active = true;
+
+			return ret;
+		}
+	}
+
+free:
+	if (ret) {
+		DRM_ERROR("Suspending crtc's failed with %i\n", ret);
+		drm_atomic_state_free(state);
+		return ret;
+	}
+
+	return 0;
+}
+static int dm_suspend(void *handle)
+{
+	struct amdgpu_device *adev = handle;
+	struct amdgpu_display_manager *dm = &adev->dm;
+	struct drm_device *ddev = adev->ddev;
+	int ret = 0;
+
+	drm_modeset_lock_all(ddev);
+	ret = dm_display_suspend(ddev);
+	drm_modeset_unlock_all(ddev);
+
+	if (ret)
+		goto fail;
+
+	dc_set_power_state(
+		dm->dc,
+		DC_ACPI_CM_POWER_STATE_D3,
+		DC_VIDEO_POWER_SUSPEND);
+
+	amdgpu_dm_irq_suspend(adev);
+fail:
+	return ret;
+}
+
+static int dm_display_resume(struct drm_device *ddev)
+{
+	int ret = 0;
+	struct drm_connector *connector;
+
+	struct drm_atomic_state *state = drm_atomic_state_alloc(ddev);
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+
+	if (!state)
+		return ENOMEM;
+
+	state->acquire_ctx = ddev->mode_config.acquire_ctx;
+
+	/* Construct an atomic state to restore previous display setting*/
+	/* Attach crtcs to drm_atomic_state*/
+	list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
+		struct drm_crtc_state *crtc_state =
+			drm_atomic_get_crtc_state(state, crtc);
+
+		ret = PTR_ERR_OR_ZERO(crtc_state);
+		if (ret)
+			goto err;
+
+		/* force a restore */
+		crtc_state->mode_changed = true;
+	}
+
+	/* Attach planes to drm_atomic_state*/
+	list_for_each_entry(plane, &ddev->mode_config.plane_list, head) {
+		ret = PTR_ERR_OR_ZERO(drm_atomic_get_plane_state(state, plane));
+		if (ret)
+			goto err;
+	}
+
+	/* Attach connectors to drm_atomic_state*/
+	list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
+		ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(state, connector));
+		if (ret)
+			goto err;
+	}
+
+	/* Call commit internally with the state we just constructed */
+	ret = drm_atomic_commit(state);
+	if (!ret)
+		return 0;
+
+err:
+	DRM_ERROR("Restoring old state failed with %i\n", ret);
+	drm_atomic_state_free(state);
+
+	return ret;
+}
+
+static int dm_resume(void *handle)
+{
+	struct amdgpu_device *adev = handle;
+	struct drm_device *ddev = adev->ddev;
+	struct amdgpu_display_manager *dm = &adev->dm;
+	struct amdgpu_connector *aconnector;
+	struct drm_connector *connector;
+	int ret = 0;
+
+	/* power on hardware */
+	dc_set_power_state(
+		dm->dc,
+		DC_ACPI_CM_POWER_STATE_D0,
+		DC_VIDEO_POWER_ON);
+
+	/* Do detection*/
+	list_for_each_entry(connector,
+			&ddev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		dc_link_detect(aconnector->dc_link, false);
+		aconnector->dc_sink = NULL;
+		amdgpu_dm_update_connector_after_detect(aconnector);
+	}
+
+
+	drm_modeset_lock_all(ddev);
+	ret = dm_display_resume(ddev);
+	drm_modeset_unlock_all(ddev);
+
+	drm_kms_helper_hotplug_event(ddev);
+
+	/* program HPD filter*/
+	dc_resume(dm->dc);
+	/* resume IRQ */
+	amdgpu_dm_irq_resume(adev);
+
+	return ret;
+}
+const struct amd_ip_funcs amdgpu_dm_funcs = {
+	.early_init = dm_early_init,
+	.late_init = NULL,
+	.sw_init = dm_sw_init,
+	.sw_fini = dm_sw_fini,
+	.hw_init = dm_hw_init,
+	.hw_fini = dm_hw_fini,
+	.suspend = dm_suspend,
+	.resume = dm_resume,
+	.is_idle = dm_is_idle,
+	.wait_for_idle = dm_wait_for_idle,
+	.soft_reset = dm_soft_reset,
+	.print_status = dm_print_status,
+	.set_clockgating_state = dm_set_clockgating_state,
+	.set_powergating_state = dm_set_powergating_state,
+};
+
+/* TODO: it is temporary non-const, should fixed later */
+static struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
+	.atomic_check = amdgpu_dm_atomic_check,
+	.atomic_commit = amdgpu_dm_atomic_commit
+};
+
+
+void amdgpu_dm_update_connector_after_detect(
+	struct amdgpu_connector *aconnector)
+{
+	struct drm_connector *connector = &aconnector->base;
+	struct drm_device *dev = connector->dev;
+	const struct dc_sink *sink;
+
+	/* MST handled by drm_mst framework */
+	if (aconnector->mst_mgr.mst_state == true)
+		return;
+
+	sink = aconnector->dc_link->local_sink;
+
+	/*
+	 * TODO: temporary guard to look for proper fix
+	 * if this sink is MST sink, we should not do anything
+	 */
+	if (sink && sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+		return;
+
+	if (aconnector->dc_sink == sink) {
+		/* We got a DP short pulse (Link Loss, DP CTS, etc...).
+		 * Do nothing!! */
+		DRM_INFO("DCHPD: connector_id=%d: dc_sink didn't change.\n",
+				aconnector->connector_id);
+		return;
+	}
+
+	DRM_INFO("DCHPD: connector_id=%d: Old sink=%p New sink=%p\n",
+		aconnector->connector_id, aconnector->dc_sink, sink);
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	/* 1. Update status of the drm connector
+	 * 2. Send an event and let userspace tell us what to do */
+	if (sink) {
+		/* TODO: check if we still need the S3 mode update workaround.
+		 * If yes, put it here. */
+
+		aconnector->dc_sink = sink;
+		if (sink->dc_edid.length == 0)
+			aconnector->edid = NULL;
+		else {
+			aconnector->edid =
+				(struct edid *) sink->dc_edid.raw_edid;
+			drm_mode_connector_update_edid_property(connector,
+					aconnector->edid);
+		}
+	} else {
+		drm_mode_connector_update_edid_property(connector, NULL);
+		aconnector->num_modes = 0;
+		aconnector->dc_sink = NULL;
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void handle_hpd_irq(void *param)
+{
+	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
+	struct drm_connector *connector = &aconnector->base;
+	struct drm_device *dev = connector->dev;
+
+	/* In case of failure or MST no need to update connector status or notify the OS
+	 * since (for MST case) MST does this in it's own context.
+	 */
+	if (dc_link_detect(aconnector->dc_link, false)) {
+		amdgpu_dm_update_connector_after_detect(aconnector);
+		drm_kms_helper_hotplug_event(dev);
+	}
+}
+
+static void handle_hpd_rx_irq(void *param)
+{
+	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
+	struct drm_connector *connector = &aconnector->base;
+	struct drm_device *dev = connector->dev;
+	bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
+
+	if (dc_link_handle_hpd_rx_irq(aconnector->dc_link) &&
+			!is_mst_root_connector) {
+		/* Downstream Port status changed. */
+		if (dc_link_detect(aconnector->dc_link, false)) {
+			amdgpu_dm_update_connector_after_detect(aconnector);
+			drm_kms_helper_hotplug_event(dev);
+		}
+	}
+
+	if (is_mst_root_connector)
+		dm_helpers_dp_mst_handle_mst_hpd_rx_irq(param);
+}
+
+static void register_hpd_handlers(struct amdgpu_device *adev)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_connector *connector;
+	struct amdgpu_connector *aconnector;
+	const struct dc_link *dc_link;
+	struct dc_interrupt_params int_params = {0};
+
+	int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
+	int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
+
+	list_for_each_entry(connector,
+			&dev->mode_config.connector_list, head)	{
+
+		aconnector = to_amdgpu_connector(connector);
+		dc_link = aconnector->dc_link;
+
+		int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
+		int_params.irq_source = dc_link->irq_source_hpd;
+
+		amdgpu_dm_irq_register_interrupt(adev, &int_params,
+				handle_hpd_irq,
+				(void *) aconnector);
+
+		if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+
+			/* Also register for DP short pulse (hpd_rx). */
+			int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
+			int_params.irq_source =	dc_link->irq_source_hpd_rx;
+
+			amdgpu_dm_irq_register_interrupt(adev, &int_params,
+					handle_hpd_rx_irq,
+					(void *) aconnector);
+		}
+	}
+}
+
+/* Register IRQ sources and initialize IRQ callbacks */
+static int dce110_register_irq_handlers(struct amdgpu_device *adev)
+{
+	struct dc *dc = adev->dm.dc;
+	struct common_irq_params *c_irq_params;
+	struct dc_interrupt_params int_params = {0};
+	int r;
+	int i;
+	struct dc_caps caps = { 0 };
+
+	dc_get_caps(dc, &caps);
+
+	int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
+	int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
+
+	/* Actions of amdgpu_irq_add_id():
+	 * 1. Register a set() function with base driver.
+	 *    Base driver will call set() function to enable/disable an
+	 *    interrupt in DC hardware.
+	 * 2. Register amdgpu_dm_irq_handler().
+	 *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
+	 *    coming from DC hardware.
+	 *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
+	 *    for acknowledging and handling. */
+
+	for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT;
+			i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) {
+		r = amdgpu_irq_add_id(adev, i, &adev->crtc_irq);
+		if (r) {
+			DRM_ERROR("Failed to add crtc irq id!\n");
+			return r;
+		}
+
+		int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+		int_params.irq_source =
+			dc_interrupt_to_irq_source(dc, i, 0);
+
+		c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
+
+		c_irq_params->adev = adev;
+		c_irq_params->irq_src = int_params.irq_source;
+
+		amdgpu_dm_irq_register_interrupt(adev, &int_params,
+				dm_crtc_high_irq, c_irq_params);
+	}
+
+	for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP;
+			i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) {
+		r = amdgpu_irq_add_id(adev, i, &adev->pageflip_irq);
+		if (r) {
+			DRM_ERROR("Failed to add page flip irq id!\n");
+			return r;
+		}
+
+		int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+		int_params.irq_source =
+			dc_interrupt_to_irq_source(dc, i, 0);
+
+		c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST];
+
+		c_irq_params->adev = adev;
+		c_irq_params->irq_src = int_params.irq_source;
+
+		amdgpu_dm_irq_register_interrupt(adev, &int_params,
+				dm_pflip_high_irq, c_irq_params);
+
+	}
+
+	/* HPD */
+	r = amdgpu_irq_add_id(adev, VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A,
+			&adev->hpd_irq);
+	if (r) {
+		DRM_ERROR("Failed to add hpd irq id!\n");
+		return r;
+	}
+
+	register_hpd_handlers(adev);
+
+	return 0;
+}
+
+static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
+{
+	int r;
+
+	adev->mode_info.mode_config_initialized = true;
+
+	amdgpu_dm_mode_funcs.fb_create =
+		amdgpu_mode_funcs.fb_create;
+	amdgpu_dm_mode_funcs.output_poll_changed =
+		amdgpu_mode_funcs.output_poll_changed;
+
+	adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs;
+
+	adev->ddev->mode_config.max_width = 16384;
+	adev->ddev->mode_config.max_height = 16384;
+
+	adev->ddev->mode_config.preferred_depth = 24;
+	adev->ddev->mode_config.prefer_shadow = 1;
+
+	adev->ddev->mode_config.fb_base = adev->mc.aper_base;
+
+	r = amdgpu_modeset_create_props(adev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
+	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
+{
+	struct amdgpu_display_manager *dm = bl_get_data(bd);
+
+	if (dc_link_set_backlight_level(dm->backlight_link,
+			bd->props.brightness))
+		return 0;
+	else
+		return 1;
+}
+
+static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static const struct backlight_ops amdgpu_dm_backlight_ops = {
+	.get_brightness = amdgpu_dm_backlight_get_brightness,
+	.update_status	= amdgpu_dm_backlight_update_status,
+};
+
+void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
+{
+	char bl_name[16];
+	struct backlight_properties props = { 0 };
+
+	props.max_brightness = AMDGPU_MAX_BL_LEVEL;
+	props.type = BACKLIGHT_RAW;
+
+	snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
+			dm->adev->ddev->primary->index);
+
+	dm->backlight_dev = backlight_device_register(bl_name,
+			dm->adev->ddev->dev,
+			dm,
+			&amdgpu_dm_backlight_ops,
+			&props);
+
+	if (NULL == dm->backlight_dev)
+		DRM_ERROR("DM: Backlight registration failed!\n");
+	else
+		DRM_INFO("DM: Registered Backlight device: %s\n", bl_name);
+}
+
+#endif
+
+/* In this architecture, the association
+ * connector -> encoder -> crtc
+ * id not really requried. The crtc and connector will hold the
+ * display_index as an abstraction to use with DAL component
+ *
+ * Returns 0 on success
+ */
+int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+{
+	struct amdgpu_display_manager *dm = &adev->dm;
+	uint32_t i;
+	struct amdgpu_connector *aconnector;
+	struct amdgpu_encoder *aencoder;
+	struct amdgpu_crtc *acrtc;
+	struct dc_caps caps = { 0 };
+	uint32_t link_cnt;
+
+	dc_get_caps(dm->dc, &caps);
+	link_cnt = caps.max_links;
+
+	if (amdgpu_dm_mode_config_init(dm->adev)) {
+		DRM_ERROR("DM: Failed to initialize mode config\n");
+		return -1;
+	}
+
+	for (i = 0; i < caps.max_targets; i++) {
+		acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL);
+		if (!acrtc)
+			goto fail;
+
+		if (amdgpu_dm_crtc_init(
+			dm,
+			acrtc,
+			i)) {
+			DRM_ERROR("KMS: Failed to initialize crtc\n");
+			kfree(acrtc);
+			goto fail;
+		}
+	}
+
+	dm->display_indexes_num = caps.max_targets;
+
+	/* loops over all connectors on the board */
+	for (i = 0; i < link_cnt; i++) {
+
+		if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) {
+			DRM_ERROR(
+				"KMS: Cannot support more than %d display indexes\n",
+					AMDGPU_DM_MAX_DISPLAY_INDEX);
+			continue;
+		}
+
+		aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
+		if (!aconnector)
+			goto fail;
+
+		aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL);
+		if (!aencoder) {
+			goto fail_free_connector;
+		}
+
+		if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) {
+			DRM_ERROR("KMS: Failed to initialize encoder\n");
+			goto fail_free_encoder;
+		}
+
+		if (amdgpu_dm_connector_init(dm, aconnector, i, aencoder)) {
+			DRM_ERROR("KMS: Failed to initialize connector\n");
+			goto fail_free_connector;
+		}
+
+		if (dc_link_detect(dc_get_link_at_index(dm->dc, i), true))
+			amdgpu_dm_update_connector_after_detect(
+				aconnector);
+	}
+
+	/* Software is initialized. Now we can register interrupt handlers. */
+	switch (adev->asic_type) {
+	case CHIP_TONGA:
+	case CHIP_FIJI:
+	case CHIP_CARRIZO:
+	case CHIP_STONEY:
+		if (dce110_register_irq_handlers(dm->adev)) {
+			DRM_ERROR("DM: Failed to initialize IRQ\n");
+			return -1;
+		}
+		break;
+	default:
+		DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type);
+		return -1;
+	}
+
+	drm_mode_config_reset(dm->ddev);
+
+	return 0;
+fail_free_encoder:
+	kfree(aencoder);
+fail_free_connector:
+	kfree(aconnector);
+fail:
+	return -1;
+}
+
+void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
+{
+	drm_mode_config_cleanup(dm->ddev);
+	return;
+}
+
+/******************************************************************************
+ * amdgpu_display_funcs functions
+ *****************************************************************************/
+
+/**
+ * dm_bandwidth_update - program display watermarks
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Calculate and program the display watermarks and line buffer allocation.
+ */
+static void dm_bandwidth_update(struct amdgpu_device *adev)
+{
+	AMDGPU_DM_NOT_IMPL("%s\n", __func__);
+}
+
+static void dm_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder,
+				     u8 level)
+{
+	/* TODO: translate amdgpu_encoder to display_index and call DAL */
+	AMDGPU_DM_NOT_IMPL("%s\n", __func__);
+}
+
+static u8 dm_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder)
+{
+	/* TODO: translate amdgpu_encoder to display_index and call DAL */
+	AMDGPU_DM_NOT_IMPL("%s\n", __func__);
+	return 0;
+}
+
+/******************************************************************************
+ * Page Flip functions
+ ******************************************************************************/
+
+void amdgpu_dm_flip_cleanup(
+	struct amdgpu_device *adev,
+	struct amdgpu_crtc *acrtc)
+{
+	int r;
+	struct amdgpu_flip_work *works = acrtc->pflip_works;
+
+	acrtc->pflip_works = NULL;
+	acrtc->pflip_status = AMDGPU_FLIP_NONE;
+
+	if (works) {
+		if(works->event)
+			drm_send_vblank_event(
+				adev->ddev,
+				acrtc->crtc_id,
+				works->event);
+
+		r = amdgpu_bo_reserve(works->old_rbo, false);
+		if (likely(r == 0)) {
+			r = amdgpu_bo_unpin(works->old_rbo);
+			if (unlikely(r != 0)) {
+				DRM_ERROR("failed to unpin buffer after flip\n");
+			}
+			amdgpu_bo_unreserve(works->old_rbo);
+		} else
+			DRM_ERROR("failed to reserve buffer after flip\n");
+
+		amdgpu_bo_unref(&works->old_rbo);
+		kfree(works->shared);
+		kfree(works);
+	}
+}
+
+/**
+ * dm_page_flip - called by amdgpu_flip_work_func(), which is triggered
+ * 			via DRM IOCTL, by user mode.
+ *
+ * @adev: amdgpu_device pointer
+ * @crtc_id: crtc to cleanup pageflip on
+ * @crtc_base: new address of the crtc (GPU MC address)
+ *
+ * Does the actual pageflip (surface address update).
+ */
+static void dm_page_flip(struct amdgpu_device *adev,
+			int crtc_id, u64 crtc_base)
+{
+	struct amdgpu_crtc *acrtc;
+	struct dc_target *target;
+	struct dc_flip_addrs addr = { {0} };
+
+	/*
+	 * TODO risk of concurrency issues
+	 *
+	 * This should guarded by the dal_mutex but we can't do this since the
+	 * caller uses a spin_lock on event_lock.
+	 *
+	 * If we wait on the dal_mutex a second page flip interrupt might come,
+	 * spin on the event_lock, disabling interrupts while it does so. At
+	 * this point the core can no longer be pre-empted and return to the
+	 * thread that waited on the dal_mutex and we're deadlocked.
+	 *
+	 * With multiple cores the same essentially happens but might just take
+	 * a little longer to lock up all cores.
+	 *
+	 * The reason we should lock on dal_mutex is so that we can be sure
+	 * nobody messes with acrtc->target after we read and check its value.
+	 *
+	 * We might be able to fix our concurrency issues with a work queue
+	 * where we schedule all work items (mode_set, page_flip, etc.) and
+	 * execute them one by one. Care needs to be taken to still deal with
+	 * any potential concurrency issues arising from interrupt calls.
+	 */
+
+	acrtc = adev->mode_info.crtcs[crtc_id];
+	target = acrtc->target;
+
+	/*
+	 * Received a page flip call after the display has been reset.
+	 * Just return in this case. Everything should be clean-up on reset.
+	 */
+	if (!target)
+		return;
+
+	addr.address.grph.addr.low_part = lower_32_bits(crtc_base);
+	addr.address.grph.addr.high_part = upper_32_bits(crtc_base);
+
+	dc_flip_surface_addrs(
+			adev->dm.dc,
+			dc_target_get_status(target)->surfaces,
+			&addr, 1);
+}
+
+static const struct amdgpu_display_funcs dm_dce_v8_0_display_funcs = {
+	.set_vga_render_state = dce_v8_0_set_vga_render_state,
+	.bandwidth_update = dm_bandwidth_update, /* called unconditionally */
+	.vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */
+	.vblank_wait = NULL,
+	.is_display_hung = NULL, /* not called anywhere */
+	.backlight_set_level =
+		dm_set_backlight_level,/* called unconditionally */
+	.backlight_get_level =
+		dm_get_backlight_level,/* called unconditionally */
+	.hpd_sense = NULL,/* called unconditionally */
+	.hpd_set_polarity = NULL, /* called unconditionally */
+	.hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */
+	.page_flip = dm_page_flip, /* called unconditionally */
+	.page_flip_get_scanoutpos =
+		dm_crtc_get_scanoutpos,/* called unconditionally */
+	.add_encoder = NULL, /* VBIOS parsing. DAL does it. */
+	.add_connector = NULL, /* VBIOS parsing. DAL does it. */
+	.stop_mc_access = dce_v8_0_stop_mc_access, /* called unconditionally */
+	.resume_mc_access = dce_v8_0_resume_mc_access, /* called unconditionally */
+};
+
+static const struct amdgpu_display_funcs dm_dce_v10_0_display_funcs = {
+	.set_vga_render_state = dce_v10_0_set_vga_render_state,
+	.bandwidth_update = dm_bandwidth_update, /* called unconditionally */
+	.vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */
+	.vblank_wait = NULL,
+	.is_display_hung = NULL, /* not called anywhere */
+	.backlight_set_level =
+		dm_set_backlight_level,/* called unconditionally */
+	.backlight_get_level =
+		dm_get_backlight_level,/* called unconditionally */
+	.hpd_sense = NULL,/* called unconditionally */
+	.hpd_set_polarity = NULL, /* called unconditionally */
+	.hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */
+	.page_flip = dm_page_flip, /* called unconditionally */
+	.page_flip_get_scanoutpos =
+		dm_crtc_get_scanoutpos,/* called unconditionally */
+	.add_encoder = NULL, /* VBIOS parsing. DAL does it. */
+	.add_connector = NULL, /* VBIOS parsing. DAL does it. */
+	.stop_mc_access = dce_v10_0_stop_mc_access, /* called unconditionally */
+	.resume_mc_access = dce_v10_0_resume_mc_access, /* called unconditionally */
+};
+
+static const struct amdgpu_display_funcs dm_dce_v11_0_display_funcs = {
+	.set_vga_render_state = dce_v11_0_set_vga_render_state,
+	.bandwidth_update = dm_bandwidth_update, /* called unconditionally */
+	.vblank_get_counter = dm_vblank_get_counter,/* called unconditionally */
+	.vblank_wait = NULL,
+	.is_display_hung = NULL, /* not called anywhere */
+	.backlight_set_level =
+		dm_set_backlight_level,/* called unconditionally */
+	.backlight_get_level =
+		dm_get_backlight_level,/* called unconditionally */
+	.hpd_sense = NULL,/* called unconditionally */
+	.hpd_set_polarity = NULL, /* called unconditionally */
+	.hpd_get_gpio_reg = NULL, /* VBIOS parsing. DAL does it. */
+	.page_flip = dm_page_flip, /* called unconditionally */
+	.page_flip_get_scanoutpos =
+		dm_crtc_get_scanoutpos,/* called unconditionally */
+	.add_encoder = NULL, /* VBIOS parsing. DAL does it. */
+	.add_connector = NULL, /* VBIOS parsing. DAL does it. */
+	.stop_mc_access = dce_v11_0_stop_mc_access, /* called unconditionally */
+	.resume_mc_access = dce_v11_0_resume_mc_access, /* called unconditionally */
+};
+
+static int dm_early_init(void *handle)
+{
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	amdgpu_dm_set_irq_funcs(adev);
+
+	switch (adev->asic_type) {
+	case CHIP_FIJI:
+	case CHIP_TONGA:
+		adev->mode_info.num_crtc = 6;
+		adev->mode_info.num_hpd = 6;
+		adev->mode_info.num_dig = 7;
+		if (adev->mode_info.funcs == NULL)
+			adev->mode_info.funcs = &dm_dce_v10_0_display_funcs;
+		break;
+	case CHIP_CARRIZO:
+	case CHIP_STONEY:
+		adev->mode_info.num_crtc = 3;
+		adev->mode_info.num_hpd = 6;
+		adev->mode_info.num_dig = 9;
+		if (adev->mode_info.funcs == NULL)
+			adev->mode_info.funcs = &dm_dce_v11_0_display_funcs;
+		break;
+	default:
+		DRM_ERROR("Usupported ASIC type: 0x%X\n", adev->asic_type);
+		return -EINVAL;
+	}
+
+	/* Note: Do NOT change adev->audio_endpt_rreg and
+	 * adev->audio_endpt_wreg because they are initialised in
+	 * amdgpu_device_init() */
+
+
+
+	return 0;
+}
+
+
+bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm)
+{
+	/* TODO */
+	return true;
+}
+
+bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm)
+{
+	/* TODO */
+	return true;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
new file mode 100644
index 000000000000..c4ae90b31523
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AMDGPU_DM_H__
+#define __AMDGPU_DM_H__
+
+/*
+#include "linux/switch.h"
+*/
+
+/*
+ * This file contains the definition for amdgpu_display_manager
+ * and its API for amdgpu driver's use.
+ * This component provides all the display related functionality
+ * and this is the only component that calls DAL API.
+ * The API contained here intended for amdgpu driver use.
+ * The API that is called directly from KMS framework is located
+ * in amdgpu_dm_kms.h file
+ */
+
+#define AMDGPU_DM_MAX_DISPLAY_INDEX 31
+/*
+#include "include/amdgpu_dal_power_if.h"
+#include "amdgpu_dm_irq.h"
+*/
+
+#include "irq_types.h"
+
+/* Forward declarations */
+struct amdgpu_device;
+struct drm_device;
+struct amdgpu_dm_irq_handler_data;
+
+struct amdgpu_dm_prev_state {
+	struct drm_framebuffer *fb;
+	int32_t x;
+	int32_t y;
+	struct drm_display_mode mode;
+};
+
+struct common_irq_params {
+	struct amdgpu_device *adev;
+	enum dc_irq_source irq_src;
+};
+
+struct irq_list_head {
+	struct list_head head;
+	/* In case this interrupt needs post-processing, 'work' will be queued*/
+	struct work_struct work;
+};
+
+struct amdgpu_display_manager {
+	struct dal *dal;
+	struct dc *dc;
+	void *cgs_device;
+	/* lock to be used when DAL is called from SYNC IRQ context */
+	spinlock_t dal_lock;
+
+	struct amdgpu_device *adev;	/*AMD base driver*/
+	struct drm_device *ddev;	/*DRM base driver*/
+	u16 display_indexes_num;
+
+	struct amdgpu_dm_prev_state prev_state;
+
+	/*
+	 * 'irq_source_handler_table' holds a list of handlers
+	 * per (DAL) IRQ source.
+	 *
+	 * Each IRQ source may need to be handled at different contexts.
+	 * By 'context' we mean, for example:
+	 * - The ISR context, which is the direct interrupt handler.
+	 * - The 'deferred' context - this is the post-processing of the
+	 *	interrupt, but at a lower priority.
+	 *
+	 * Note that handlers are called in the same order as they were
+	 * registered (FIFO).
+	 */
+	struct irq_list_head irq_handler_list_low_tab[DAL_IRQ_SOURCES_NUMBER];
+	struct list_head irq_handler_list_high_tab[DAL_IRQ_SOURCES_NUMBER];
+
+	struct common_irq_params
+	pflip_params[DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1];
+
+	struct common_irq_params
+	vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1];
+
+	/* this spin lock synchronizes access to 'irq_handler_list_table' */
+	spinlock_t irq_handler_list_table_lock;
+
+	/* Timer-related data. */
+	struct list_head timer_handler_list;
+	struct workqueue_struct *timer_workqueue;
+
+	/* Use dal_mutex for any activity which is NOT syncronized by
+	 * DRM mode setting locks.
+	 * For example: amdgpu_dm_hpd_low_irq() calls into DAL *without*
+	 * DRM mode setting locks being acquired. This is where dal_mutex
+	 * is acquired before calling into DAL. */
+	struct mutex dal_mutex;
+
+	struct backlight_device *backlight_dev;
+
+	const struct dc_link *backlight_link;
+
+	struct work_struct mst_hotplug_work;
+};
+
+
+/* basic init/fini API */
+int amdgpu_dm_init(struct amdgpu_device *adev);
+
+void amdgpu_dm_fini(struct amdgpu_device *adev);
+
+void amdgpu_dm_destroy(void);
+
+/* initializes drm_device display related structures, based on the information
+ * provided by DAL. The drm strcutures are: drm_crtc, drm_connector,
+ * drm_encoder, drm_mode_config
+ *
+ * Returns 0 on success
+ */
+int amdgpu_dm_initialize_drm_device(
+	struct amdgpu_device *adev);
+
+/* removes and deallocates the drm structures, created by the above function */
+void amdgpu_dm_destroy_drm_device(
+	struct amdgpu_display_manager *dm);
+
+/* Locking/Mutex */
+bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm);
+
+bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm);
+
+/* Register "Backlight device" accessible by user-mode. */
+void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm);
+
+void amdgpu_dm_flip_cleanup(
+	struct amdgpu_device *adev,
+	struct amdgpu_crtc *acrtc);
+
+extern const struct amd_ip_funcs amdgpu_dm_funcs;
+
+void amdgpu_dm_update_connector_after_detect(
+	struct amdgpu_connector *aconnector);
+
+#endif /* __AMDGPU_DM_H__ */
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
new file mode 100644
index 000000000000..57ff7919db77
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_helpers.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/acpi.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/amdgpu_drm.h>
+#include <drm/drm_edid.h>
+
+#include "dm_services.h"
+#include "amdgpu.h"
+#include "dc.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_irq.h"
+#include "amdgpu_dm_types.h"
+
+#include "dm_helpers.h"
+
+/* dm_helpers_parse_edid_caps
+ *
+ * Parse edid caps
+ *
+ * @edid:	[in] pointer to edid
+ *  edid_caps:	[in] pointer to edid caps
+ * @return
+ *	void
+ * */
+enum dc_edid_status dm_helpers_parse_edid_caps(
+		struct dc_context *ctx,
+		const struct dc_edid *edid,
+		struct dc_edid_caps *edid_caps)
+{
+	struct edid *edid_buf = (struct edid *) edid->raw_edid;
+	struct cea_sad *sads;
+	int sad_count = -1;
+	int sadb_count = -1;
+	int i = 0;
+	int j = 0;
+	uint8_t *sadb = NULL;
+
+	enum dc_edid_status result = EDID_OK;
+
+	if (!edid_caps || !edid)
+		return EDID_BAD_INPUT;
+
+	if (!drm_edid_is_valid(edid_buf))
+		result = EDID_BAD_CHECKSUM;
+
+	edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] |
+					((uint16_t) edid_buf->mfg_id[1])<<8;
+	edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] |
+					((uint16_t) edid_buf->prod_code[1])<<8;
+	edid_caps->serial_number = edid_buf->serial;
+	edid_caps->manufacture_week = edid_buf->mfg_week;
+	edid_caps->manufacture_year = edid_buf->mfg_year;
+
+	/* One of the four detailed_timings stores the monitor name. It's
+	 * stored in an array of length 13. */
+	for (i = 0; i < 4; i++) {
+		if (edid_buf->detailed_timings[i].data.other_data.type == 0xfc) {
+			while (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] && j < 13) {
+				if (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] == '\n')
+					break;
+
+				edid_caps->display_name[j] =
+					edid_buf->detailed_timings[i].data.other_data.data.str.str[j];
+				j++;
+			}
+		}
+	}
+
+	sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
+	if (sad_count <= 0) {
+		DRM_INFO("SADs count is: %d, don't need to read it\n",
+				sad_count);
+		return result;
+	}
+
+	edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT;
+	for (i = 0; i < edid_caps->audio_mode_count; ++i) {
+		struct cea_sad *sad = &sads[i];
+
+		edid_caps->audio_modes[i].format_code = sad->format;
+		edid_caps->audio_modes[i].channel_count = sad->channels;
+		edid_caps->audio_modes[i].sample_rate = sad->freq;
+		edid_caps->audio_modes[i].sample_size = sad->byte2;
+	}
+
+	sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb);
+
+	if (sadb_count < 0) {
+		DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count);
+		sadb_count = 0;
+	}
+
+	if (sadb_count)
+		edid_caps->speaker_flags = sadb[0];
+	else
+		edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION;
+
+	kfree(sads);
+	kfree(sadb);
+
+	return result;
+}
+
+static struct amdgpu_connector *get_connector_for_sink(
+	struct drm_device *dev,
+	const struct dc_sink *sink)
+{
+	struct drm_connector *connector;
+	struct amdgpu_connector *aconnector = NULL;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		if (aconnector->dc_sink == sink)
+			break;
+	}
+
+	return aconnector;
+}
+
+static struct amdgpu_connector *get_connector_for_link(
+	struct drm_device *dev,
+	const struct dc_link *link)
+{
+	struct drm_connector *connector;
+	struct amdgpu_connector *aconnector = NULL;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		if (aconnector->dc_link == link)
+			break;
+	}
+
+	return aconnector;
+}
+
+
+static void get_payload_table(
+		struct amdgpu_connector *aconnector,
+		struct dp_mst_stream_allocation_table *proposed_table)
+{
+	int i;
+	struct drm_dp_mst_topology_mgr *mst_mgr =
+			&aconnector->mst_port->mst_mgr;
+
+	mutex_lock(&mst_mgr->payload_lock);
+
+	proposed_table->stream_count = 0;
+
+	/* number of active streams */
+	for (i = 0; i < mst_mgr->max_payloads; i++) {
+		if (mst_mgr->payloads[i].num_slots == 0)
+			break; /* end of vcp_id table */
+
+		ASSERT(mst_mgr->payloads[i].payload_state !=
+				DP_PAYLOAD_DELETE_LOCAL);
+
+		if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL ||
+			mst_mgr->payloads[i].payload_state ==
+					DP_PAYLOAD_REMOTE) {
+
+			struct dp_mst_stream_allocation *sa =
+					&proposed_table->stream_allocations[
+						proposed_table->stream_count];
+
+			sa->slot_count = mst_mgr->payloads[i].num_slots;
+			sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi;
+			proposed_table->stream_count++;
+		}
+	}
+
+	mutex_unlock(&mst_mgr->payload_lock);
+}
+
+/*
+ * Writes payload allocation table in immediate downstream device.
+ */
+bool dm_helpers_dp_mst_write_payload_allocation_table(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		struct dp_mst_stream_allocation_table *proposed_table,
+		bool enable)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
+	struct drm_dp_mst_port *mst_port;
+	int slots = 0;
+	bool ret;
+	int clock;
+	int bpp = 0;
+	int pbn = 0;
+
+	aconnector = get_connector_for_sink(dev, stream->sink);
+
+	if (!aconnector->mst_port)
+		return false;
+
+	mst_mgr = &aconnector->mst_port->mst_mgr;
+
+	if (!mst_mgr->mst_state)
+		return false;
+
+	mst_port = aconnector->port;
+
+	if (enable) {
+		clock = stream->timing.pix_clk_khz;
+
+		switch (stream->timing.display_color_depth) {
+
+		case COLOR_DEPTH_666:
+			bpp = 6;
+			break;
+		case COLOR_DEPTH_888:
+			bpp = 8;
+			break;
+		case COLOR_DEPTH_101010:
+			bpp = 10;
+			break;
+		case COLOR_DEPTH_121212:
+			bpp = 12;
+			break;
+		case COLOR_DEPTH_141414:
+			bpp = 14;
+			break;
+		case COLOR_DEPTH_161616:
+			bpp = 16;
+			break;
+		default:
+			ASSERT(bpp != 0);
+			break;
+		}
+
+		bpp = bpp * 3;
+
+		/* TODO need to know link rate */
+
+		pbn = drm_dp_calc_pbn_mode(clock, bpp);
+
+		ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, &slots);
+
+		if (!ret)
+			return false;
+
+	} else {
+		drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port);
+	}
+
+	ret = drm_dp_update_payload_part1(mst_mgr);
+
+	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
+	 * AUX message. The sequence is slot 1-63 allocated sequence for each
+	 * stream. AMD ASIC stream slot allocation should follow the same
+	 * sequence. copy DRM MST allocation to dc */
+
+	get_payload_table(aconnector, proposed_table);
+
+	if (ret)
+		return false;
+
+	return true;
+}
+
+/*
+ * Polls for ACT (allocation change trigger) handled and sends
+ * ALLOCATE_PAYLOAD message.
+ */
+bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
+		struct dc_context *ctx,
+		const struct dc_stream *stream)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
+	int ret;
+
+	aconnector = get_connector_for_sink(dev, stream->sink);
+
+	if (!aconnector->mst_port)
+		return false;
+
+	mst_mgr = &aconnector->mst_port->mst_mgr;
+
+	if (!mst_mgr->mst_state)
+		return false;
+
+	ret = drm_dp_check_act_status(mst_mgr);
+
+	if (ret)
+		return false;
+
+	return true;
+}
+
+bool dm_helpers_dp_mst_send_payload_allocation(
+		struct dc_context *ctx,
+		const struct dc_stream *stream,
+		bool enable)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector;
+	struct drm_dp_mst_topology_mgr *mst_mgr;
+	struct drm_dp_mst_port *mst_port;
+	int ret;
+
+	aconnector = get_connector_for_sink(dev, stream->sink);
+
+	mst_port = aconnector->port;
+
+	if (!aconnector->mst_port)
+		return false;
+
+	mst_mgr = &aconnector->mst_port->mst_mgr;
+
+	if (!mst_mgr->mst_state)
+		return false;
+
+	ret = drm_dp_update_payload_part2(mst_mgr);
+
+	if (ret)
+		return false;
+
+	if (!enable)
+		drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port);
+
+	return true;
+}
+
+void dm_helpers_dp_mst_handle_mst_hpd_rx_irq(void *param)
+{
+	uint8_t esi[8] = { 0 };
+	uint8_t dret;
+	bool new_irq_handled = true;
+	struct amdgpu_connector *aconnector = (struct amdgpu_connector *)param;
+
+	/* DPCD 0x2002 - 0x2008 for down stream IRQ from MST, eDP etc. */
+	dret = drm_dp_dpcd_read(
+		&aconnector->dm_dp_aux.aux,
+		DP_SINK_COUNT_ESI, esi, 8);
+
+	while ((dret == 8) && new_irq_handled) {
+		uint8_t retry;
+
+		DRM_DEBUG_KMS("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+
+		/* handle HPD short pulse irq */
+		drm_dp_mst_hpd_irq(&aconnector->mst_mgr, esi, &new_irq_handled);
+
+		if (new_irq_handled) {
+			/* ACK at DPCD to notify down stream */
+			for (retry = 0; retry < 3; retry++) {
+				uint8_t wret;
+
+				wret = drm_dp_dpcd_write(
+					&aconnector->dm_dp_aux.aux,
+					DP_SINK_COUNT_ESI + 1,
+					&esi[1],
+					3);
+				if (wret == 3)
+					break;
+			}
+
+			/* check if there is new irq to be handle */
+			dret = drm_dp_dpcd_read(
+				&aconnector->dm_dp_aux.aux,
+				DP_SINK_COUNT_ESI, esi, 8);
+		}
+	}
+}
+
+bool dm_helpers_dp_mst_start_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		bool boot)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	if (boot) {
+		DRM_INFO("DM_MST: Differing MST start on aconnector: %p [id: %d]\n",
+					aconnector, aconnector->base.base.id);
+		return true;
+	}
+
+	DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n",
+			aconnector, aconnector->base.base.id);
+
+	return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0);
+}
+
+void dm_helpers_dp_mst_stop_top_mgr(
+		struct dc_context *ctx,
+		const struct dc_link *link)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n",
+			aconnector, aconnector->base.base.id);
+
+	if (aconnector->mst_mgr.mst_state == true)
+		drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false);
+}
+
+bool dm_helpers_dp_read_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size)
+{
+
+
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	if (!aconnector) {
+		DRM_ERROR("Failed to found connector for link!");
+		return false;
+	}
+
+	return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address,
+			data, size) > 0;
+}
+
+bool dm_helpers_dp_write_dpcd(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		uint32_t address,
+		const uint8_t *data,
+		uint32_t size)
+{
+
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+
+	if (!aconnector) {
+		DRM_ERROR("Failed to found connector for link!");
+		return false;
+	}
+
+	return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux,
+			address, (uint8_t *)data, size) > 0;
+}
+
+bool dm_helpers_submit_i2c(
+		struct dc_context *ctx,
+		const struct dc_link *link,
+		struct i2c_command *cmd)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+	struct drm_device *dev = adev->ddev;
+	struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
+	struct i2c_msg *msgs;
+	int i = 0;
+	int num = cmd->number_of_payloads;
+	bool result;
+
+	if (!aconnector) {
+		DRM_ERROR("Failed to found connector for link!");
+		return false;
+	}
+
+	msgs = kzalloc(num * sizeof(struct i2c_msg), GFP_KERNEL);
+
+	if (!msgs)
+		return false;
+
+	for (i = 0; i < num; i++) {
+		msgs[i].flags = cmd->payloads[i].write ? I2C_M_RD : 0;
+		msgs[i].addr = cmd->payloads[i].address;
+		msgs[i].len = cmd->payloads[i].length;
+		msgs[i].buf = cmd->payloads[i].data;
+	}
+
+	result = i2c_transfer(&aconnector->i2c->base, msgs, num) == num;
+
+	kfree(msgs);
+
+	return result;
+}
+
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
new file mode 100644
index 000000000000..9b5fd7063a0b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.c
@@ -0,0 +1,820 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <drm/drmP.h>
+
+#include "dm_services_types.h"
+#include "dc.h"
+
+#include "amdgpu.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_irq.h"
+
+
+/******************************************************************************
+ * Private declarations.
+ *****************************************************************************/
+
+struct handler_common_data {
+	struct list_head list;
+	interrupt_handler handler;
+	void *handler_arg;
+
+	/* DM which this handler belongs to */
+	struct amdgpu_display_manager *dm;
+};
+
+struct amdgpu_dm_irq_handler_data {
+	struct handler_common_data hcd;
+	/* DAL irq source which registered for this interrupt. */
+	enum dc_irq_source irq_source;
+};
+
+struct amdgpu_dm_timer_handler_data {
+	struct handler_common_data hcd;
+	struct delayed_work d_work;
+};
+
+
+#define DM_IRQ_TABLE_LOCK(adev, flags) \
+	spin_lock_irqsave(&adev->dm.irq_handler_list_table_lock, flags)
+
+#define DM_IRQ_TABLE_UNLOCK(adev, flags) \
+	spin_unlock_irqrestore(&adev->dm.irq_handler_list_table_lock, flags)
+
+/******************************************************************************
+ * Private functions.
+ *****************************************************************************/
+
+static void init_handler_common_data(
+	struct handler_common_data *hcd,
+	void (*ih)(void *),
+	void *args,
+	struct amdgpu_display_manager *dm)
+{
+	hcd->handler = ih;
+	hcd->handler_arg = args;
+	hcd->dm = dm;
+}
+
+/**
+ * dm_irq_work_func - Handle an IRQ outside of the interrupt handler proper.
+ *
+ * @work: work struct
+ */
+static void dm_irq_work_func(struct work_struct *work)
+{
+	struct list_head *entry;
+	struct irq_list_head *irq_list_head =
+		container_of(work, struct irq_list_head, work);
+	struct list_head *handler_list = &irq_list_head->head;
+	struct amdgpu_dm_irq_handler_data *handler_data;
+
+	list_for_each(entry, handler_list) {
+		handler_data =
+			list_entry(
+				entry,
+				struct amdgpu_dm_irq_handler_data,
+				hcd.list);
+
+		DRM_DEBUG_KMS("DM_IRQ: work_func: for dal_src=%d\n",
+				handler_data->irq_source);
+
+		DRM_DEBUG_KMS("DM_IRQ: schedule_work: for dal_src=%d\n",
+			handler_data->irq_source);
+
+		handler_data->hcd.handler(handler_data->hcd.handler_arg);
+	}
+
+	/* Call a DAL subcomponent which registered for interrupt notification
+	 * at INTERRUPT_LOW_IRQ_CONTEXT.
+	 * (The most common use is HPD interrupt) */
+}
+
+/**
+ * Remove a handler and return a pointer to hander list from which the
+ * handler was removed.
+ */
+static struct list_head *remove_irq_handler(
+	struct amdgpu_device *adev,
+	void *ih,
+	const struct dc_interrupt_params *int_params)
+{
+	struct list_head *hnd_list;
+	struct list_head *entry, *tmp;
+	struct amdgpu_dm_irq_handler_data *handler;
+	unsigned long irq_table_flags;
+	bool handler_removed = false;
+	enum dc_irq_source irq_source;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	irq_source = int_params->irq_source;
+
+	switch (int_params->int_context) {
+	case INTERRUPT_HIGH_IRQ_CONTEXT:
+		hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source];
+		break;
+	case INTERRUPT_LOW_IRQ_CONTEXT:
+	default:
+		hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head;
+		break;
+	}
+
+	list_for_each_safe(entry, tmp, hnd_list) {
+
+		handler = list_entry(entry, struct amdgpu_dm_irq_handler_data,
+				hcd.list);
+
+		if (ih == handler) {
+			/* Found our handler. Remove it from the list. */
+			list_del(&handler->hcd.list);
+			handler_removed = true;
+			break;
+		}
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	if (handler_removed == false) {
+		/* Not necessarily an error - caller may not
+		 * know the context. */
+		return NULL;
+	}
+
+	kfree(handler);
+
+	DRM_DEBUG_KMS(
+	"DM_IRQ: removed irq handler: %p for: dal_src=%d, irq context=%d\n",
+		ih, int_params->irq_source, int_params->int_context);
+
+	return hnd_list;
+}
+
+/* If 'handler_in == NULL' then remove ALL handlers. */
+static void remove_timer_handler(
+	struct amdgpu_device *adev,
+	struct amdgpu_dm_timer_handler_data *handler_in)
+{
+	struct amdgpu_dm_timer_handler_data *handler_temp;
+	struct list_head *handler_list;
+	struct list_head *entry, *tmp;
+	unsigned long irq_table_flags;
+	bool handler_removed = false;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	handler_list = &adev->dm.timer_handler_list;
+
+	list_for_each_safe(entry, tmp, handler_list) {
+		/* Note that list_for_each_safe() guarantees that
+		 * handler_temp is NOT null. */
+		handler_temp = list_entry(entry,
+				struct amdgpu_dm_timer_handler_data, hcd.list);
+
+		if (handler_in == NULL || handler_in == handler_temp) {
+			list_del(&handler_temp->hcd.list);
+			DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+			DRM_DEBUG_KMS("DM_IRQ: removing timer handler: %p\n",
+					handler_temp);
+
+			if (handler_in == NULL) {
+				/* Since it is still in the queue, it must
+				 * be cancelled. */
+				cancel_delayed_work_sync(&handler_temp->d_work);
+			}
+
+			kfree(handler_temp);
+			handler_removed = true;
+
+			DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+		}
+
+		if (handler_in == NULL) {
+			/* Remove ALL handlers. */
+			continue;
+		}
+
+		if (handler_in == handler_temp) {
+			/* Remove a SPECIFIC handler.
+			 * Found our handler - we can stop here. */
+			break;
+		}
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	if (handler_in != NULL && handler_removed == false) {
+		DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n",
+				handler_in);
+	}
+}
+
+/**
+ * dm_timer_work_func - Handle a timer.
+ *
+ * @work: work struct
+ */
+static void dm_timer_work_func(
+	struct work_struct *work)
+{
+	struct amdgpu_dm_timer_handler_data *handler_data =
+		container_of(work, struct amdgpu_dm_timer_handler_data,
+				d_work.work);
+
+	DRM_DEBUG_KMS("DM_IRQ: work_func: handler_data=%p\n", handler_data);
+
+	/* Call a DAL subcomponent which registered for timer notification. */
+	handler_data->hcd.handler(handler_data->hcd.handler_arg);
+
+	/* We support only "single shot" timers. That means we must delete
+	 * the handler after it was called. */
+	remove_timer_handler(handler_data->hcd.dm->adev, handler_data);
+}
+
+static bool validate_irq_registration_params(
+	struct dc_interrupt_params *int_params,
+	void (*ih)(void *))
+{
+	if (NULL == int_params || NULL == ih) {
+		DRM_ERROR("DM_IRQ: invalid input!\n");
+		return false;
+	}
+
+	if (int_params->int_context >= INTERRUPT_CONTEXT_NUMBER) {
+		DRM_ERROR("DM_IRQ: invalid context: %d!\n",
+				int_params->int_context);
+		return false;
+	}
+
+	if (!DAL_VALID_IRQ_SRC_NUM(int_params->irq_source)) {
+		DRM_ERROR("DM_IRQ: invalid irq_source: %d!\n",
+				int_params->irq_source);
+		return false;
+	}
+
+	return true;
+}
+
+static bool validate_irq_unregistration_params(
+	enum dc_irq_source irq_source,
+	irq_handler_idx handler_idx)
+{
+	if (DAL_INVALID_IRQ_HANDLER_IDX == handler_idx) {
+		DRM_ERROR("DM_IRQ: invalid handler_idx==NULL!\n");
+		return false;
+	}
+
+	if (!DAL_VALID_IRQ_SRC_NUM(irq_source)) {
+		DRM_ERROR("DM_IRQ: invalid irq_source:%d!\n", irq_source);
+		return false;
+	}
+
+	return true;
+}
+/******************************************************************************
+ * Public functions.
+ *
+ * Note: caller is responsible for input validation.
+ *****************************************************************************/
+
+void *amdgpu_dm_irq_register_interrupt(
+	struct amdgpu_device *adev,
+	struct dc_interrupt_params *int_params,
+	void (*ih)(void *),
+	void *handler_args)
+{
+	struct list_head *hnd_list;
+	struct amdgpu_dm_irq_handler_data *handler_data;
+	unsigned long irq_table_flags;
+	enum dc_irq_source irq_source;
+
+	if (false == validate_irq_registration_params(int_params, ih))
+		return DAL_INVALID_IRQ_HANDLER_IDX;
+
+	handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL);
+	if (!handler_data) {
+		DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n");
+		return DAL_INVALID_IRQ_HANDLER_IDX;
+	}
+
+	memset(handler_data, 0, sizeof(*handler_data));
+
+	init_handler_common_data(&handler_data->hcd, ih, handler_args,
+			&adev->dm);
+
+	irq_source = int_params->irq_source;
+
+	handler_data->irq_source = irq_source;
+
+	/* Lock the list, add the handler. */
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	switch (int_params->int_context) {
+	case INTERRUPT_HIGH_IRQ_CONTEXT:
+		hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source];
+		break;
+	case INTERRUPT_LOW_IRQ_CONTEXT:
+	default:
+		hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head;
+		break;
+	}
+
+	list_add_tail(&handler_data->hcd.list, hnd_list);
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	/* This pointer will be stored by code which requested interrupt
+	 * registration.
+	 * The same pointer will be needed in order to unregister the
+	 * interrupt. */
+
+	DRM_DEBUG_KMS(
+		"DM_IRQ: added irq handler: %p for: dal_src=%d, irq context=%d\n",
+		handler_data,
+		irq_source,
+		int_params->int_context);
+
+	return handler_data;
+}
+
+void amdgpu_dm_irq_unregister_interrupt(
+	struct amdgpu_device *adev,
+	enum dc_irq_source irq_source,
+	void *ih)
+{
+	struct list_head *handler_list;
+	struct dc_interrupt_params int_params;
+	int i;
+
+	if (false == validate_irq_unregistration_params(irq_source, ih))
+		return;
+
+	memset(&int_params, 0, sizeof(int_params));
+
+	int_params.irq_source = irq_source;
+
+	for (i = 0; i < INTERRUPT_CONTEXT_NUMBER; i++) {
+
+		int_params.int_context = i;
+
+		handler_list = remove_irq_handler(adev, ih, &int_params);
+
+		if (handler_list != NULL)
+			break;
+	}
+
+	if (handler_list == NULL) {
+		/* If we got here, it means we searched all irq contexts
+		 * for this irq source, but the handler was not found. */
+		DRM_ERROR(
+		"DM_IRQ: failed to find irq handler:%p for irq_source:%d!\n",
+			ih, irq_source);
+	}
+}
+
+int amdgpu_dm_irq_init(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct irq_list_head *lh;
+
+	DRM_DEBUG_KMS("DM_IRQ\n");
+
+	spin_lock_init(&adev->dm.irq_handler_list_table_lock);
+
+	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+		/* low context handler list init */
+		lh = &adev->dm.irq_handler_list_low_tab[src];
+		INIT_LIST_HEAD(&lh->head);
+		INIT_WORK(&lh->work, dm_irq_work_func);
+
+		/* high context handler init */
+		INIT_LIST_HEAD(&adev->dm.irq_handler_list_high_tab[src]);
+	}
+
+	INIT_LIST_HEAD(&adev->dm.timer_handler_list);
+
+	/* allocate and initialize the workqueue for DM timer */
+	adev->dm.timer_workqueue = create_singlethread_workqueue(
+			"dm_timer_queue");
+	if (adev->dm.timer_workqueue == NULL) {
+		DRM_ERROR("DM_IRQ: unable to create timer queue!\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+void amdgpu_dm_irq_register_timer(
+	struct amdgpu_device *adev,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *args)
+{
+	unsigned long jf_delay;
+	struct list_head *handler_list;
+	struct amdgpu_dm_timer_handler_data *handler_data;
+	unsigned long irq_table_flags;
+
+	handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL);
+	if (!handler_data) {
+		DRM_ERROR("DM_IRQ: failed to allocate timer handler!\n");
+		return;
+	}
+
+	memset(handler_data, 0, sizeof(*handler_data));
+
+	init_handler_common_data(&handler_data->hcd, ih, args, &adev->dm);
+
+	INIT_DELAYED_WORK(&handler_data->d_work, dm_timer_work_func);
+
+	/* Lock the list, add the handler. */
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	handler_list = &adev->dm.timer_handler_list;
+
+	list_add_tail(&handler_data->hcd.list, handler_list);
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	jf_delay = usecs_to_jiffies(int_params->micro_sec_interval);
+
+	queue_delayed_work(adev->dm.timer_workqueue, &handler_data->d_work,
+			jf_delay);
+
+	DRM_DEBUG_KMS("DM_IRQ: added handler:%p with micro_sec_interval=%u\n",
+			handler_data, int_params->micro_sec_interval);
+	return;
+}
+
+/* DM IRQ and timer resource release */
+void amdgpu_dm_irq_fini(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct irq_list_head *lh;
+	DRM_DEBUG_KMS("DM_IRQ: releasing resources.\n");
+
+	for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+
+		/* The handler was removed from the table,
+		 * it means it is safe to flush all the 'work'
+		 * (because no code can schedule a new one). */
+		lh = &adev->dm.irq_handler_list_low_tab[src];
+		flush_work(&lh->work);
+	}
+
+	/* Cancel ALL timers and release handlers (if any). */
+	remove_timer_handler(adev, NULL);
+	/* Release the queue itself. */
+	destroy_workqueue(adev->dm.timer_workqueue);
+}
+
+int amdgpu_dm_irq_suspend(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct list_head *hnd_list_h;
+	struct list_head *hnd_list_l;
+	unsigned long irq_table_flags;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	DRM_DEBUG_KMS("DM_IRQ: suspend\n");
+
+	/* disable HW interrupt */
+	for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+		hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
+		hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
+		if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
+			dc_interrupt_set(adev->dm.dc, src, false);
+
+		DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+		flush_work(&adev->dm.irq_handler_list_low_tab[src].work);
+
+		DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	return 0;
+}
+
+int amdgpu_dm_irq_resume(
+	struct amdgpu_device *adev)
+{
+	int src;
+	struct list_head *hnd_list_h, *hnd_list_l;
+	unsigned long irq_table_flags;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	DRM_DEBUG_KMS("DM_IRQ: resume\n");
+
+	/* re-enable HW interrupt */
+	for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) {
+		hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
+		hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
+		if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
+			dc_interrupt_set(adev->dm.dc, src, true);
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	return 0;
+}
+
+
+/**
+ * amdgpu_dm_irq_schedule_work - schedule all work items registered for the
+ * "irq_source".
+ */
+static void amdgpu_dm_irq_schedule_work(
+	struct amdgpu_device *adev,
+	enum dc_irq_source irq_source)
+{
+	unsigned long irq_table_flags;
+	struct work_struct *work = NULL;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	if (!list_empty(&adev->dm.irq_handler_list_low_tab[irq_source].head))
+		work = &adev->dm.irq_handler_list_low_tab[irq_source].work;
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+
+	if (work) {
+		if (!schedule_work(work))
+			DRM_INFO("amdgpu_dm_irq_schedule_work FAILED src %d\n",
+						irq_source);
+	}
+
+}
+
+/** amdgpu_dm_irq_immediate_work
+ *  Callback high irq work immediately, don't send to work queue
+ */
+static void amdgpu_dm_irq_immediate_work(
+	struct amdgpu_device *adev,
+	enum dc_irq_source irq_source)
+{
+	struct amdgpu_dm_irq_handler_data *handler_data;
+	struct list_head *entry;
+	unsigned long irq_table_flags;
+
+	DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
+
+	list_for_each(
+		entry,
+		&adev->dm.irq_handler_list_high_tab[irq_source]) {
+
+		handler_data =
+			list_entry(
+				entry,
+				struct amdgpu_dm_irq_handler_data,
+				hcd.list);
+
+		/* Call a subcomponent which registered for immediate
+		 * interrupt notification */
+		handler_data->hcd.handler(handler_data->hcd.handler_arg);
+	}
+
+	DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
+}
+
+/*
+ * amdgpu_dm_irq_handler
+ *
+ * Generic IRQ handler, calls all registered high irq work immediately, and
+ * schedules work for low irq
+ */
+int amdgpu_dm_irq_handler(
+		struct amdgpu_device *adev,
+		struct amdgpu_irq_src *source,
+		struct amdgpu_iv_entry *entry)
+{
+
+	enum dc_irq_source src =
+		dc_interrupt_to_irq_source(
+			adev->dm.dc,
+			entry->src_id,
+			entry->src_data);
+
+	dc_interrupt_ack(adev->dm.dc, src);
+
+	/* Call high irq work immediately */
+	amdgpu_dm_irq_immediate_work(adev, src);
+	/*Schedule low_irq work */
+	amdgpu_dm_irq_schedule_work(adev, src);
+
+	return 0;
+}
+
+static enum dc_irq_source amdgpu_dm_hpd_to_dal_irq_source(unsigned type)
+{
+	switch (type) {
+	case AMDGPU_HPD_1:
+		return DC_IRQ_SOURCE_HPD1;
+	case AMDGPU_HPD_2:
+		return DC_IRQ_SOURCE_HPD2;
+	case AMDGPU_HPD_3:
+		return DC_IRQ_SOURCE_HPD3;
+	case AMDGPU_HPD_4:
+		return DC_IRQ_SOURCE_HPD4;
+	case AMDGPU_HPD_5:
+		return DC_IRQ_SOURCE_HPD5;
+	case AMDGPU_HPD_6:
+		return DC_IRQ_SOURCE_HPD6;
+	default:
+		return DC_IRQ_SOURCE_INVALID;
+	}
+}
+
+static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev,
+					struct amdgpu_irq_src *source,
+					unsigned type,
+					enum amdgpu_interrupt_state state)
+{
+	enum dc_irq_source src = amdgpu_dm_hpd_to_dal_irq_source(type);
+	bool st = (state == AMDGPU_IRQ_STATE_ENABLE);
+
+	dc_interrupt_set(adev->dm.dc, src, st);
+	return 0;
+}
+
+static inline int dm_irq_state(
+	struct amdgpu_device *adev,
+	struct amdgpu_irq_src *source,
+	unsigned crtc_id,
+	enum amdgpu_interrupt_state state,
+	const enum irq_type dal_irq_type,
+	const char *func)
+{
+	bool st;
+	enum dc_irq_source irq_source;
+
+	struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc_id];
+
+	if (!acrtc->target) {
+		DRM_INFO(
+			"%s: target is null for crtc %d, talk to David R\n",
+			func,
+			crtc_id);
+		WARN_ON(true);
+		return 0;
+	}
+
+	irq_source = dc_target_get_irq_src(acrtc->target, dal_irq_type);
+
+	st = (state == AMDGPU_IRQ_STATE_ENABLE);
+
+	dc_interrupt_set(adev->dm.dc, irq_source, st);
+	return 0;
+}
+
+static int amdgpu_dm_set_pflip_irq_state(struct amdgpu_device *adev,
+					struct amdgpu_irq_src *source,
+					unsigned crtc_id,
+					enum amdgpu_interrupt_state state)
+{
+	return dm_irq_state(
+		adev,
+		source,
+		crtc_id,
+		state,
+		IRQ_TYPE_PFLIP,
+		__func__);
+}
+
+static int amdgpu_dm_set_crtc_irq_state(struct amdgpu_device *adev,
+					struct amdgpu_irq_src *source,
+					unsigned crtc_id,
+					enum amdgpu_interrupt_state state)
+{
+	return dm_irq_state(
+		adev,
+		source,
+		crtc_id,
+		state,
+		IRQ_TYPE_VUPDATE,
+		__func__);
+}
+
+static const struct amdgpu_irq_src_funcs dm_crtc_irq_funcs = {
+	.set = amdgpu_dm_set_crtc_irq_state,
+	.process = amdgpu_dm_irq_handler,
+};
+
+static const struct amdgpu_irq_src_funcs dm_pageflip_irq_funcs = {
+	.set = amdgpu_dm_set_pflip_irq_state,
+	.process = amdgpu_dm_irq_handler,
+};
+
+static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = {
+	.set = amdgpu_dm_set_hpd_irq_state,
+	.process = amdgpu_dm_irq_handler,
+};
+
+void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev)
+{
+	adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST;
+	adev->crtc_irq.funcs = &dm_crtc_irq_funcs;
+
+	adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST;
+	adev->pageflip_irq.funcs = &dm_pageflip_irq_funcs;
+
+	adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
+	adev->hpd_irq.funcs = &dm_hpd_irq_funcs;
+}
+
+/*
+ * amdgpu_dm_hpd_init - hpd setup callback.
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Setup the hpd pins used by the card (evergreen+).
+ * Enable the pin, set the polarity, and enable the hpd interrupts.
+ */
+void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct amdgpu_connector *amdgpu_connector =
+				to_amdgpu_connector(connector);
+
+		const struct dc_link *dc_link = amdgpu_connector->dc_link;
+
+		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+			connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+			/* don't try to enable hpd on eDP or LVDS avoid breaking
+			 * the aux dp channel on imac and help (but not
+			 * completely fix)
+			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
+			 * also avoid interrupt storms during dpms.
+			 */
+			continue;
+		}
+
+		dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, true);
+
+		if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+			dc_interrupt_set(adev->dm.dc,
+					dc_link->irq_source_hpd_rx,
+					true);
+		}
+	}
+}
+
+/**
+ * amdgpu_dm_hpd_fini - hpd tear down callback.
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Tear down the hpd pins used by the card (evergreen+).
+ * Disable the hpd interrupts.
+ */
+void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
+{
+	struct drm_device *dev = adev->ddev;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct amdgpu_connector *amdgpu_connector =
+				to_amdgpu_connector(connector);
+		const struct dc_link *dc_link = amdgpu_connector->dc_link;
+
+		dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, false);
+
+		if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+			dc_interrupt_set(adev->dm.dc,
+					dc_link->irq_source_hpd_rx,
+					false);
+		}
+	}
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
new file mode 100644
index 000000000000..afedb50897bd
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_irq.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION 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 __AMDGPU_DM_IRQ_H__
+#define __AMDGPU_DM_IRQ_H__
+
+#include "irq_types.h" /* DAL irq definitions */
+
+/*
+ * Display Manager IRQ-related interfaces (for use by DAL).
+ */
+
+/**
+ * amdgpu_dm_irq_init - Initialize internal structures of 'amdgpu_dm_irq'.
+ *
+ * This function should be called exactly once - during DM initialization.
+ *
+ * Returns:
+ *	0 - success
+ *	non-zero - error
+ */
+int amdgpu_dm_irq_init(
+	struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_fini - deallocate internal structures of 'amdgpu_dm_irq'.
+ *
+ * This function should be called exactly once - during DM destruction.
+ *
+ */
+void amdgpu_dm_irq_fini(
+	struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_register_interrupt - register irq handler for Display block.
+ *
+ * @adev: AMD DRM device
+ * @int_params: parameters for the irq
+ * @ih: pointer to the irq hander function
+ * @handler_args: arguments which will be passed to ih
+ *
+ * Returns:
+ * 	IRQ Handler Index on success.
+ * 	NULL on failure.
+ *
+ * Cannot be called from an interrupt handler.
+ */
+void *amdgpu_dm_irq_register_interrupt(
+		struct amdgpu_device *adev,
+		struct dc_interrupt_params *int_params,
+		void (*ih)(void *),
+		void *handler_args);
+
+/**
+ * amdgpu_dm_irq_unregister_interrupt - unregister handler which was registered
+ *	by amdgpu_dm_irq_register_interrupt().
+ *
+ * @adev: AMD DRM device.
+ * @ih_index: irq handler index which was returned by
+ *	amdgpu_dm_irq_register_interrupt
+ */
+void amdgpu_dm_irq_unregister_interrupt(
+		struct amdgpu_device *adev,
+		enum dc_irq_source irq_source,
+		void *ih_index);
+
+void amdgpu_dm_irq_register_timer(
+	struct amdgpu_device *adev,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *args);
+
+/**
+ * amdgpu_dm_irq_handler
+ * Generic IRQ handler, calls all registered high irq work immediately, and
+ * schedules work for low irq
+ */
+int amdgpu_dm_irq_handler(
+		struct amdgpu_device *adev,
+		struct amdgpu_irq_src *source,
+		struct amdgpu_iv_entry *entry);
+
+void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev);
+
+void amdgpu_dm_hpd_init(struct amdgpu_device *adev);
+void amdgpu_dm_hpd_fini(struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_suspend - disable ASIC interrupt during suspend.
+ *
+ */
+int amdgpu_dm_irq_suspend(
+	struct amdgpu_device *adev);
+
+/**
+ * amdgpu_dm_irq_resume - enable ASIC interrupt during resume.
+ *
+ */
+int amdgpu_dm_irq_resume(
+	struct amdgpu_device *adev);
+
+#endif /* __AMDGPU_DM_IRQ_H__ */
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
new file mode 100644
index 000000000000..22ba13080cf1
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/version.h>
+#include <drm/drm_atomic_helper.h>
+#include "dm_services.h"
+#include "amdgpu.h"
+#include "amdgpu_dm_types.h"
+#include "amdgpu_dm_mst_types.h"
+
+#include "dc.h"
+#include "dm_helpers.h"
+
+
+/* #define TRACE_DPCD */
+
+#ifdef TRACE_DPCD
+#define SIDE_BAND_MSG(address) (address >= DP_SIDEBAND_MSG_DOWN_REQ_BASE && address < DP_SINK_COUNT_ESI)
+
+static inline char *side_band_msg_type_to_str(uint32_t address)
+{
+	static char str[10] = {0};
+
+	if (address < DP_SIDEBAND_MSG_UP_REP_BASE)
+		strcpy(str, "DOWN_REQ");
+	else if (address < DP_SIDEBAND_MSG_DOWN_REP_BASE)
+		strcpy(str, "UP_REP");
+	else if (address < DP_SIDEBAND_MSG_UP_REQ_BASE)
+		strcpy(str, "DOWN_REP");
+	else
+		strcpy(str, "UP_REQ");
+
+	return str;
+}
+
+void log_dpcd(uint8_t type,
+		uint32_t address,
+		uint8_t *data,
+		uint32_t size,
+		bool res)
+{
+	DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n",
+			(type == DP_AUX_NATIVE_READ) ||
+			(type == DP_AUX_I2C_READ) ?
+					"Read" : "Write",
+			address,
+			SIDE_BAND_MSG(address) ?
+					side_band_msg_type_to_str(address) : "Nop",
+			res ? "OK" : "Fail");
+
+	if (res) {
+		print_hex_dump(KERN_INFO, "Body: ", DUMP_PREFIX_NONE, 16, 1, data, size, false);
+	}
+}
+#endif
+
+static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
+{
+	struct pci_dev *pdev = to_pci_dev(aux->dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct amdgpu_device *adev = drm_dev->dev_private;
+	struct dc *dc = adev->dm.dc;
+	bool res;
+
+	switch (msg->request) {
+	case DP_AUX_NATIVE_READ:
+		res = dc_read_dpcd(
+			dc,
+			TO_DM_AUX(aux)->link_index,
+			msg->address,
+			msg->buffer,
+			msg->size);
+		break;
+	case DP_AUX_NATIVE_WRITE:
+		res = dc_write_dpcd(
+			dc,
+			TO_DM_AUX(aux)->link_index,
+			msg->address,
+			msg->buffer,
+			msg->size);
+		break;
+	default:
+		return 0;
+	}
+
+#ifdef TRACE_DPCD
+	log_dpcd(msg->request,
+			msg->address,
+			msg->buffer,
+			msg->size,
+			res);
+#endif
+
+	return msg->size;
+}
+
+static enum drm_connector_status
+dm_dp_mst_detect(struct drm_connector *connector, bool force)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+	struct amdgpu_connector *master = aconnector->mst_port;
+
+	enum drm_connector_status status =
+		drm_dp_mst_detect_port(
+			connector,
+			&master->mst_mgr,
+			aconnector->port);
+
+	if (status == connector_status_disconnected && aconnector->edid) {
+		kfree(aconnector->edid);
+		aconnector->edid = NULL;
+	}
+
+	/*
+	 * we do not want to make this connector connected until we have edid on
+	 * it
+	 */
+	if (status == connector_status_connected &&
+		!aconnector->port->cached_edid)
+		status = connector_status_disconnected;
+
+	return status;
+}
+
+static void
+dm_dp_mst_connector_destroy(struct drm_connector *connector)
+{
+	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+	struct amdgpu_encoder *amdgpu_encoder = amdgpu_connector->mst_encoder;
+
+	drm_encoder_cleanup(&amdgpu_encoder->base);
+	kfree(amdgpu_encoder);
+	drm_connector_cleanup(connector);
+	kfree(amdgpu_connector);
+}
+
+static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = dm_dp_mst_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = dm_dp_mst_connector_destroy,
+	.reset = amdgpu_dm_connector_funcs_reset,
+	.atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
+	.atomic_destroy_state = amdgpu_dm_connector_atomic_destroy_state,
+	.atomic_set_property = amdgpu_dm_connector_atomic_set_property
+};
+
+static struct dc_sink *dm_dp_mst_add_mst_sink(
+		const struct dc_link *dc_link,
+		uint8_t *edid,
+		uint16_t len)
+{
+	struct dc_sink *dc_sink;
+	struct dc_sink_init_data init_params = {
+			.link = dc_link,
+			.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST};
+	enum dc_edid_status edid_status;
+
+	if (len > MAX_EDID_BUFFER_SIZE) {
+		DRM_ERROR("Max EDID buffer size breached!\n");
+		return NULL;
+	}
+
+	if (!dc_link) {
+		BREAK_TO_DEBUGGER();
+		return NULL;
+	}
+
+	/*
+	 * TODO make dynamic-ish?
+	 * dc_link->connector_signal;
+	 */
+
+	dc_sink = dc_sink_create(&init_params);
+
+	if (!dc_sink)
+		return NULL;
+
+	dm_memmove(dc_sink->dc_edid.raw_edid, edid, len);
+	dc_sink->dc_edid.length = len;
+
+	if (!dc_link_add_remote_sink(
+			dc_link,
+			dc_sink))
+		goto fail_add_sink;
+
+	edid_status = dm_helpers_parse_edid_caps(
+			NULL,
+			&dc_sink->dc_edid,
+			&dc_sink->edid_caps);
+	if (edid_status != EDID_OK)
+		goto fail;
+
+	/* dc_sink_retain(&core_sink->public); */
+
+	return dc_sink;
+fail:
+	dc_link_remove_remote_sink(dc_link, dc_sink);
+fail_add_sink:
+	return NULL;
+}
+
+static int dm_dp_mst_get_modes(struct drm_connector *connector)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+	struct amdgpu_connector *master = aconnector->mst_port;
+	struct edid *edid;
+	const struct dc_sink *sink;
+	int ret = 0;
+
+	if (!aconnector->edid) {
+		edid = drm_dp_mst_get_edid(connector, &master->mst_mgr, aconnector->port);
+
+		if (!edid) {
+			drm_mode_connector_update_edid_property(
+				&aconnector->base,
+				NULL);
+
+			return ret;
+		}
+
+		aconnector->edid = edid;
+
+		if (aconnector->dc_sink)
+			dc_link_remove_remote_sink(
+				aconnector->dc_link,
+				aconnector->dc_sink);
+
+		sink = dm_dp_mst_add_mst_sink(
+			aconnector->dc_link,
+			(uint8_t *)edid,
+			(edid->extensions + 1) * EDID_LENGTH);
+		aconnector->dc_sink = sink;
+	} else
+		edid = aconnector->edid;
+
+	DRM_DEBUG_KMS("edid retrieved %p\n", edid);
+
+	drm_mode_connector_update_edid_property(
+		&aconnector->base,
+		aconnector->edid);
+
+	ret = drm_add_edid_modes(&aconnector->base, aconnector->edid);
+
+	drm_edid_to_eld(&aconnector->base, aconnector->edid);
+
+	return ret;
+}
+
+static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
+{
+	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
+
+	return &amdgpu_connector->mst_encoder->base;
+}
+
+static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = {
+	.get_modes = dm_dp_mst_get_modes,
+	.mode_valid = amdgpu_dm_connector_mode_valid,
+	.best_encoder = dm_mst_best_encoder,
+};
+
+static struct amdgpu_encoder *
+dm_dp_create_fake_mst_encoder(struct amdgpu_connector *connector)
+{
+	struct drm_device *dev = connector->base.dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct amdgpu_encoder *amdgpu_encoder;
+	struct drm_encoder *encoder;
+	const struct drm_connector_helper_funcs *connector_funcs =
+		connector->base.helper_private;
+	struct drm_encoder *enc_master =
+		connector_funcs->best_encoder(&connector->base);
+
+	DRM_DEBUG_KMS("enc master is %p\n", enc_master);
+	amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
+	if (!amdgpu_encoder)
+		return NULL;
+
+	encoder = &amdgpu_encoder->base;
+	encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
+
+	drm_encoder_init(
+		dev,
+		&amdgpu_encoder->base,
+		NULL,
+		DRM_MODE_ENCODER_DPMST,
+		NULL);
+
+	drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
+
+	return amdgpu_encoder;
+}
+
+static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
+							 struct drm_dp_mst_port *port,
+							 const char *pathprop)
+{
+	struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr);
+	struct drm_device *dev = master->base.dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct amdgpu_connector *aconnector;
+	struct drm_connector *connector;
+
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		aconnector = to_amdgpu_connector(connector);
+		if (aconnector->mst_port == master
+				&& !aconnector->port) {
+			DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n",
+						aconnector, connector->base.id, aconnector->mst_port);
+
+			aconnector->port = port;
+			drm_mode_connector_set_path_property(connector, pathprop);
+
+			drm_modeset_unlock(&dev->mode_config.connection_mutex);
+			return &aconnector->base;
+		}
+	}
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+
+	aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
+	if (!aconnector)
+		return NULL;
+
+	connector = &aconnector->base;
+	aconnector->port = port;
+	aconnector->mst_port = master;
+
+	if (drm_connector_init(
+		dev,
+		connector,
+		&dm_dp_mst_connector_funcs,
+		DRM_MODE_CONNECTOR_DisplayPort)) {
+		kfree(aconnector);
+		return NULL;
+	}
+	drm_connector_helper_add(connector, &dm_dp_mst_connector_helper_funcs);
+
+	amdgpu_dm_connector_init_helper(
+		&adev->dm,
+		aconnector,
+		DRM_MODE_CONNECTOR_DisplayPort,
+		master->dc_link,
+		master->connector_id);
+
+	aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
+
+	/*
+	 * TODO: understand why this one is needed
+	 */
+	drm_object_attach_property(
+		&connector->base,
+		dev->mode_config.path_property,
+		0);
+	drm_object_attach_property(
+		&connector->base,
+		dev->mode_config.tile_property,
+		0);
+
+	drm_mode_connector_set_path_property(connector, pathprop);
+
+	/*
+	 * Initialize connector state before adding the connectror to drm and
+	 * framebuffer lists
+	 */
+	amdgpu_dm_connector_funcs_reset(connector);
+
+	DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n",
+			aconnector, connector->base.id, aconnector->mst_port);
+
+	DRM_DEBUG_KMS(":%d\n", connector->base.id);
+
+	return connector;
+}
+
+static void dm_dp_destroy_mst_connector(
+	struct drm_dp_mst_topology_mgr *mgr,
+	struct drm_connector *connector)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+
+	DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n",
+				aconnector, connector->base.id, aconnector->mst_port);
+
+	aconnector->port = NULL;
+	if (aconnector->dc_sink) {
+		dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink);
+		aconnector->dc_sink = NULL;
+	}
+}
+
+static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr);
+	struct drm_device *dev = master->base.dev;
+	struct amdgpu_device *adev = dev->dev_private;
+
+	schedule_work(&adev->dm.mst_hotplug_work);
+}
+
+static void dm_dp_mst_register_connector(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	int i;
+
+	drm_modeset_lock_all(dev);
+	if (adev->mode_info.rfbdev) {
+		/*Do not add if already registered in past*/
+		for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) {
+			if (adev->mode_info.rfbdev->helper.connector_info[i]->connector
+					== connector) {
+				drm_modeset_unlock_all(dev);
+				return;
+			}
+		}
+
+		drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector);
+	}
+	else
+		DRM_ERROR("adev->mode_info.rfbdev is NULL\n");
+
+	drm_modeset_unlock_all(dev);
+
+	drm_connector_register(connector);
+
+}
+
+struct drm_dp_mst_topology_cbs dm_mst_cbs = {
+	.add_connector = dm_dp_add_mst_connector,
+	.destroy_connector = dm_dp_destroy_mst_connector,
+	.hotplug = dm_dp_mst_hotplug,
+	.register_connector = dm_dp_mst_register_connector
+};
+
+
+void amdgpu_dm_initialize_mst_connector(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector)
+{
+	aconnector->dm_dp_aux.aux.name = "dmdc";
+	aconnector->dm_dp_aux.aux.dev = dm->adev->dev;
+	aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
+	aconnector->dm_dp_aux.link_index = aconnector->connector_id;
+
+	drm_dp_aux_register(&aconnector->dm_dp_aux.aux);
+	aconnector->mst_mgr.cbs = &dm_mst_cbs;
+	drm_dp_mst_topology_mgr_init(
+		&aconnector->mst_mgr,
+		dm->adev->dev,
+		&aconnector->dm_dp_aux.aux,
+		16,
+		4,
+		aconnector->connector_id);
+}
+
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
new file mode 100644
index 000000000000..6130d62ac65c
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_AMDGPU_DM_MST_TYPES_H__
+#define __DAL_AMDGPU_DM_MST_TYPES_H__
+
+struct amdgpu_display_manager;
+struct amdgpu_connector;
+
+void amdgpu_dm_initialize_mst_connector(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector);
+
+#endif
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
new file mode 100644
index 000000000000..b1552700d9e0
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_services.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/acpi.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/amdgpu_drm.h>
+#include "dm_services.h"
+#include "amdgpu.h"
+#include "amdgpu_dm.h"
+#include "amdgpu_dm_irq.h"
+#include "amdgpu_dm_types.h"
+#include "amdgpu_pm.h"
+
+/*
+#include "logger_interface.h"
+#include "acpimethod_atif.h"
+#include "amdgpu_powerplay.h"
+#include "amdgpu_notifications.h"
+*/
+
+/* if the pointer is not NULL, the allocated memory is zeroed */
+void *dm_alloc(struct dc_context *ctx, uint32_t size)
+{
+	return kzalloc(size, GFP_KERNEL);
+}
+
+/* Reallocate memory. The contents will remain unchanged.*/
+void *dm_realloc(struct dc_context *ctx, const void *ptr, uint32_t size)
+{
+	return krealloc(ptr, size, GFP_KERNEL);
+}
+
+void dm_memmove(void *dst, const void *src, uint32_t size)
+{
+	memmove(dst, src, size);
+}
+
+void dm_free(struct dc_context *ctx, void *p)
+{
+	kfree(p);
+}
+
+void dm_memset(void *p, int32_t c, uint32_t count)
+{
+	memset(p, c, count);
+}
+
+int32_t dm_memcmp(const void *p1, const void *p2, uint32_t count)
+{
+	return memcmp(p1, p2, count);
+}
+
+int32_t dm_strncmp(const int8_t *p1, const int8_t *p2, uint32_t count)
+{
+	return strncmp(p1, p2, count);
+}
+
+void dm_sleep_in_milliseconds(struct dc_context *ctx, uint32_t milliseconds)
+{
+	if (milliseconds >= 20)
+		msleep(milliseconds);
+	else
+		usleep_range(milliseconds*1000, milliseconds*1000+1);
+}
+
+void dal_delay_in_nanoseconds(uint32_t nanoseconds)
+{
+	ndelay(nanoseconds);
+}
+
+void dm_delay_in_microseconds(struct dc_context *ctx, uint32_t microseconds)
+{
+	udelay(microseconds);
+}
+
+/******************************************************************************
+ * IRQ Interfaces.
+ *****************************************************************************/
+
+void dal_register_timer_interrupt(
+	struct dc_context *ctx,
+	struct dc_timer_interrupt_params *int_params,
+	interrupt_handler ih,
+	void *args)
+{
+	struct amdgpu_device *adev = ctx->driver_context;
+
+	if (!adev || !int_params) {
+		DRM_ERROR("DM_IRQ: invalid input!\n");
+		return;
+	}
+
+	if (int_params->int_context != INTERRUPT_LOW_IRQ_CONTEXT) {
+		/* only low irq ctx is supported. */
+		DRM_ERROR("DM_IRQ: invalid context: %d!\n",
+				int_params->int_context);
+		return;
+	}
+
+	amdgpu_dm_irq_register_timer(adev, int_params, ih, args);
+}
+
+void dal_isr_acquire_lock(struct dc_context *ctx)
+{
+	/*TODO*/
+}
+
+void dal_isr_release_lock(struct dc_context *ctx)
+{
+	/*TODO*/
+}
+
+/******************************************************************************
+ * End-of-IRQ Interfaces.
+ *****************************************************************************/
+
+bool dm_get_platform_info(struct dc_context *ctx,
+			struct platform_info_params *params)
+{
+	/*TODO*/
+	return false;
+}
+
+/**** power component interfaces ****/
+
+bool dm_pp_pre_dce_clock_change(
+		struct dc_context *ctx,
+		struct dal_to_power_info *input,
+		struct power_to_dal_info *output)
+{
+	/*TODO*/
+	return false;
+}
+
+bool dm_pp_apply_safe_state(
+		const struct dc_context *ctx)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+
+	if (adev->pm.dpm_enabled) {
+		/* TODO: Does this require PreModeChange event to PPLIB? */
+	}
+
+	return true;
+#else
+	return false;
+#endif
+}
+
+bool dm_pp_apply_display_requirements(
+		const struct dc_context *ctx,
+		const struct dc_pp_display_configuration *pp_display_cfg)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+
+	if (adev->pm.dpm_enabled) {
+
+		memset(&adev->pm.pm_display_cfg, 0,
+				sizeof(adev->pm.pm_display_cfg));
+
+		adev->pm.pm_display_cfg.cpu_cc6_disable =
+			pp_display_cfg->cpu_cc6_disable;
+
+		adev->pm.pm_display_cfg.cpu_pstate_disable =
+			pp_display_cfg->cpu_pstate_disable;
+
+		adev->pm.pm_display_cfg.cpu_pstate_separation_time =
+			pp_display_cfg->cpu_pstate_separation_time;
+
+		adev->pm.pm_display_cfg.nb_pstate_switch_disable =
+			pp_display_cfg->nb_pstate_switch_disable;
+
+		adev->pm.pm_display_cfg.num_display =
+				pp_display_cfg->display_count;
+		adev->pm.pm_display_cfg.num_path_including_non_display =
+				pp_display_cfg->display_count;
+
+		adev->pm.pm_display_cfg.min_core_set_clock =
+				pp_display_cfg->min_engine_clock_khz/10;
+		adev->pm.pm_display_cfg.min_core_set_clock_in_sr =
+				pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
+		adev->pm.pm_display_cfg.min_mem_set_clock =
+				pp_display_cfg->min_memory_clock_khz/10;
+
+		adev->pm.pm_display_cfg.multi_monitor_in_sync =
+				pp_display_cfg->all_displays_in_sync;
+		adev->pm.pm_display_cfg.min_vblank_time =
+				pp_display_cfg->avail_mclk_switch_time_us;
+
+		adev->pm.pm_display_cfg.display_clk =
+				pp_display_cfg->disp_clk_khz/10;
+
+		adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency =
+				pp_display_cfg->avail_mclk_switch_time_in_disp_active_us;
+
+		adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index;
+		adev->pm.pm_display_cfg.line_time_in_us =
+				pp_display_cfg->line_time_in_us;
+
+		adev->pm.pm_display_cfg.crossfire_display_index = -1;
+		adev->pm.pm_display_cfg.min_bus_bandwidth = 0;
+
+		/* TODO: complete implementation of
+		 * amd_powerplay_display_configuration_change().
+		 * Follow example of:
+		 * PHM_StoreDALConfigurationData - powerplay\hwmgr\hardwaremanager.c
+		 * PP_IRI_DisplayConfigurationChange - powerplay\eventmgr\iri.c */
+		amd_powerplay_display_configuration_change(
+				adev->powerplay.pp_handle,
+				&adev->pm.pm_display_cfg);
+
+		/* TODO: replace by a separate call to 'apply display cfg'? */
+		amdgpu_pm_compute_clocks(adev);
+	}
+
+	return true;
+#else
+	return false;
+#endif
+}
+
+bool dc_service_get_system_clocks_range(
+		const struct dc_context *ctx,
+		struct dal_system_clock_range *sys_clks)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+#endif
+
+	/* Default values, in case PPLib is not compiled-in. */
+	sys_clks->max_mclk = 80000;
+	sys_clks->min_mclk = 80000;
+
+	sys_clks->max_sclk = 60000;
+	sys_clks->min_sclk = 30000;
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	if (adev->pm.dpm_enabled) {
+		sys_clks->max_mclk = amdgpu_dpm_get_mclk(adev, false);
+		sys_clks->min_mclk = amdgpu_dpm_get_mclk(adev, true);
+
+		sys_clks->max_sclk = amdgpu_dpm_get_sclk(adev, false);
+		sys_clks->min_sclk = amdgpu_dpm_get_sclk(adev, true);
+	}
+#endif
+
+	return true;
+}
+
+static void get_default_clock_levels(
+		enum dc_pp_clock_type clk_type,
+		struct dc_pp_clock_levels *clks)
+{
+	uint32_t disp_clks_in_khz[6] = {
+			300000, 400000, 496560, 626090, 685720, 757900 };
+	uint32_t sclks_in_khz[6] = {
+			300000, 360000, 423530, 514290, 626090, 720000 };
+	uint32_t mclks_in_khz[2] = { 333000, 800000 };
+
+	switch (clk_type) {
+	case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
+		clks->num_levels = 6;
+		dm_memmove(clks->clocks_in_khz, disp_clks_in_khz,
+				sizeof(disp_clks_in_khz));
+		break;
+	case DC_PP_CLOCK_TYPE_ENGINE_CLK:
+		clks->num_levels = 6;
+		dm_memmove(clks->clocks_in_khz, sclks_in_khz,
+				sizeof(sclks_in_khz));
+		break;
+	case DC_PP_CLOCK_TYPE_MEMORY_CLK:
+		clks->num_levels = 2;
+		dm_memmove(clks->clocks_in_khz, mclks_in_khz,
+				sizeof(mclks_in_khz));
+		break;
+	default:
+		clks->num_levels = 0;
+		break;
+	}
+}
+
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+static enum amd_pp_clock_type dc_to_pp_clock_type(
+		enum dc_pp_clock_type dc_pp_clk_type)
+{
+	enum amd_pp_clock_type amd_pp_clk_type = 0;
+
+	switch (dc_pp_clk_type) {
+	case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
+		amd_pp_clk_type = amd_pp_disp_clock;
+		break;
+	case DC_PP_CLOCK_TYPE_ENGINE_CLK:
+		amd_pp_clk_type = amd_pp_sys_clock;
+		break;
+	case DC_PP_CLOCK_TYPE_MEMORY_CLK:
+		amd_pp_clk_type = amd_pp_mem_clock;
+		break;
+	default:
+		DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
+				dc_pp_clk_type);
+		break;
+	}
+
+	return amd_pp_clk_type;
+}
+
+static void pp_to_dc_clock_levels(
+		const struct amd_pp_clocks *pp_clks,
+		struct dc_pp_clock_levels *dc_clks,
+		enum dc_pp_clock_type dc_clk_type)
+{
+	uint32_t i;
+
+	if (pp_clks->count > DC_PP_MAX_CLOCK_LEVELS) {
+		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
+				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
+				pp_clks->count,
+				DC_PP_MAX_CLOCK_LEVELS);
+
+		dc_clks->num_levels = DC_PP_MAX_CLOCK_LEVELS;
+	} else
+		dc_clks->num_levels = pp_clks->count;
+
+	DRM_INFO("DM_PPLIB: values for %s clock\n",
+			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
+
+	for (i = 0; i < dc_clks->num_levels; i++) {
+		DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
+		/* translate 10kHz to kHz */
+		dc_clks->clocks_in_khz[i] = pp_clks->clock[i] * 10;
+	}
+}
+#endif
+
+bool dm_pp_get_clock_levels_by_type(
+		const struct dc_context *ctx,
+		enum dc_pp_clock_type clk_type,
+		struct dc_pp_clock_levels *dc_clks)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = ctx->driver_context;
+	void *pp_handle = adev->powerplay.pp_handle;
+	struct amd_pp_clocks pp_clks = { 0 };
+	struct amd_pp_simple_clock_info validation_clks = { 0 };
+	uint32_t i;
+
+	if (amd_powerplay_get_clock_by_type(pp_handle,
+			dc_to_pp_clock_type(clk_type), &pp_clks)) {
+		/* Error in pplib. Provide default values. */
+		get_default_clock_levels(clk_type, dc_clks);
+		return true;
+	}
+
+	pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
+
+	if (amd_powerplay_get_display_mode_validation_clocks(pp_handle,
+			&validation_clks)) {
+		/* Error in pplib. Provide default values. */
+		DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
+		validation_clks.engine_max_clock = 72000;
+		validation_clks.memory_max_clock = 80000;
+		validation_clks.level = 0;
+	}
+
+	DRM_INFO("DM_PPLIB: Validation clocks:\n");
+	DRM_INFO("DM_PPLIB:    engine_max_clock: %d\n",
+			validation_clks.engine_max_clock);
+	DRM_INFO("DM_PPLIB:    memory_max_clock: %d\n",
+			validation_clks.memory_max_clock);
+	DRM_INFO("DM_PPLIB:    level           : %d\n",
+			validation_clks.level);
+
+	/* Translate 10 kHz to kHz. */
+	validation_clks.engine_max_clock *= 10;
+	validation_clks.memory_max_clock *= 10;
+
+	/* Determine the highest non-boosted level from the Validation Clocks */
+	if (clk_type == DC_PP_CLOCK_TYPE_ENGINE_CLK) {
+		for (i = 0; i < dc_clks->num_levels; i++) {
+			if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
+				/* This clock is higher the validation clock.
+				 * Than means the previous one is the highest
+				 * non-boosted one. */
+				DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
+						dc_clks->num_levels, i + 1);
+				dc_clks->num_levels = i;
+				break;
+			}
+		}
+	} else if (clk_type == DC_PP_CLOCK_TYPE_MEMORY_CLK) {
+		for (i = 0; i < dc_clks->num_levels; i++) {
+			if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
+				DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
+						dc_clks->num_levels, i + 1);
+				dc_clks->num_levels = i;
+				break;
+			}
+		}
+	}
+#else
+	get_default_clock_levels(clk_type, dc_clks);
+#endif
+	return true;
+}
+
+/**** end of power component interfaces ****/
+
+
+/* Calls to notification */
+
+void dal_notify_setmode_complete(struct dc_context *ctx,
+	uint32_t h_total,
+	uint32_t v_total,
+	uint32_t h_active,
+	uint32_t v_active,
+	uint32_t pix_clk_in_khz)
+{
+	/*TODO*/
+}
+/* End of calls to notification */
+
+long dm_get_pid(void)
+{
+	return current->pid;
+}
+
+long dm_get_tgid(void)
+{
+	return current->tgid;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
new file mode 100644
index 000000000000..f3164104f15b
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.c
@@ -0,0 +1,2649 @@
+/*
+ * Copyright 2012-13 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic.h>
+
+#include "amdgpu.h"
+#include "amdgpu_pm.h"
+#include "dm_services_types.h"
+
+// We need to #undef FRAME_SIZE and DEPRECATED because they conflict
+// with ptrace-abi.h's #define's of them.
+#undef FRAME_SIZE
+#undef DEPRECATED
+
+#include "dc.h"
+
+#include "amdgpu_dm_types.h"
+#include "amdgpu_dm_mst_types.h"
+
+struct dm_connector_state {
+	struct drm_connector_state base;
+
+	enum amdgpu_rmx_type scaling;
+	uint8_t underscan_vborder;
+	uint8_t underscan_hborder;
+	bool underscan_enable;
+};
+
+#define to_dm_connector_state(x)\
+	container_of((x), struct dm_connector_state, base)
+
+#define AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET 1
+#define MAX_TARGET_NUM 6
+
+void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+	kfree(encoder);
+}
+
+static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
+	.destroy = amdgpu_dm_encoder_destroy,
+};
+
+static void dm_set_cursor(
+	struct amdgpu_crtc *amdgpu_crtc,
+	uint64_t gpu_addr,
+	uint32_t width,
+	uint32_t height)
+{
+	struct dc_cursor_attributes attributes;
+	amdgpu_crtc->cursor_width = width;
+	amdgpu_crtc->cursor_height = height;
+
+	attributes.address.high_part = upper_32_bits(gpu_addr);
+	attributes.address.low_part  = lower_32_bits(gpu_addr);
+	attributes.width             = width-1;
+	attributes.height            = height-1;
+	attributes.x_hot             = 0;
+	attributes.y_hot             = 0;
+	attributes.color_format      = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA;
+	attributes.rotation_angle    = 0;
+	attributes.attribute_flags.value = 0;
+
+	if (!dc_target_set_cursor_attributes(
+				amdgpu_crtc->target,
+				&attributes)) {
+		DRM_ERROR("DC failed to set cursor attributes\n");
+	}
+}
+
+static int dm_crtc_unpin_cursor_bo_old(
+	struct amdgpu_crtc *amdgpu_crtc)
+{
+	struct amdgpu_bo *robj;
+	int ret = 0;
+
+	if (NULL != amdgpu_crtc && NULL != amdgpu_crtc->cursor_bo) {
+		robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
+
+		ret = amdgpu_bo_reserve(robj, false);
+
+		if (likely(ret == 0)) {
+			ret = amdgpu_bo_unpin(robj);
+
+			if (unlikely(ret != 0)) {
+				DRM_ERROR(
+					"%s: unpin failed (ret=%d), bo %p\n",
+					__func__,
+					ret,
+					amdgpu_crtc->cursor_bo);
+			}
+
+			amdgpu_bo_unreserve(robj);
+		} else {
+			DRM_ERROR(
+				"%s: reserve failed (ret=%d), bo %p\n",
+				__func__,
+				ret,
+				amdgpu_crtc->cursor_bo);
+		}
+
+		drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo);
+		amdgpu_crtc->cursor_bo = NULL;
+	}
+
+	return ret;
+}
+
+static int dm_crtc_pin_cursor_bo_new(
+	struct drm_crtc *crtc,
+	struct drm_file *file_priv,
+	uint32_t handle,
+	struct amdgpu_bo **ret_obj)
+{
+	struct amdgpu_crtc *amdgpu_crtc;
+	struct amdgpu_bo *robj;
+	struct drm_gem_object *obj;
+	int ret = -EINVAL;
+
+	if (NULL != crtc) {
+		struct drm_device *dev = crtc->dev;
+		struct amdgpu_device *adev = dev->dev_private;
+		uint64_t gpu_addr;
+
+		amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+		obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+
+		if (!obj) {
+			DRM_ERROR(
+				"Cannot find cursor object %x for crtc %d\n",
+				handle,
+				amdgpu_crtc->crtc_id);
+			goto release;
+		}
+		robj = gem_to_amdgpu_bo(obj);
+
+		ret  = amdgpu_bo_reserve(robj, false);
+
+		if (unlikely(ret != 0)) {
+			drm_gem_object_unreference_unlocked(obj);
+		DRM_ERROR("dm_crtc_pin_cursor_bo_new ret %x, handle %x\n",
+				 ret, handle);
+			goto release;
+		}
+
+		ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, 0,
+						adev->mc.visible_vram_size,
+						&gpu_addr);
+
+		if (ret == 0) {
+			amdgpu_crtc->cursor_addr = gpu_addr;
+			*ret_obj  = robj;
+		}
+		amdgpu_bo_unreserve(robj);
+		if (ret)
+			drm_gem_object_unreference_unlocked(obj);
+
+	}
+release:
+
+	return ret;
+}
+
+static int dm_crtc_cursor_set(
+	struct drm_crtc *crtc,
+	struct drm_file *file_priv,
+	uint32_t handle,
+	uint32_t width,
+	uint32_t height)
+{
+	struct amdgpu_bo *new_cursor_bo;
+	struct dc_cursor_position position;
+
+	int ret;
+
+	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+	ret		= EINVAL;
+	new_cursor_bo	= NULL;
+
+	DRM_DEBUG_KMS(
+	"%s: crtc_id=%d with handle %d and size %d to %d, bo_object %p\n",
+		__func__,
+		amdgpu_crtc->crtc_id,
+		handle,
+		width,
+		height,
+		amdgpu_crtc->cursor_bo);
+
+	if (!handle) {
+		/* turn off cursor */
+		position.enable = false;
+		position.x = 0;
+		position.y = 0;
+		position.hot_spot_enable = false;
+
+		if (amdgpu_crtc->target) {
+			/*set cursor visible false*/
+			dc_target_set_cursor_position(
+				amdgpu_crtc->target,
+				&position);
+		}
+		/*unpin old cursor buffer and update cache*/
+		ret = dm_crtc_unpin_cursor_bo_old(amdgpu_crtc);
+		goto release;
+
+	}
+
+	if ((width > amdgpu_crtc->max_cursor_width) ||
+		(height > amdgpu_crtc->max_cursor_height)) {
+		DRM_ERROR(
+			"%s: bad cursor width or height %d x %d\n",
+			__func__,
+			width,
+			height);
+		goto release;
+	}
+	/*try to pin new cursor bo*/
+	ret = dm_crtc_pin_cursor_bo_new(crtc, file_priv, handle, &new_cursor_bo);
+	/*if map not successful then return an error*/
+	if (ret)
+		goto release;
+
+	/*program new cursor bo to hardware*/
+	dm_set_cursor(amdgpu_crtc, amdgpu_crtc->cursor_addr, width, height);
+
+	/*un map old, not used anymore cursor bo ,
+	 * return memory and mapping back */
+	dm_crtc_unpin_cursor_bo_old(amdgpu_crtc);
+
+	/*assign new cursor bo to our internal cache*/
+	amdgpu_crtc->cursor_bo = &new_cursor_bo->gem_base;
+
+release:
+	return ret;
+
+}
+
+static int dm_crtc_cursor_move(struct drm_crtc *crtc,
+				     int x, int y)
+{
+	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+	int xorigin = 0, yorigin = 0;
+	struct dc_cursor_position position;
+
+	/* avivo cursor are offset into the total surface */
+	x += crtc->primary->state->src_x >> 16;
+	y += crtc->primary->state->src_y >> 16;
+
+	/*
+	 * TODO: for cursor debugging unguard the following
+	 */
+#if 0
+	DRM_DEBUG_KMS(
+		"%s: x %d y %d c->x %d c->y %d\n",
+		__func__,
+		x,
+		y,
+		crtc->x,
+		crtc->y);
+#endif
+
+	if (x < 0) {
+		xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1);
+		x = 0;
+	}
+	if (y < 0) {
+		yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1);
+		y = 0;
+	}
+
+	position.enable = true;
+	position.x = x;
+	position.y = y;
+
+	position.hot_spot_enable = true;
+	position.x_origin = xorigin;
+	position.y_origin = yorigin;
+
+	if (!dc_target_set_cursor_position(
+				amdgpu_crtc->target,
+				&position)) {
+		DRM_ERROR("DC failed to set cursor position\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void dm_crtc_cursor_reset(struct drm_crtc *crtc)
+{
+	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
+	DRM_DEBUG_KMS(
+		"%s: with cursor_bo %p\n",
+		__func__,
+		amdgpu_crtc->cursor_bo);
+
+	if (amdgpu_crtc->cursor_bo && amdgpu_crtc->target) {
+		dm_set_cursor(
+		amdgpu_crtc,
+		amdgpu_crtc->cursor_addr,
+		amdgpu_crtc->cursor_width,
+		amdgpu_crtc->cursor_height);
+	}
+}
+static bool fill_rects_from_plane_state(
+	const struct drm_plane_state *state,
+	struct dc_surface *surface)
+{
+	surface->src_rect.x = state->src_x >> 16;
+	surface->src_rect.y = state->src_y >> 16;
+	/*we ignore for now mantissa and do not to deal with floating pixels :(*/
+	surface->src_rect.width = state->src_w >> 16;
+
+	if (surface->src_rect.width == 0)
+		return false;
+
+	surface->src_rect.height = state->src_h >> 16;
+	if (surface->src_rect.height == 0)
+		return false;
+
+	surface->dst_rect.x = state->crtc_x;
+	surface->dst_rect.y = state->crtc_y;
+
+	if (state->crtc_w == 0)
+		return false;
+
+	surface->dst_rect.width = state->crtc_w;
+
+	if (state->crtc_h == 0)
+		return false;
+
+	surface->dst_rect.height = state->crtc_h;
+
+	surface->clip_rect = surface->dst_rect;
+
+	switch (state->rotation) {
+	case BIT(DRM_ROTATE_0):
+		surface->rotation = ROTATION_ANGLE_0;
+		break;
+	case BIT(DRM_ROTATE_90):
+		surface->rotation = ROTATION_ANGLE_90;
+		break;
+	case BIT(DRM_ROTATE_180):
+		surface->rotation = ROTATION_ANGLE_180;
+		break;
+	case BIT(DRM_ROTATE_270):
+		surface->rotation = ROTATION_ANGLE_270;
+		break;
+	default:
+		surface->rotation = ROTATION_ANGLE_0;
+		break;
+	}
+
+	return true;
+}
+static bool get_fb_info(
+	const struct amdgpu_framebuffer *amdgpu_fb,
+	uint64_t *tiling_flags,
+	uint64_t *fb_location)
+{
+	struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->obj);
+	int r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r != 0)){
+		DRM_ERROR("Unable to reserve buffer\n");
+		return false;
+	}
+
+
+	if (fb_location)
+		*fb_location = amdgpu_bo_gpu_offset(rbo);
+
+	if (tiling_flags)
+		amdgpu_bo_get_tiling_flags(rbo, tiling_flags);
+
+	amdgpu_bo_unreserve(rbo);
+
+	return true;
+}
+static void fill_plane_attributes_from_fb(
+	struct dc_surface *surface,
+	const struct amdgpu_framebuffer *amdgpu_fb)
+{
+	uint64_t tiling_flags;
+	uint64_t fb_location;
+	const struct drm_framebuffer *fb = &amdgpu_fb->base;
+
+	get_fb_info(
+		amdgpu_fb,
+		&tiling_flags,
+		&fb_location);
+
+	surface->address.type                = PLN_ADDR_TYPE_GRAPHICS;
+	surface->address.grph.addr.low_part  = lower_32_bits(fb_location);
+	surface->address.grph.addr.high_part = upper_32_bits(fb_location);
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_C8:
+		surface->format = SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS;
+		break;
+	case DRM_FORMAT_RGB565:
+		surface->format = SURFACE_PIXEL_FORMAT_GRPH_RGB565;
+		break;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+		surface->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888;
+		break;
+	default:
+		DRM_ERROR("Unsupported screen depth %d\n", fb->bits_per_pixel);
+		return;
+	}
+
+	memset(&surface->tiling_info, 0, sizeof(surface->tiling_info));
+
+	if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1)
+	{
+		unsigned bankw, bankh, mtaspect, tile_split, num_banks;
+
+		bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
+		bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
+		mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
+		tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
+		num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
+
+
+		/* XXX fix me for VI */
+		surface->tiling_info.num_banks = num_banks;
+		surface->tiling_info.array_mode =
+				DC_ARRAY_2D_TILED_THIN1;
+		surface->tiling_info.tile_split = tile_split;
+		surface->tiling_info.bank_width = bankw;
+		surface->tiling_info.bank_height = bankh;
+		surface->tiling_info.tile_aspect = mtaspect;
+		surface->tiling_info.tile_mode =
+				DC_ADDR_SURF_MICRO_TILING_DISPLAY;
+	} else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE)
+			== DC_ARRAY_1D_TILED_THIN1) {
+		surface->tiling_info.array_mode = DC_ARRAY_1D_TILED_THIN1;
+	}
+
+	surface->tiling_info.pipe_config =
+			AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
+
+	surface->plane_size.grph.surface_size.x = 0;
+	surface->plane_size.grph.surface_size.y = 0;
+	surface->plane_size.grph.surface_size.width = fb->width;
+	surface->plane_size.grph.surface_size.height = fb->height;
+	surface->plane_size.grph.surface_pitch =
+		fb->pitches[0] / (fb->bits_per_pixel / 8);
+
+	surface->visible = true;
+	surface->scaling_quality.h_taps_c = 2;
+	surface->scaling_quality.v_taps_c = 2;
+
+	/* TODO: unhardcode */
+	surface->colorimetry.limited_range = false;
+	surface->colorimetry.color_space = SURFACE_COLOR_SPACE_SRGB;
+	surface->scaling_quality.h_taps = 2;
+	surface->scaling_quality.v_taps = 2;
+	surface->stereo_format = PLANE_STEREO_FORMAT_NONE;
+
+}
+
+#define NUM_OF_RAW_GAMMA_RAMP_RGB_256 256
+
+static void fill_gamma_from_crtc(
+	const struct drm_crtc *crtc,
+	struct dc_surface *dc_surface)
+{
+	int i;
+	struct gamma_ramp *gamma;
+	uint16_t *red, *green, *blue;
+	int end = (crtc->gamma_size > NUM_OF_RAW_GAMMA_RAMP_RGB_256) ?
+			NUM_OF_RAW_GAMMA_RAMP_RGB_256 : crtc->gamma_size;
+
+	red = crtc->gamma_store;
+	green = red + crtc->gamma_size;
+	blue = green + crtc->gamma_size;
+
+	gamma = &dc_surface->gamma_correction;
+
+	for (i = 0; i < end; i++) {
+		gamma->gamma_ramp_rgb256x3x16.red[i] =
+				(unsigned short) red[i];
+		gamma->gamma_ramp_rgb256x3x16.green[i] =
+				(unsigned short) green[i];
+		gamma->gamma_ramp_rgb256x3x16.blue[i] =
+				(unsigned short) blue[i];
+	}
+
+	gamma->type = GAMMA_RAMP_RBG256X3X16;
+	gamma->size = sizeof(gamma->gamma_ramp_rgb256x3x16);
+}
+
+static void fill_plane_attributes(
+			struct dc_surface *surface,
+			struct drm_plane_state *state)
+{
+	const struct amdgpu_framebuffer *amdgpu_fb =
+		to_amdgpu_framebuffer(state->fb);
+	const struct drm_crtc *crtc = state->crtc;
+
+	fill_rects_from_plane_state(state, surface);
+	fill_plane_attributes_from_fb(
+		surface,
+		amdgpu_fb);
+
+	/* In case of gamma set, update gamma value */
+	if (crtc->mode.private_flags &
+		AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET) {
+		fill_gamma_from_crtc(crtc, surface);
+	}
+}
+
+/*****************************************************************************/
+
+struct amdgpu_connector *aconnector_from_drm_crtc_id(
+		const struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+	struct amdgpu_connector *aconnector;
+
+	list_for_each_entry(connector,
+			&dev->mode_config.connector_list, head)	{
+
+		aconnector = to_amdgpu_connector(connector);
+
+		if (aconnector->base.state->crtc != &acrtc->base)
+			continue;
+
+		/* Found the connector */
+		return aconnector;
+	}
+
+	/* If we get here, not found. */
+	return NULL;
+}
+
+static void calculate_stream_scaling_settings(
+		const struct drm_display_mode *mode,
+		const struct dc_stream *stream,
+		struct dm_connector_state *dm_state)
+{
+	enum amdgpu_rmx_type rmx_type;
+
+	struct rect src = { 0 }; /* viewport in target space*/
+	struct rect dst = { 0 }; /* stream addressable area */
+
+	/* Full screen scaling by default */
+	src.width = mode->hdisplay;
+	src.height = mode->vdisplay;
+	dst.width = stream->timing.h_addressable;
+	dst.height = stream->timing.v_addressable;
+
+	rmx_type = dm_state->scaling;
+	if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) {
+		if (src.width * dst.height <
+				src.height * dst.width) {
+			/* height needs less upscaling/more downscaling */
+			dst.width = src.width *
+					dst.height / src.height;
+		} else {
+			/* width needs less upscaling/more downscaling */
+			dst.height = src.height *
+					dst.width / src.width;
+		}
+	} else if (rmx_type == RMX_CENTER) {
+		dst = src;
+	}
+
+	dst.x = (stream->timing.h_addressable - dst.width) / 2;
+	dst.y = (stream->timing.v_addressable - dst.height) / 2;
+
+	if (dm_state->underscan_enable) {
+		dst.x += dm_state->underscan_hborder / 2;
+		dst.y += dm_state->underscan_vborder / 2;
+		dst.width -= dm_state->underscan_hborder;
+		dst.height -= dm_state->underscan_vborder;
+	}
+
+	dc_update_stream(stream, &src, &dst);
+
+	DRM_DEBUG_KMS("Destination Rectangle x:%d  y:%d  width:%d  height:%d\n",
+			dst.x, dst.y, dst.width, dst.height);
+
+}
+
+static void dm_dc_surface_commit(
+		struct dc *dc,
+		struct drm_crtc *crtc,
+		struct dm_connector_state *dm_state)
+{
+	struct dc_surface *dc_surface;
+	const struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+	struct dc_target *dc_target = acrtc->target;
+
+	if (!dc_target) {
+		dm_error(
+			"%s: Failed to obtain target on crtc (%d)!\n",
+			__func__,
+			acrtc->crtc_id);
+		goto fail;
+	}
+
+	dc_surface = dc_create_surface(dc);
+
+	if (!dc_surface) {
+		dm_error(
+			"%s: Failed to create a surface!\n",
+			__func__);
+		goto fail;
+	}
+
+	calculate_stream_scaling_settings(&crtc->state->mode,
+			dc_target->streams[0],
+			dm_state);
+
+	/* Surface programming */
+	fill_plane_attributes(dc_surface, crtc->primary->state);
+	if (crtc->mode.private_flags &
+		AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET) {
+		/* reset trigger of gamma */
+		crtc->mode.private_flags &=
+			~AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET;
+	}
+
+	if (false == dc_commit_surfaces_to_target(
+			dc,
+			&dc_surface,
+			1,
+			dc_target)) {
+		dm_error(
+			"%s: Failed to attach surface!\n",
+			__func__);
+	}
+
+	dc_surface_release(dc_surface);
+fail:
+	return;
+}
+
+static enum dc_color_depth convert_color_depth_from_display_info(
+		const struct drm_connector *connector)
+{
+	uint32_t bpc = connector->display_info.bpc;
+
+	/* Limited color depth to 8bit
+	 * TODO: Still need to handle deep color*/
+	if (bpc > 8)
+		bpc = 8;
+
+	switch (bpc) {
+	case 0:
+		/* Temporary Work around, DRM don't parse color depth for
+		 * EDID revision before 1.4
+		 * TODO: Fix edid parsing
+		 */
+		return COLOR_DEPTH_888;
+	case 6:
+		return COLOR_DEPTH_666;
+	case 8:
+		return COLOR_DEPTH_888;
+	case 10:
+		return COLOR_DEPTH_101010;
+	case 12:
+		return COLOR_DEPTH_121212;
+	case 14:
+		return COLOR_DEPTH_141414;
+	case 16:
+		return COLOR_DEPTH_161616;
+	default:
+		return COLOR_DEPTH_UNDEFINED;
+	}
+}
+
+static enum dc_aspect_ratio get_aspect_ratio(
+		const struct drm_display_mode *mode_in)
+{
+	int32_t width = mode_in->crtc_hdisplay * 9;
+	int32_t height = mode_in->crtc_vdisplay * 16;
+	if ((width - height) < 10 && (width - height) > -10)
+		return ASPECT_RATIO_16_9;
+	else
+		return ASPECT_RATIO_4_3;
+}
+
+/*****************************************************************************/
+
+static void dc_timing_from_drm_display_mode(
+	struct dc_crtc_timing *timing_out,
+	const struct drm_display_mode *mode_in,
+	const struct drm_connector *connector)
+{
+	memset(timing_out, 0, sizeof(struct dc_crtc_timing));
+
+	timing_out->h_border_left = 0;
+	timing_out->h_border_right = 0;
+	timing_out->v_border_top = 0;
+	timing_out->v_border_bottom = 0;
+	/* TODO: un-hardcode */
+	timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
+	timing_out->timing_standard = TIMING_STANDARD_HDMI;
+	timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
+	timing_out->display_color_depth = convert_color_depth_from_display_info(
+			connector);
+	timing_out->scan_type = SCANNING_TYPE_NODATA;
+	timing_out->hdmi_vic = 0;
+	timing_out->vic = drm_match_cea_mode(mode_in);
+
+	timing_out->h_addressable = mode_in->crtc_hdisplay;
+	timing_out->h_total = mode_in->crtc_htotal;
+	timing_out->h_sync_width =
+		mode_in->crtc_hsync_end - mode_in->crtc_hsync_start;
+	timing_out->h_front_porch =
+		mode_in->crtc_hsync_start - mode_in->crtc_hdisplay;
+	timing_out->v_total = mode_in->crtc_vtotal;
+	timing_out->v_addressable = mode_in->crtc_vdisplay;
+	timing_out->v_front_porch =
+		mode_in->crtc_vsync_start - mode_in->crtc_vdisplay;
+	timing_out->v_sync_width =
+		mode_in->crtc_vsync_end - mode_in->crtc_vsync_start;
+	timing_out->pix_clk_khz = mode_in->crtc_clock;
+	timing_out->aspect_ratio = get_aspect_ratio(mode_in);
+}
+
+static void fill_audio_info(
+	struct audio_info *audio_info,
+	const struct drm_connector *drm_connector,
+	const struct dc_sink *dc_sink)
+{
+	int i = 0;
+	int cea_revision = 0;
+	const struct dc_edid_caps *edid_caps = &dc_sink->edid_caps;
+
+	audio_info->manufacture_id = edid_caps->manufacturer_id;
+	audio_info->product_id = edid_caps->product_id;
+
+	cea_revision = drm_connector->display_info.cea_rev;
+
+	while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS &&
+		edid_caps->display_name[i]) {
+		audio_info->display_name[i] = edid_caps->display_name[i];
+		i++;
+	}
+
+	if(cea_revision >= 3) {
+		audio_info->mode_count = edid_caps->audio_mode_count;
+
+		for (i = 0; i < audio_info->mode_count; ++i) {
+			audio_info->modes[i].format_code =
+					(enum audio_format_code)
+					(edid_caps->audio_modes[i].format_code);
+			audio_info->modes[i].channel_count =
+					edid_caps->audio_modes[i].channel_count;
+			audio_info->modes[i].sample_rates.all =
+					edid_caps->audio_modes[i].sample_rate;
+			audio_info->modes[i].sample_size =
+					edid_caps->audio_modes[i].sample_size;
+		}
+	}
+
+	audio_info->flags.all = edid_caps->speaker_flags;
+
+	/* TODO: We only check for the progressive mode, check for interlace mode too */
+	if(drm_connector->latency_present[0]) {
+		audio_info->video_latency = drm_connector->video_latency[0];
+		audio_info->audio_latency = drm_connector->audio_latency[0];
+	}
+
+	/* TODO: For DP, video and audio latency should be calculated from DPCD caps */
+
+}
+
+/*TODO: move these defines elsewhere*/
+#define DAL_MAX_CONTROLLERS 4
+
+static void copy_crtc_timing_for_drm_display_mode(
+		const struct drm_display_mode *src_mode,
+		struct drm_display_mode *dst_mode)
+{
+	dst_mode->crtc_hdisplay = src_mode->crtc_hdisplay;
+	dst_mode->crtc_vdisplay = src_mode->crtc_vdisplay;
+	dst_mode->crtc_clock = src_mode->crtc_clock;
+	dst_mode->crtc_hblank_start = src_mode->crtc_hblank_start;
+	dst_mode->crtc_hblank_end = src_mode->crtc_hblank_end;
+	dst_mode->crtc_hsync_start=  src_mode->crtc_hsync_start;
+	dst_mode->crtc_hsync_end = src_mode->crtc_hsync_end;
+	dst_mode->crtc_htotal = src_mode->crtc_htotal;
+	dst_mode->crtc_hskew = src_mode->crtc_hskew;
+	dst_mode->crtc_vblank_start = src_mode->crtc_vblank_start;;
+	dst_mode->crtc_vblank_end = src_mode->crtc_vblank_end;;
+	dst_mode->crtc_vsync_start = src_mode->crtc_vsync_start;;
+	dst_mode->crtc_vsync_end = src_mode->crtc_vsync_end;;
+	dst_mode->crtc_vtotal = src_mode->crtc_vtotal;;
+}
+
+static void decide_crtc_timing_for_drm_display_mode(
+		struct drm_display_mode *drm_mode,
+		const struct drm_display_mode *native_mode,
+		bool scale_enabled)
+{
+	if (scale_enabled) {
+		copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode);
+	} else if (native_mode->clock == drm_mode->clock &&
+			native_mode->htotal == drm_mode->htotal &&
+			native_mode->vtotal == drm_mode->vtotal) {
+		copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode);
+	} else {
+		/* no scaling nor amdgpu inserted, no need to patch */
+	}
+}
+
+
+static struct dc_target *create_target_for_sink(
+		const struct amdgpu_connector *aconnector,
+		struct drm_display_mode *drm_mode)
+{
+	struct drm_display_mode *preferred_mode = NULL;
+	const struct drm_connector *drm_connector;
+	struct dm_connector_state *dm_state;
+	struct dc_target *target = NULL;
+	struct dc_stream *stream;
+	struct drm_display_mode mode = *drm_mode;
+	bool native_mode_found = false;
+
+	if (NULL == aconnector) {
+		DRM_ERROR("aconnector is NULL!\n");
+		goto drm_connector_null;
+	}
+
+	drm_connector = &aconnector->base;
+	dm_state = to_dm_connector_state(drm_connector->state);
+	stream = dc_create_stream_for_sink(aconnector->dc_sink);
+
+	if (NULL == stream) {
+		DRM_ERROR("Failed to create stream for sink!\n");
+		goto stream_create_fail;
+	}
+
+	list_for_each_entry(preferred_mode, &aconnector->base.modes, head) {
+		/* Search for preferred mode */
+		if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) {
+			native_mode_found = true;
+			break;
+		}
+	}
+	if (!native_mode_found)
+		preferred_mode = list_first_entry_or_null(
+				&aconnector->base.modes,
+				struct drm_display_mode,
+				head);
+	if (NULL == preferred_mode) {
+		DRM_ERROR("No preferred mode found\n");
+		goto stream_create_fail;
+	}
+
+	decide_crtc_timing_for_drm_display_mode(
+			&mode, preferred_mode,
+			dm_state->scaling != RMX_OFF);
+
+	dc_timing_from_drm_display_mode(&stream->timing,
+			&mode, &aconnector->base);
+
+	fill_audio_info(
+		&stream->audio_info,
+		drm_connector,
+		aconnector->dc_sink);
+
+	target = dc_create_target_for_streams(&stream, 1);
+	dc_stream_release(stream);
+
+	if (NULL == target) {
+		DRM_ERROR("Failed to create target with streams!\n");
+		goto target_create_fail;
+	}
+
+drm_connector_null:
+target_create_fail:
+stream_create_fail:
+	return target;
+}
+
+void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
+{
+	drm_crtc_cleanup(crtc);
+	kfree(crtc);
+}
+
+static void amdgpu_dm_atomic_crtc_gamma_set(
+		struct drm_crtc *crtc,
+		u16 *red,
+		u16 *green,
+		u16 *blue,
+		uint32_t start,
+		uint32_t size)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_property *prop = dev->mode_config.prop_crtc_id;
+
+	crtc->state->mode.private_flags |= AMDGPU_CRTC_MODE_PRIVATE_FLAGS_GAMMASET;
+
+	drm_atomic_helper_crtc_set_property(crtc, prop, 0);
+}
+
+static int dm_crtc_funcs_atomic_set_property(
+	struct drm_crtc *crtc,
+	struct drm_crtc_state *crtc_state,
+	struct drm_property *property,
+	uint64_t val)
+{
+	struct drm_plane_state *plane_state;
+
+	crtc_state->planes_changed = true;
+
+	/*
+	 * Bit of magic done here. We need to ensure
+	 * that planes get update after mode is set.
+	 * So, we need to add primary plane to state,
+	 * and this way atomic_update would be called
+	 * for it
+	 */
+	plane_state =
+		drm_atomic_get_plane_state(
+			crtc_state->state,
+			crtc->primary);
+
+	if (!plane_state)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Implemented only the options currently availible for the driver */
+static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
+	.reset = drm_atomic_helper_crtc_reset,
+	.cursor_set = dm_crtc_cursor_set,
+	.cursor_move = dm_crtc_cursor_move,
+	.destroy = amdgpu_dm_crtc_destroy,
+	.gamma_set = amdgpu_dm_atomic_crtc_gamma_set,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.atomic_set_property = dm_crtc_funcs_atomic_set_property
+};
+
+static enum drm_connector_status
+amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
+{
+	bool connected;
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+
+	/* Notes:
+	 * 1. This interface is NOT called in context of HPD irq.
+	 * 2. This interface *is called* in context of user-mode ioctl. Which
+	 * makes it a bad place for *any* MST-related activit. */
+
+	connected = (NULL != aconnector->dc_sink);
+
+	return (connected ? connector_status_connected :
+			connector_status_disconnected);
+}
+
+int amdgpu_dm_connector_atomic_set_property(
+	struct drm_connector *connector,
+	struct drm_connector_state *connector_state,
+	struct drm_property *property,
+	uint64_t val)
+{
+	struct drm_device *dev = connector->dev;
+	struct amdgpu_device *adev = dev->dev_private;
+	struct dm_connector_state *dm_old_state =
+		to_dm_connector_state(connector->state);
+	struct dm_connector_state *dm_new_state =
+		to_dm_connector_state(connector_state);
+
+	if (property == dev->mode_config.scaling_mode_property) {
+		struct drm_crtc_state *new_crtc_state;
+		struct drm_crtc *crtc;
+		int i;
+		enum amdgpu_rmx_type rmx_type;
+
+		switch (val) {
+		case DRM_MODE_SCALE_CENTER:
+			rmx_type = RMX_CENTER;
+			break;
+		case DRM_MODE_SCALE_ASPECT:
+			rmx_type = RMX_ASPECT;
+			break;
+		case DRM_MODE_SCALE_FULLSCREEN:
+			rmx_type = RMX_FULL;
+			break;
+		case DRM_MODE_SCALE_NONE:
+		default:
+			rmx_type = RMX_OFF;
+			break;
+		}
+
+		if (dm_old_state->scaling == rmx_type)
+			return 0;
+
+		dm_new_state->scaling = rmx_type;
+
+		for_each_crtc_in_state(
+			connector_state->state,
+			crtc,
+			new_crtc_state,
+			i) {
+
+			if (crtc == connector_state->crtc) {
+				struct drm_plane_state *plane_state;
+
+				new_crtc_state->mode_changed = true;
+
+				/*
+				 * Bit of magic done here. We need to ensure
+				 * that planes get update after mode is set.
+				 * So, we need to add primary plane to state,
+				 * and this way atomic_update would be called
+				 * for it
+				 */
+				plane_state =
+					drm_atomic_get_plane_state(
+						connector_state->state,
+						crtc->primary);
+
+				if (!plane_state)
+					return -EINVAL;
+			}
+		}
+
+		return 0;
+	} else if (property == adev->mode_info.underscan_hborder_property) {
+		dm_new_state->underscan_hborder = val;
+		return 0;
+	} else if (property == adev->mode_info.underscan_vborder_property) {
+		dm_new_state->underscan_vborder = val;
+		return 0;
+	} else if (property == adev->mode_info.underscan_property) {
+		struct drm_crtc_state *new_crtc_state;
+		struct drm_crtc *crtc;
+		int i;
+
+		dm_new_state->underscan_enable = val;
+
+		for_each_crtc_in_state(
+			connector_state->state,
+			crtc,
+			new_crtc_state,
+			i) {
+
+			if (crtc == connector_state->crtc) {
+				struct drm_plane_state *plane_state;
+
+				/*
+				 * Bit of magic done here. We need to ensure
+				 * that planes get update after mode is set.
+				 * So, we need to add primary plane to state,
+				 * and this way atomic_update would be called
+				 * for it
+				 */
+				plane_state =
+					drm_atomic_get_plane_state(
+						connector_state->state,
+						crtc->primary);
+
+				if (!plane_state)
+					return -EINVAL;
+			}
+		}
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+void amdgpu_dm_connector_destroy(struct drm_connector *connector)
+{
+	struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+	const struct dc_link *link = aconnector->dc_link;
+	struct amdgpu_device *adev = connector->dev->dev_private;
+	struct amdgpu_display_manager *dm = &adev->dm;
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
+	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+	if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) {
+		amdgpu_dm_register_backlight_device(dm);
+
+		if (dm->backlight_dev) {
+			backlight_device_unregister(dm->backlight_dev);
+			dm->backlight_dev = NULL;
+		}
+
+	}
+#endif
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
+{
+	struct dm_connector_state *state =
+		to_dm_connector_state(connector->state);
+
+	kfree(state);
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+
+	if (state) {
+		state->scaling = RMX_OFF;
+		state->underscan_enable = false;
+		state->underscan_hborder = 0;
+		state->underscan_vborder = 0;
+
+		connector->state = &state->base;
+		connector->state->connector = connector;
+	}
+}
+
+struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state(
+	struct drm_connector *connector)
+{
+	struct dm_connector_state *state =
+		to_dm_connector_state(connector->state);
+
+	struct dm_connector_state *new_state =
+		kzalloc(sizeof(*new_state), GFP_KERNEL);
+
+	if (new_state) {
+		*new_state = *state;
+
+		return &new_state->base;
+	}
+
+	return NULL;
+}
+
+void amdgpu_dm_connector_atomic_destroy_state(
+	struct drm_connector *connector,
+	struct drm_connector_state *state)
+{
+	struct dm_connector_state *dm_state =
+		to_dm_connector_state(state);
+
+	__drm_atomic_helper_connector_destroy_state(connector, state);
+
+	kfree(dm_state);
+}
+
+static const struct drm_connector_funcs amdgpu_dm_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = amdgpu_dm_connector_funcs_reset,
+	.detect = amdgpu_dm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = drm_atomic_helper_connector_set_property,
+	.destroy = amdgpu_dm_connector_destroy,
+	.atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
+	.atomic_destroy_state = amdgpu_dm_connector_atomic_destroy_state,
+	.atomic_set_property = amdgpu_dm_connector_atomic_set_property
+};
+
+static struct drm_encoder *best_encoder(struct drm_connector *connector)
+{
+	int enc_id = connector->encoder_ids[0];
+	struct drm_mode_object *obj;
+	struct drm_encoder *encoder;
+
+	DRM_DEBUG_KMS("Finding the best encoder\n");
+
+	/* pick the encoder ids */
+	if (enc_id) {
+		obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
+		if (!obj) {
+			DRM_ERROR("Couldn't find a matching encoder for our connector\n");
+			return NULL;
+		}
+		encoder = obj_to_encoder(obj);
+		return encoder;
+	}
+	DRM_ERROR("No encoder id\n");
+	return NULL;
+}
+
+static int get_modes(struct drm_connector *connector)
+{
+	return amdgpu_dm_connector_get_modes(connector);
+}
+
+int amdgpu_dm_connector_mode_valid(
+		struct drm_connector *connector,
+		struct drm_display_mode *mode)
+{
+	int result = MODE_ERROR;
+	const struct dc_sink *dc_sink =
+			to_amdgpu_connector(connector)->dc_sink;
+	struct amdgpu_device *adev = connector->dev->dev_private;
+	struct dc_validation_set val_set = { 0 };
+	/* TODO: Unhardcode stream count */
+	struct dc_stream *streams[1];
+	struct dc_target *target;
+
+	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+			(mode->flags & DRM_MODE_FLAG_DBLSCAN))
+		return result;
+
+	if (NULL == dc_sink) {
+		DRM_ERROR("dc_sink is NULL!\n");
+		goto stream_create_fail;
+	}
+
+	streams[0] = dc_create_stream_for_sink(dc_sink);
+
+	if (NULL == streams[0]) {
+		DRM_ERROR("Failed to create stream for sink!\n");
+		goto stream_create_fail;
+	}
+
+	drm_mode_set_crtcinfo(mode, 0);
+	dc_timing_from_drm_display_mode(&streams[0]->timing, mode, connector);
+
+	target = dc_create_target_for_streams(streams, 1);
+	val_set.target = target;
+
+	if (NULL == val_set.target) {
+		DRM_ERROR("Failed to create target with stream!\n");
+		goto target_create_fail;
+	}
+
+	val_set.surface_count = 0;
+	streams[0]->src.width = mode->hdisplay;
+	streams[0]->src.height = mode->vdisplay;
+	streams[0]->dst = streams[0]->src;
+
+	if (dc_validate_resources(adev->dm.dc, &val_set, 1))
+		result = MODE_OK;
+
+	dc_target_release(target);
+target_create_fail:
+	dc_stream_release(streams[0]);
+stream_create_fail:
+	/* TODO: error handling*/
+	return result;
+}
+
+
+static const struct drm_connector_helper_funcs
+amdgpu_dm_connector_helper_funcs = {
+	/*
+	* If hotplug a second bigger display in FB Con mode, bigger resolution
+	* modes will be filtered by drm_mode_validate_size(), and those modes
+	* is missing after user start lightdm. So we need to renew modes list.
+	* in get_modes call back, not just return the modes count
+	*/
+	.get_modes = get_modes,
+	.mode_valid = amdgpu_dm_connector_mode_valid,
+	.best_encoder = best_encoder
+};
+
+static void dm_crtc_helper_disable(struct drm_crtc *crtc)
+{
+}
+
+static int dm_crtc_helper_atomic_check(
+	struct drm_crtc *crtc,
+	struct drm_crtc_state *state)
+{
+	return 0;
+}
+
+static bool dm_crtc_helper_mode_fixup(
+	struct drm_crtc *crtc,
+	const struct drm_display_mode *mode,
+	struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = {
+	.disable = dm_crtc_helper_disable,
+	.atomic_check = dm_crtc_helper_atomic_check,
+	.mode_fixup = dm_crtc_helper_mode_fixup
+};
+
+static void dm_encoder_helper_disable(struct drm_encoder *encoder)
+{
+
+}
+
+static int dm_encoder_helper_atomic_check(
+	struct drm_encoder *encoder,
+	struct drm_crtc_state *crtc_state,
+	struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = {
+	.disable = dm_encoder_helper_disable,
+	.atomic_check = dm_encoder_helper_atomic_check
+};
+
+static const struct drm_plane_funcs dm_plane_funcs = {
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state
+};
+
+static void clear_unrelated_fields(struct drm_plane_state *state)
+{
+	state->crtc = NULL;
+	state->fb = NULL;
+	state->state = NULL;
+	state->fence = NULL;
+}
+
+static bool page_flip_needed(
+	const struct drm_plane_state *new_state,
+	const struct drm_plane_state *old_state)
+{
+	struct drm_plane_state old_state_tmp;
+	struct drm_plane_state new_state_tmp;
+
+	struct amdgpu_framebuffer *amdgpu_fb_old;
+	struct amdgpu_framebuffer *amdgpu_fb_new;
+
+	uint64_t old_tiling_flags;
+	uint64_t new_tiling_flags;
+
+	if (!old_state)
+		return false;
+
+	if (!old_state->fb)
+		return false;
+
+	if (!new_state)
+		return false;
+
+	if (!new_state->fb)
+		return false;
+
+	old_state_tmp = *old_state;
+	new_state_tmp = *new_state;
+
+	if (!new_state->crtc->state->event)
+		return false;
+
+	amdgpu_fb_old = to_amdgpu_framebuffer(old_state->fb);
+	amdgpu_fb_new = to_amdgpu_framebuffer(new_state->fb);
+
+	if (!get_fb_info(amdgpu_fb_old, &old_tiling_flags, NULL))
+		return false;
+
+	if (!get_fb_info(amdgpu_fb_new, &new_tiling_flags, NULL))
+		return false;
+
+	if (old_tiling_flags != new_tiling_flags)
+		return false;
+
+	clear_unrelated_fields(&old_state_tmp);
+	clear_unrelated_fields(&new_state_tmp);
+
+	return memcmp(&old_state_tmp, &new_state_tmp, sizeof(old_state_tmp)) == 0;
+}
+
+static int dm_plane_helper_prepare_fb(
+	struct drm_plane *plane,
+	const struct drm_plane_state *new_state)
+{
+	struct drm_framebuffer *fb = new_state->fb;
+	struct amdgpu_framebuffer *afb;
+	struct drm_gem_object *obj;
+	struct amdgpu_bo *rbo;
+	int r;
+
+	if (!fb) {
+		DRM_DEBUG_KMS("No FB bound\n");
+		return 0;
+	}
+
+	afb = to_amdgpu_framebuffer(fb);
+
+	obj = afb->obj;
+	rbo = gem_to_amdgpu_bo(obj);
+	r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r != 0))
+		return r;
+
+	r = amdgpu_bo_pin(rbo, AMDGPU_GEM_DOMAIN_VRAM, NULL);
+
+	amdgpu_bo_unreserve(rbo);
+
+	if (unlikely(r != 0)) {
+		DRM_ERROR("Failed to pin framebuffer\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static void dm_plane_helper_cleanup_fb(
+	struct drm_plane *plane,
+	const struct drm_plane_state *old_state)
+{
+	struct drm_framebuffer *fb = old_state->fb;
+	struct amdgpu_bo *rbo;
+	struct amdgpu_framebuffer *afb;
+	int r;
+
+	if (!fb)
+		return;
+
+	afb = to_amdgpu_framebuffer(fb);
+	rbo = gem_to_amdgpu_bo(afb->obj);
+	r = amdgpu_bo_reserve(rbo, false);
+	if (unlikely(r)) {
+		DRM_ERROR("failed to reserve rbo before unpin\n");
+		return;
+	} else {
+		amdgpu_bo_unpin(rbo);
+		amdgpu_bo_unreserve(rbo);
+	}
+}
+
+int dm_create_validation_set_for_target(struct drm_connector *connector,
+		struct drm_display_mode *mode, struct dc_validation_set *val_set)
+{
+	int result = MODE_ERROR;
+	const struct dc_sink *dc_sink =
+			to_amdgpu_connector(connector)->dc_sink;
+	/* TODO: Unhardcode stream count */
+	struct dc_stream *streams[1];
+	struct dc_target *target;
+
+	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+			(mode->flags & DRM_MODE_FLAG_DBLSCAN))
+		return result;
+
+	if (NULL == dc_sink) {
+		DRM_ERROR("dc_sink is NULL!\n");
+		return result;
+	}
+
+	streams[0] = dc_create_stream_for_sink(dc_sink);
+
+	if (NULL == streams[0]) {
+		DRM_ERROR("Failed to create stream for sink!\n");
+		return result;
+	}
+
+	drm_mode_set_crtcinfo(mode, 0);
+	dc_timing_from_drm_display_mode(&streams[0]->timing, mode, connector);
+
+	target = dc_create_target_for_streams(streams, 1);
+	val_set->target = target;
+
+	if (NULL == val_set->target) {
+		DRM_ERROR("Failed to create target with stream!\n");
+		goto fail;
+	}
+
+	streams[0]->src.width = mode->hdisplay;
+	streams[0]->src.height = mode->vdisplay;
+	streams[0]->dst = streams[0]->src;
+
+	return MODE_OK;
+
+fail:
+	dc_stream_release(streams[0]);
+	return result;
+
+}
+
+static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
+	.prepare_fb = dm_plane_helper_prepare_fb,
+	.cleanup_fb = dm_plane_helper_cleanup_fb,
+};
+
+/*
+ * TODO: these are currently initialized to rgb formats only.
+ * For future use cases we should either initialize them dynamically based on
+ * plane capabilities, or initialize this array to all formats, so internal drm
+ * check will succeed, and let DC to implement proper check
+ */
+static uint32_t rgb_formats[] = {
+	DRM_FORMAT_XRGB4444,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_RGBA4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_RGBA8888,
+};
+
+int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
+			struct amdgpu_crtc *acrtc,
+			uint32_t crtc_index)
+{
+	int res = -ENOMEM;
+
+	struct drm_plane *primary_plane =
+		kzalloc(sizeof(*primary_plane), GFP_KERNEL);
+
+	if (!primary_plane)
+		goto fail_plane;
+
+	primary_plane->format_default = true;
+
+	res = drm_universal_plane_init(
+		dm->adev->ddev,
+		primary_plane,
+		0,
+		&dm_plane_funcs,
+		rgb_formats,
+		ARRAY_SIZE(rgb_formats),
+		DRM_PLANE_TYPE_PRIMARY,
+		NULL);
+
+	primary_plane->crtc = &acrtc->base;
+
+	drm_plane_helper_add(primary_plane, &dm_plane_helper_funcs);
+
+	res = drm_crtc_init_with_planes(
+			dm->ddev,
+			&acrtc->base,
+			primary_plane,
+			NULL,
+			&amdgpu_dm_crtc_funcs,
+			NULL);
+
+	if (res)
+		goto fail;
+
+	drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs);
+
+	acrtc->max_cursor_width = 128;
+	acrtc->max_cursor_height = 128;
+
+	acrtc->crtc_id = crtc_index;
+	acrtc->base.enabled = false;
+
+	dm->adev->mode_info.crtcs[crtc_index] = acrtc;
+	drm_mode_crtc_set_gamma_size(&acrtc->base, 256);
+
+	return 0;
+fail:
+	kfree(primary_plane);
+fail_plane:
+	acrtc->crtc_id = -1;
+	return res;
+}
+
+static int to_drm_connector_type(enum signal_type st)
+{
+	switch (st) {
+	case SIGNAL_TYPE_HDMI_TYPE_A:
+		return DRM_MODE_CONNECTOR_HDMIA;
+	case SIGNAL_TYPE_EDP:
+		return DRM_MODE_CONNECTOR_eDP;
+	case SIGNAL_TYPE_RGB:
+		return DRM_MODE_CONNECTOR_VGA;
+	case SIGNAL_TYPE_DISPLAY_PORT:
+	case SIGNAL_TYPE_DISPLAY_PORT_MST:
+		return DRM_MODE_CONNECTOR_DisplayPort;
+	case SIGNAL_TYPE_DVI_DUAL_LINK:
+	case SIGNAL_TYPE_DVI_SINGLE_LINK:
+		return DRM_MODE_CONNECTOR_DVID;
+	case SIGNAL_TYPE_VIRTUAL:
+		return DRM_MODE_CONNECTOR_VIRTUAL;
+
+	default:
+		return DRM_MODE_CONNECTOR_Unknown;
+	}
+}
+
+static void amdgpu_dm_get_native_mode(struct drm_connector *connector)
+{
+	const struct drm_connector_helper_funcs *helper =
+		connector->helper_private;
+	struct drm_encoder *encoder;
+	struct amdgpu_encoder *amdgpu_encoder;
+
+	encoder = helper->best_encoder(connector);
+
+	if (encoder == NULL)
+		return;
+
+	amdgpu_encoder = to_amdgpu_encoder(encoder);
+
+	amdgpu_encoder->native_mode.clock = 0;
+
+	if (!list_empty(&connector->probed_modes)) {
+		struct drm_display_mode *preferred_mode = NULL;
+		list_for_each_entry(preferred_mode,
+				&connector->probed_modes,
+				head) {
+		if (preferred_mode->type & DRM_MODE_TYPE_PREFERRED) {
+			amdgpu_encoder->native_mode = *preferred_mode;
+		}
+			break;
+		}
+
+	}
+}
+
+static struct drm_display_mode *amdgpu_dm_create_common_mode(
+		struct drm_encoder *encoder, char *name,
+		int hdisplay, int vdisplay)
+{
+	struct drm_device *dev = encoder->dev;
+	struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
+	struct drm_display_mode *mode = NULL;
+	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
+
+	mode = drm_mode_duplicate(dev, native_mode);
+
+	if(mode == NULL)
+		return NULL;
+
+	mode->hdisplay = hdisplay;
+	mode->vdisplay = vdisplay;
+	mode->type &= ~DRM_MODE_TYPE_PREFERRED;
+	strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN);
+
+	return mode;
+
+}
+
+static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
+					struct drm_connector *connector)
+{
+	struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
+	struct drm_display_mode *mode = NULL;
+	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
+	struct amdgpu_connector *amdgpu_connector =
+				to_amdgpu_connector(connector);
+	int i;
+	int n;
+	struct mode_size {
+		char name[DRM_DISPLAY_MODE_LEN];
+		int w;
+		int h;
+	}common_modes[] = {
+		{  "640x480",  640,  480},
+		{  "800x600",  800,  600},
+		{ "1024x768", 1024,  768},
+		{ "1280x720", 1280,  720},
+		{ "1280x800", 1280,  800},
+		{"1280x1024", 1280, 1024},
+		{ "1440x900", 1440,  900},
+		{"1680x1050", 1680, 1050},
+		{"1600x1200", 1600, 1200},
+		{"1920x1080", 1920, 1080},
+		{"1920x1200", 1920, 1200}
+	};
+
+	n = sizeof(common_modes) / sizeof(common_modes[0]);
+
+	for (i = 0; i < n; i++) {
+		struct drm_display_mode *curmode = NULL;
+		bool mode_existed = false;
+
+		if (common_modes[i].w > native_mode->hdisplay ||
+			common_modes[i].h > native_mode->vdisplay ||
+			(common_modes[i].w == native_mode->hdisplay &&
+			common_modes[i].h == native_mode->vdisplay))
+				continue;
+
+		list_for_each_entry(curmode, &connector->probed_modes, head) {
+			if (common_modes[i].w == curmode->hdisplay &&
+				common_modes[i].h == curmode->vdisplay) {
+				mode_existed = true;
+				break;
+			}
+		}
+
+		if (mode_existed)
+			continue;
+
+		mode = amdgpu_dm_create_common_mode(encoder,
+				common_modes[i].name, common_modes[i].w,
+				common_modes[i].h);
+		drm_mode_probed_add(connector, mode);
+		amdgpu_connector->num_modes++;
+	}
+}
+
+static void amdgpu_dm_connector_ddc_get_modes(
+	struct drm_connector *connector,
+	struct edid *edid)
+{
+	struct amdgpu_connector *amdgpu_connector =
+			to_amdgpu_connector(connector);
+
+	if (edid) {
+		/* empty probed_modes */
+		INIT_LIST_HEAD(&connector->probed_modes);
+		amdgpu_connector->num_modes =
+				drm_add_edid_modes(connector, edid);
+
+		drm_edid_to_eld(connector, edid);
+
+		amdgpu_dm_get_native_mode(connector);
+	} else
+		amdgpu_connector->num_modes = 0;
+}
+
+int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
+{
+	const struct drm_connector_helper_funcs *helper =
+			connector->helper_private;
+	struct amdgpu_connector *amdgpu_connector =
+			to_amdgpu_connector(connector);
+	struct drm_encoder *encoder;
+	struct edid *edid = amdgpu_connector->edid;
+
+	encoder = helper->best_encoder(connector);
+
+	amdgpu_dm_connector_ddc_get_modes(connector, edid);
+	amdgpu_dm_connector_add_common_modes(encoder, connector);
+	return amdgpu_connector->num_modes;
+}
+
+void amdgpu_dm_connector_init_helper(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector,
+	int connector_type,
+	const struct dc_link *link,
+	int link_index)
+{
+	struct amdgpu_device *adev = dm->ddev->dev_private;
+
+	aconnector->connector_id = link_index;
+	aconnector->dc_link = link;
+	aconnector->base.interlace_allowed = true;
+	aconnector->base.doublescan_allowed = true;
+	aconnector->base.dpms = DRM_MODE_DPMS_OFF;
+	aconnector->hpd.hpd = AMDGPU_HPD_NONE; /* not used */
+
+	/*configure suport HPD hot plug connector_>polled default value is 0
+	 * which means HPD hot plug not supported*/
+	switch (connector_type) {
+	case DRM_MODE_CONNECTOR_HDMIA:
+		aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	case DRM_MODE_CONNECTOR_DisplayPort:
+		aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	case DRM_MODE_CONNECTOR_DVID:
+		aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
+		break;
+	default:
+		break;
+	}
+
+	drm_object_attach_property(&aconnector->base.base,
+				dm->ddev->mode_config.scaling_mode_property,
+				DRM_MODE_SCALE_NONE);
+
+	drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.underscan_property,
+				UNDERSCAN_OFF);
+	drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.underscan_hborder_property,
+				0);
+	drm_object_attach_property(&aconnector->base.base,
+				adev->mode_info.underscan_vborder_property,
+				0);
+}
+
+int amdgpu_dm_i2c_xfer(struct i2c_adapter *i2c_adap,
+		      struct i2c_msg *msgs, int num)
+{
+	struct amdgpu_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
+	struct i2c_command cmd;
+	int i;
+	int result = -EIO;
+
+	cmd.payloads = kzalloc(num * sizeof(struct i2c_payload), GFP_KERNEL);
+
+	if (!cmd.payloads)
+		return result;
+
+	cmd.number_of_payloads = num;
+	cmd.engine = I2C_COMMAND_ENGINE_DEFAULT;
+	cmd.speed = 100;
+
+	for (i = 0; i < num; i++) {
+		cmd.payloads[i].write = (msgs[i].flags & I2C_M_RD);
+		cmd.payloads[i].address = msgs[i].addr;
+		cmd.payloads[i].length = msgs[i].len;
+		cmd.payloads[i].data = msgs[i].buf;
+	}
+
+	if (dc_submit_i2c(i2c->dm->dc, i2c->link_index, &cmd))
+		result = num;
+
+	kfree(cmd.payloads);
+
+	return result;
+}
+
+u32 amdgpu_dm_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm amdgpu_dm_i2c_algo = {
+	.master_xfer = amdgpu_dm_i2c_xfer,
+	.functionality = amdgpu_dm_i2c_func,
+};
+
+struct amdgpu_i2c_adapter *create_i2c(unsigned int link_index, struct amdgpu_display_manager *dm, int *res)
+{
+	struct amdgpu_i2c_adapter *i2c;
+
+	i2c = kzalloc(sizeof (struct amdgpu_i2c_adapter), GFP_KERNEL);
+	i2c->dm = dm;
+	i2c->base.owner = THIS_MODULE;
+	i2c->base.class = I2C_CLASS_DDC;
+	i2c->base.dev.parent = &dm->adev->pdev->dev;
+	i2c->base.algo = &amdgpu_dm_i2c_algo;
+	snprintf(i2c->base.name, sizeof (i2c->base.name), "AMDGPU DM i2c hw bus %d", link_index);
+	i2c->link_index = link_index;
+	i2c_set_adapdata(&i2c->base, i2c);
+
+	return i2c;
+}
+
+/* Note: this function assumes that dc_link_detect() was called for the
+ * dc_link which will be represented by this aconnector. */
+int amdgpu_dm_connector_init(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector,
+	uint32_t link_index,
+	struct amdgpu_encoder *aencoder)
+{
+	int res = 0;
+	int connector_type;
+	struct dc *dc = dm->dc;
+	const struct dc_link *link = dc_get_link_at_index(dc, link_index);
+	struct amdgpu_i2c_adapter *i2c;
+
+	DRM_DEBUG_KMS("%s()\n", __func__);
+
+	i2c = create_i2c(link->link_index, dm, &res);
+	aconnector->i2c = i2c;
+	res = i2c_add_adapter(&i2c->base);
+
+	if (res) {
+		DRM_ERROR("Failed to register hw i2c %d\n", link->link_index);
+		goto out_free;
+	}
+
+	connector_type = to_drm_connector_type(link->connector_signal);
+
+	res = drm_connector_init(
+			dm->ddev,
+			&aconnector->base,
+			&amdgpu_dm_connector_funcs,
+			connector_type);
+
+	if (res) {
+		DRM_ERROR("connector_init failed\n");
+		aconnector->connector_id = -1;
+		goto out_free;
+	}
+
+	drm_connector_helper_add(
+			&aconnector->base,
+			&amdgpu_dm_connector_helper_funcs);
+
+	amdgpu_dm_connector_init_helper(
+		dm,
+		aconnector,
+		connector_type,
+		link,
+		link_index);
+
+	drm_mode_connector_attach_encoder(
+		&aconnector->base, &aencoder->base);
+
+	drm_connector_register(&aconnector->base);
+
+	if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
+		|| connector_type == DRM_MODE_CONNECTOR_eDP)
+		amdgpu_dm_initialize_mst_connector(dm, aconnector);
+
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
+	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+	/* NOTE: this currently will create backlight device even if a panel
+	 * is not connected to the eDP/LVDS connector.
+	 *
+	 * This is less than ideal but we don't have sink information at this
+	 * stage since detection happens after. We can't do detection earlier
+	 * since MST detection needs connectors to be created first.
+	 */
+	if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) {
+		/* Event if registration failed, we should continue with
+		 * DM initialization because not having a backlight control
+		 * is better then a black screen. */
+		amdgpu_dm_register_backlight_device(dm);
+
+		if (dm->backlight_dev)
+			dm->backlight_link = link;
+	}
+#endif
+
+out_free:
+	if (res) {
+		kfree(i2c);
+		aconnector->i2c = NULL;
+	}
+	return res;
+}
+
+int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev)
+{
+	switch (adev->mode_info.num_crtc) {
+	case 1:
+		return 0x1;
+	case 2:
+		return 0x3;
+	case 3:
+		return 0x7;
+	case 4:
+		return 0xf;
+	case 5:
+		return 0x1f;
+	case 6:
+	default:
+		return 0x3f;
+	}
+}
+
+int amdgpu_dm_encoder_init(
+	struct drm_device *dev,
+	struct amdgpu_encoder *aencoder,
+	uint32_t link_index)
+{
+	struct amdgpu_device *adev = dev->dev_private;
+
+	int res = drm_encoder_init(dev,
+				   &aencoder->base,
+				   &amdgpu_dm_encoder_funcs,
+				   DRM_MODE_ENCODER_TMDS,
+				   NULL);
+
+	aencoder->base.possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
+
+	if (!res)
+		aencoder->encoder_id = link_index;
+	else
+		aencoder->encoder_id = -1;
+
+	drm_encoder_helper_add(&aencoder->base, &amdgpu_dm_encoder_helper_funcs);
+
+	return res;
+}
+
+enum dm_commit_action {
+	DM_COMMIT_ACTION_NOTHING,
+	DM_COMMIT_ACTION_RESET,
+	DM_COMMIT_ACTION_DPMS_ON,
+	DM_COMMIT_ACTION_DPMS_OFF,
+	DM_COMMIT_ACTION_SET
+};
+
+static enum dm_commit_action get_dm_commit_action(struct drm_crtc_state *state)
+{
+	/* mode changed means either actually mode changed or enabled changed */
+	/* active changed means dpms changed */
+	if (state->mode_changed) {
+		/* if it is got disabled - call reset mode */
+		if (!state->enable)
+			return DM_COMMIT_ACTION_RESET;
+
+		if (state->active)
+			return DM_COMMIT_ACTION_SET;
+		else
+			return DM_COMMIT_ACTION_RESET;
+	} else {
+		/* ! mode_changed */
+
+		/* if it is remain disable - skip it */
+		if (!state->enable)
+			return DM_COMMIT_ACTION_NOTHING;
+
+		if (state->active_changed) {
+			if (state->active) {
+				return DM_COMMIT_ACTION_DPMS_ON;
+			} else {
+				return DM_COMMIT_ACTION_DPMS_OFF;
+			}
+		} else {
+			/* ! active_changed */
+			return DM_COMMIT_ACTION_NOTHING;
+		}
+	}
+}
+
+static void manage_dm_interrupts(
+	struct amdgpu_device *adev,
+	struct amdgpu_crtc *acrtc,
+	bool enable)
+{
+	/*
+	 * this is not correct translation but will work as soon as VBLANK
+	 * constant is the same as PFLIP
+	 */
+	int irq_type =
+		amdgpu_crtc_idx_to_irq_type(
+			adev,
+			acrtc->crtc_id);
+
+	if (enable) {
+		drm_crtc_vblank_on(&acrtc->base);
+		amdgpu_irq_get(
+			adev,
+			&adev->pageflip_irq,
+			irq_type);
+	} else {
+		unsigned long flags;
+		amdgpu_irq_put(
+			adev,
+			&adev->pageflip_irq,
+			irq_type);
+		drm_crtc_vblank_off(&acrtc->base);
+
+		/*
+		 * should be called here, to guarantee no works left in queue.
+		 * As this function sleeps it was bug to call it inside the
+		 * amdgpu_dm_flip_cleanup function under locked event_lock
+		 */
+		if (acrtc->pflip_works) {
+			flush_work(&acrtc->pflip_works->flip_work);
+			flush_work(&acrtc->pflip_works->unpin_work);
+		}
+
+		/*
+		 * TODO: once Vitaly's change to adjust locking in
+		 * page_flip_work_func is submitted to base driver move
+		 * lock and check to amdgpu_dm_flip_cleanup function
+		 */
+
+		spin_lock_irqsave(&adev->ddev->event_lock, flags);
+		if (acrtc->pflip_status != AMDGPU_FLIP_NONE) {
+			/*
+			 * this is the case when on reset, last pending pflip
+			 * interrupt did not not occur. Clean-up
+			 */
+			amdgpu_dm_flip_cleanup(adev, acrtc);
+		}
+		spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+	}
+}
+
+/*
+ * Handle headless hotplug workaround
+ *
+ * In case of headless hotplug, if plugging the same monitor to the same
+ * DDI, DRM consider it as mode unchanged. We should check whether the
+ * sink pointer changed, and set mode_changed properly to
+ * make sure commit is doing everything.
+ */
+static void handle_headless_hotplug(
+		const struct amdgpu_crtc *acrtc,
+		struct drm_crtc_state *state,
+		struct amdgpu_connector **aconnector)
+{
+	struct amdgpu_connector *old_connector =
+			aconnector_from_drm_crtc_id(&acrtc->base);
+
+	/*
+	 * TODO Revisit this. This code is kinda hacky and might break things.
+	 */
+
+	if (!old_connector)
+		return;
+
+	if (!*aconnector)
+		*aconnector = old_connector;
+
+	if (acrtc->target && (*aconnector)->dc_sink) {
+		if ((*aconnector)->dc_sink !=
+				acrtc->target->streams[0]->sink) {
+			state->mode_changed = true;
+		}
+	}
+
+	if (!acrtc->target) {
+		/* In case of headless with DPMS on, when system waked up,
+		 * if no monitor connected, target is null and will not create
+		 * new target, on that condition, we should check
+		 * if any connector is connected, if connected,
+		 * it means a hot plug happened after wake up,
+		 * mode_changed should be set to true to make sure
+		 * commit targets will do everything.
+		 */
+		state->mode_changed =
+			(*aconnector)->base.status ==
+					connector_status_connected;
+	} else {
+		/* In case of headless hotplug, if plug same monitor to same
+		 * DDI, DRM consider it as mode unchanged, we should check
+		 * sink pointer changed, and set mode changed properly to
+		 * make sure commit doing everything.
+		 */
+		/* check if sink has changed from last commit */
+		if ((*aconnector)->dc_sink && (*aconnector)->dc_sink !=
+					acrtc->target->streams[0]->sink)
+			state->mode_changed = true;
+	}
+}
+
+int amdgpu_dm_atomic_commit(
+	struct drm_device *dev,
+	struct drm_atomic_state *state,
+	bool async)
+{
+	struct amdgpu_device *adev = dev->dev_private;
+	struct amdgpu_display_manager *dm = &adev->dm;
+	struct drm_plane *plane;
+	struct drm_plane_state *old_plane_state;
+	uint32_t i, j;
+	int32_t ret;
+	uint32_t commit_targets_count = 0;
+	uint32_t new_crtcs_count = 0;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *old_crtc_state;
+
+	struct dc_target *commit_targets[DAL_MAX_CONTROLLERS];
+	struct amdgpu_crtc *new_crtcs[DAL_MAX_CONTROLLERS];
+
+	/* In this step all new fb would be pinned */
+
+	ret = drm_atomic_helper_prepare_planes(dev, state);
+	if (ret)
+		return ret;
+
+	/*
+	 * This is the point of no return - everything below never fails except
+	 * when the hw goes bonghits. Which means we can commit the new state on
+	 * the software side now.
+	 */
+
+	drm_atomic_helper_swap_state(dev, state);
+
+	/*
+	 * From this point state become old state really. New state is
+	 * initialized to appropriate objects and could be accessed from there
+	 */
+
+	/*
+	 * there is no fences usage yet in state. We can skip the following line
+	 * wait_for_fences(dev, state);
+	 */
+
+	drm_atomic_helper_update_legacy_modeset_state(dev, state);
+
+	/* update changed items */
+	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+		struct amdgpu_crtc *acrtc;
+		struct amdgpu_connector *aconnector = NULL;
+		enum dm_commit_action action;
+		struct drm_crtc_state *new_state = crtc->state;
+		struct drm_connector *connector;
+		struct drm_connector_state *old_con_state;
+
+		acrtc = to_amdgpu_crtc(crtc);
+
+		for_each_connector_in_state(
+			state,
+			connector,
+			old_con_state,
+			j) {
+			if (connector->state->crtc == crtc) {
+				aconnector = to_amdgpu_connector(connector);
+				break;
+			}
+		}
+
+		/* handles headless hotplug case, updating new_state and
+		 * aconnector as needed
+		 */
+		handle_headless_hotplug(acrtc, new_state, &aconnector);
+
+		action = get_dm_commit_action(new_state);
+
+		switch (action) {
+		case DM_COMMIT_ACTION_DPMS_ON:
+		case DM_COMMIT_ACTION_SET: {
+			struct dc_target *new_target =
+				create_target_for_sink(
+					aconnector,
+					&crtc->state->mode);
+
+			DRM_DEBUG_KMS("Atomic commit: SET.\n");
+
+			if (!new_target) {
+				/*
+				 * this could happen because of issues with
+				 * userspace notifications delivery.
+				 * In this case userspace tries to set mode on
+				 * display which is disconnect in fact.
+				 * dc_sink in NULL in this case on aconnector.
+				 * We expect reset mode will come soon.
+				 *
+				 * This can also happen when unplug is done
+				 * during resume sequence ended
+				 */
+				new_state->planes_changed = false;
+				DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n",
+						__func__, acrtc->base.base.id);
+				break;
+			}
+
+			if (acrtc->target) {
+				/*
+				 * we evade vblanks and pflips on crtc that
+				 * should be changed
+				 */
+				manage_dm_interrupts(adev, acrtc, false);
+				/* this is the update mode case */
+				dc_target_release(acrtc->target);
+				acrtc->target = NULL;
+			}
+
+			/*
+			 * this loop saves set mode crtcs
+			 * we needed to enable vblanks once all
+			 * resources acquired in dc after dc_commit_targets
+			 */
+			new_crtcs[new_crtcs_count] = acrtc;
+			new_crtcs_count++;
+
+			acrtc->target = new_target;
+			acrtc->enabled = true;
+
+			break;
+		}
+
+		case DM_COMMIT_ACTION_NOTHING:
+			break;
+
+		case DM_COMMIT_ACTION_DPMS_OFF:
+		case DM_COMMIT_ACTION_RESET:
+			DRM_DEBUG_KMS("Atomic commit: RESET.\n");
+			/* i.e. reset mode */
+			if (acrtc->target) {
+				manage_dm_interrupts(adev, acrtc, false);
+
+				dc_target_release(acrtc->target);
+				acrtc->target = NULL;
+				acrtc->enabled = false;
+			}
+			break;
+		} /* switch() */
+	} /* for_each_crtc_in_state() */
+
+	commit_targets_count = 0;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+		if (acrtc->target) {
+			commit_targets[commit_targets_count] = acrtc->target;
+			++commit_targets_count;
+		}
+	}
+
+	/* DC is optimized not to do anything if 'targets' didn't change. */
+	dc_commit_targets(dm->dc, commit_targets, commit_targets_count);
+
+	/* update planes when needed */
+	for_each_plane_in_state(state, plane, old_plane_state, i) {
+		struct drm_plane_state *plane_state = plane->state;
+		struct drm_crtc *crtc = plane_state->crtc;
+		struct drm_framebuffer *fb = plane_state->fb;
+		struct drm_connector *connector;
+		struct dm_connector_state *dm_state = NULL;
+		enum dm_commit_action action;
+
+		if (!fb || !crtc || !crtc->state->planes_changed ||
+			!crtc->state->active)
+			continue;
+
+		action = get_dm_commit_action(crtc->state);
+
+		/* Surfaces are created under two scenarios:
+		 * 1. This commit is not a page flip.
+		 * 2. This commit is a page flip, and targets are created.
+		 */
+		if (!page_flip_needed(plane_state, old_plane_state) ||
+				action == DM_COMMIT_ACTION_DPMS_ON ||
+				action == DM_COMMIT_ACTION_SET) {
+			list_for_each_entry(connector,
+				&dev->mode_config.connector_list, head)	{
+				if (connector->state->crtc == crtc) {
+					dm_state = to_dm_connector_state(
+						connector->state);
+					break;
+				}
+			}
+
+			/*
+			 * This situation happens in the following case:
+			 * we are about to get set mode for connector who's only
+			 * possible crtc (in encoder crtc mask) is used by
+			 * another connector, that is why it will try to
+			 * re-assing crtcs in order to make configuration
+			 * supported. For our implementation we need to make all
+			 * encoders support all crtcs, then this issue will
+			 * never arise again. But to guard code from this issue
+			 * check is left.
+			 *
+			 * Also it should be needed when used with actual
+			 * drm_atomic_commit ioctl in future
+			 */
+			if (!dm_state)
+				continue;
+
+			dm_dc_surface_commit(
+				dm->dc,
+				crtc,
+				dm_state);
+		}
+	}
+
+	for (i = 0; i < new_crtcs_count; i++) {
+		/*
+		 * loop to enable interrupts on newly arrived crtc
+		 */
+		struct amdgpu_crtc *acrtc = new_crtcs[i];
+
+		manage_dm_interrupts(adev, acrtc, true);
+		dm_crtc_cursor_reset(&acrtc->base);
+
+	}
+
+	/* Page flip if needed */
+	for_each_plane_in_state(state, plane, old_plane_state, i) {
+		struct drm_plane_state *plane_state = plane->state;
+		struct drm_crtc *crtc = plane_state->crtc;
+		struct drm_framebuffer *fb = plane_state->fb;
+
+		if (!fb || !crtc || !crtc->state->planes_changed ||
+			!crtc->state->active)
+			continue;
+
+		if (page_flip_needed(plane_state, old_plane_state))
+			amdgpu_crtc_page_flip(
+				crtc,
+				fb,
+				crtc->state->event,
+				0);
+	}
+
+	drm_atomic_helper_wait_for_vblanks(dev, state);
+
+	/* In this state all old framebuffers would be unpinned */
+
+	drm_atomic_helper_cleanup_planes(dev, state);
+
+	drm_atomic_state_free(state);
+
+	return 0;
+}
+
+static uint32_t add_val_sets_surface(
+	struct dc_validation_set *val_sets,
+	uint32_t set_count,
+	const struct dc_target *target,
+	const struct dc_surface *surface)
+{
+	uint32_t i = 0;
+
+	while (i < set_count) {
+		if (val_sets[i].target == target)
+			break;
+		++i;
+	}
+
+	val_sets[i].surfaces[val_sets[i].surface_count] = surface;
+	val_sets[i].surface_count++;
+
+	return val_sets[i].surface_count;
+}
+
+static uint32_t update_in_val_sets_target(
+	struct dc_validation_set *val_sets,
+	uint32_t set_count,
+	const struct dc_target *old_target,
+	const struct dc_target *new_target)
+{
+	uint32_t i = 0;
+
+	while (i < set_count) {
+		if (val_sets[i].target == old_target)
+			break;
+		++i;
+	}
+
+	val_sets[i].target = new_target;
+
+	if (i == set_count) {
+		/* nothing found. add new one to the end */
+		return set_count + 1;
+	}
+
+	return set_count;
+}
+
+static uint32_t remove_from_val_sets(
+	struct dc_validation_set *val_sets,
+	uint32_t set_count,
+	const struct dc_target *target)
+{
+	uint32_t i = 0;
+
+	while (i < set_count) {
+		if (val_sets[i].target == target)
+			break;
+		++i;
+	}
+
+	if (i == set_count) {
+		/* nothing found */
+		return set_count;
+	}
+
+	memmove(
+		&val_sets[i],
+		&val_sets[i + 1],
+		sizeof(struct dc_validation_set *) * (set_count - i - 1));
+
+	return set_count - 1;
+}
+
+int amdgpu_dm_atomic_check(struct drm_device *dev,
+			struct drm_atomic_state *state)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_plane *plane;
+	struct drm_plane_state *plane_state;
+	int i;
+	int j;
+	int ret;
+	int set_count;
+	int new_target_count;
+	struct dc_validation_set set[MAX_TARGET_NUM] = {{ 0 }};
+	struct dc_target *new_targets[MAX_TARGET_NUM] = { 0 };
+	struct amdgpu_device *adev = dev->dev_private;
+	struct dc *dc = adev->dm.dc;
+	bool need_to_validate = false;
+
+	ret = drm_atomic_helper_check(dev, state);
+
+	if (ret) {
+		DRM_ERROR("Atomic state validation failed with error :%d !\n",
+				ret);
+		return ret;
+	}
+
+	ret = -EINVAL;
+
+	/* copy existing configuration */
+	new_target_count = 0;
+	set_count = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+
+		struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+		if (acrtc->target) {
+			set[set_count].target = acrtc->target;
+			++set_count;
+		}
+	}
+
+	/* update changed items */
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		struct amdgpu_crtc *acrtc = NULL;
+		struct amdgpu_connector *aconnector = NULL;
+		enum dm_commit_action action;
+		struct drm_connector *connector;
+		struct drm_connector_state *con_state;
+
+		acrtc = to_amdgpu_crtc(crtc);
+
+		for_each_connector_in_state(state, connector, con_state, j) {
+			if (con_state->crtc == crtc) {
+				aconnector = to_amdgpu_connector(connector);
+				break;
+			}
+		}
+
+		/*TODO:
+		handle_headless_hotplug(acrtc, crtc_state, &aconnector);*/
+
+		action = get_dm_commit_action(crtc_state);
+
+		switch (action) {
+		case DM_COMMIT_ACTION_DPMS_ON:
+		case DM_COMMIT_ACTION_SET: {
+			struct drm_display_mode mode = crtc_state->mode;
+			struct dc_target *new_target = NULL;
+
+			if (!aconnector) {
+				DRM_ERROR(
+					"%s: Can't find connector for crtc %d\n",
+					__func__,
+					acrtc->crtc_id);
+				goto connector_not_found;
+			}
+
+			new_target =
+				create_target_for_sink(
+					aconnector,
+					&mode);
+
+			/*
+			 * we can have no target on ACTION_SET if a display
+			 * was disconnected during S3, in this case it not and
+			 * error, the OS will be updated after detection, and
+			 * do the right thing on next atomic commit
+			 */
+			if (!new_target) {
+				DRM_DEBUG_KMS("%s: Failed to create new target for crtc %d\n",
+						__func__, acrtc->base.base.id);
+				break;
+			}
+
+			new_targets[new_target_count] = new_target;
+
+			set_count = update_in_val_sets_target(
+					set,
+					set_count,
+					acrtc->target,
+					new_target);
+			new_target_count++;
+			need_to_validate = true;
+			break;
+		}
+
+		case DM_COMMIT_ACTION_NOTHING:
+			break;
+		case DM_COMMIT_ACTION_DPMS_OFF:
+		case DM_COMMIT_ACTION_RESET:
+			/* i.e. reset mode */
+			if (acrtc->target) {
+				set_count = remove_from_val_sets(
+						set,
+						set_count,
+						acrtc->target);
+			}
+			break;
+		}
+	}
+
+
+	for (i = 0; i < set_count; i++) {
+		for_each_plane_in_state(state, plane, plane_state, j) {
+			struct drm_plane_state *old_plane_state = plane->state;
+			struct drm_framebuffer *fb = plane_state->fb;
+			struct drm_crtc *crtc = plane_state->crtc;
+			struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+			if (!fb || acrtc->target != set[i].target)
+				continue;
+
+			if (!crtc->state->planes_changed)
+				continue;
+
+			if (!page_flip_needed(plane_state, old_plane_state)) {
+				struct dc_surface *surface =
+					dc_create_surface(dc);
+
+				fill_plane_attributes(
+					surface,
+					plane_state);
+
+				add_val_sets_surface(
+					set,
+					set_count,
+					acrtc->target,
+					surface);
+				need_to_validate = true;
+			}
+		}
+
+	}
+
+	if (need_to_validate == false || set_count == 0
+				|| dc_validate_resources(dc, set, set_count))
+		ret = 0;
+
+connector_not_found:
+	for (i = 0; i < set_count; i++) {
+		for (j = 0; j < set[i].surface_count; j++) {
+			dc_surface_release(set[i].surfaces[j]);
+		}
+	}
+	for (i = 0; i < new_target_count; i++)
+		dc_target_release(new_targets[i]);
+
+	if (ret != 0)
+		DRM_ERROR("Atomic check failed.\n");
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
new file mode 100644
index 000000000000..0481075de6e9
--- /dev/null
+++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dm_types.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012-13 Advanced Micro Devices, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+
+#ifndef __AMDGPU_DM_TYPES_H__
+#define __AMDGPU_DM_TYPES_H__
+
+#include <drm/drmP.h>
+
+struct amdgpu_framebuffer;
+struct amdgpu_display_manager;
+struct dc_validation_set;
+struct dc_surface;
+
+/*TODO Jodan Hersen use the one in amdgpu_dm*/
+int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
+			struct amdgpu_crtc *amdgpu_crtc,
+			uint32_t link_index);
+int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
+			struct amdgpu_connector *amdgpu_connector,
+			uint32_t link_index,
+			struct amdgpu_encoder *amdgpu_encoder);
+int amdgpu_dm_encoder_init(
+	struct drm_device *dev,
+	struct amdgpu_encoder *aencoder,
+	uint32_t link_index);
+
+void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc);
+void amdgpu_dm_connector_destroy(struct drm_connector *connector);
+void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder);
+
+void dm_add_display_info(
+	struct drm_display_info *disp_info,
+	struct amdgpu_display_manager *dm,
+	uint32_t display_index);
+
+int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
+
+int amdgpu_dm_atomic_commit(
+	struct drm_device *dev,
+	struct drm_atomic_state *state,
+	bool async);
+int amdgpu_dm_atomic_check(struct drm_device *dev,
+				struct drm_atomic_state *state);
+
+int dm_create_validation_set_for_target(
+	struct drm_connector *connector,
+	struct drm_display_mode *mode,
+	struct dc_validation_set *val_set);
+
+void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector);
+struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state(
+	struct drm_connector *connector);
+void amdgpu_dm_connector_atomic_destroy_state(
+	struct drm_connector *connector,
+	struct drm_connector_state *state);
+int amdgpu_dm_connector_atomic_set_property(
+	struct drm_connector *connector,
+	struct drm_connector_state *state,
+	struct drm_property *property,
+	uint64_t val);
+
+int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev);
+
+void amdgpu_dm_connector_init_helper(
+	struct amdgpu_display_manager *dm,
+	struct amdgpu_connector *aconnector,
+	int connector_type,
+	const struct dc_link *link,
+	int link_index);
+
+int amdgpu_dm_connector_mode_valid(
+	struct drm_connector *connector,
+	struct drm_display_mode *mode);
+
+extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs;
+
+#endif		/* __AMDGPU_DM_TYPES_H__ */
diff --git a/drivers/gpu/drm/amd/dal/dc/dm_services.h b/drivers/gpu/drm/amd/dal/dc/dm_services.h
index 206c0b7df7c6..47bbb9e6e060 100644
--- a/drivers/gpu/drm/amd/dal/dc/dm_services.h
+++ b/drivers/gpu/drm/amd/dal/dc/dm_services.h
@@ -166,19 +166,7 @@ bool dm_exec_bios_cmd_table(
 	uint32_t index,
 	void *params);
 
-#ifdef BUILD_DAL_TEST
-uint32_t dm_bios_cmd_table_para_revision(
-struct dc_context *ctx,
-	uint32_t index);
 
-bool dm_bios_cmd_table_revision(
-	struct dc_context *ctx,
-	uint32_t index,
-	uint8_t *frev,
-	uint8_t *crev);
-#endif
-
-#ifndef BUILD_DAL_TEST
 static inline uint32_t dm_bios_cmd_table_para_revision(
 	struct dc_context *ctx,
 	uint32_t index)
@@ -195,11 +183,6 @@ static inline uint32_t dm_bios_cmd_table_para_revision(
 
 	return crev;
 }
-#else
-uint32_t dm_bios_cmd_table_para_revision(
-		struct dc_context *ctx,
-		uint32_t index);
-#endif
 
 /**************************************
  * Power Play (PP) interfaces
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

* [PATCH v3 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji
  2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
                     ` (4 preceding siblings ...)
  2016-02-29 21:56   ` [PATCH v3 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
@ 2016-02-29 21:56   ` Harry Wentland
  5 siblings, 0 replies; 87+ messages in thread
From: Harry Wentland @ 2016-02-29 21:56 UTC (permalink / raw)
  To: dri-devel

Start to use dal by default on Carrizo, Tonga, and Fiji ASICs.

v3 changes:
- rebase on Alex's latest drm-next-4.6-wip
- export some functions to share with DAL
- remove has_dal_support macro and move logic into amdgpu_device_has_dal_support

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/Kconfig         |   3 +
 drivers/gpu/drm/amd/amdgpu/Makefile        |  17 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu.h        |   8 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |  70 ++++++--
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c    |   4 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c     |   5 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c    |  20 ++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h   |  63 +++++++-
 drivers/gpu/drm/amd/amdgpu/dce_v10_0.c     |  12 +-
 drivers/gpu/drm/amd/amdgpu/dce_v10_0.h     |   7 +
 drivers/gpu/drm/amd/amdgpu/dce_v11_0.c     |  12 +-
 drivers/gpu/drm/amd/amdgpu/dce_v11_0.h     |   7 +
 drivers/gpu/drm/amd/amdgpu/dce_v8_0.c      |  12 +-
 drivers/gpu/drm/amd/amdgpu/dce_v8_0.h      |   7 +
 drivers/gpu/drm/amd/amdgpu/vi.c            | 250 +++++++++++++++++++++++++++++
 15 files changed, 449 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
index b30fcfa4b1f2..3a37e37bef28 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -15,3 +15,6 @@ config DRM_AMDGPU_USERPTR
 	help
 	  This option selects CONFIG_MMU_NOTIFIER if it isn't already
 	  selected to enabled full userptr support.
+
+source "drivers/gpu/drm/amd/dal/Kconfig"
+
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index c7fcdcedaadb..c434ee5c589f 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -3,13 +3,19 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 FULL_AMD_PATH=$(src)/..
+DAL_FOLDER_NAME=dal
+FULL_AMD_DAL_PATH = $(FULL_AMD_PATH)/$(DAL_FOLDER_NAME)
 
 ccflags-y := -Iinclude/drm -I$(FULL_AMD_PATH)/include/asic_reg \
 	-I$(FULL_AMD_PATH)/include \
 	-I$(FULL_AMD_PATH)/amdgpu \
 	-I$(FULL_AMD_PATH)/scheduler \
 	-I$(FULL_AMD_PATH)/powerplay/inc \
-	-I$(FULL_AMD_PATH)/acp/include
+	-I$(FULL_AMD_PATH)/acp/include \
+	-I$(FULL_AMD_DAL_PATH) \
+	-I$(FULL_AMD_DAL_PATH)/include \
+	-I$(FULL_AMD_DAL_PATH)/dc \
+	-I$(FULL_AMD_DAL_PATH)/amdgpu_dm
 
 amdgpu-y := amdgpu_drv.o
 
@@ -118,6 +124,15 @@ amdgpu-y += $(AMD_POWERPLAY_FILES)
 
 endif
 
+ifneq ($(CONFIG_DRM_AMD_DAL),)
+
+RELATIVE_AMD_DAL_PATH = ../$(DAL_FOLDER_NAME)
+include $(FULL_AMD_DAL_PATH)/Makefile
+
+amdgpu-y += $(AMD_DAL_FILES)
+
+endif
+
 obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o
 
 CFLAGS_amdgpu_trace_points.o := -I$(src)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index f5bac97a438b..9e14c2a4bcda 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -54,6 +54,7 @@
 #include "amdgpu_gds.h"
 #include "amd_powerplay.h"
 #include "amdgpu_acp.h"
+#include "amdgpu_dm.h"
 
 #include "gpu_scheduler.h"
 
@@ -85,6 +86,7 @@ extern int amdgpu_vm_debug;
 extern int amdgpu_sched_jobs;
 extern int amdgpu_sched_hw_submission;
 extern int amdgpu_powerplay;
+extern int amdgpu_dal;
 
 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS	        3000
 #define AMDGPU_MAX_USEC_TIMEOUT			100000	/* 100 ms */
@@ -2016,6 +2018,7 @@ struct amdgpu_device {
 
 	/* display */
 	struct amdgpu_mode_info		mode_info;
+	/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
 	struct work_struct		hotplug_work;
 	struct amdgpu_irq_src		crtc_irq;
 	struct amdgpu_irq_src		pageflip_irq;
@@ -2063,6 +2066,9 @@ struct amdgpu_device {
 	/* GDS */
 	struct amdgpu_gds		gds;
 
+	/* display related functionality */
+	struct amdgpu_display_manager dm;
+
 	const struct amdgpu_ip_block_version *ip_blocks;
 	int				num_ip_blocks;
 	struct amdgpu_ip_block_status	*ip_block_status;
@@ -2096,7 +2102,7 @@ void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v);
 
 u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index);
 void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v);
-
+bool amdgpu_device_has_dal_support(struct amdgpu_device *adev);
 /*
  * Cast helper
  */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index db20d2783def..fc8c765feabf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1369,6 +1369,33 @@ static int amdgpu_resume(struct amdgpu_device *adev)
 	return 0;
 }
 
+
+/**
+ * amdgpu_device_has_dal_support - check if dal is supported
+ *
+ * @adev: amdgpu_device_pointer
+ *
+ * Returns true for supported, false for not supported
+ */
+bool amdgpu_device_has_dal_support(struct amdgpu_device *adev)
+{
+	switch(adev->asic_type) {
+#if defined(CONFIG_DRM_AMD_DAL) && defined(CONFIG_DRM_AMD_DAL_DCE11_0)
+	case CHIP_CARRIZO:
+	case CHIP_STONEY:
+		return amdgpu_dal != 0;
+#endif
+#if defined(CONFIG_DRM_AMD_DAL) && defined(CONFIG_DRM_AMD_DAL_DCE10_0)
+	case CHIP_TONGA:
+	case CHIP_FIJI:
+		return amdgpu_dal != 0;
+#endif
+	default:
+		return false;
+	}
+}
+
+
 /**
  * amdgpu_device_init - initialize the driver
  *
@@ -1521,7 +1548,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
 		return r;
 	}
 	/* init i2c buses */
-	amdgpu_atombios_i2c_init(adev);
+	if (!amdgpu_device_has_dal_support(adev))
+		amdgpu_atombios_i2c_init(adev);
 
 	/* Fence driver */
 	r = amdgpu_fence_driver_init(adev);
@@ -1621,7 +1649,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
 	adev->ip_block_status = NULL;
 	adev->accel_working = false;
 	/* free i2c buses */
-	amdgpu_i2c_fini(adev);
+	if (!amdgpu_device_has_dal_support(adev))
+		amdgpu_i2c_fini(adev);
 	amdgpu_atombios_fini(adev);
 	kfree(adev->bios);
 	adev->bios = NULL;
@@ -1669,12 +1698,14 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 
 	drm_kms_helper_poll_disable(dev);
 
-	/* turn off display hw */
-	drm_modeset_lock_all(dev);
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+	if (!amdgpu_device_has_dal_support(adev)) {
+		/* turn off display hw */
+		drm_modeset_lock_all(dev);
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+		}
+		drm_modeset_unlock_all(dev);
 	}
-	drm_modeset_unlock_all(dev);
 
 	/* unpin the front buffers and cursors */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -1766,6 +1797,9 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
 
 	r = amdgpu_resume(adev);
 
+	if (r)
+		DRM_ERROR("amdgpu_resume failed (%d).\n", r);
+
 	amdgpu_fence_driver_resume(adev);
 
 	r = amdgpu_ib_ring_tests(adev);
@@ -1796,17 +1830,25 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
 
 	/* blat the mode back in */
 	if (fbcon) {
-		drm_helper_resume_force_mode(dev);
-		/* turn on display hw */
-		drm_modeset_lock_all(dev);
-		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+		if (!amdgpu_device_has_dal_support(adev)) {
+			/* pre DCE11 */
+			drm_helper_resume_force_mode(dev);
+
+			/* turn on display hw */
+			drm_modeset_lock_all(dev);
+			list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+				drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+			}
+			drm_modeset_unlock_all(dev);
 		}
-		drm_modeset_unlock_all(dev);
 	}
 
 	drm_kms_helper_poll_enable(dev);
-	drm_helper_hpd_irq_event(dev);
+
+	if (!amdgpu_device_has_dal_support(adev))
+		 drm_helper_hpd_irq_event(dev);
+	else
+		drm_kms_helper_hotplug_event(dev);
 
 	if (fbcon) {
 		amdgpu_fbdev_set_suspend(adev, 0);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index ce79a8b605a0..0306a62b72c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -80,6 +80,7 @@ int amdgpu_exp_hw_support = 0;
 int amdgpu_sched_jobs = 32;
 int amdgpu_sched_hw_submission = 2;
 int amdgpu_powerplay = -1;
+int amdgpu_dal = -1;
 
 MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
 module_param_named(vramlimit, amdgpu_vram_limit, int, 0600);
@@ -158,6 +159,9 @@ MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 =
 module_param_named(powerplay, amdgpu_powerplay, int, 0444);
 #endif
 
+MODULE_PARM_DESC(dal, "DAL display driver (1 = enable, 0 = disable, -1 = auto (default))");
+module_param_named(dal, amdgpu_dal, int, 0444);
+
 static struct pci_device_id pciidlist[] = {
 #ifdef CONFIG_DRM_AMDGPU_CIK
 	/* Kaveri */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
index 919146780a15..e694c9983bbd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -42,11 +42,6 @@
    this contains a helper + a amdgpu fb
    the helper contains a pointer to amdgpu framebuffer baseclass.
 */
-struct amdgpu_fbdev {
-	struct drm_fb_helper helper;
-	struct amdgpu_framebuffer rfb;
-	struct amdgpu_device *adev;
-};
 
 static struct fb_ops amdgpufb_ops = {
 	.owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index f594cfaa97e5..6e8469ae6b09 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -36,6 +36,10 @@
 
 #include <linux/pm_runtime.h>
 
+#ifdef CONFIG_DRM_AMD_DAL
+#include "amdgpu_dm_irq.h"
+#endif
+
 #define AMDGPU_WAIT_IDLE_TIMEOUT 200
 
 /*
@@ -215,10 +219,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
 	int r = 0;
 
 	spin_lock_init(&adev->irq.lock);
-	r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
-	if (r) {
-		return r;
-	}
+
 	/* enable msi */
 	adev->irq.msi_enabled = false;
 
@@ -230,7 +231,16 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
 		}
 	}
 
-	INIT_WORK(&adev->hotplug_work, amdgpu_hotplug_work_func);
+	if (!amdgpu_device_has_dal_support(adev)) {
+		r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
+		if (r)
+			return r;
+
+		/* pre DCE11 */
+		INIT_WORK(&adev->hotplug_work,
+				amdgpu_hotplug_work_func);
+	}
+
 	INIT_WORK(&adev->reset_work, amdgpu_irq_reset_work_func);
 
 	adev->irq.installed = true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 8d432e6901af..c30ff6cb233f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -35,11 +35,13 @@
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_fixed.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_helper.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_fb_helper.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 
+#include <drm/drm_dp_mst_helper.h>
+
 struct amdgpu_bo;
 struct amdgpu_device;
 struct amdgpu_encoder;
@@ -305,6 +307,18 @@ struct amdgpu_display_funcs {
 				 struct amdgpu_mode_mc_save *save);
 };
 
+struct amdgpu_framebuffer {
+	struct drm_framebuffer base;
+	struct drm_gem_object *obj;
+};
+
+struct amdgpu_fbdev {
+	struct drm_fb_helper helper;
+	struct amdgpu_framebuffer rfb;
+	struct list_head fbdev_list;
+	struct amdgpu_device *adev;
+};
+
 struct amdgpu_mode_info {
 	struct atom_context *atom_context;
 	struct card_info *atom_card_info;
@@ -409,6 +423,9 @@ struct amdgpu_crtc {
 	u32 wm_high;
 	u32 lb_vblank_lead_lines;
 	struct drm_display_mode hw_mode;
+
+	/* After Set Mode target will be non-NULL */
+	struct dc_target *target;
 };
 
 struct amdgpu_encoder_atom_dig {
@@ -498,6 +515,19 @@ enum amdgpu_connector_dither {
 	AMDGPU_FMT_DITHER_ENABLE = 1,
 };
 
+struct amdgpu_dm_dp_aux {
+	struct drm_dp_aux aux;
+	uint32_t link_index;
+};
+
+struct amdgpu_i2c_adapter {
+	struct i2c_adapter base;
+	struct amdgpu_display_manager *dm;
+	uint32_t link_index;
+};
+
+#define TO_DM_AUX(x) container_of((x), struct amdgpu_dm_dp_aux, aux)
+
 struct amdgpu_connector {
 	struct drm_connector base;
 	uint32_t connector_id;
@@ -509,6 +539,13 @@ struct amdgpu_connector {
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
 	struct edid *edid;
+	/* number of modes generated from EDID at 'dc_sink' */
+	int num_modes;
+	/* The 'old' sink - before an HPD.
+	 * The 'current' sink is in dc_link->sink. */
+	const struct dc_sink *dc_sink;
+	const struct dc_link *dc_link;
+	const struct dc_target *target;
 	void *con_priv;
 	bool dac_load_detect;
 	bool detected_by_load; /* if the connection status was determined by load */
@@ -519,11 +556,29 @@ struct amdgpu_connector {
 	enum amdgpu_connector_audio audio;
 	enum amdgpu_connector_dither dither;
 	unsigned pixelclock_for_modeset;
+
+	struct drm_dp_mst_topology_mgr mst_mgr;
+	struct amdgpu_dm_dp_aux dm_dp_aux;
+	struct drm_dp_mst_port *port;
+	struct amdgpu_connector *mst_port;
+	bool is_mst_connector;
+	struct amdgpu_encoder *mst_encoder;
+	struct semaphore mst_sem;
+
+	/* TODO see if we can merge with ddc_bus or make a dm_connector */
+	struct amdgpu_i2c_adapter *i2c;
 };
 
-struct amdgpu_framebuffer {
-	struct drm_framebuffer base;
-	struct drm_gem_object *obj;
+/* TODO: start to use this struct and remove same field from base one */
+struct amdgpu_mst_connector {
+	struct amdgpu_connector base;
+
+	struct drm_dp_mst_topology_mgr mst_mgr;
+	struct amdgpu_dm_dp_aux dm_dp_aux;
+	struct drm_dp_mst_port *port;
+	struct amdgpu_connector *mst_port;
+	bool is_mst_connector;
+	struct amdgpu_encoder *mst_encoder;
 };
 
 #define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index a8ac8a34df87..aa4a93e5e521 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -556,8 +556,8 @@ static bool dce_v10_0_is_display_hung(struct amdgpu_device *adev)
 	return true;
 }
 
-static void dce_v10_0_stop_mc_access(struct amdgpu_device *adev,
-				     struct amdgpu_mode_mc_save *save)
+void dce_v10_0_stop_mc_access(struct amdgpu_device *adev,
+			      struct amdgpu_mode_mc_save *save)
 {
 	u32 crtc_enabled, tmp;
 	int i;
@@ -621,8 +621,8 @@ static void dce_v10_0_stop_mc_access(struct amdgpu_device *adev,
 	}
 }
 
-static void dce_v10_0_resume_mc_access(struct amdgpu_device *adev,
-				       struct amdgpu_mode_mc_save *save)
+void dce_v10_0_resume_mc_access(struct amdgpu_device *adev,
+				struct amdgpu_mode_mc_save *save)
 {
 	u32 tmp, frame_count;
 	int i, j;
@@ -684,8 +684,8 @@ static void dce_v10_0_resume_mc_access(struct amdgpu_device *adev,
 	WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control);
 }
 
-static void dce_v10_0_set_vga_render_state(struct amdgpu_device *adev,
-					   bool render)
+void dce_v10_0_set_vga_render_state(struct amdgpu_device *adev,
+				    bool render)
 {
 	u32 tmp;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h
index 1bfa48ddd8a6..3947956b3471 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h
@@ -26,4 +26,11 @@
 
 extern const struct amd_ip_funcs dce_v10_0_ip_funcs;
 
+void dce_v10_0_set_vga_render_state(struct amdgpu_device *adev,
+				    bool render);
+void dce_v10_0_stop_mc_access(struct amdgpu_device *adev,
+			      struct amdgpu_mode_mc_save *save);
+void dce_v10_0_resume_mc_access(struct amdgpu_device *adev,
+				struct amdgpu_mode_mc_save *save);
+
 #endif
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index a7699bec270a..e66472388347 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -546,8 +546,8 @@ static bool dce_v11_0_is_display_hung(struct amdgpu_device *adev)
 	return true;
 }
 
-static void dce_v11_0_stop_mc_access(struct amdgpu_device *adev,
-				     struct amdgpu_mode_mc_save *save)
+void dce_v11_0_stop_mc_access(struct amdgpu_device *adev,
+			      struct amdgpu_mode_mc_save *save)
 {
 	u32 crtc_enabled, tmp;
 	int i;
@@ -611,8 +611,8 @@ static void dce_v11_0_stop_mc_access(struct amdgpu_device *adev,
 	}
 }
 
-static void dce_v11_0_resume_mc_access(struct amdgpu_device *adev,
-				       struct amdgpu_mode_mc_save *save)
+void dce_v11_0_resume_mc_access(struct amdgpu_device *adev,
+				struct amdgpu_mode_mc_save *save)
 {
 	u32 tmp, frame_count;
 	int i, j;
@@ -674,8 +674,8 @@ static void dce_v11_0_resume_mc_access(struct amdgpu_device *adev,
 	WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control);
 }
 
-static void dce_v11_0_set_vga_render_state(struct amdgpu_device *adev,
-					   bool render)
+void dce_v11_0_set_vga_render_state(struct amdgpu_device *adev,
+				    bool render)
 {
 	u32 tmp;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h
index 84e4618f5253..dc6ff0430c27 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h
@@ -26,4 +26,11 @@
 
 extern const struct amd_ip_funcs dce_v11_0_ip_funcs;
 
+void dce_v11_0_set_vga_render_state(struct amdgpu_device *adev,
+				    bool render);
+void dce_v11_0_stop_mc_access(struct amdgpu_device *adev,
+			      struct amdgpu_mode_mc_save *save);
+void dce_v11_0_resume_mc_access(struct amdgpu_device *adev,
+				struct amdgpu_mode_mc_save *save);
+
 #endif
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index 628d7b2433b9..bdaba7b256e1 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -504,8 +504,8 @@ static bool dce_v8_0_is_display_hung(struct amdgpu_device *adev)
 	return true;
 }
 
-static void dce_v8_0_stop_mc_access(struct amdgpu_device *adev,
-				    struct amdgpu_mode_mc_save *save)
+void dce_v8_0_stop_mc_access(struct amdgpu_device *adev,
+			     struct amdgpu_mode_mc_save *save)
 {
 	u32 crtc_enabled, tmp;
 	int i;
@@ -569,8 +569,8 @@ static void dce_v8_0_stop_mc_access(struct amdgpu_device *adev,
 	}
 }
 
-static void dce_v8_0_resume_mc_access(struct amdgpu_device *adev,
-				      struct amdgpu_mode_mc_save *save)
+void dce_v8_0_resume_mc_access(struct amdgpu_device *adev,
+			       struct amdgpu_mode_mc_save *save)
 {
 	u32 tmp, frame_count;
 	int i, j;
@@ -632,8 +632,8 @@ static void dce_v8_0_resume_mc_access(struct amdgpu_device *adev,
 	WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control);
 }
 
-static void dce_v8_0_set_vga_render_state(struct amdgpu_device *adev,
-					  bool render)
+void dce_v8_0_set_vga_render_state(struct amdgpu_device *adev,
+				   bool render)
 {
 	u32 tmp;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h
index 77016852b252..4bb72abb57ed 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h
@@ -26,4 +26,11 @@
 
 extern const struct amd_ip_funcs dce_v8_0_ip_funcs;
 
+void dce_v8_0_set_vga_render_state(struct amdgpu_device *adev,
+				   bool render);
+void dce_v8_0_stop_mc_access(struct amdgpu_device *adev,
+			     struct amdgpu_mode_mc_save *save);
+void dce_v8_0_resume_mc_access(struct amdgpu_device *adev,
+			       struct amdgpu_mode_mc_save *save);
+
 #endif
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 125003517544..4b27092d14c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -77,6 +77,7 @@
 #if defined(CONFIG_DRM_AMD_ACP)
 #include "amdgpu_acp.h"
 #endif
+#include "amdgpu_dm.h"
 
 /*
  * Indirect registers accessor
@@ -984,6 +985,225 @@ static const struct amdgpu_ip_block_version cz_ip_blocks[] =
 #endif
 };
 
+/*
+ * This is temporary. After we've gone through full testing with
+ * DAL we want to remove dce_v11
+ */
+#if defined(CONFIG_DRM_AMD_DAL)
+static const struct amdgpu_ip_block_version cz_ip_blocks_dal[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &cz_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 11,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &amdgpu_dm_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+#if defined(CONFIG_DRM_AMD_ACP)
+	{
+		.type = AMD_IP_BLOCK_TYPE_ACP,
+		.major = 2,
+		.minor = 2,
+		.rev = 0,
+		.funcs = &acp_ip_funcs,
+	},
+#endif
+};
+
+static const struct amdgpu_ip_block_version tonga_ip_blocks_dal[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &tonga_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 7,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 10,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &amdgpu_dm_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 5,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v5_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+};
+
+static const struct amdgpu_ip_block_version fiji_ip_blocks_dal[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 5,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &tonga_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 7,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 10,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &amdgpu_dm_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+};
+#endif
+
 int vi_set_ip_blocks(struct amdgpu_device *adev)
 {
 	switch (adev->asic_type) {
@@ -992,17 +1212,47 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
 		adev->num_ip_blocks = ARRAY_SIZE(topaz_ip_blocks);
 		break;
 	case CHIP_FIJI:
+#if defined(CONFIG_DRM_AMD_DAL)
+		if (amdgpu_dal && amdgpu_device_has_dal_support(adev)) {
+			adev->ip_blocks = fiji_ip_blocks_dal;
+			adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks_dal);
+		} else {
+			adev->ip_blocks = fiji_ip_blocks;
+			adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks);
+		}
+#else
 		adev->ip_blocks = fiji_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks);
+#endif
 		break;
 	case CHIP_TONGA:
+#if defined(CONFIG_DRM_AMD_DAL)
+		if (amdgpu_dal && amdgpu_device_has_dal_support(adev)) {
+			adev->ip_blocks = tonga_ip_blocks_dal;
+			adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks_dal);
+		} else {
+			adev->ip_blocks = tonga_ip_blocks;
+			adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
+		}
+#else
 		adev->ip_blocks = tonga_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
+#endif
 		break;
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
+#if defined(CONFIG_DRM_AMD_DAL)
+		if (amdgpu_dal && amdgpu_device_has_dal_support(adev)) {
+			adev->ip_blocks = cz_ip_blocks_dal;
+			adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks_dal);
+		} else {
+			adev->ip_blocks = cz_ip_blocks;
+			adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks);
+		}
+#else
 		adev->ip_blocks = cz_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks);
+#endif
 		break;
 	default:
 		/* FIXME: not supported yet */
-- 
2.5.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 87+ messages in thread

end of thread, other threads:[~2016-02-29 21:56 UTC | newest]

Thread overview: 87+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-11 17:19 [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
2016-02-11 17:19 ` [PATCH 01/29] drm/amd/dal: Add dal headers Harry Wentland
2016-02-11 17:19 ` [PATCH 02/29] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
2016-02-11 17:19 ` [PATCH 03/29] drm/amd/dal: Fixed point arithmetic Harry Wentland
2016-02-11 17:19 ` [PATCH 04/29] drm/amd/dal: Asic Capabilities Harry Wentland
2016-02-11 17:19 ` [PATCH 05/29] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-11 17:19 ` [PATCH 06/29] drm/amd/dal: Adapter Service Harry Wentland
2016-02-12  0:26   ` Dave Airlie
2016-02-12 14:30     ` Wentland, Harry
2016-02-11 17:19 ` [PATCH 07/29] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-11 17:19 ` [PATCH 08/29] drm/amd/dal: I2C Aux Manager Harry Wentland
2016-02-11 20:19   ` Rob Clark
2016-02-11 20:52     ` Daniel Vetter
2016-02-17  3:23     ` Harry Wentland
2016-02-11 17:19 ` [PATCH 09/29] drm/amd/dal: IRQ Service Harry Wentland
2016-02-11 17:19 ` [PATCH 10/29] drm/amd/dal: GPU Harry Wentland
2016-02-11 17:19 ` [PATCH 11/29] drm/amd/dal: Audio Harry Wentland
2016-02-11 17:19 ` [PATCH 12/29] drm/amd/dal: Bandwidth calculations Harry Wentland
2016-02-11 17:19 ` [PATCH 13/29] drm/amd/dal: Add encoder HW programming Harry Wentland
2016-02-11 17:19 ` [PATCH 14/29] drm/amd/dal: Add clock source " Harry Wentland
2016-02-11 17:19 ` [PATCH 15/29] drm/amd/dal: Add timing generator " Harry Wentland
2016-02-11 17:19 ` [PATCH 16/29] drm/amd/dal: Add surface " Harry Wentland
2016-02-11 17:19 ` [PATCH 17/29] drm/amd/dal: Add framebuffer compression " Harry Wentland
2016-02-11 17:19 ` [PATCH 18/29] drm/amd/dal: Add input pixel processing " Harry Wentland
2016-02-11 17:19 ` [PATCH 19/29] drm/amd/dal: Add output " Harry Wentland
2016-02-11 17:20 ` [PATCH 20/29] drm/amd/dal: Add transform & scaler " Harry Wentland
2016-02-11 17:20 ` [PATCH 21/29] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
2016-02-11 17:20 ` [PATCH 22/29] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
2016-02-11 17:20 ` [PATCH 23/29] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
2016-02-11 17:20 ` [PATCH 24/29] drm/amd/dal: Add display core Harry Wentland
2016-02-11 17:20 ` [PATCH 25/29] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-11 17:20 ` [PATCH 26/29] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
2016-02-11 17:20 ` [PATCH 27/29] drm/amd/dal: Correctly interpret rotation as bit set Harry Wentland
2016-02-11 21:00   ` Oded Gabbay
2016-02-16 16:46     ` Harry Wentland
2016-02-11 17:20 ` [PATCH 28/29] drm/amd/dal: fix flip clean-up state Harry Wentland
2016-02-11 17:20 ` [PATCH 29/29] drm/amd/dal: Force bw programming for DCE 10 until we start calculate BW Harry Wentland
2016-02-11 20:02 ` [PATCH 00/29] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Mike Lothian
2016-02-11 20:05   ` Wentland, Harry
2016-02-11 20:52 ` Dave Airlie
2016-02-11 21:06   ` Daniel Vetter
2016-02-12  0:57     ` Dave Airlie
2016-02-12  5:34     ` Daniel Vetter
2016-02-13  0:05       ` Wentland, Harry
2016-02-14 11:22         ` Jerome Glisse
2016-02-14 13:23           ` Daniel Vetter
2016-02-17  3:28           ` Harry Wentland
2016-02-14 13:32         ` Rob Clark
2016-02-14 13:51           ` Daniel Vetter
2016-02-17  3:26           ` Harry Wentland
2016-02-14 14:01         ` Daniel Vetter
2016-02-17  3:32           ` Harry Wentland
2016-02-14 21:44         ` Daniel Stone
2016-02-16 22:27 ` [PATCH v2 00/26] " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 01/26] drm/amd/dal: Add dal headers Harry Wentland
2016-02-16 22:27   ` [PATCH v2 02/26] drm/amd/dal: Add DAL Basic Types and Logger Harry Wentland
2016-02-16 22:27   ` [PATCH v2 03/26] drm/amd/dal: Fixed point arithmetic Harry Wentland
2016-02-16 22:27   ` [PATCH v2 04/26] drm/amd/dal: Asic Capabilities Harry Wentland
2016-02-16 22:27   ` [PATCH v2 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-16 22:27   ` [PATCH v2 06/26] drm/amd/dal: Adapter Service Harry Wentland
2016-02-16 22:27   ` [PATCH v2 07/26] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-16 22:27   ` [PATCH v2 08/26] drm/amd/dal: I2C Aux Manager Harry Wentland
2016-02-16 22:27   ` [PATCH v2 09/26] drm/amd/dal: IRQ Service Harry Wentland
2016-02-16 22:27   ` [PATCH v2 10/26] drm/amd/dal: GPU Harry Wentland
2016-02-16 22:27   ` [PATCH v2 11/26] drm/amd/dal: Audio Harry Wentland
2016-02-16 22:27   ` [PATCH v2 12/26] drm/amd/dal: Bandwidth calculations Harry Wentland
2016-02-16 22:27   ` [PATCH v2 13/26] drm/amd/dal: Add encoder HW programming Harry Wentland
2016-02-16 22:27   ` [PATCH v2 14/26] drm/amd/dal: Add clock source " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 15/26] drm/amd/dal: Add timing generator " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 16/26] drm/amd/dal: Add surface " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 17/26] drm/amd/dal: Add framebuffer compression " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 18/26] drm/amd/dal: Add input pixel processing " Harry Wentland
2016-02-16 22:27   ` [PATCH v2 19/26] drm/amd/dal: Add output " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 20/26] drm/amd/dal: Add transform & scaler " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 21/26] drm/amd/dal: Add Carrizo HW sequencer and resource Harry Wentland
2016-02-16 22:28   ` [PATCH v2 22/26] drm/amd/dal: Add Tonga/Fiji " Harry Wentland
2016-02-16 22:28   ` [PATCH v2 23/26] drm/amd/dal: Add empty encoder programming for virtual HW Harry Wentland
2016-02-16 22:28   ` [PATCH v2 24/26] drm/amd/dal: Add display core Harry Wentland
2016-02-16 22:28   ` [PATCH v2 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-16 22:28   ` [PATCH v2 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland
2016-02-29 21:56 ` [PATCH v3 00/26] Enabling new DAL display driver for amdgpu on Carrizo and Tonga Harry Wentland
2016-02-29 21:56   ` [PATCH v3 01/26] drm/amd/dal: Add dal headers Harry Wentland
2016-02-29 21:56   ` [PATCH v3 05/26] drm/amd/dal: GPIO (General Purpose IO) Harry Wentland
2016-02-29 21:56   ` [PATCH v3 07/26] drm/amd/dal: BIOS Parser Harry Wentland
2016-02-29 21:56   ` [PATCH v3 24/26] drm/amd/dal: Add display core Harry Wentland
2016-02-29 21:56   ` [PATCH v3 25/26] drm/amd/dal: Adding amdgpu_dm for dal Harry Wentland
2016-02-29 21:56   ` [PATCH v3 26/26] drm/amdgpu: Use dal driver for Carrizo, Tonga, and Fiji Harry Wentland

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.